注入不起作用的方法

时间:2018-02-01 09:00:38

标签: python code-injection inject

我正在尝试注入我的方法而不是另一种方法,但它仅适用于参数数量较少的方法。

我的注射器:

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,如何     正确地将参数传递给原始函数?

1 个答案:

答案 0 :(得分:3)

您遇到的根本问题是您将inject的输出分配给方法属性。 inject的结果始终接受原始函数作为其第一个参数,而始终使用self作为第一个参数调用方法。世界上没有任何装饰者会为你改变这一点,所以你必须解决它。

inject_tosetattr(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):
    ...