#20223 closed New feature (fixed)
Allow allow_lazy to be used as a decorator
Reported by: | Alexey Boriskin | Owned by: | Iacopo Spalletti |
---|---|---|---|
Component: | Utilities | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | bmispelon@…, github@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
allow_lazy
cannot be used as a decorator for now, at least not in @-notation, because *resultclasses is required argument for this function. Decorator with arguments are functions, which accept arguments, returning function, which decorates source function. In allow_lazy signature arguments and function are mixed.
So, proposal is to distinguish on type: if first argument of allow_lazy is of type type
, then treat it like a three-def-decorator, while allowing current two-def-decorator behaviour if first argument is a function.
Change History (9)
comment:1 by , 12 years ago
Cc: | added |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 12 years ago
Please let's not have type checking to decide what type of thing to return, because:
- isinstance is always a smell, and you can always find code that will break it.
- it results in confusing code.
- whenever I have come across code that does this in the past, it has caused problems, especially in higher-level situations (like decorating the decorator), because the 'decorator' no longer functions predictably.
I'd be happy with a new function that acts as a decorator, like the suggested handle_lazy_args
.
comment:3 by , 12 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
It's kind of related to #20221 and #20222 so I'll try and fix those three in one pull-request.
For anyone interested, I'll be working on this branch: https://github.com/bmispelon/django/compare/allow-lazy-refactor
comment:4 by , 12 years ago
I've prepared a pull request for this ticket that include fixes for 3 other ones: https://github.com/django/django/pull/1007
comment:5 by , 10 years ago
I've updated bmispelon's patch so it merges cleanly as a pull request 4202:
https://github.com/django/django/pull/4202
comment:6 by , 9 years ago
Owner: | changed from | to
---|
Assigning this to me to rebase and help get this merged
comment:7 by , 9 years ago
Cc: | added |
---|---|
Has patch: | set |
Rebased version of the above PRs opened at https://github.com/django/django/pull/5581
I don't know if there is a rigorous definition of what a decorator is.
The glossary on python's documentation [1] says it's a "function that returns a function".
In that sense,
allow_lazy
is indeed a decorator.However, it's a bit unexpected that it's not compatible with the usual @-syntax for decorators (because it takes arguments too).
It actually works with the @-syntax, but only if you don't pass it any extra arguments. The problem is that these arguments are probably required, though it's not very clear:
lazy
[3] is unambiguous: "You need to give result classes or types" (emphasis mine)I think the docstring is the one that's correct and that the extra arguments are indeed required, as indicated by a ticket like #20222.
Personally, I'd like to see
allow_lazy
refactored into a proper two-step decorator, with some checks to make sure we're actually passing the required arguments:This breaks backwards-compatibility though, so we'd need to plan a deprecation path.
It could be done quite simply by introducing a new
handle_lazy_args
decorator (with a better name)that would work with the @-syntax and have
allow_lazy
raise warnings.I'm not sure I like the idea of type-checking the arguments like the OP suggested,
though it might be another valid way to handle the deprecation path.
[1] http://docs.python.org/2/glossary.html
[2] https://docs.djangoproject.com/en/1.5/ref/utils/#module-django.utils.functional
[3] https://github.com/django/django/blob/master/django/utils/functional.py#L63-L66