←back to thread

107 points joouha | 2 comments | | HN request time: 0.001s | source

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.

Show context
o11c ◴[] No.45665197[source]
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.

replies(1): >>45665232 #
theptip ◴[] No.45665232[source]
> 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?

replies(1): >>45665275 #
1. o11c ◴[] No.45665275[source]
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()
replies(1): >>45673192 #
2. joouha ◴[] No.45673192[source]
It should in theory be possible to mount the new virtual package over the lower module - but I don't think works currently (I'll have to test this). Doing this would make modifications available globally like you describe.