A simple mixin system with method exports
Project description
Mixit
A lightweight and flexible mixin system for Python that allows dynamic composition of functionality through mixins.
Features
- Dynamic mixin composition at runtime
- Method export system with conflict detection
- Optional initialization through
mix_init - Clean mixin coordination through mixer access
- Simple and intuitive API
Installation
pip install git+https://github.com/joshms123/mixit.git
Quick Start
from mixit import Mixer, Mixin, export
# Define a mixin
class LoggerMixin(Mixin):
def __init__(self):
super().__init__()
self.logs = []
self.prefix = ""
def mix_init(self, prefix: str = "", **kwargs):
self.prefix = prefix
@export
def log(self, message: str):
self.logs.append(f"{self.prefix}{message}")
return len(self.logs)
# Create a mixer and add the mixin
mixer = Mixer()
mixer.add_mixin("logger", LoggerMixin, prefix="[INFO] ")
# Use the exported method
mixer.log("Hello world!") # Returns: 1
print(mixer.logger.logs) # Prints: ['[INFO] Hello world!']
Auto-derived names (v0.7+)
You can omit the explicit name. The mixer derives one by converting the class name to snake_case:
mixer = Mixer()
mixer.add_mixin(LoggerMixin, prefix="[INFO] ") # registered as "logger_mixin"
mixer.log("Hello!")
print(mixer.logger_mixin.logs)
For batches of plain mixins (no mix_init kwargs), add_mixins registers them in order:
mixer.add_mixins(CounterMixin, MathMixin, LoggerMixin)
mixer.add_mixin(DatabaseMixin, dsn="...") # use add_mixin for kwarg cases
mixer.add_mixins(CacheMixin, MetricsMixin)
Core Concepts
Mixins
Mixins are classes that inherit from Mixin and provide functionality that can be mixed into a Mixer instance. Methods can be marked for export using the @export decorator, making them directly accessible from the mixer instance.
class CounterMixin(Mixin):
def __init__(self):
super().__init__()
self.value = 0
@export
def increment(self):
self.value += 1
return self.value
Initialization
Mixins can define an optional mix_init method that will be called when the mixin is added to a mixer. Any additional keyword arguments passed to add_mixin will be forwarded to mix_init.
class MathMixin(Mixin):
def __init__(self):
super().__init__()
self.precision = 2
def mix_init(self, precision: int = 2, **kwargs):
self.precision = precision
@export
def add(self, a: float, b: float) -> float:
return round(a + b, self.precision)
mixer.add_mixin("math", MathMixin, precision=3)
Method Export
Methods marked with @export are made available directly on the mixer instance. If multiple mixins try to export methods with the same name, only the first one is exported and conflicts are tracked.
# Method available directly on mixer
result = mixer.add(1.23, 4.56)
# Access through mixin instance
result = mixer.math.add(1.23, 4.56)
# Check for conflicts
conflicts = mixer.get_conflicts()
Mixin Coordination
Mixins can coordinate with each other through the mixer instance. By default, the mixer is accessible via the mixer property, but you can customize this name to avoid conflicts or improve readability:
# Using default 'mixer' attribute
class WorkerMixin(Mixin):
@export
def do_work(self):
self.mixer.log("Starting work") # Use another mixin's exported method
result = self.perform_work()
self.mixer.logger.log("Done!") # Access mixin instance directly
return result
# Using custom mixer attribute name
class DatabaseMixin(Mixin, mixer_attr='app'):
@export
def query(self, sql: str):
# Access mixer through custom name
logger = self.app.logger
logger.log(f"Executing: {sql}")
return self.execute_query(sql)
API Reference
Mixer
add_mixin(mixin_class: Type[Mixin], **kwargs) -> Mixin— auto-derives the registration name from the class name.add_mixin(name: str, mixin_class: Type[Mixin], **kwargs) -> Mixin— explicit name.add_mixin_instance(instance: Mixin) -> Mixin— auto-derives the name; for pre-built instances.add_mixin_instance(name: str, instance: Mixin) -> Mixin— explicit name.add_mixins(*mixin_classes: Type[Mixin]) -> List[Mixin]— bulk-register plain mixins in order, no kwargs.remove_mixin(name: str) -> Noneget_mixin(name: str) -> Mixinget_mixins() -> Dict[str, Mixin]get_conflicts() -> Dict[str, List[str]]call_all_mixins(func_name: str, *args, **kwargs) -> Dict[str, Any]
Helpers
derive_mixin_name(cls: Type[Mixin]) -> str— exported helper that converts a class name to its snake_case registration key.
Mixin
mix_init(**kwargs) -> None- Optional initialization methodcleanup() -> None- Clean up resources when removedmixerproperty - Default access to mixer instancemixer_attrclass parameter - Customize mixer attribute name (e.g.class MyMixin(Mixin, mixer_attr='app'))
Decorators
@export- Mark a method for export to the mixer namespace
License
MIT License
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mixit-0.7.0.tar.gz.
File metadata
- Download URL: mixit-0.7.0.tar.gz
- Upload date:
- Size: 10.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e389ba3bd81a9565e7ed57eaf255a0e4881a177122d28f3326dad67e8ac6e237
|
|
| MD5 |
edc3001be1fbd125db6cb8af844c4e13
|
|
| BLAKE2b-256 |
152490a0547efe05b6d4da542c7dcd605d8b112b9286759eb0b6b1db20b64277
|
Provenance
The following attestation bundles were made for mixit-0.7.0.tar.gz:
Publisher:
publish.yml on joshms123/mixit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mixit-0.7.0.tar.gz -
Subject digest:
e389ba3bd81a9565e7ed57eaf255a0e4881a177122d28f3326dad67e8ac6e237 - Sigstore transparency entry: 1391482994
- Sigstore integration time:
-
Permalink:
joshms123/mixit@6bf20b3a27d7de7454a361e0c775cfd7eaa02108 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/joshms123
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6bf20b3a27d7de7454a361e0c775cfd7eaa02108 -
Trigger Event:
release
-
Statement type:
File details
Details for the file mixit-0.7.0-py3-none-any.whl.
File metadata
- Download URL: mixit-0.7.0-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b8352c1d2dc83645193685c5b02652432413ab0ce05bb7e991a2ac90fae6415
|
|
| MD5 |
3251d59c527678dbe15bde48e8f69f0c
|
|
| BLAKE2b-256 |
011b250fc376f5ccab4a98489ee32f9c2417676a854f5aebcd040d42b7e0ad04
|
Provenance
The following attestation bundles were made for mixit-0.7.0-py3-none-any.whl:
Publisher:
publish.yml on joshms123/mixit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mixit-0.7.0-py3-none-any.whl -
Subject digest:
0b8352c1d2dc83645193685c5b02652432413ab0ce05bb7e991a2ac90fae6415 - Sigstore transparency entry: 1391482996
- Sigstore integration time:
-
Permalink:
joshms123/mixit@6bf20b3a27d7de7454a361e0c775cfd7eaa02108 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/joshms123
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6bf20b3a27d7de7454a361e0c775cfd7eaa02108 -
Trigger Event:
release
-
Statement type: