mirror of https://github.com/python/cpython
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.
This commit is contained in:
parent
bb1d30336e
commit
f88c14d412
|
@ -970,10 +970,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__
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -821,7 +821,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__])
|
||||
|
@ -929,6 +929,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
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix :func:`inspect.getsource` for generated classes with Python base classes
|
||||
(e.g. enums).
|
Loading…
Reference in New Issue