Skip to content

Commit

Permalink
gh-83035: handle decorator with nested parens in inspect.getsource (G…
Browse files Browse the repository at this point in the history
…H-99654)

(cherry picked from commit 68e4129)

Co-authored-by: Carl Meyer <carl@oddbird.net>
  • Loading branch information
miss-islington and carljm committed Dec 7, 2022
1 parent 2b97ddd commit 2997f39
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 9 deletions.
10 changes: 1 addition & 9 deletions Lib/inspect.py
Expand Up @@ -1175,7 +1175,6 @@ def __init__(self):
self.started = False
self.passline = False
self.indecorator = False
self.decoratorhasargs = False
self.last = 1
self.body_col0 = None

Expand All @@ -1190,21 +1189,14 @@ def tokeneater(self, type, token, srowcol, erowcol, line):
self.islambda = True
self.started = True
self.passline = True # skip to the end of the line
elif token == "(":
if self.indecorator:
self.decoratorhasargs = True
elif token == ")":
if self.indecorator:
self.indecorator = False
self.decoratorhasargs = False
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
raise EndOfBlock
# hitting a NEWLINE when in a decorator without args
# ends the decorator
if self.indecorator and not self.decoratorhasargs:
if self.indecorator:
self.indecorator = False
elif self.passline:
pass
Expand Down
14 changes: 14 additions & 0 deletions Lib/test/inspect_fodder2.py
Expand Up @@ -259,3 +259,17 @@ def all_markers_with_args_and_kwargs(a, b, /, c, d, *args, e, f, **kwargs):
#line 259
def all_markers_with_defaults(a, b=1, /, c=2, d=3, *, e=4, f=5):
pass

# line 263
def deco_factory(**kwargs):
def deco(f):
@wraps(f)
def wrapper(*a, **kwd):
kwd.update(kwargs)
return f(*a, **kwd)
return wrapper
return deco

@deco_factory(foo=(1 + 2), bar=lambda: 1)
def complex_decorated(foo=0, bar=lambda: 0):
return foo + bar()
6 changes: 6 additions & 0 deletions Lib/test/test_inspect.py
Expand Up @@ -886,6 +886,12 @@ def test_class(self):
self.assertSourceEqual(self.fodderModule.X, 1, 2)


class TestComplexDecorator(GetSourceBase):
fodderModule = mod2

def test_parens_in_decorator(self):
self.assertSourceEqual(self.fodderModule.complex_decorated, 273, 275)

class _BrokenDataDescriptor(object):
"""
A broken data descriptor. See bug #1785.
Expand Down
@@ -0,0 +1 @@
Fix :func:`inspect.getsource` handling of decorator calls with nested parentheses.

0 comments on commit 2997f39

Please sign in to comment.