]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-83035: handle decorator with nested parens in inspect.getsource (GH-99654)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 7 Dec 2022 17:26:11 +0000 (09:26 -0800)
committerGitHub <noreply@github.com>
Wed, 7 Dec 2022 17:26:11 +0000 (09:26 -0800)
(cherry picked from commit 68e41295b8611a990de68f15c89f1eb3dea51867)

Co-authored-by: Carl Meyer <carl@oddbird.net>
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 d1a9daf289131a105a525ddc7b5b55e241387245..cab92b6b8fb88ac980c03938622c4a9aff82c663 100644 (file)
@@ -1175,7 +1175,6 @@ class BlockFinder:
         self.started = False
         self.passline = False
         self.indecorator = False
-        self.decoratorhasargs = False
         self.last = 1
         self.body_col0 = None
 
@@ -1190,13 +1189,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]
@@ -1204,7 +1196,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 a54e6eb53e680cbec2590d8c2053e5c0dba60d24..6c5e674aa69f5a2cda45b74f050267b26640843a 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.