Dynamically add a decorator to a class

I have a rather large and attractive decorator for debugging PyQt signals , which I want to dynamically add to the class. Is there a way to add a decorator to a class dynamically?

I could approach this problem from the wrong angle, so this is what I want to do.

purpose

  • I have a decorator that will detect / attach to all pyqt signals in the class and print debugging information when these signals are emitted.
  • This decorator is great for debugging signals of one class. However, there may be a time when I would like to bind ALL my signals in the application. This can be used to see if I emit signals at unexpected times, etc.
  • I would like to dynamically attach this decorator to all my classes that have signals.

Possible solutions / ideas

I examined several possible solutions:

  • Inheritance: It would be easy if all my classes had the same base class (except for the built-in Python object and PyQt built-in QtCore.QObject ). I suppose I could just attach this decorator to my base class, and everything will work as expected. However, this is not the case in this particular application. I do not want to change all my classes in order to have the same base class.
  • Monkey-patch Python object or QtCore.QObject : I don't know how this will work in practice. However, theoretically, can I change one of these base __init__ classes as new_init , which I define in my decorator? It seems really dangerous and hacky, but maybe this is a good way?
  • Metaclasses: I do not think that metaclasses will work in this scenario because I will have to dynamically add the __metaclass__ attribute to the classes into which I want to insert a decorator. I think this is not possible because to insert this attribute the class must already be built. This way, any metaclass that I define will not be called. It's true?

I tried several variations of metaclassical magic, but nothing worked. I feel that using metaclasses may be the way to accomplish what I want, but I can't get it to work.

Again, I could all be wrong. Essentially, I want to bind the behavior of my decorator, mentioned above, to all classes of my application (maybe even to the list of selected classes). In addition, I could reorganize my decorator if necessary. I don't care if I attach this behavior with a decorator or some other mechanism. I just assumed that this decorator is already doing what I want for one class, so it might be easy to extend it.

+6
source share
1 answer

Decorators are nothing more than callers that are automatically applied. To apply it manually, replace the class with the return value of the decorator:

 import somemodule somemodule.someclass = debug_signals(somemodule.someclass) 

This replaces the name somemodule.someclass with the return value of debug_signals , which we passed to the source class somemodule.someclass .

+6
source

All Articles