imagine using a python library. Suppose that this library has one script and a couple of classes that are of interest. All these classes are defined in individual files. Suppose that class D is imported and used by class A,B and C in multiple ways. In the same way class A uses class B and class B uses class C. The script makes direct use of class A and thus direct and indirect use of class D. Now suppose that you want to customize D and locally define a class D' that is derived from class D.
What would be the most elegant way to make the script and the other classes (A,B, C) use class D' instead of D?
Thank you and have a nice day!
You can monkey patch the library.
# a.py
import d
class A():
my_d = d.D()
# script.py
A.d.D = D_prime
def foo():
a_cls = a.A() # uses A.d.D is D'
The way that a.py imports D matters
# a.py
from d import D
class A():
my_d = D()
# script.py
A.D = D_prime
def foo():
a_cls = a.A() # uses A.D is D'
Other import schemes may involve similar patterns. Something like this might be very difficult to patch.
def builder():
from d import D
return D()
It may also be helpful to see how the mock
library does this. If it's a toy, you could use this directly. patch
in particular is interesting.
@patch('A.d.D', new=D_prime)
def my_func(...):
a = A() # a.d.D is D_prime
Monkey patching is a code smell, depending on unittest in application code is a smell. None of it is "elegant". If you are the library author, please support dependency injection instead.
If you're brave, you might pull out some of the patch decorator into something that's not focused on mocks. Because this pattern exists in the unittest library, it can be considered pythonic and "elegant" with the caveat above.
If you're interested in how this works, you're modifying the symbol table for the module a
. See globals and locals for details.