5

I want to patch some code that uses an object from an external module.

One method of this object is called all over the place, and I need to set a new default kwarg in all those calls.

Rather than add so much duplicate code, I thought it would be better to change the object method. What is the cleanest way to do this?

so12311
  • 4,179
  • 1
  • 29
  • 37

2 Answers2

3

This is called monkey-patching and there is no "clean" version of it.

If you need to replace a method bar in a class Foo, use this code:

oldMethod = Foo.bar
def newMethod(self, **kwargs):
    ... fix kwargs as necessary ...
    oldMethod(self, **kwargs)
Foo.bar = newMethod
  1. First, we save the old method handle in a variable
  2. Then we define the new method as a function. The first argument has to be self, just as if this function was inside of a class.
  3. To call the original method, we use oldMethod(self, ...). This will take the method pointer, and call it with the instance as first argument. self.oldMethod() doesn't work since we're not in a class context (I think).
  4. Lastly, we install the patched method in the class.

Related:

Community
  • 1
  • 1
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
0

I decided to write a wrapper class which inherits from the object I needed to modify.

class Wrapper(Target):
    def method(self, *args, **kwargs):
        kwargs['option'] = True
        return super(Wrapper, self).method(*args, **kwargs)

instance = Target()
instance.__class__ = Wrapper
so12311
  • 4,179
  • 1
  • 29
  • 37
  • why not just: `instance = Wrapper()`? – OozeMeister Jan 05 '15 at 23:34
  • in my real situation, the instance is returned by a function from an external module that I don't want to edit. quite possibly there is a better way to do this though I know very little about classes. – so12311 Jan 06 '15 at 01:18