Reputation: 3473
I am trying to inject my method instead of another method but it works only with methods with small count of arguments.
My injector:
def inject(target_function, new_function):
@wraps(target_function)
def _inject(*args, **kwargs):
return new_function(target_function, *args, **kwargs)
return _inject
# decorator injection.
def inject_to(target_object, target_function_name):
def _inject_to(new_function):
target_function = getattr(target_object, target_function_name)
setattr(target_object, target_function_name, inject(target_function, new_function))
return new_function
return _inject_to
Original method, that I want to replace with my method:
@macros.macro
class Logger:
__qualname__ = 'Logger'
suppress = False
def exception(self, message, *args, exc=None, log_current_callstack=True, level=150, owner=None, trigger_breakpoint=False):
if Logger.suppress:
return
My method:
@injector.inject_to(Logger, 'exception')
def exception(original, self, *args, **kwargs):
f.writeLine("Logger.exception !!!")
f.writeLine("original" + str(original))
f.writeLine("self" + str(self))
f.writeLine("args" + str(*args))
f.writeLine("kwargs" + str(**kwargs))
This injector works fine with functions like def update_progress(self):
, but for Logger.exception it doesn't work.
Interesting moment - when my method was injected, it doesn't work and original method Logger.exception doesn't executed too.
So, can I ask you two questions?
Upvotes: 1
Views: 314
Reputation: 114330
The fundamental problem you have is that you assign the output of inject
to a method attribute. The result of inject
always accepts the original function as its first argument, while a method is always invoked with self
as the first parameter. There is no amount of decorators in the world that will change this for you, so you will have to work around it.
Whatever inject_to
assigns in the line setattr(target_object, target_function_name, ...)
must accept self
as a first parameter. Just rewrite _inject
to accept self
first. Perhaps allow both versions and add a boolean parameter to inject
. Also change the order of the arguments to your version of exception
:
def inject(target_function, new_function, method=False):
if method:
@wraps(target_function)
def _inject(self, *args, **kwargs):
return new_function(self, target_function, *args, **kwargs)
else:
@wraps(target_function)
def _inject(*args, **kwargs):
return new_function(target_function, *args, **kwargs)
return _inject
...
setattr(target_object, target_function_name, inject(target_function, new_function, method=True))
...
@injector.inject_to(Logger, 'exception')
def exception(self, original, *args, **kwargs):
...
Upvotes: 3