The way decorators are parsng

Hello
Today I've tried to write a one-liner for a decorator, The decorator is a method in a class.
I wanted to do something like this:
@Class().decorator() def function(): ...
That threw a syntax error to my surprise.
But the semantic is correct, since I am currently writing:
obj = Class()
@obj.decorator() def function(): ...
And I can also write
dec = Class().decorator
@dec() def function(): ...
Is there something obvious I am missing, or is there a weird thing in the way decoratirs are parsed ?
Demo:
class Some(object):
... def stuff(self, func): ... return func ...
s = Some() @s.stuff
... def ok(): ... print 'ok' ...
ok()
ok
s = Some().stuff @s
... def ok(): ... print 'ok' ...
ok()
ok
@Some().stuff
File "<stdin>", line 1 @Some().stuff ^ SyntaxError: invalid syntax
Cheers Tarek

On Wed, Oct 19, 2011 at 2:32 PM, Tarek Ziadé ziade.tarek@gmail.com wrote: Hello
Today I've tried to write a one-liner for a decorator, The decorator is a method in a class.
I wanted to do something like this:
@Class().decorator() def function(): ...
That threw a syntax error to my surprise.
<snip>
Is there something obvious I am missing, or is there a weird thing in the way decoratirs are parsed ?
PEP 318 -- Decorators for Functions and Methods (http://www.python.org/dev/peps/pep-0318/ ): "Current Syntax [...] The decorator statement is limited in what it can accept -- arbitrary expressions will not work. Guido preferred this because of a gut feeling [17]." [17]: http://mail.python.org/pipermail/python-dev/2004-August/046711.html
According to Python 2.7's grammar (http://docs.python.org/reference/grammar.html ): decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE dotted_name: NAME ('.' NAME)*
So, you're limited to an arbitrarily-long sequence of attribute accesses, followed by an optional call.
Cheers, Chris -- http://rebertia.com

On Wed, Oct 19, 2011 at 3:43 PM, Chris Rebert pyideas@rebertia.com wrote:
On Wed, Oct 19, 2011 at 2:32 PM, Tarek Ziadé ziade.tarek@gmail.com wrote: Hello
Today I've tried to write a one-liner for a decorator, The decorator is a method in a class.
I wanted to do something like this:
@Class().decorator() def function(): ...
That threw a syntax error to my surprise.
<snip> > Is there something obvious I am missing, or is there a weird thing in > the way decoratirs are parsed ?
PEP 318 -- Decorators for Functions and Methods (http://www.python.org/dev/peps/pep-0318/ ): "Current Syntax [...] The decorator statement is limited in what it can accept -- arbitrary expressions will not work. Guido preferred this because of a gut feeling [17]." [17]: http://mail.python.org/pipermail/python-dev/2004-August/046711.html
According to Python 2.7's grammar (http://docs.python.org/reference/grammar.html ): decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE dotted_name: NAME ('.' NAME)*
So, you're limited to an arbitrarily-long sequence of attribute accesses, followed by an optional call.
Interesting. I would have expected at least the following to work:
decorator: '@' NAME trailer* NEWLINE trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
Regardless, good to know, even if uncommon.
-eric
Cheers, Chris -- http://rebertia.com _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

On Wed, Oct 19, 2011 at 11:43 PM, Chris Rebert pyideas@rebertia.com wrote:
<snip> > Is there something obvious I am missing, or is there a weird thing in > the way decoratirs are parsed ?
PEP 318 -- Decorators for Functions and Methods (http://www.python.org/dev/peps/pep-0318/ ): "Current Syntax [...] The decorator statement is limited in what it can accept -- arbitrary expressions will not work. Guido preferred this because of a gut feeling [17]." [17]: http://mail.python.org/pipermail/python-dev/2004-August/046711.html
According to Python 2.7's grammar (http://docs.python.org/reference/grammar.html ): decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE dotted_name: NAME ('.' NAME)*
So, you're limited to an arbitrarily-long sequence of attribute accesses, followed by an optional call.
Thanks for the pointers
Cheers, Chris -- http://rebertia.com

On Thu, Oct 20, 2011 at 7:52 AM, Tarek Ziadé ziade.tarek@gmail.com wrote:
So, you're limited to an arbitrarily-long sequence of attribute accesses, followed by an optional call.
Thanks for the pointers
In the time since, Guido gave his approval to removing the restriction, but nobody has been interested enough to actually implement the change. He was persuaded the restriction was pointless largely due to people using tricks like the following to avoid it:
def deco(x): return x
@deco(anything[I].like().can.go[here].and_the.compiler.will_not(care)) def f(): pass
(There were also legitimate use cases related to looking up decorators via a subscript rather than a function call).
Cheers, Nick.

On Wed, Oct 19, 2011 at 3:36 PM, Nick Coghlan ncoghlan@gmail.com wrote:
On Thu, Oct 20, 2011 at 7:52 AM, Tarek Ziadé ziade.tarek@gmail.com wrote:
So, you're limited to an arbitrarily-long sequence of attribute accesses, followed by an optional call.
Thanks for the pointers
In the time since, Guido gave his approval to removing the restriction, but nobody has been interested enough to actually implement the change. He was persuaded the restriction was pointless largely due to people using tricks like the following to avoid it:
def deco(x): return x
@deco(anything[I].like().can.go[here].and_the.compiler.will_not(care)) def f(): pass
(There were also legitimate use cases related to looking up decorators via a subscript rather than a function call).
If this gets changed we won't be able to give a different meaning to e.g.
@(...) @[...] @{...}
since those will all have to be accepted as valid forms of the syntax
@<expr>

2011/10/20 Guido van Rossum guido@python.org:
If this gets changed we won't be able to give a different meaning to e.g.
@(...) @[...] @{...}
since those will all have to be accepted as valid forms of the syntax
@<expr>
True, although the restriction could just be weakened to "must start with an identifier" rather than eliminated entirely. Since tuples, lists, dictionaries and sets aren't callable, that wouldn't be a noticeable restriction in practice.
Cheers, Nick.

2011/10/19 Nick Coghlan ncoghlan@gmail.com:
2011/10/20 Guido van Rossum guido@python.org:
If this gets changed we won't be able to give a different meaning to e.g.
@(...) @[...] @{...}
since those will all have to be accepted as valid forms of the syntax
@<expr>
True, although the restriction could just be weakened to "must start with an identifier" rather than eliminated entirely. Since tuples, lists, dictionaries and sets aren't callable, that wouldn't be a noticeable restriction in practice.
But surely someone would manage to come up with a use case for an expression *starting* with one of those, e.g.
@[f, g, h][i]
or
@{a: b, c: d}[x]
I don't think it's reasonable to constrain it less than it currently is but more than a general expression. Though I wouldn't allow commas -- there's no way that
@f, g def pooh(): ...
can make sense. Oh way, it could be a shorthand for
@f @g def pooh(): ...
:-)
participants (5)
-
Chris Rebert
-
Eric Snow
-
Guido van Rossum
-
Nick Coghlan
-
Tarek Ziadé