方法注入不起作用

Method injecting not working

我正在尝试注入我的方法而不是其他方法,但它只适用于参数数量较少的方法。

我的注射器:

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

原始方法,我想用我的方法替换:

@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

我的方法:

@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))

这个注入器可以很好地使用 def update_progress(self): 等函数,但对于 Logger.exception 它不起作用。

有趣的时刻 - 当我的方法被注入时,它不起作用并且原始方法 Logger.exception 也没有执行。

那么,我可以问你两个问题吗?

  1. 如何用我的方法正确替换Logger.exception?
  2. 如何在我的方法中正确调用原来的Logger.exception,如何 正确地将参数传递给原始函数?

您遇到的根本问题是您将 inject 的输出分配给方法属性。 inject 的结果始终接受原始函数作为其第一个参数,而方法始终以 self 作为第一个参数调用。世界上没有多少装饰器可以为您更改此设置,因此您将不得不解决它。

无论 inject_to 在行 setattr(target_object, target_function_name, ...) 中分配什么,都必须接受 self 作为第一个参数。只需重写 _inject 以首先接受 self。也许允许两个版本并向 inject 添加一个布尔参数。同时将参数的顺序更改为您的 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):
    ...