From ed9c0c3cbe9505eca07f2cb6fb38bed63a56b359 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Tue, 7 Oct 2025 20:48:40 +0200 Subject: [PATCH] [3.14] gh-137477: Fix inspect.getblock() for generator expressions (GH-137488) (#137993) gh-137477: Fix inspect.getblock() for generator expressions (GH-137488) This fixes also inspect.getsourcelines() and inspect.getsource(). (cherry picked from commit eae9d7de1c45a64076a926d53672823e6ae1777d) Co-authored-by: Serhiy Storchaka --- Lib/inspect.py | 17 +++++++++------- Lib/test/test_inspect/inspect_fodder2.py | 20 +++++++++++++++++++ Lib/test/test_inspect/test_inspect.py | 6 ++++++ ...-08-06-23-16-42.gh-issue-137477.bk6BDV.rst | 2 ++ 4 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-08-06-23-16-42.gh-issue-137477.bk6BDV.rst diff --git a/Lib/inspect.py b/Lib/inspect.py index 183e67fabf96..faaddadbb87d 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1056,7 +1056,7 @@ class BlockFinder: """Provide a tokeneater() method to detect the end of a code block.""" def __init__(self): self.indent = 0 - self.islambda = False + self.singleline = False self.started = False self.passline = False self.indecorator = False @@ -1065,19 +1065,22 @@ class BlockFinder: def tokeneater(self, type, token, srowcol, erowcol, line): if not self.started and not self.indecorator: + if type == tokenize.INDENT or token == "async": + pass # skip any decorators - if token == "@": + elif token == "@": self.indecorator = True - # look for the first "def", "class" or "lambda" - elif token in ("def", "class", "lambda"): - if token == "lambda": - self.islambda = True + else: + # For "def" and "class" scan to the end of the block. + # For "lambda" and generator expression scan to + # the end of the logical line. + self.singleline = token not in ("def", "class") self.started = True self.passline = True # skip to the end of the line elif type == tokenize.NEWLINE: self.passline = False # stop skipping when a NEWLINE is seen self.last = srowcol[0] - if self.islambda: # lambdas always end at the first NEWLINE + if self.singleline: raise EndOfBlock # hitting a NEWLINE when in a decorator without args # ends the decorator diff --git a/Lib/test/test_inspect/inspect_fodder2.py b/Lib/test/test_inspect/inspect_fodder2.py index 43fda6622537..1de283f672d3 100644 --- a/Lib/test/test_inspect/inspect_fodder2.py +++ b/Lib/test/test_inspect/inspect_fodder2.py @@ -369,3 +369,23 @@ class dc364: # line 369 dc370 = dataclasses.make_dataclass('dc370', (('x', int), ('y', int))) dc371 = dataclasses.make_dataclass('dc370', (('x', int), ('y', int)), module=__name__) + +import inspect +import itertools + +# line 376 +ge377 = ( + inspect.currentframe() + for i in itertools.count() +) + +# line 382 +def func383(): + # line 384 + ge385 = ( + inspect.currentframe() + for i in itertools.count() + ) + return ge385 + +pass # end of file diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 0a8926e00cf8..50eb1703125c 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -1189,12 +1189,18 @@ class TestBuggyCases(GetSourceBase): self.assertSourceEqual(run(mod2.func225), 226, 227) self.assertSourceEqual(mod2.cls226, 231, 235) + self.assertSourceEqual(mod2.cls226.func232, 232, 235) self.assertSourceEqual(run(mod2.cls226().func232), 233, 234) def test_class_definition_same_name_diff_methods(self): self.assertSourceEqual(mod2.cls296, 296, 298) self.assertSourceEqual(mod2.cls310, 310, 312) + def test_generator_expression(self): + self.assertSourceEqual(next(mod2.ge377), 377, 380) + self.assertSourceEqual(next(mod2.func383()), 385, 388) + + class TestNoEOL(GetSourceBase): def setUp(self): self.tempdir = TESTFN + '_dir' diff --git a/Misc/NEWS.d/next/Library/2025-08-06-23-16-42.gh-issue-137477.bk6BDV.rst b/Misc/NEWS.d/next/Library/2025-08-06-23-16-42.gh-issue-137477.bk6BDV.rst new file mode 100644 index 000000000000..a6e097ea0262 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-08-06-23-16-42.gh-issue-137477.bk6BDV.rst @@ -0,0 +1,2 @@ +Fix :func:`!inspect.getblock`, :func:`inspect.getsourcelines` and +:func:`inspect.getsource` for generator expressions. -- 2.47.3