Skip to content

DomWeldon/partialdispatch

Repository files navigation

Python 3.8+ Code style: black

partialdispatch

Google Slides explaining how this repository works!.

This project is currently under development, with a release of a partialdispatch function expected soon. If you're interested in it, please get in touch, but but be aware this is very much "building in (semi)-public", until a proper documented version is up.

Currently, the only supported function is partialdispatch.singledispatch_literal, which implements the functionality of functools.singledispatch for literal types and values, including enums.

partialdispatch.singledispatch_literal

Transform a function into a single-dispatch generic function, which also supports dispatching to a different callable based on a literal value.

Literal values are specified using either the typing.Literal type annotation, a literal type such as an enum, or by passing the keyword argument literal=True to the register function.

The example below shows how this function can be used. The code should run "as-is" (and will use rich to print in colour if you have it on your system or in your virtualenv).

import enum
import typing

import partialdispatch

_use_rich = None
try:
    import rich
except ModuleNotFoundError:
    pass
    _use_rich = False
else:
    _use_rich = True
    print = rich.print

class Pet(enum.Enum):
    Cat: str = "🐱"
    Dog: str = "🐕"
    Shark: str = "🦈"

@partialdispatch.singledispatch_literal
def func(a, b):

    return f"default: {a=}, {b=}"

@func.register
def _(a: int, b):

    return f"int: {a=}, {b=}"

@func.register
def _(a: typing.Literal[49], b):

    return f"The meaning of life {a=}, {b=}"

@func.register
def _(a: Pet.Cat, b):

    return f"meow! {a=}, {b=}"


@func.register(Pet.Dog, literal=True)
def _(a, b):

    return f"Good boy! {a=}, {b=}"


vals = [
    123,
    "some string",
    49,
    Pet.Cat,
    Pet.Dog,
    Pet.Shark,
    None,
]

for v in vals:
    output = func(v, None)
    fmt = ("[yellow]", "[/yellow]") if _use_rich else ("", "")
    print(f"Calling func with {v}: {fmt[0]}{output}{fmt[1]}")
$ pdm run python example.py 
Calling func with 123: int: a=123, b=None
Calling func with some string: default: a='some string', b=None
Calling func with 49: The meaning of life a=49, b=None
Calling func with Pet.Cat: meow! a=<Pet.Cat: '🐱'>, b=None
Calling func with Pet.Dog: Good boy! a=<Pet.Dog: '🐕'>, b=None
Calling func with Pet.Shark: default: a=<Pet.Shark: '🦈'>, b=None
Calling func with None: default: a=None, b=None

Drawbacks

  • Currently only works on hash equality

The argument literal=True must be passed when:

  • Value is callable
  • Value is a type
  • Value is None

About

Function-level logic inspired by functools.singledispatch and functools.partial

Resources

License

Stars

Watchers

Forks

Packages

No packages published