9

Is it possible to find out if a function is decorated at runtime? For example could I find all functions in a module that are decorated by "example"?

@example
def test1():
    print "test1"
TheDude
  • 1,182
  • 3
  • 10
  • 14

5 Answers5

14

Since you have indicated that you have the control over the wrapper code, here is an example:

def example(f):
    f.wrapped = True
    return f

@example
def test1():
    print "test1"

def test2():
    print "test2"


print test1.wrapped
print hasattr(test2, 'wrapped')
ivan.mylyanyk
  • 2,051
  • 4
  • 30
  • 37
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
10

In the general case it is not possible because the example decorator might not leave any trace that's detectable at runtime -- for example, it could be

def example(f):
  return f

If you do control the source for example, it's of course easy to make it mark or record the functions it's decorating; if you don't, it may be utterly impossible to do what you want.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
3

I don't think there's a general way since a decorator is a simple function call. Your code is identical to this:

def test1():
    print "test1"

test1 = example(test1)

You could probably detect specific decorators by disassembling and analysing (using the dis module). Or you could simply parse the source file, though that's a bit ugly.

Why do you want to detect them in the first place?

Max Shawabkeh
  • 37,799
  • 10
  • 82
  • 91
  • 2
    My script is used to access a RESTful interface. I wanted to introspect my module and find all the methods "marked" with a certain decorator and build my "optparse" options at runtime. Since the decorator enforces some consistency for my arguments, it made sense to check against that as all of the REST endpoints would be decorated by it. – TheDude Jan 27 '10 at 02:20
  • 1
    If you could edit some sample code from the decorated module and the definition of the decorator, we could probably figure a way to do that. – Max Shawabkeh Jan 27 '10 at 02:31
  • I can actually easily achieve what I want if I simply prefixed my "optparse"-able functions with "do_" or something like that. Then I can loop through the functions and create an optparse option for functions that start with "do_". I just felt it would be cleaner to check based on my decorator. – TheDude Jan 27 '10 at 03:00
  • 2
    If you're the one writing the decorator, you can make it add the function to a module-level variable (then return it) and simply read the variable in the client code. – Max Shawabkeh Jan 27 '10 at 03:09
  • I don't believe the `dis` modules will help, but I also thought of parsing the sourcecode. The downside is that it only gives you a name and not a reference (though you could put the name through `globals()` if all your decorators are in your module namespace). It may be a year late, but if anyone is still interested, it is here: http://stackoverflow.com/q/5910703/711085 – ninjagecko May 06 '11 at 22:58
2

You may find this recent question provides detailed information on 3 ways to do this:

Howto get all methods of a python class with given decorator

Community
  • 1
  • 1
ninjagecko
  • 88,546
  • 24
  • 137
  • 145
-1

If you can, monkeypatch the decorator at runtime to catch which functions are being passed to it:

decfuncs = []

def decpatch(dec):
  def catchdec(func, *args, **kwargs):
    decfuncs.append(func)
    return dec(func, *args, **kwargs)
  return catchdec

somemodule.somedecorator = decpatch(somemodule.somedecorator)
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358