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:
Miss Islington (bot) 2020-12-04 12:20:05 -08:00 committed by GitHub
parent c7cf66d2fe
commit 81ac030d03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 4 deletions

View File

@ -926,6 +926,7 @@ class BlockFinder:
self.indecorator = False
self.decoratorhasargs = False
self.last = 1
self.body_col0 = None
def tokeneater(self, type, token, srowcol, erowcol, line):
if not self.started and not self.indecorator:
@ -957,6 +958,8 @@ class BlockFinder:
elif self.passline:
pass
elif type == tokenize.INDENT:
if self.body_col0 is None and self.started:
self.body_col0 = erowcol[1]
self.indent = self.indent + 1
self.passline = True
elif type == tokenize.DEDENT:
@ -966,6 +969,10 @@ class BlockFinder:
# not e.g. for "if: else:" or "try: finally:" blocks)
if self.indent <= 0:
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):
# any other token on the same indentation level end the previous
# block as well, except the pseudo-tokens COMMENT and NL.

View File

@ -91,3 +91,25 @@ class Callable:
custom_method = Callable().as_method_of(42)
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

View File

@ -388,6 +388,7 @@ class TestRetrievingSourceCode(GetSourceBase):
('ParrotDroppings', mod.ParrotDroppings),
('StupidGit', mod.StupidGit),
('Tit', mod.MalodorousPervert),
('WhichComments', mod.WhichComments),
])
tree = inspect.getclasstree([cls[1] for cls in classes])
self.assertEqual(tree,
@ -401,7 +402,8 @@ class TestRetrievingSourceCode(GetSourceBase):
[(mod.FesteringGob, (mod.MalodorousPervert,
mod.ParrotDroppings))
]
]
],
(mod.WhichComments, (object,),)
]
])
tree = inspect.getclasstree([cls[1] for cls in classes], True)
@ -413,7 +415,8 @@ class TestRetrievingSourceCode(GetSourceBase):
[(mod.FesteringGob, (mod.MalodorousPervert,
mod.ParrotDroppings))
]
]
],
(mod.WhichComments, (object,),)
]
])
@ -644,6 +647,18 @@ class TestOneliners(GetSourceBase):
# as argument to another function.
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):
fodderModule = mod2
@ -4016,8 +4031,8 @@ def foo():
def test_main():
run_unittest(
TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments,
TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
TestGetcallargsFunctions, TestGetcallargsMethods,
TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,

View File

@ -0,0 +1 @@
Fix handling of trailing comments by :func:`inspect.getsource`.