Last active
August 30, 2021 11:52
-
-
Save maxfischer2781/5c8660f76a8136aee076a75c48187624 to your computer and use it in GitHub Desktop.
Helper that allows using the same decorator for both functions and methods
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Basic "Decoscriptor" example | |
""" | |
from decoscriptor import anydeco | |
@anydeco | |
def art(fun, *args, **kwargs): | |
print("Big Whoop and a bottle of", args, kwargs) | |
print("Fun is set to", getattr(fun, "__self__", "<unbound>")) | |
return fun(*args, **kwargs) | |
class Foo: | |
@art | |
def decome(self, *args, **kwargs): | |
print("decome:", args, kwargs) | |
@art | |
def decofu(*args, **kwargs): | |
print("decofu:", args, kwargs) | |
print(" ### Test Method ### ") | |
Foo().decome(1, 2, three=4) | |
print(" ### Test Function ### ") | |
decofu(1, 2, three=4) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Basic "Decoscriptor" sketch that allows using the same decorator for functions and methods | |
""" | |
from functools import partial | |
class Decoscriptor: | |
""" | |
Helper to treat decoration of functions and methods equivalently | |
This class expresses that a ``call`` is decorated by ``deco``. | |
When called, ``deco`` is passed ``call`` and all arguments. | |
When used a method on an object, the ``self`` parameter is | |
automatically bound to ``call`` and does not appear as a positional | |
parameter to ``deco``. If the ``self`` parameter is desired | |
in the decorator, it can be extracted as ``call.__self__``. | |
""" | |
def __init__(self, deco, call): | |
self.deco = deco | |
self.call = call | |
def __call__(self, *args, **kwargs): | |
return self.deco(self.call, *args, **kwargs) | |
def __get__(self, instance, owner): | |
# TODO: Handle @classmethod and @staticmethod targets | |
if instance is None: | |
return self | |
return partial(self.deco, self.call.__get__(instance, owner)) | |
def anydeco(deco): | |
"""Mark a decorator as handling both methods and functions equally""" | |
return partial(Decoscriptor, deco) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment