On Ian McCracken's blog, he has an article where he talks about decorator factory factories. In the article, he gives an example of one:
def decorator_factory_factory(method):
def decorator_factory(regex):
def decorator(f):
def inner(*args, **kwargs):
# do stuff with f(*args, **kwargs)
# and method and regex
return inner
return decorator
return decorator_factory
He then gives an example of how he could call the decorator:
@decorator_factory_factory('GET')('^/.*$')
def onGetAnything(self):
pass
This caught my attention. I had never tried calling a decorator decorator factory before, so I decided to see how the code would behave:
>>> def decorator_factory_factory(method):
def decorator_factory(regex):
def decorator(f):
def inner(*args, **kwargs):
print(args, kwargs)
return inner
return decorator
return decorator_factory
>>> @decorator_factory_factory('GET')('^/.*$')
def onGetAnything(self):
pass
SyntaxError: invalid syntax
>>>
As you can see from above, Python raises a SyntaxError. Why is that? Besides the code apparently working for Mr. McCraken, it seems like code such should run perfectly fine. Isn't it basically the same syntax as chaining function calls together, which does work? eg:
>>> def foo():
def bar():
return 2
return bar
>>> foo()()
2
>>>
I thought perhaps he was using an older version of Python which allowed such syntax, so I looked over the grammar for the Python version which he was probably using when he wrote the article back in 2009; 2.6.9. But the grammar still doesn't seem to allow chained decorator calls:
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef)
Has this syntax ever been allowed in any Python version. If not, then how was Ian able to run his code? Did he simply make a mistake?