Skip to main content

A Python package for advanced function dispatching based on complex, nested, and parameterized types. Inspired by singledispatch.

Project description

Dispatchery 🧙‍♂️✨

Dispatch your functions based on complex types.

dispatchery is a lightweight Python package inspired by the standard singledispatch decorator, but with support for complex, nested, parameterized types. With dispatchery, you can dispatch based on annotations such as tuple[int, str, dict[str, int]] or list[dict[str, list[int]]].

Unlike singledispatch, dispatchery can also dispatch based on multiple arguments and keyword arguments, rather than only the first one. It also supports nested types and union types such as Union[int, str] or int | str, making it a powerful tool for writing clean, type-specific code.

Features

  • Advanced Type Dispatching: Supports complex generic types.
  • Recursive Type Matching: Handles nested types like tuple[int, str, dict[str, int]].
  • Union Types: Dispatch based on union types like Union[int, str].
  • Multi Argument Dispatch: Dispatch based on multiple arguments types, not just the first.
  • Simple Integration: Works just like functools.singledispatch with added power.

Installation

Install dispatchery from PyPI:

pip install dispatchery

Usage

If you know how to use functools.singledispatch then you already know how to use dispatchery. Decorate your main function with @dispatchery and register specific types as needed.

Examples

Suppose we want a function, process, that behaves differently based on complex types like tuple[int, str], list[str], or str | int, we can use dispatchery to achieve this:

from dispatchery import dispatchery

@dispatchery
def process(value):
    return "Standard stuff."

@process.register
def _(value: list[str]):
    return "Nice, a parameterized type."

@process.register
def _(value: list[int]):
    return "That's different? Cool."

@process.register
def _(value: list[tuple[int, str]]):
    return "Nested, too? Alright."

@process.register
def _(value: bool | str | int):
    return "Union types? No problem."

@process.register
def _(value: list[tuple[int | list[float], dict[str, tuple[list[bool], dict[str, float | str]]]]]):
    return "Now this is just getting silly."

print(process(1.111))  # "Standard stuff."
print(process(["hello", "world"]))  # "Nice, a parameterized type."
print(process([1, 2, 3]))  # "That's different? Cool."
print(process([(1, "hello"), (2, "world")]))  # "Nested, too? Alright."
print(process(True))  # "Union types? No problem."
print(process([(1, {"a": ([True, False], {"x": 3.14})})]))  # "Now this is just getting silly."

Multi Argument Dispatch

dispatchery also supports dispatching based on multiple arguments:

@dispatchery
def process(a, b):
    pass

@process.register
def _(a: int, b: str):
    return "Bip boop."

@process.register
def _(a: str, b: int):
    return "Boopidy bop."

print(process(42, "hello"))  # "Bip boop."

print(process("hello", 42))  # "Boopidy bop."

Keyword Arguments

You can also dispatch with kwargs:

@dispatchery
def process(a, key="hello"):
    pass

@process.register
def _(a: str, key: int = 42):
    return "Round number."

@process.register
def _(a: str, key: float = 3.14):
    return "Decimals."

print(process("hello", key=1987))  # "Round number."
print(process("hello", key=1.618))  # "Decimals."

Types as Decorator Parameters

You can also pass types as arguments to the decorator instead of using type hints:

@dispatchery
def process(a, b):
    pass

@process.register(int, str)
def _(a, b):
    pass

@process.register(str, int)
def _(a, b):
    pass

Why Use Dispatchery?

  • Better Readability: Your code is clean and type-specific without bulky type-checking clutter.
  • Enhanced Maintainability: Add new types easily without modifying existing code.
  • More Flexible: Embrace the power of Python’s dynamic typing with elegant dispatching.

Optimizing Performance

By default dispatchery runs in strict mode. This means that it will check every value in lists and dictionaries for type matching. If you are planning to process lists of millions of items, this can be quite computationally expensive, so you may want to disable it:

from dispatchery import dispatchery

dispatchery.strict_mode = False

This will massively speedup execution for long values, but only the first value will be used for type matching.

Moreover dispatchery has a built-in cache that stores the type matching results. This cache is disabled by default, but you can enable it by setting the cached_mode attribute to True:

from dispatchery import dispatchery

dispatchery.cached_mode = True

For most use cases the overhead from the cache is larger than the gains, so it's generally not worth it. But if you need to do a lot of dispatching per second with recurring complex types, it can potentially speedup dispatchery significantly.

Dependencies

None, but you might want typing-extensions>=3.7 if you need backward compatibility for typing features.

Integration

To integrate dispatchery in an existing codebase, you can import it as a drop-in replacement for singledispatch:

from dispatchery import dispatchery as singledispatch

License

dispatchery is licensed under the 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

dispatchery-0.3.0.tar.gz (12.8 kB view details)

Uploaded Source

Built Distribution

dispatchery-0.3.0-py3-none-any.whl (9.4 kB view details)

Uploaded Python 3

File details

Details for the file dispatchery-0.3.0.tar.gz.

File metadata

  • Download URL: dispatchery-0.3.0.tar.gz
  • Upload date:
  • Size: 12.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.9.20

File hashes

Hashes for dispatchery-0.3.0.tar.gz
Algorithm Hash digest
SHA256 4805f0b619d9ad4b03684b1c9316b1a4814ac685b9376e24ee0f907b80695a0d
MD5 edababfdc59c07ca110010218f53b14b
BLAKE2b-256 b54ec1ac3b3f2c77b77353610076a507e7d59e39d1197f4b61254ff1c415c68d

See more details on using hashes here.

File details

Details for the file dispatchery-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: dispatchery-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 9.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.9.20

File hashes

Hashes for dispatchery-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e9f906afdb7c67223b5411c7c5f4db4cf9f902275227ef7ea645306953467385
MD5 51c09562118c0c63c4577385b1314702
BLAKE2b-256 2d47f496b22ec5f44ad4f260749bc6f054a87849f90374dab03086c9820afd59

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