0

First of all, here is my (pseudo) code:

somemodule.py:

class parentclass(object):
    def __init__(self):
        if(not prevent_infinite_reursion) #Just to make shure this is not a problem ;)
            self.somefunction()

    def somefunction():

        # ... deep down in a function ...

        # I want to "monkey patch" to call constructor of childclass, 
        # not parentclass
        parentclass() 

othermodule.py

from somemodule import parentclass

class childclass(parentclass):
    def __init__(self):
        # ... some preprocessing ...

        super(childclass, self).__init__()

The problem is, i want to monkey patch parent class, so it would call constructor of childclass, without changing code of somemodule.py. It doesn't matter if it's patched only in class instance(that's shure better) or globally.

I know i can override somefunction, but it contains too many lines of code, for this being sane.

Thanks!

offlinehacker
  • 842
  • 1
  • 9
  • 14
  • You want _all_ attempts to construct a `parentclass` to instead construct a `childclass`, or only attempts within `parentclass`, or only this specific attempt within `parentclass.somefunction`, or one of the latter two but only when `self` is a `childclass`? – abarnert May 13 '13 at 08:06
  • Well any of this, so i will appreciate any kind of answer, but the best would be attempts in parentclass. – offlinehacker May 13 '13 at 08:10
  • Actually, that's probably the most difficult possibility. But let me think about it… – abarnert May 13 '13 at 08:10
  • I covered this in [my very first answer on StackOverflow](http://stackoverflow.com/a/4714744/566644), though it replaces *all* occurances of `parentclass()`. – Lauritz V. Thaulow May 13 '13 at 08:11
  • @LauritzV.Thaulow: Yes, hooking `__new__` is fine for hooking all attempts to construct a `parentclass`, but it won't hook only attempts within `parenclass` itself, which is what the OP said would be best. Can you think of a way to do that? – abarnert May 13 '13 at 08:12
  • 1
    I can think of two horribly hacky things that might work: (1) Replace each method of `parentclass` with a wrapper that patches out `__new__`, calls the original, and restores `__new__`. (2) Replace each method of `parentclass` with a wrapper that runs the original inside a modified `globals` where `parentclass` has been replaced by `childclass`. But I don't think either of these is a good enough idea to be worth coding. – abarnert May 13 '13 at 08:15
  • @abarnert well i think i could do it, because currently i have to patch only one function, will try. – offlinehacker May 13 '13 at 08:20

1 Answers1

3

You could use mock.patch for this:

class childclass(parentclass):
    def somefunction(self):
        with patch('somemodule.parentclass', childclass):
            super(childclass, self).somefunction()
Lauritz V. Thaulow
  • 49,139
  • 12
  • 73
  • 92
  • 1
    A nice clean way to do my "horribly hacky thing (1)". – abarnert May 13 '13 at 08:42
  • Hm it doesn't work in my case, because parentclass is eventually a children of some other class and parent of parentclass __new__ method gets called and it creates parentclass instead of supposedly patched child class, will try to find how to manage that. – offlinehacker May 13 '13 at 09:13
  • @offlinehacker You can patch the `__new__` method as well. Also it might help to read [where to patch](http://www.voidspace.org.uk/python/mock/patch.html#id1). – Lauritz V. Thaulow May 13 '13 at 09:17
  • @LauritzV.Thaulow eventually it worked like a charm with patching `__new__` of a top class. This one was hard. Thanks! – offlinehacker May 13 '13 at 10:27