Skip to content

Instantly share code, notes, and snippets.

@dutc
Last active December 28, 2015 22:29
Show Gist options
  • Save dutc/7571743 to your computer and use it in GitHub Desktop.
Save dutc/7571743 to your computer and use it in GitHub Desktop.
diff -r 1e79ca2bc494 Doc/reference/compound_stmts.rst
--- a/Doc/reference/compound_stmts.rst Wed Nov 20 11:53:31 2013 -0800
+++ b/Doc/reference/compound_stmts.rst Wed Nov 20 20:23:32 2013 -0500
@@ -442,7 +442,7 @@
.. productionlist::
funcdef: [`decorators`] "def" `funcname` "(" [`parameter_list`] ")" ["->" `expression`] ":" `suite`
decorators: `decorator`+
- decorator: "@" `dotted_name` ["(" [`parameter_list` [","]] ")"] NEWLINE
+ decorator: "@" `expression` NEWLINE
dotted_name: `identifier` ("." `identifier`)*
parameter_list: (`defparameter` ",")*
: ( "*" [`parameter`] ("," `defparameter`)* ["," "**" `parameter`]
diff -r 1e79ca2bc494 Grammar/Grammar
--- a/Grammar/Grammar Wed Nov 20 11:53:31 2013 -0800
+++ b/Grammar/Grammar Wed Nov 20 20:23:32 2013 -0500
@@ -19,7 +19,7 @@
file_input: (NEWLINE | stmt)* ENDMARKER
eval_input: testlist NEWLINE* ENDMARKER
-decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
+decorator: '@' testlist NEWLINE
decorators: decorator+
decorated: decorators (classdef | funcdef)
funcdef: 'def' NAME parameters ['->' test] ':' suite
diff -r 1e79ca2bc494 Lib/test/test_decorators.py
--- a/Lib/test/test_decorators.py Wed Nov 20 11:53:31 2013 -0800
+++ b/Lib/test/test_decorators.py Wed Nov 20 20:23:32 2013 -0500
@@ -90,9 +90,30 @@
self.assertEqual(foo(), 42)
self.assertEqual(foo.author, 'Cleese')
+ def test_chained(self):
+ def d1():
+ class d2:
+ def d3(self, f):
+ return f
+ @d1().d2().d3
+ def foo(): return 42
+ self.assertEqual(foo(), 42)
+
+ def test_conditional(self):
+ def d1(f): return f
+ def d2(f): return None
+ @(d1 if True else d2)
+ def foo(): return 42
+ self.assertEqual(foo(), 42)
+
+ def test_lambda(self):
+ @(lambda f: f)
+ def foo(): return 42
+ self.assertEqual(foo(), 42)
+
def test_argforms(self):
- # A few tests of argument passing, as we use restricted form
- # of expressions for decorators.
+ # A few tests of argument passing; note that we no longer
+ # restrict decorators to just this form.
def noteargs(*args, **kwds):
def decorate(func):
@@ -152,15 +173,6 @@
self.assertEqual(counts['double'], 4)
def test_errors(self):
- # Test syntax restrictions - these are all compile-time errors:
- #
- for expr in [ "1+2", "x[3]", "(1, 2)" ]:
- # Sanity check: is expr is a valid expression by itself?
- compile(expr, "testexpr", "exec")
-
- codestr = "@%s\ndef f(): pass" % expr
- self.assertRaises(SyntaxError, compile, codestr, "test", "exec")
-
# You can't put multiple decorators on a single line:
#
self.assertRaises(SyntaxError, compile,
diff -r 1e79ca2bc494 Modules/parsermodule.c
--- a/Modules/parsermodule.c Wed Nov 20 11:53:31 2013 -0800
+++ b/Modules/parsermodule.c Wed Nov 20 20:23:32 2013 -0500
@@ -2541,7 +2541,7 @@
ok = (validate_ntype(tree, decorator) &&
(nch == 3 || nch == 5 || nch == 6) &&
validate_at(CHILD(tree, 0)) &&
- validate_dotted_name(CHILD(tree, 1)) &&
+ validate_testlist(CHILD(tree, 1)) &&
validate_newline(RCHILD(tree, -1)));
if (ok && nch != 3) {
diff -r 1e79ca2bc494 Python/ast.c
--- a/Python/ast.c Wed Nov 20 11:53:31 2013 -0800
+++ b/Python/ast.c Wed Nov 20 20:23:32 2013 -0500
@@ -1429,7 +1429,7 @@
REQ(CHILD(n, 0), AT);
REQ(RCHILD(n, -1), NEWLINE);
- name_expr = ast_for_dotted_name(c, CHILD(n, 1));
+ name_expr = ast_for_testlist(c, CHILD(n, 1));
if (!name_expr)
return NULL;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment