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.5.0.tar.gz (31.6 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.5.0-py3-none-any.whl (30.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: smart_monkeypatching-1.5.0.tar.gz
  • Upload date:
  • Size: 31.6 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.5.0.tar.gz
Algorithm Hash digest
SHA256 ee82bc2d0d68dae9e60e9faa78f4d367ba9d88211fd0a9a845592fbcd937f427
MD5 84495127eedb4f933730497af90b8040
BLAKE2b-256 f9d58801c24fe42d079b6ad375c85816b717aedfebf4629bcc7745a21028553a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for smart_monkeypatching-1.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b45a3a406d0761ba59beafcae4d4924f0bf266b73a20c7f0c6aa4badd86cb959
MD5 8cec8e6aeac5f75bed5ba6dfd4852ad7
BLAKE2b-256 cd001fa45c064f7d780de0707e126cfe0c4063617af10db5788c89119d09b860

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