as an example:
def decorator(func):
def nested(*args, **kwargs):
return func(*args, **kwargs)
return nested
@decorator
def decorated(): pass
is there a way for decorated to know it is getting decorated?
as an example:
def decorator(func):
def nested(*args, **kwargs):
return func(*args, **kwargs)
return nested
@decorator
def decorated(): pass
is there a way for decorated to know it is getting decorated?
You can use a decorator that uses ast.NodeVistor
to traverse through the AST nodes of the function to look for decorators of the function. If the decorator list includes more than the decorator checker itself, you can then get the details of the other decorators from the decorator nodes:
import inspect
import ast
from textwrap import dedent
class CheckDecorators(ast.NodeVisitor):
def visit_FunctionDef(self, node):
if len(node.decorator_list) > 1:
print("function '%s' is decorated by: %s" % (node.name, ', '.join(ast.dump(decorator) for decorator in node.decorator_list if not isinstance(decorator, ast.Name) or decorator.id != 'check_decorators')))
def check_decorators(func):
CheckDecorators().visit(ast.parse(dedent(inspect.getsource(func))))
return func
so that:
def decorator(func):
def nested(*args, **kwargs):
return func(*args, **kwargs)
return nested
@decorator
@check_decorators
def decorated():
pass
would output:
function 'decorated' is decorated by: Name(id='decorator', ctx=Load())
Following is a partial solution that works on closures that look exactly like your example.
import inspect
def decorator(func):
def nested(*args, **kwargs):
return func(*args, **kwargs)
return nested
@decorator
def decorated(): pass
def not_decorated(): pass
print(inspect.getclosurevars(decorated).nonlocals)
print(inspect.getclosurevars(not_decorated).nonlocals)
# => {'func': <function decorated at 0x10e1408c8>}
# => {}
Decorated functions like yours will have closure variables, though there is no guarantee that others won't.
Also, there are other things in inspect
that you can play with. Plus, it would be easy if functools.wrap
is used in the first place (@kindall). For class method, you can look up How to detect is decorator has been applied to method or function?