diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2024-05-06 09:02:37 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-06 09:02:37 (GMT) |
commit | 153b3f75306b5d26e29ea157105d0fdc247ef853 (patch) | |
tree | f73ede56af175d27698ef56bec21073f98889bbc /Lib/test | |
parent | 716ec4bfcf1a564db9936122c442baa99f9c4a8c (diff) | |
download | cpython-153b3f75306b5d26e29ea157105d0fdc247ef853.zip cpython-153b3f75306b5d26e29ea157105d0fdc247ef853.tar.gz cpython-153b3f75306b5d26e29ea157105d0fdc247ef853.tar.bz2 |
gh-118465: Add __firstlineno__ attribute to class (GH-118475)
It is set by compiler with the line number of the first line of
the class definition.
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_compile.py | 5 | ||||
-rw-r--r-- | Lib/test/test_descr.py | 8 | ||||
-rw-r--r-- | Lib/test/test_inspect/test_inspect.py | 15 | ||||
-rw-r--r-- | Lib/test/test_metaclass.py | 8 |
4 files changed, 29 insertions, 7 deletions
diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 484d72e..1f4368b 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -1958,7 +1958,10 @@ class TestSourcePositions(unittest.TestCase): def test_load_super_attr(self): source = "class C:\n def __init__(self):\n super().__init__()" - code = compile(source, "<test>", "exec").co_consts[0].co_consts[1] + for const in compile(source, "<test>", "exec").co_consts[0].co_consts: + if isinstance(const, types.CodeType): + code = const + break self.assertOpcodeSourcePositionIs( code, "LOAD_GLOBAL", line=3, end_line=3, column=4, end_column=9 ) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 93f66a7..18144c8 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -5088,7 +5088,8 @@ class DictProxyTests(unittest.TestCase): self.assertNotIsInstance(it, list) keys = list(it) keys.sort() - self.assertEqual(keys, ['__dict__', '__doc__', '__module__', + self.assertEqual(keys, ['__dict__', '__doc__', '__firstlineno__', + '__module__', '__static_attributes__', '__weakref__', 'meth']) @@ -5099,7 +5100,7 @@ class DictProxyTests(unittest.TestCase): it = self.C.__dict__.values() self.assertNotIsInstance(it, list) values = list(it) - self.assertEqual(len(values), 6) + self.assertEqual(len(values), 7) @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), 'trace function introduces __local__') @@ -5109,7 +5110,8 @@ class DictProxyTests(unittest.TestCase): self.assertNotIsInstance(it, list) keys = [item[0] for item in it] keys.sort() - self.assertEqual(keys, ['__dict__', '__doc__', '__module__', + self.assertEqual(keys, ['__dict__', '__doc__', '__firstlineno__', + '__module__', '__static_attributes__', '__weakref__', 'meth']) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index d122403..82e466e 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -817,6 +817,21 @@ class TestRetrievingSourceCode(GetSourceBase): def test_getsource_on_code_object(self): self.assertSourceEqual(mod.eggs.__code__, 12, 18) + def test_getsource_on_generated_class(self): + A = type('A', (), {}) + self.assertEqual(inspect.getsourcefile(A), __file__) + self.assertEqual(inspect.getfile(A), __file__) + self.assertIs(inspect.getmodule(A), sys.modules[__name__]) + self.assertRaises(OSError, inspect.getsource, A) + self.assertRaises(OSError, inspect.getsourcelines, A) + self.assertIsNone(inspect.getcomments(A)) + + def test_getsource_on_class_without_firstlineno(self): + __firstlineno__ = 1 + class C: + nonlocal __firstlineno__ + self.assertRaises(OSError, inspect.getsource, C) + class TestGetsourceInteractive(unittest.TestCase): def test_getclasses_interactive(self): # bpo-44648: simulate a REPL session; diff --git a/Lib/test/test_metaclass.py b/Lib/test/test_metaclass.py index 70f9c5d..b37b7de 100644 --- a/Lib/test/test_metaclass.py +++ b/Lib/test/test_metaclass.py @@ -164,6 +164,7 @@ Use a __prepare__ method that returns an instrumented dict. ... d['__module__'] = 'test.test_metaclass' d['__qualname__'] = 'C' + d['__firstlineno__'] = 1 d['foo'] = 4 d['foo'] = 42 d['bar'] = 123 @@ -183,12 +184,12 @@ Use a metaclass that doesn't derive from type. ... b = 24 ... meta: C () - ns: [('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('__static_attributes__', ()), ('a', 42), ('b', 24)] + ns: [('__firstlineno__', 1), ('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('__static_attributes__', ()), ('a', 42), ('b', 24)] kw: [] >>> type(C) is dict True >>> print(sorted(C.items())) - [('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('__static_attributes__', ()), ('a', 42), ('b', 24)] + [('__firstlineno__', 1), ('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('__static_attributes__', ()), ('a', 42), ('b', 24)] >>> And again, with a __prepare__ attribute. @@ -206,12 +207,13 @@ And again, with a __prepare__ attribute. prepare: C () [('other', 'booh')] d['__module__'] = 'test.test_metaclass' d['__qualname__'] = 'C' + d['__firstlineno__'] = 1 d['a'] = 1 d['a'] = 2 d['b'] = 3 d['__static_attributes__'] = () meta: C () - ns: [('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('__static_attributes__', ()), ('a', 2), ('b', 3)] + ns: [('__firstlineno__', 1), ('__module__', 'test.test_metaclass'), ('__qualname__', 'C'), ('__static_attributes__', ()), ('a', 2), ('b', 3)] kw: [('other', 'booh')] >>> |