Skip to content

Commit 3b14f18

Browse files
bpo-42116: Fix inspect.getsource handling of trailing comments (GH-23630)
(cherry picked from commit 6e1eec7) Co-authored-by: Irit Katriel <[email protected]>
1 parent 8e8f82d commit 3b14f18

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

Lib/inspect.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ def __init__(self):
899899
self.indecorator = False
900900
self.decoratorhasargs = False
901901
self.last = 1
902+
self.body_col0 = None
902903

903904
def tokeneater(self, type, token, srowcol, erowcol, line):
904905
if not self.started and not self.indecorator:
@@ -930,6 +931,8 @@ def tokeneater(self, type, token, srowcol, erowcol, line):
930931
elif self.passline:
931932
pass
932933
elif type == tokenize.INDENT:
934+
if self.body_col0 is None and self.started:
935+
self.body_col0 = erowcol[1]
933936
self.indent = self.indent + 1
934937
self.passline = True
935938
elif type == tokenize.DEDENT:
@@ -939,6 +942,10 @@ def tokeneater(self, type, token, srowcol, erowcol, line):
939942
# not e.g. for "if: else:" or "try: finally:" blocks)
940943
if self.indent <= 0:
941944
raise EndOfBlock
945+
elif type == tokenize.COMMENT:
946+
if self.body_col0 is not None and srowcol[1] >= self.body_col0:
947+
# Include comments if indented at least as much as the block
948+
self.last = srowcol[0]
942949
elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL):
943950
# any other token on the same indentation level end the previous
944951
# block as well, except the pseudo-tokens COMMENT and NL.

Lib/test/inspect_fodder.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,25 @@ def as_method_of(self, obj):
9191

9292
custom_method = Callable().as_method_of(42)
9393
del Callable
94+
95+
# line 95
96+
class WhichComments:
97+
# line 97
98+
# before f
99+
def f(self):
100+
# line 100
101+
# start f
102+
return 1
103+
# line 103
104+
# end f
105+
# line 105
106+
# after f
107+
108+
# before asyncf - line 108
109+
async def asyncf(self):
110+
# start asyncf
111+
return 2
112+
# end asyncf
113+
# after asyncf - line 113
114+
# end of WhichComments - line 114
115+
# after WhichComments - line 115

Lib/test/test_inspect.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ def test_getclasses(self):
392392
('ParrotDroppings', mod.ParrotDroppings),
393393
('StupidGit', mod.StupidGit),
394394
('Tit', mod.MalodorousPervert),
395+
('WhichComments', mod.WhichComments),
395396
])
396397
tree = inspect.getclasstree([cls[1] for cls in classes])
397398
self.assertEqual(tree,
@@ -405,7 +406,8 @@ def test_getclasses(self):
405406
[(mod.FesteringGob, (mod.MalodorousPervert,
406407
mod.ParrotDroppings))
407408
]
408-
]
409+
],
410+
(mod.WhichComments, (object,),)
409411
]
410412
])
411413
tree = inspect.getclasstree([cls[1] for cls in classes], True)
@@ -417,7 +419,8 @@ def test_getclasses(self):
417419
[(mod.FesteringGob, (mod.MalodorousPervert,
418420
mod.ParrotDroppings))
419421
]
420-
]
422+
],
423+
(mod.WhichComments, (object,),)
421424
]
422425
])
423426

@@ -647,6 +650,18 @@ def test_anonymous(self):
647650
# as argument to another function.
648651
self.assertSourceEqual(mod2.anonymous, 55, 55)
649652

653+
class TestBlockComments(GetSourceBase):
654+
fodderModule = mod
655+
656+
def test_toplevel_class(self):
657+
self.assertSourceEqual(mod.WhichComments, 96, 114)
658+
659+
def test_class_method(self):
660+
self.assertSourceEqual(mod.WhichComments.f, 99, 104)
661+
662+
def test_class_async_method(self):
663+
self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112)
664+
650665
class TestBuggyCases(GetSourceBase):
651666
fodderModule = mod2
652667

@@ -3970,8 +3985,8 @@ def test_getsource_reload(self):
39703985

39713986
def test_main():
39723987
run_unittest(
3973-
TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3974-
TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3988+
TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments,
3989+
TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
39753990
TestGetcallargsFunctions, TestGetcallargsMethods,
39763991
TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
39773992
TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix handling of trailing comments by :func:`inspect.getsource`.

0 commit comments

Comments
 (0)