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
Release history Release notifications | RSS feed
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)
Built Distribution
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
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5856837ce05d1a0012d4dd7cc15c17c37451b9ba7d512b573cb1758412846fd0 |
|
MD5 | e54c4c5c81d0edaa1fdf120e1d8484a3 |
|
BLAKE2b-256 | 6666c0ad0135ee4d2798d219fc6dafc617838df9d3acb2e477b23bad22c0047a |
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
Algorithm | Hash digest | |
---|---|---|
SHA256 | 86b6e3107b0d6dcf186ff4aa8c76c54bd187f54cb0bca31f010651ee2ea29620 |
|
MD5 | ba20026ef29fc0182def119a625370a4 |
|
BLAKE2b-256 | cf20d0e56094b5d6a9eb2236893717ee25481ac19b9f5a99beeb278a97d17a37 |