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:09 -08:00 committed by GitHub
parent 8e8f82dd94
commit 3b14f18205
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 4 deletions

View File

@ -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.

View File

@ -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

View File

@ -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,

View File

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