mirror of
https://github.com/python/cpython.git
synced 2025-11-24 12:20:42 +00:00
[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 eae9d7de1c)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
137c784fbf
commit
ed9c0c3cbe
4 changed files with 38 additions and 7 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
Fix :func:`!inspect.getblock`, :func:`inspect.getsourcelines` and
|
||||
:func:`inspect.getsource` for generator expressions.
|
||||
Loading…
Add table
Add a link
Reference in a new issue