v0.7.4
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