bpo-42116: Fix inspect.getsource handling of trailing comments (GH-23630)
(cherry picked from commit 6e1eec71f5
)
Co-authored-by: Irit Katriel <iritkatriel@yahoo.com>
This commit is contained in:
parent
8e8f82dd94
commit
3b14f18205
|
@ -899,6 +899,7 @@ class BlockFinder:
|
||||||
self.indecorator = False
|
self.indecorator = False
|
||||||
self.decoratorhasargs = False
|
self.decoratorhasargs = False
|
||||||
self.last = 1
|
self.last = 1
|
||||||
|
self.body_col0 = None
|
||||||
|
|
||||||
def tokeneater(self, type, token, srowcol, erowcol, line):
|
def tokeneater(self, type, token, srowcol, erowcol, line):
|
||||||
if not self.started and not self.indecorator:
|
if not self.started and not self.indecorator:
|
||||||
|
@ -930,6 +931,8 @@ class BlockFinder:
|
||||||
elif self.passline:
|
elif self.passline:
|
||||||
pass
|
pass
|
||||||
elif type == tokenize.INDENT:
|
elif type == tokenize.INDENT:
|
||||||
|
if self.body_col0 is None and self.started:
|
||||||
|
self.body_col0 = erowcol[1]
|
||||||
self.indent = self.indent + 1
|
self.indent = self.indent + 1
|
||||||
self.passline = True
|
self.passline = True
|
||||||
elif type == tokenize.DEDENT:
|
elif type == tokenize.DEDENT:
|
||||||
|
@ -939,6 +942,10 @@ class BlockFinder:
|
||||||
# not e.g. for "if: else:" or "try: finally:" blocks)
|
# not e.g. for "if: else:" or "try: finally:" blocks)
|
||||||
if self.indent <= 0:
|
if self.indent <= 0:
|
||||||
raise EndOfBlock
|
raise EndOfBlock
|
||||||
|
elif type == tokenize.COMMENT:
|
||||||
|
if self.body_col0 is not None and srowcol[1] >= self.body_col0:
|
||||||
|
# Include comments if indented at least as much as the block
|
||||||
|
self.last = srowcol[0]
|
||||||
elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL):
|
elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL):
|
||||||
# any other token on the same indentation level end the previous
|
# any other token on the same indentation level end the previous
|
||||||
# block as well, except the pseudo-tokens COMMENT and NL.
|
# block as well, except the pseudo-tokens COMMENT and NL.
|
||||||
|
|
|
@ -91,3 +91,25 @@ class Callable:
|
||||||
|
|
||||||
custom_method = Callable().as_method_of(42)
|
custom_method = Callable().as_method_of(42)
|
||||||
del Callable
|
del Callable
|
||||||
|
|
||||||
|
# line 95
|
||||||
|
class WhichComments:
|
||||||
|
# line 97
|
||||||
|
# before f
|
||||||
|
def f(self):
|
||||||
|
# line 100
|
||||||
|
# start f
|
||||||
|
return 1
|
||||||
|
# line 103
|
||||||
|
# end f
|
||||||
|
# line 105
|
||||||
|
# after f
|
||||||
|
|
||||||
|
# before asyncf - line 108
|
||||||
|
async def asyncf(self):
|
||||||
|
# start asyncf
|
||||||
|
return 2
|
||||||
|
# end asyncf
|
||||||
|
# after asyncf - line 113
|
||||||
|
# end of WhichComments - line 114
|
||||||
|
# after WhichComments - line 115
|
||||||
|
|
|
@ -392,6 +392,7 @@ class TestRetrievingSourceCode(GetSourceBase):
|
||||||
('ParrotDroppings', mod.ParrotDroppings),
|
('ParrotDroppings', mod.ParrotDroppings),
|
||||||
('StupidGit', mod.StupidGit),
|
('StupidGit', mod.StupidGit),
|
||||||
('Tit', mod.MalodorousPervert),
|
('Tit', mod.MalodorousPervert),
|
||||||
|
('WhichComments', mod.WhichComments),
|
||||||
])
|
])
|
||||||
tree = inspect.getclasstree([cls[1] for cls in classes])
|
tree = inspect.getclasstree([cls[1] for cls in classes])
|
||||||
self.assertEqual(tree,
|
self.assertEqual(tree,
|
||||||
|
@ -405,7 +406,8 @@ class TestRetrievingSourceCode(GetSourceBase):
|
||||||
[(mod.FesteringGob, (mod.MalodorousPervert,
|
[(mod.FesteringGob, (mod.MalodorousPervert,
|
||||||
mod.ParrotDroppings))
|
mod.ParrotDroppings))
|
||||||
]
|
]
|
||||||
]
|
],
|
||||||
|
(mod.WhichComments, (object,),)
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
tree = inspect.getclasstree([cls[1] for cls in classes], True)
|
tree = inspect.getclasstree([cls[1] for cls in classes], True)
|
||||||
|
@ -417,7 +419,8 @@ class TestRetrievingSourceCode(GetSourceBase):
|
||||||
[(mod.FesteringGob, (mod.MalodorousPervert,
|
[(mod.FesteringGob, (mod.MalodorousPervert,
|
||||||
mod.ParrotDroppings))
|
mod.ParrotDroppings))
|
||||||
]
|
]
|
||||||
]
|
],
|
||||||
|
(mod.WhichComments, (object,),)
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -647,6 +650,18 @@ class TestOneliners(GetSourceBase):
|
||||||
# as argument to another function.
|
# as argument to another function.
|
||||||
self.assertSourceEqual(mod2.anonymous, 55, 55)
|
self.assertSourceEqual(mod2.anonymous, 55, 55)
|
||||||
|
|
||||||
|
class TestBlockComments(GetSourceBase):
|
||||||
|
fodderModule = mod
|
||||||
|
|
||||||
|
def test_toplevel_class(self):
|
||||||
|
self.assertSourceEqual(mod.WhichComments, 96, 114)
|
||||||
|
|
||||||
|
def test_class_method(self):
|
||||||
|
self.assertSourceEqual(mod.WhichComments.f, 99, 104)
|
||||||
|
|
||||||
|
def test_class_async_method(self):
|
||||||
|
self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112)
|
||||||
|
|
||||||
class TestBuggyCases(GetSourceBase):
|
class TestBuggyCases(GetSourceBase):
|
||||||
fodderModule = mod2
|
fodderModule = mod2
|
||||||
|
|
||||||
|
@ -3970,8 +3985,8 @@ def foo():
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
run_unittest(
|
run_unittest(
|
||||||
TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
|
TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments,
|
||||||
TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
|
TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
|
||||||
TestGetcallargsFunctions, TestGetcallargsMethods,
|
TestGetcallargsFunctions, TestGetcallargsMethods,
|
||||||
TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
|
TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
|
||||||
TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
|
TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix handling of trailing comments by :func:`inspect.getsource`.
|
Loading…
Reference in New Issue