[Python-checkins] gh-83035: handle decorator with nested parens in inspect.getsource (#99654)
JelleZijlstra
webhook-mailer at python.org
Wed Dec 7 11:55:43 EST 2022
https://github.com/python/cpython/commit/68e41295b8611a990de68f15c89f1eb3dea51867
commit: 68e41295b8611a990de68f15c89f1eb3dea51867
branch: main
author: Carl Meyer <carl at oddbird.net>
committer: JelleZijlstra <jelle.zijlstra at gmail.com>
date: 2022-12-07T08:55:12-08:00
summary:
gh-83035: handle decorator with nested parens in inspect.getsource (#99654)
files:
A Misc/NEWS.d/next/Library/2022-11-21-16-24-01.gh-issue-83035.qZIujU.rst
M Lib/inspect.py
M Lib/test/inspect_fodder2.py
M Lib/test/test_inspect.py
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 31ac888126b5..e165937e448a 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -1160,7 +1160,6 @@ def __init__(self):
self.started = False
self.passline = False
self.indecorator = False
- self.decoratorhasargs = False
self.last = 1
self.body_col0 = None
@@ -1175,13 +1174,6 @@ 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]
@@ -1189,7 +1181,7 @@ def tokeneater(self, type, token, srowcol, erowcol, line):
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
diff --git a/Lib/test/inspect_fodder2.py b/Lib/test/inspect_fodder2.py
index e7d4b53ebefc..2dc49817087c 100644
--- a/Lib/test/inspect_fodder2.py
+++ b/Lib/test/inspect_fodder2.py
@@ -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
+
+ at deco_factory(foo=(1 + 2), bar=lambda: 1)
+def complex_decorated(foo=0, bar=lambda: 0):
+ return foo + bar()
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index 3f5c299ce681..2b7977b1648f 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -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.
diff --git a/Misc/NEWS.d/next/Library/2022-11-21-16-24-01.gh-issue-83035.qZIujU.rst b/Misc/NEWS.d/next/Library/2022-11-21-16-24-01.gh-issue-83035.qZIujU.rst
new file mode 100644
index 000000000000..629d9aefb2d8
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-11-21-16-24-01.gh-issue-83035.qZIujU.rst
@@ -0,0 +1 @@
+Fix :func:`inspect.getsource` handling of decorator calls with nested parentheses.
More information about the Python-checkins
mailing list