diff options
| author | Rigel Di Scala <rigel.discala@propylon.com> | 2015-07-21 21:54:37 +0100 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2015-08-01 08:38:03 -0400 |
| commit | 3bdaaf6777804d33ee46cdb5a889b8cc544a91f1 (patch) | |
| tree | 86399ce870c06f59584c98bc3988d9ed8c739c87 /django | |
| parent | 1a76257b1b385ac8afd67bd36d061f508613e4d2 (diff) | |
Fixed #25146 -- Allowed method_decorator() to decorate classes.
Diffstat (limited to 'django')
| -rw-r--r-- | django/utils/decorators.py | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/django/utils/decorators.py b/django/utils/decorators.py index 1ea12b32d2..294761672c 100644 --- a/django/utils/decorators.py +++ b/django/utils/decorators.py @@ -17,13 +17,34 @@ class classonlymethod(classmethod): return super(classonlymethod, self).__get__(instance, owner) -def method_decorator(decorator): +def method_decorator(decorator, name=''): """ Converts a function decorator into a method decorator """ - # 'func' is a function at the time it is passed to _dec, but will eventually - # be a method of the class it is defined on. - def _dec(func): + # 'obj' can be a class or a function. If 'obj' is a function at the time it + # is passed to _dec, it will eventually be a method of the class it is + # defined on. If 'obj' is a class, the 'name' is required to be the name + # of the method that will be decorated. + def _dec(obj): + is_class = isinstance(obj, type) + if is_class: + if name and hasattr(obj, name): + func = getattr(obj, name) + if not callable(func): + raise TypeError( + "Cannot decorate '{0}' as it isn't a callable " + "attribute of {1} ({2})".format(name, obj, func) + ) + else: + raise ValueError( + "The keyword argument `name` must be the name of a method " + "of the decorated class: {0}. Got '{1}' instead".format( + obj, name, + ) + ) + else: + func = obj + def _wrapper(self, *args, **kwargs): @decorator def bound_func(*args2, **kwargs2): @@ -43,6 +64,10 @@ def method_decorator(decorator): # Need to preserve any existing attributes of 'func', including the name. update_wrapper(_wrapper, func) + if is_class: + setattr(obj, name, _wrapper) + return obj + return _wrapper update_wrapper(_dec, decorator, assigned=available_attrs(decorator)) |
