Skip to main content

tools to carefully monkeypatch classes

Project description

smart-monkeypatching

Tools to aid in monkeypatching classes. Two decorators:

@add_new_class(ExistingClass)
class MyClass: ...

will (in the module where ExistingClass is defined)

  1. Create orig_ExistingClass, as a backup of ExistingClass
  2. Create new_ExistingClass, as a backup of MyClass
  3. Make ExistingClass be new_ExistingClass (that is, MyClass) fixing __name__ and __qualname__ between new_ExistingClass and orig_ExistingClass as well
    Then restore_class(ExistingClass) will restore the original, and restore_new_class(ExistingClass) will put back the new version again.
@add_to_class(ExistingClass)
def fn():...

or

@add_to_class(ExistingClass)
def new_fn():...

Both will (in ExistingClass) add a method fn. If fn already exists, the the original is backed up as orig_fn. new_fn is created and names are fixed as for @add_new_class.

@add_to_class can be combined with one of @classmethod, @staticmethod, or @property (and if property, then fn in the local namespace will be the property, so you can then do

@add_to_class(ExistingClass)
@fn@setter
def fn():...

This takes care of the following potential issues;

  1. Create ExistingClass.orig_fn, as a backup of ExistingClass.fn. This way you can delegate part of the work back to the original function (calling orig_fn in your code), or undo the monkeypatching (with restore_method(ExistingClass.fn)).
  2. Create ExistingClass.new_fn, as a backup of fn (so you can switch back to the new version if you have restored the old, with restore_new_method(ExistingClass.fn)).
  3. Fixing __name__ and __qualname__ between versions of ExistingClass.fn, so that whether fn is actually orig_fn or new_fn, it's name will be fn.
  4. Specifically deals with special issues for @classmethod, @staticmethod, and @property. If the function you are replacing is a classmethod, staticmethod, or property, automatically modifies your function appropriately.
  5. Specifically deals with condition that ExistingClass.fn was actually defined in a parent class of ExistingClass, so we don't want to change the parent class when adjusting names, by copying fn into ExistingClass.
  6. Specifically deals with condition that ExistingClass.fn is a builtin, and can't be copied in the same way (or modified at all, even __name__)
  7. Specifically deals with condition that ExistingClass.fn is a Descriptor type inherited from a parent (and __code__ cannot be accessed for copying).
  8. Modifies the __doc__ to note that the function is monkeypatched.
  9. in submodule util there is a specific function to "copy" class methods so that they will have the same interface.

You should know that monkeypatching will wreack havoc with mypy, since it does stuff you shouldn't generally do. You can get an idea of the kind of mypy issues that arise by checking out the test code # test: ignore[] annotations.

For examples, use help(...), and/or download the source package and look at the tests.

The library can be built with hatchling build, tested with tests/test_tools.py -v, and should pass mypy.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

smart_monkeypatching-1.4.0.tar.gz (30.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

smart_monkeypatching-1.4.0-py3-none-any.whl (27.7 kB view details)

Uploaded Python 3

File details

Details for the file smart_monkeypatching-1.4.0.tar.gz.

File metadata

  • Download URL: smart_monkeypatching-1.4.0.tar.gz
  • Upload date:
  • Size: 30.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for smart_monkeypatching-1.4.0.tar.gz
Algorithm Hash digest
SHA256 3d8da20e1debcedbe2a241ab602e8212fff2cdd72bc54ea70fbb18e63b24e848
MD5 9c315e313d718863cea52ed6cf5ce944
BLAKE2b-256 c110d758ebd515edad1bc0e0ec3ba08953612003bb6872cd63cce6dcaa4e65d2

See more details on using hashes here.

File details

Details for the file smart_monkeypatching-1.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for smart_monkeypatching-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0677615962ea79ecd8a6418ab06dfcf39708a92099d48f741c1793cd95854454
MD5 61b6b60cd6dc8feab3e0e7ec644fe9e3
BLAKE2b-256 605c69df1064d63441108729b610154c819e05c219fcc8367e41ac79e24d752f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page