Introspection to get decorator names on a method?

Tony picture Tony · Jul 12, 2010 · Viewed 18.9k times · Source

I am trying to figure out how to get the names of all decorators on a method. I can already get the method name and docstring, but cannot figure out how to get a list of decorators.

Answer

Jaymon picture Jaymon · Jul 3, 2015

I'm surprised that this question is so old and no one has taken the time to add the actual introspective way to do this, so here it is:

The code you want to inspect...

def template(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

baz = template
che = template

class Foo(object):
    @baz
    @che
    def bar(self):
        pass

Now you can inspect the above Foo class with something like this...

import ast
import inspect

def get_decorators(cls):
    target = cls
    decorators = {}

    def visit_FunctionDef(node):
        decorators[node.name] = []
        for n in node.decorator_list:
            name = ''
            if isinstance(n, ast.Call):
                name = n.func.attr if isinstance(n.func, ast.Attribute) else n.func.id
            else:
                name = n.attr if isinstance(n, ast.Attribute) else n.id

            decorators[node.name].append(name)

    node_iter = ast.NodeVisitor()
    node_iter.visit_FunctionDef = visit_FunctionDef
    node_iter.visit(ast.parse(inspect.getsource(target)))
    return decorators

print get_decorators(Foo)

That should print something like this...

{'bar': ['baz', 'che']}

or at least it did when I tested this with Python 2.7.9 real quick :)