Search code examples
pythonpython-3.xpython-decorators

How can I use a decorator inside a class with the definition in the same module?


Inside the BasePlugin module I have 2 main things defined. A class called BasePlugin, and a decorator that is not part of the class called ValidateEvent.

When I write a plugin and run:

from BasePlugin import *

This works and I can use the decorator on methods inside the plugin class.

However, if I try to decorate a method inside the BasePlugin class, it cannot find the decorator.

I have tried many ways to reference the decorator, and even tried to import it in to it's own module but nothing seems to work. I would rather not create another module for the decorator.

Is it possible to reference a decorator inside a class that is defined in the same module but not as part of the class?

Edit: Here is a snippet of the offending code

#BasePlugin.py
class BasePlugin():

   def __init__(self, event_manager):
      pass

   @ValidateEvent
   def ProvideModeEventHandler(self, event):
      self._mode = event.Message

def ValidateEvent(func):
   """
   Decorator used to check if the event(s) fired should be
   handled by the plugin.
   """
   def new_func(plugin, event, *args, **kwargs):
      if plugin.Name == event.Name or event.Name == '':
         return func(plugin, event, *args, **kwargs)
   return new_func

Solution

  • The problem you have is with the order of your definitions in the module. When you use ValidateEvent as a decorator on a method in the BasePlugin class, it needs to be available already in the global namespace, since the decorator runs immediately when the method is defined (not only when the method is called).

    In the snippet of code you've shown, ValidateEvent is defined below the class definition, so the Python interpreter doesn't know about it yet.

    To fix the issue, move your decorator's definition above the class definition:

    def ValidateEvent(func):
        ...
    
    class BasePlugin():
    
       @ValidateEvent
       def ProvideModeEventHandler(self, event):
           ...