GitXplorerGitXplorer
r

paramorator

public
4 stars
0 forks
0 issues

Commits

List of commits on branch main.
Unverified
55e1e32f71a6e074dbc07b3626f6b02678628dda

make it 1.0

rrmorshea committed 4 months ago
Unverified
30c833afb527166e383487c4d8085b3d87c83b93

initial work

rrmorshea committed 4 months ago
Unverified
f7cb023b0135495e45576179b656d876dee9ca3a

initial commit

rrmorshea committed 4 months ago

README

The README file for this repository.

Paramorator

A dead simple utility for defining decorators with parameters that make type checkers happy.

Installation

pip install paramorator

Usage

from typing import Callable, ParamSpec

from paramorator import paramorator

P = ParamSpec("P")

@paramorator
def multiply(func: Callable[P, float], factor: float = 2) -> Callable[P, float]:
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> float:
        return factor * func(*args, **kwargs)
    return wrapper


@multiply(factor=3)
def add_then_triple(a: float, b: float) -> float:
    return a + b


assert add_then_triple(2, 3) == 15

# also supports inline usage
sub_then_double = multiply(lambda a, b: a - b, factor=2)
assert sub_then_double(5, 3) == 4

This isn't exactly rocket science, but to achieve the same result without paramorator, you need to write a bunch boilerplate code just to satisfy your type checker. Here is the equivalent multiple decorator written without paramorator:

from typing import Any, ParamSpec, Callable, overload, cast

P = ParamSpec("P")


@overload
def multiply(func: Callable[P, float], /, factor: float = ...) -> Callable[P, float]:
    ...

@overload
def multiply(func: None = ..., /, factor: float = ...) -> Callable[[Callable[P, float]], Callable[P, float]]:
    ...

def multiply(
    func: Callable[P, float] | None = None,
    /,
    factor: float = 2,
) -> Callable[P, float] | Callable[[Callable[P, float]], Callable[P, float]]:

    def decorator(func: Callable[P, float]) -> Callable[P, float]:
        def wrapper(*args: P.args, **kwargs: P.kwargs) -> float:
            return factor * func(*args, **kwargs)
        return wrapper

    return decorator(func) if func else decorator

Development

Install flit and run:

flit install

To run tests:

python tests.py

Check the types with Pyright:

pyright paramorator.py tests.py