]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-83035: handle decorator with nested parens in inspect.getsource (#99654)
authorCarl Meyer <carl@oddbird.net>
Wed, 7 Dec 2022 16:55:12 +0000 (09:55 -0700)
committerGitHub <noreply@github.com>
Wed, 7 Dec 2022 16:55:12 +0000 (08:55 -0800)
Lib/inspect.py
Lib/test/inspect_fodder2.py
Lib/test/test_inspect.py
Misc/NEWS.d/next/Library/2022-11-21-16-24-01.gh-issue-83035.qZIujU.rst [new file with mode: 0644]

index 31ac888126b57c4c5dbe4bf03035ae2ccb58b15a..e165937e448a95ccfdecbc4d7c764bb30808a7e8 100644 (file)
@@ -1160,7 +1160,6 @@ class BlockFinder:
         self.started = False
         self.passline = False
         self.indecorator = False
-        self.decoratorhasargs = False
         self.last = 1
         self.body_col0 = None
 
@@ -1175,13 +1174,6 @@ class BlockFinder:
                     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 @@ class BlockFinder:
                 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
index e7d4b53ebefcc6f782f4a1e720ec7dcf6db7428d..2dc49817087c44e2e71d37cb9b509b71f69eefca 100644 (file)
@@ -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()
index 3f5c299ce681c59a324e9751cf0e3c1e9fe15a9a..2b7977b1648f702b3c2df0675be21e0238714af3 100644 (file)
@@ -886,6 +886,12 @@ class TestNoEOL(GetSourceBase):
         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 (file)
index 0000000..629d9ae
--- /dev/null
@@ -0,0 +1 @@
+Fix :func:`inspect.getsource` handling of decorator calls with nested parentheses.