Let foo
be a Python package, built on top of another Python
package bar
. Sometimes foo
may wish to extend the bar
package by adding features (e.g. methods) to existing classes or
modules. Sometimes the whole package is meant as a temporary location
where experimental features can mature and be distributed early until
they get merged into the bar
package.
In such cases, it's desirable to write the source code of those
features as closely as if they were in the bar
package.
recursive-monkey-patch
enables this by providing a tool to
recursively monkey patch the bar
package. Let's assume for example
that we are writing a package bar-foo
that requires the addition
of a method f
to the class bar.x.y.z.Z
.
To achieve this, one writes a module foo.x.y.z.Z
containing a
dummy Z
class:
class Z: def f(self): return "f"
And then, upon initializing the package, one runs:
import bar import foo from recursive_monkey_patch import monkey_patch monkey_patch(foo, bar)
which will recursively crawl through foo
, and insert methods like
f
at the corresponding location in bar
. If a class or module
in foo
does not exist in bar
, then the module is inserted at
the corresponding location in bar
This package is primarily meant for writing (experimental) packages on
top of SageMath, an open source software for
mathematics that includes a large Python library. However, the
dependency upon the SageMath
package is actually light:
- Running the doctests requires
sage
; - When the SageMath package is present, the monkey patching involves a few additional Sage specific hacks.
- Support for lazy imports
- Where is the natural place for running ``monkey_patch` in a package?
- patchy: runtime application of source patches at the granularity of functions
- unittest.mock.patch: temporary runtime monkey patching of functions; meant primarily for testing purposes