-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A way to know if a frame is a decorator call (for example in inspect
)
#3
Comments
inspect
)
inspect
)inspect
)
Let me play devil's advocate: There is no fundamental reason to force decorator factories to work directly "without parentheses". If you have a decorator factory @my_decorator_factory()
def func():
... The "no-parentheses" pattern is a convention (that, if I had to guess, gained popularity simply because the extra |
Thanks for the feedback @plammens ! Well the important part is "you need to do something", while most users are so accustomed with this being the reference way to work with decorators, that they expect it to be easy to develop. In other words, this makes it very hard to go from user to developer. It is after all just a design choice: theoretical beauty vs. practical usability. No good answer... except that many theoretically beautiful languages are now dead ;) |
Yes, after all, practicality beats purity... I agree that now it's to late to just "forget about the current convention", and that users just expect this to work.
Although it is regrettable that this convention was born at all, because I see absolutely no difference in practical usability between
|
In python there is absolutely no way (no way!) to disambiguate between
This is extremely annoying and many popular libraries implement ugly tricks to work around the problem.
Here is the text that I wrote in this pending issue:
Python decorators are frequently proposed by libraries as an easy way to add functionality to user-written functions: see
attrs
,pytest
,click
,marshmallow
, etc.A common pattern in most such libraries, is that they do not want to provide users with two different symbols for the same function. So they end up implementing decorators that can be used both as decorators (no arguments no parenthesis) AND decorator factories (arguments in parenthesis). This is convenient and intuitive for users. Unfortunately this is not something trivial to implement because the python language does not make any difference between a no-parenthesis decorator call and a with-parenthesis decorator factory call.
So these libraries have to rely on "tricks", the most common one being to check existence of a non-default first parameter that is a callable.
Examples:
attrs
,pytest
,marshmallow
Implementing these tricks is a bit ugly, but more importantly it is a waste of development time because when one changes his decorators signatures, the trick has to possibly be changed (order of arguments, default values, etc). Therefore it is quite a brake to agile development in the first phase of a project, where the api is not very stable.
I regrouped all known and possible tricks in a library decopatch to provide a handy way to solve this problem. But it is still "a bunch of tricks". This library, or the manual implementations such as the examples above, could be much faster/efficient if there were at least, a way to determine if a frame is a call to
@
.PEP Proposal
At least let's have a
inspect.is_decorator_call(frame)
feature in the stdlib. That function would returnTrue
if the frame is a decorator call using@
. For the following example to work:Then
is_decorator_call
shouldTrue
only if the current frame is the one directly following the decorator application. In nested frames (such as the one obtained after first recursive call toset_hello_tag
above,is_decorator_call
should returnFalse
.Note that a more convenient way to solve this problem is also proposed in here : it would be to offer a
@decorator_factory
helper in the stdlib. But first feedback from python-ideas mailing list showed that this was maybe too disruptive.The text was updated successfully, but these errors were encountered: