summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2024-05-06 09:02:37 (GMT)
committerGitHub <noreply@github.com>2024-05-06 09:02:37 (GMT)
commit153b3f75306b5d26e29ea157105d0fdc247ef853 (patch)
treef73ede56af175d27698ef56bec21073f98889bbc /Lib/test
parent716ec4bfcf1a564db9936122c442baa99f9c4a8c (diff)
downloadcpython-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.py5
-rw-r--r--Lib/test/test_descr.py8
-rw-r--r--Lib/test/test_inspect/test_inspect.py15
-rw-r--r--Lib/test/test_metaclass.py8
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')]
>>>