Skip to main content

Method behavior modification at runtime, made easy.

Project description

Harmonify

Harmonify is a Python library that allows users to change the behavior of classes at runtime, with nothing more than a few function calls. Inspired by Harmony (the very popular C# library that also allows runtime behavior modification), Harmonify is flexible and uses a simple system based on monkey-patching. Like its C# equivalent, it can be used for:

  • Debugging: Inject logging or checks into methods without changing them permanently.
  • Testing: Isolate parts of your code by temporarily changing how certain methods behave.
  • Extending Libraries: Add new features or modify behavior of classes from libraries you can't edit directly.
  • Experimentation: Play around with how code runs in a non-destructive way.

Features

  • Prefix Patching: Run your custom code before the original method executes.
  • Postfix Patching: Run your custom code after the original method executes, even allowing you to modify its return value.
  • Replace Patching: Completely swap out the original method's logic with your own.
  • Create & Delete methods: Add or remove methods from a class or a module, without changing the other ones.
  • Easy Unpatching: Restore methods to their original state with a simple call.
  • Function patching: Patch functions as easily as methods!
  • Code Injection & Injection undo-ing: Add you own code inside any Python function or method and revert at any time.
    • Note: Be careful with code injection, and do not inject code coming from a source you don't trust! If you're a library developer and want to prevent your code from being injected into, decorate your code with the harmonify.injector_security.no_inject decorator.

Installation

Installing Harmonify is as easy as using pip:

pip install harmonify-patcher

After that, Harmonify will be available globally!

Example Programs

Function Patching

my_library.py

def sqrt(x: float) -> float:
	return x ** (1 / 2)

def pow(x: float, n: int) -> float:
	return x ** n

def get_version():
	return "1.0"

main.py

import harmonify
import my_library

def new_get_ver():
	return "Latest release"

print(my_library.get_version())   # 1.0
harmonify.patch_function(
	target_module = my_library,
	function_name = "get_version",
	replace = new_get_ver
)
print(my_library.get_version())   # Latest release

Code Injection

api_lib.py

import harmonify

def open_api1():
	print("Doing API stuff...")

@harmonify.allow_inject
def open_api2():
	print("More API stuff...")

@harmonify.no_inject
def restricted_api(uname, passwd):
	print(f"Doing restricted API access with:\n\tUsername: {uname}\n\tPassword: {passwd}")

main.py

import harmonify
if harmonify.inject_function(
    harmonify.get_current_module(),
    "open_api1", 1,
    "print('Done!')"
):
    print("Successfully injected open_api1")

    
if harmonify.inject_function(
    harmonify.get_current_module(),
    "open_api2", 1,
    "print('Done!')"
):
    print("Successfully injected open_api2")


if harmonify.inject_function(
    harmonify.get_current_module(),
    "restricted_api", 1,
    "print('Done!')"
):
    print("Successfully injected restricted_api")

open_api1()
open_api2()
restricted_api("secret service agent #42", "super secret password")

Changelog

1.3.2

Fixed an internal bug where an AttributeError would appear.

1.3.1

Added the PatchInfo utility class and two new fucntions, get_function_patches and get_method_patches. These two functions return informations about every patch that has been applied up until the call.

1.3.0

Slightly improved safeguards to provide an easy API. This does mean that the library dev needs to have Harmonify installed, which is not ideal.

1.2.3

  • Added injection safeguards. These should be applied in the target library.

1.2.2

  • Fixed a problem where the code would be injected before the target line.

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

harmonify_patcher-1.3.2.tar.gz (10.9 kB view details)

Uploaded Source

Built Distribution

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

harmonify_patcher-1.3.2-py3-none-any.whl (10.9 kB view details)

Uploaded Python 3

File details

Details for the file harmonify_patcher-1.3.2.tar.gz.

File metadata

  • Download URL: harmonify_patcher-1.3.2.tar.gz
  • Upload date:
  • Size: 10.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.2

File hashes

Hashes for harmonify_patcher-1.3.2.tar.gz
Algorithm Hash digest
SHA256 88210f787a6d76df893a0fa6fec642c1885d4ae8f483e7f9b2e86a0e91f1989c
MD5 c45fab9cae021760f612736b06282ee8
BLAKE2b-256 5121ed0c7ce280658452124d9fd7870aca9dd8c6f7dc6a4c1b4e9b28a7536864

See more details on using hashes here.

File details

Details for the file harmonify_patcher-1.3.2-py3-none-any.whl.

File metadata

File hashes

Hashes for harmonify_patcher-1.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9fbb5697060d270d6d1848d40de33be286af26c76b459222ac688517f155a1b8
MD5 8a1a368a73387c099934a9ca2cdb7182
BLAKE2b-256 7aa5c76b5bb30b99ce89cfb0f9ecde83a5c92b25a27eed5e52f99a66ce7f6efa

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