diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2024-09-02 11:07:08 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-02 11:07:08 (GMT) |
commit | 2b4c31d87d6fe9ec7cdc88eb6139ce9370666739 (patch) | |
tree | 8cb12a16715991260b3cd0aadac5828639980293 | |
parent | 8b6dd92db78cd2c0170e30d9e2fd2851b7f60b13 (diff) | |
download | cpython-2b4c31d87d6fe9ec7cdc88eb6139ce9370666739.zip cpython-2b4c31d87d6fe9ec7cdc88eb6139ce9370666739.tar.gz cpython-2b4c31d87d6fe9ec7cdc88eb6139ce9370666739.tar.bz2 |
[3.13] gh-122981: Fix inspect.getsource() for generated classes with Python base classes (GH-123001) (#123182)
gh-122981: Fix inspect.getsource() for generated classes with Python base classes (GH-123001)
Look up __firstlineno__ only in the class' dict, without searching in
base classes.
(cherry picked from commit f88c14d412522587085ae039ebe70b91d5b4e226)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
-rw-r--r-- | Lib/inspect.py | 6 | ||||
-rw-r--r-- | Lib/test/test_inspect/inspect_fodder2.py | 42 | ||||
-rw-r--r-- | Lib/test/test_inspect/test_inspect.py | 20 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2024-08-14-10-41-11.gh-issue-122981.BHV0Z9.rst | 2 |
4 files changed, 66 insertions, 4 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index 845d55f..9499dc5 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1082,10 +1082,10 @@ def findsource(object): if isclass(object): try: - firstlineno = object.__firstlineno__ - except AttributeError: + firstlineno = vars(object)['__firstlineno__'] + except (TypeError, KeyError): raise OSError('source code not available') - return lines, object.__firstlineno__ - 1 + return lines, firstlineno - 1 if ismethod(object): object = object.__func__ diff --git a/Lib/test/test_inspect/inspect_fodder2.py b/Lib/test/test_inspect/inspect_fodder2.py index bb9d3e8..43e9f85 100644 --- a/Lib/test/test_inspect/inspect_fodder2.py +++ b/Lib/test/test_inspect/inspect_fodder2.py @@ -315,3 +315,45 @@ else: class ClassWithCodeObject: import sys code = sys._getframe(0).f_code + +import enum + +# line 321 +class enum322(enum.Enum): + A = 'a' + +# line 325 +class enum326(enum.IntEnum): + A = 1 + +# line 329 +class flag330(enum.Flag): + A = 1 + +# line 333 +class flag334(enum.IntFlag): + A = 1 + +# line 337 +simple_enum338 = enum.Enum('simple_enum338', 'A') +simple_enum339 = enum.IntEnum('simple_enum339', 'A') +simple_flag340 = enum.Flag('simple_flag340', 'A') +simple_flag341 = enum.IntFlag('simple_flag341', 'A') + +import typing + +# line 345 +class nt346(typing.NamedTuple): + x: int + y: int + +# line 350 +nt351 = typing.NamedTuple('nt351', (('x', int), ('y', int))) + +# line 353 +class td354(typing.TypedDict): + x: int + y: int + +# line 358 +td359 = typing.TypedDict('td359', (('x', int), ('y', int))) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 6060494..766b3fe 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -824,7 +824,7 @@ class TestRetrievingSourceCode(GetSourceBase): self.assertSourceEqual(mod.eggs.__code__, 12, 18) def test_getsource_on_generated_class(self): - A = type('A', (), {}) + A = type('A', (unittest.TestCase,), {}) self.assertEqual(inspect.getsourcefile(A), __file__) self.assertEqual(inspect.getfile(A), __file__) self.assertIs(inspect.getmodule(A), sys.modules[__name__]) @@ -932,6 +932,24 @@ class TestOneliners(GetSourceBase): # as argument to another function. self.assertSourceEqual(mod2.anonymous, 55, 55) + def test_enum(self): + self.assertSourceEqual(mod2.enum322, 322, 323) + self.assertSourceEqual(mod2.enum326, 326, 327) + self.assertSourceEqual(mod2.flag330, 330, 331) + self.assertSourceEqual(mod2.flag334, 334, 335) + self.assertRaises(OSError, inspect.getsource, mod2.simple_enum338) + self.assertRaises(OSError, inspect.getsource, mod2.simple_enum339) + self.assertRaises(OSError, inspect.getsource, mod2.simple_flag340) + self.assertRaises(OSError, inspect.getsource, mod2.simple_flag341) + + def test_namedtuple(self): + self.assertSourceEqual(mod2.nt346, 346, 348) + self.assertRaises(OSError, inspect.getsource, mod2.nt351) + + def test_typeddict(self): + self.assertSourceEqual(mod2.td354, 354, 356) + self.assertRaises(OSError, inspect.getsource, mod2.td359) + class TestBlockComments(GetSourceBase): fodderModule = mod diff --git a/Misc/NEWS.d/next/Library/2024-08-14-10-41-11.gh-issue-122981.BHV0Z9.rst b/Misc/NEWS.d/next/Library/2024-08-14-10-41-11.gh-issue-122981.BHV0Z9.rst new file mode 100644 index 0000000..7713d80 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-08-14-10-41-11.gh-issue-122981.BHV0Z9.rst @@ -0,0 +1,2 @@ +Fix :func:`inspect.getsource` for generated classes with Python base classes +(e.g. enums). |