pythonmockingprivatemonkeypatch

Monkey Patch private instance function in python 2 with calling old function


I want to monkey patch a function which private and part of a class but I also want to call the patched function.

Example:

class SomeClass:
    def __some_function(self, foo):
        return do_something()

Now I want to write something like

def new_function(self, foo)
    if foo == 'bar':
        return True
    return super(self).__some_function(foo)

SomeClass.__some_function = new_function

I tried to overwrite this with a decorator but I had problems to call the old function because it wasn't accessible. Also I checked the mock library but didn't understand how to something like this with calling the old function with the parameters.


The decorator I tried:

def patch_something(method):
    def new_function(self, foo):
        if foo == 'bar':
            return True
        return method(self, foo)
    return new_function

SomeClass.__some_function = patch_something(SomeClass.__some_function)

I getting this error (the class is in another file - is this a problem?).

AttributeError: type object 'SomeClass' has no attribute '__some_function'

Solution

  • Attributes with double underscore __ are name mangled and need to be accessed by the mangled name as described in the documentation:

    Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.