Skip to content

v0.7.4

Choose a tag to compare

@crypt0lith crypt0lith released this 27 Aug 03:24
· 60 commits to master since this release
v0.7.4
bbb16e4

This release reworks the rgb_dispatch decorator: it adds a replace_defaults option, fixes color-name default replacement under the bare @rgb_dispatch form and undefined-name handling when a target has **kwargs, and drops the undocumented fg/bg parameter-name inference. See Compatibility notes below.

Compatibility notes

Bare @rgb_dispatch no longer infers fg/bg parameter names

Applying rgb_dispatch with no names previously auto-selected parameters named fg or bg, along with any parameter whose name started with fg_/bg_ or ended with _fg/_bg. This was undocumented shorthand intended for internal use, and no call site in the package relied on it; every internal use passes explicit names. The inference also overrode the bare form's intended meaning, since it would resolve those named parameters instead of targeting positional parameters.

The inference is removed. The bare @rgb_dispatch form now consistently targets all positional-only and variadic positional parameters. Code that relied on the old behavior should name the parameters explicitly:

@rgb_dispatch("fg", "bg")
def f(fg, bg): ...

New features

replace_defaults keyword parameter

rgb_dispatch gains a keyword-only replace_defaults parameter, defaulting to True:

def rgb_dispatch(*names, replace_defaults=True): ...

When True (the default, matching prior behavior), default argument values that are color-name strings are replaced with their RGB tuples on the wrapped callable. Pass replace_defaults=False to leave defaults untouched and only convert arguments supplied at call time:

@rgb_dispatch(replace_defaults=False)
def func(fruit_or_color="orange", /):
    res = "fruit" if isinstance(fruit_or_color, str) else "color"
    return f"{fruit_or_color} is a {res}"

func()          # 'orange is a fruit'   (default left as the string "orange")
func("orange")  # '(255, 165, 0) is a color'

The stub overloads in palette.pyi are updated to accept the new parameter.

Fixes

Color-name defaults on positional-only parameters under the bare form

Under @rgb_dispatch with no names, color-name string defaults on positional-only parameters were never replaced. The bare form recorded its target positions as a single full slice, and default replacement matches positions by integer index, so no default was ever matched. Positional-only indices are now recorded individually, so their string defaults are converted:

@rgb_dispatch
def func(r="red", b="blue", g="green", x="not a color", /):
    return r, g, b, x

func()  # ((255, 0, 0), (0, 128, 0), (0, 0, 255), 'not a color')

Targeted names ignored when the function accepts **kwargs

When a targeted name was not a declared parameter but the wrapped function accepted **kwargs, rgb_dispatch previously ignored it and passed the value through unchanged. Such leftover names are now registered as keyword targets, so a name matched only through variadic keywords is converted:

@rgb_dispatch("color")
def func(**kwargs):
    return kwargs

func(color="red")  # {'color': (255, 0, 0)}

Full Changelog: v0.7.3...v0.7.4