Skip to main content

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) -> None
  • get_mixin(name: str) -> Mixin
  • get_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 method
  • cleanup() -> None - Clean up resources when removed
  • mixer property - Default access to mixer instance
  • mixer_attr class 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mixit-0.7.0.tar.gz (10.0 kB view details)

Uploaded Source

Built Distribution

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

mixit-0.7.0-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

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

Hashes for mixit-0.7.0.tar.gz
Algorithm Hash digest
SHA256 e389ba3bd81a9565e7ed57eaf255a0e4881a177122d28f3326dad67e8ac6e237
MD5 edc3001be1fbd125db6cb8af844c4e13
BLAKE2b-256 152490a0547efe05b6d4da542c7dcd605d8b112b9286759eb0b6b1db20b64277

See more details on using hashes here.

Provenance

The following attestation bundles were made for mixit-0.7.0.tar.gz:

Publisher: publish.yml on joshms123/mixit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for mixit-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0b8352c1d2dc83645193685c5b02652432413ab0ce05bb7e991a2ac90fae6415
MD5 3251d59c527678dbe15bde48e8f69f0c
BLAKE2b-256 011b250fc376f5ccab4a98489ee32f9c2417676a854f5aebcd040d42b7e0ad04

See more details on using hashes here.

Provenance

The following attestation bundles were made for mixit-0.7.0-py3-none-any.whl:

Publisher: publish.yml on joshms123/mixit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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