Show HN: Modshim – A new alternative to monkey-patching in Python
11 comments
·October 16, 2025o11c
The import limitation seems to make this not useful for me. Usually when I am monkeypatching, it's because some code I do not control has a (possibly dynamic) import of the "buggy" module under another name, so I need to make my changes visible under the original name.
If I control all the imports I can usually subclass things myself just fine.
theptip
> Because our enhanced Session class now enables retries by default, we don't even need to instantiate it directly. modshim's AST rewriting ensures that internal references within the requests module are updated. This means convenience functions like requests.get() will automatically use our enhanced Session class
This seems to explicitly handle the case you are interested in - automatically updating library-internal references to the lower to instead use the upper?
o11c
That's talking about internal imports (and static - as much as python supports - ones at that), not external ones.
If A is my application, B is buggy, and C is some other library, consider:
# A.py
monkeypatch_B()
import C
# C.py
B = __import__('B')
# B.py
bugs()
moezd
This feels too much like breaking the guarantee sticker of a vendor code, and if your vendor pushes updates weekly, or daily, you are stuck pushing updates to your shimmed code, which officially becomes "unnamed fork". Even for tests, let's say that they changed an input type, I don't see an improvement in my workflow: I still need to update my "unnamed fork". At least with a fork I get to see the whole git history, including my contributions, and testing with monkey patching helps me create clear setUp and tearDown steps.
When you have a scalpel, you give it to operating doctors during the operation, not to 5 year olds on the street.
procaryote
Of these:
> * Fix bugs in third-party libraries without forking
> * Modify the behavior of existing functions
> * Add new features or options to existing classes
> * Test alternative implementations in an isolated way
only the last sounds close to something you might actually want to do, and then only as a throwaway thing
If you want to change a library, fork it. If you want to change the behavior of existing functions, don't or at least fork first. If you want to add new features to a class, write a new class, or again, at least fork first
epgui
I ported the clojure bond library over to python. It’s not quite as neat as the original, but IMO the pseudo-FP style is much more ergonomic.
satya71
This is a nice system. I wonder if modshim can be used to or extended to do hot reload.
boxed
Also check out https://github.com/adamchainz/patchy
Izkata
Monkey-patching is altering the code at runtime, not the source code, so from the "alternative to forking and modifying" part it doesn't sound like an alternative to that.
Edit: okay Readme is clear on it and the description does make sense, the short description here just confused me.
Uptrenda
What Python versions have you tested on, OP? Good license choice, by the way.
BiteCode_dev
The is really awesome and an original and clean solution to a dirty old problem. Kudos.
I've invented a new alternative to forking / vendoring / monkey-patching packages in Python.
It's a bit like OverlayFS for Python modules - it allows you write modifications for a target module (lower) in a new module (upper), and have these combined in a new virtual module (mount).
It works by rewriting imports using AST transformations, then running both the lower and upper module's code in the new Python module.
This prevents polluting the global namespace when monkey-patching, and means if you want to make changes to a third-party package, you don't have to take on the maintenance burden of forking, you can package and distribute just your changes.