0

I have a @on_event decorator that registers function as a callback for a specified event :

@on_event('MY_EVENT')
def on_event_triggers(*a, **k):
    print('Event triggered')

But, I want my decorator to work on "global" functions (as above) and on class functions:

class MyModule(Module):
    @on_event('MY_EVENT')
    def on_event_triggered(self, *a, **k):
         print('Event triggered in a method')

Of course, the self argument will be passed correctly (and determined by some piece of code I don't show here). However, for this to work I have to be able to know if the function passed to my decorator is a method or a global function.

I'm using Python 3.3.

Thibaut D.
  • 2,521
  • 5
  • 22
  • 33
  • 4
    Why do you have to differentiate between them to make both work? Most decorators should simply pass all arguments through and don't need to inspect any of them, so a method can be decorated the same way as any other function. –  Jan 05 '14 at 20:18
  • You can't, because at the time your decorator is called, the class doesn't exist yet, so the function doesn't know it will become a method. Why does the decorator need to know that anyway? – BrenBarn Jan 05 '14 at 20:19
  • Because in the second case I have to pass a value for "self", and in the first one I don't. The @on_event decorator will keep a list of methods to call when the event triggers, so when I call these methods I have to pass "self" or not. – Thibaut D. Jan 05 '14 at 20:20
  • 2
    @ThibautD.: If you pass `*args` and `**kwargs`, self will automatically be passed, since it's just a normal argument. – BrenBarn Jan 05 '14 at 20:20
  • @ThibautD. Ah, so you want `@on_event` in a class register event handlers for *all* instances? That seems more involved (and like a bad idea, to be completely honest). –  Jan 05 '14 at 20:24
  • @BrenBarn: on_event() fill a list of methods to call. When the event happen, I iterate over this list and call the methods. But in the sezcond case, I have tu manually pass a "self" argument (that I can guess and which is related to my API). – Thibaut D. Jan 05 '14 at 20:24
  • 1
    @ThibuatD: Please edit your question to provide more details about how you are using this code and how you hope to determine the value of self. What exactly is `on_event` supposed to do and when is it supposed to do it? – BrenBarn Jan 05 '14 at 20:25
  • The goal of the decorator is to "attach" IRC events to methods. on_event('IRC_JOIN', **filters). This decorator will be used in "module" of my applications (an IRC bot). I want to support 2 kind of modules: basic ones, which simply defines a few methods and register callbacks with the decorator and more sophisticated API based on a Module class, that can be used to store module-related data instead of storing them in the global scope. I tried to use the same decorator for both cases. If it's not possible I will use a self.on_event() method in module's __init__ instead of the global decorator. – Thibaut D. Jan 05 '14 at 20:31
  • @delnan: Yes, I want to call the function for all instances. – Thibaut D. Jan 05 '14 at 20:33

1 Answers1

2

You should offer two decorators, one for free functions and one for methods. There is no easy or reliable way to find differentiate one from the other from inside a decorator. It's trivial for the person writing the code though.