Hey everyone,

I came across a case which *might* be a use case for a syntax extension,
but I'm not sure. Wanted to get feedback from the group.

*The extension: *Extend the decorator syntax from

decorator ::=  "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE

to

decorator ::= "@" expression NEWLINE

where the expression must return a callable that accepts a function of the
indicated signature as its argument.

*The motivating case: *I'm using function decorators to define cron jobs in
my system, with the rather nice syntax "@cronJob(parameters) def
myFunction(standard args)". The decorator registers the function, this
causes all sorts of magic to occur, and out the other end of the pipe jobs
run in production. It's working very nicely. However, we'd like to improve
the syntax to allow different cron configurations for the job in different
production environments. Since the default-plus-overrides model is natural
for the actual use cases, a nice way to do this would be to replace the
cronJob function with a class whose __init__ and __call__ methods
respectively load up the parameters and do the actual work of registration,
but which also has an override() method that lets you specify
per-environment overrides and then returns self. This would allow a syntax
like:

@CronJob('job-name', params...).override('dev', more-params...)
def myFunction(...)

However, this is invalid syntax in Python 3.8 because you can't have a
general expression in a decorator statement. Instead, the nearest option is

myJob = CronJob('job-name', params...).override('dev', more-params...)
@myJob
def myFunction(...)

Which is uglier for no obvious benefit.

*Possible pros and cons: *

This extends the existing syntax in a way that's very intuitive w.r.t. the
current one -- the docs say "A function definition may be wrapped by one or
more decorator expressions. Decorator expressions are evaluated when the
function is defined, in the scope that contains the function definition.
The result must be a callable, which is invoked with the function object as
the only argument. The returned value is bound to the function name instead
of the function object. Multiple decorators are applied in nested fashion."
It's not obvious from the syntax why the decorator expression *needs* to
have this limited form.

It increases consistency, by eliminating this one unusual use of dotted
expressions as special relative to other expressions. (NB this is the only
call to ast_for_dotted_expr in ast.c!)

The meaning of the operation remains unambiguous, and is just as accessible
to tools like linters, type checkers, and syntax highlighters, as the @
operator simply modifies the succeeding expression.

On the downside, it's more flexible, and so offers more chances for a user
to shoot themselves in the foot.

It's somewhat of a corner case, so it's not obvious that the syntax
extension is worth it.


What do people think?
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/ECOVHGZKRMCFD2JWFCOKGY2LZJAJTH4E/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to