Skip to main content

A high-level library for manipulating Python Bytecode in an easy way.

Project description

PyMixin

PyMixin is a python library designed to help inject code in a compatible way. It is heavily inspired by the SpongePowered Mixin project.

Features

Redirect function calls

>>> from mixin import *
>>> from math import log, log10
>>> 
>>> def test_function(n: int) -> int:
...     return log(n)
... 
>>> @redirect(method=test_function, at=At(value=AtValue.INVOKE, target=log))
... def real_input(n: int) -> int:
...     # Call log10 instead of log
...     return log10(n)
... 
>>> test_function(10)
1.0

Change constants

>>> from mixin import *
>>> from random import randint
>>> 
>>> def percent(n: int) -> float:
...     return n / 100
... 
>>> @modify_const(method=percent, at=At(value=AtValue.LOAD, target=100))
... def random_denominator():
...     return randint(0, 100)
... 
>>> percent(10)
0.2777777777777778
>>> percent(10)
0.35714285714285715

Inject callbacks

>>> from mixin import *
>>> 
>>> def internal_message_handler(data: bytes):
...     return  # Dummy implementation
... 
>>> @inject(method=internal_message_handler, at=At(value=AtValue.HEAD))
... def log_message(data: bytes, callback_info: CallbackInfo):
...     print("Received data:", data)
... 
>>> internal_message_handler(b"Hello world")
Received data: b'Hello world'

Cancel functions

>>> from mixin import *
>>> 
>>> def process(body: str):
...     if body == "Hello":
...         print("World")
...     else:
...         print("Invalid body")
... 
>>> @inject(method=process, at=At(value=AtValue.HEAD), cancellable=True)
... def cancel_if_bad(body: str, callback_info: CallbackInfo):
...     if body != "Hello":
...         callback_info.cancel()
... 
>>> process("Hello")
World
>>> process("World")
>>> 

Modify returned value

>>> from mixin import *
>>> 
>>> def return_n_squared(n):
...     return n * n
... 
>>> @inject(method=return_n_squared, at=At(value=AtValue.RETURN), cancellable=True)  # Warning: injects at EVERY return by default
... def return_n_cubed_instead(callback_info: CallbackInfo):
...     n = (callback_info.return_value**0.5)
...     callback_info.set_return(n**3)
... 
>>> return_n_squared(10)
1000.0

Overwrite functions

>>> from mixin import *
>>> 
>>> def spam_a():
...     while True:
...         print("a")
... 
>>> @overwrite(method=spam_a)
... def replacement():
...     print("b")
... 
>>> spam_a()
b

A note on decorators

Often in python, a function is wrapped with a decorator. This means the value of a function is no longer the same. To resolve this, we added mixin.unwrap, to get the original function back (assuming functools.wraps) was used.

>>> from mixin import *
>>> from functools import wraps
>>> 
>>> def with_print(func):
...     @wraps(func)
...     def inner(*args, **kwargs):
...         print("args", args, kwargs)
...         return func(*args, **kwargs)
...     return inner
... 
>>> @with_print
... def test(n):
...     return n*2
... 
>>> @inject(method=unwrap(test), at=At(value=AtValue.HEAD))
... def log_n(n, callback_info):
...     print("N:", n)
... 
>>> test(10)
args (10,) {}
N: 10
20

Installing

To install PyMixin, you can just use pip:

pip install pymixin

License

PyMixin is licensed under MIT.

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

pymixin-1.1.1.tar.gz (8.1 kB view details)

Uploaded Source

Built Distribution

pymixin-1.1.1-py3-none-any.whl (8.1 kB view details)

Uploaded Python 3

File details

Details for the file pymixin-1.1.1.tar.gz.

File metadata

  • Download URL: pymixin-1.1.1.tar.gz
  • Upload date:
  • Size: 8.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.26.0 setuptools/57.4.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.9.7

File hashes

Hashes for pymixin-1.1.1.tar.gz
Algorithm Hash digest
SHA256 5856837ce05d1a0012d4dd7cc15c17c37451b9ba7d512b573cb1758412846fd0
MD5 e54c4c5c81d0edaa1fdf120e1d8484a3
BLAKE2b-256 6666c0ad0135ee4d2798d219fc6dafc617838df9d3acb2e477b23bad22c0047a

See more details on using hashes here.

File details

Details for the file pymixin-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: pymixin-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 8.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.26.0 setuptools/57.4.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.9.7

File hashes

Hashes for pymixin-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 86b6e3107b0d6dcf186ff4aa8c76c54bd187f54cb0bca31f010651ee2ea29620
MD5 ba20026ef29fc0182def119a625370a4
BLAKE2b-256 cf20d0e56094b5d6a9eb2236893717ee25481ac19b9f5a99beeb278a97d17a37

See more details on using hashes here.

Supported by

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