From e87a4a7f23dcca196a8dbf922593e92f1dfd2206 Mon Sep 17 00:00:00 2001 From: Vivid Date: Thu, 21 May 2026 13:14:37 +0000 Subject: [PATCH 1/2] Add type stub for colour package --- stubs/colour/@tests/stubtest_allowlist.txt | 1 + stubs/colour/METADATA.toml | 2 + stubs/colour/colour.pyi | 98 ++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 stubs/colour/@tests/stubtest_allowlist.txt create mode 100644 stubs/colour/METADATA.toml create mode 100644 stubs/colour/colour.pyi diff --git a/stubs/colour/@tests/stubtest_allowlist.txt b/stubs/colour/@tests/stubtest_allowlist.txt new file mode 100644 index 000000000000..3de0f7e02e80 --- /dev/null +++ b/stubs/colour/@tests/stubtest_allowlist.txt @@ -0,0 +1 @@ +colour.Color.set_hex_l diff --git a/stubs/colour/METADATA.toml b/stubs/colour/METADATA.toml new file mode 100644 index 000000000000..bd433d77c277 --- /dev/null +++ b/stubs/colour/METADATA.toml @@ -0,0 +1,2 @@ +version = "0.1.5" +upstream-repository = "https://github.com/vaab/colour" diff --git a/stubs/colour/colour.pyi b/stubs/colour/colour.pyi new file mode 100644 index 000000000000..4670b42b3d30 --- /dev/null +++ b/stubs/colour/colour.pyi @@ -0,0 +1,98 @@ +import re +from collections.abc import Callable, Generator, Hashable +from typing import Any, overload +from typing_extensions import Self + +FLOAT_ERROR: float = 0.0000005 + +RGB_TO_COLOR_NAMES: dict[tuple[int, int, int], list[str]] + +COLOR_NAME_TO_RGB: dict[list[str], tuple[int, int, int]] + +LONG_HEX_COLOR: re.Pattern[str] +SHORT_HEX_COLOR: re.Pattern[str] + +class C_HSL: + def __getattr__(self, value: str) -> tuple[float, float, float]: ... + +class C_RGB: + def __getattr__(self, value: str) -> tuple[float, float, float]: ... + +class C_HEX: + def __getattr__(self, value: str) -> str: ... + +HSL: C_HSL +RGB: C_RGB +HEX: C_HEX + +def hsl2rgb(hsl: tuple[float, float, float]) -> tuple[float, float, float]: ... +def rgb2hsl(rgb: tuple[float, float, float]) -> tuple[float, float, float]: ... +def _hue2rgb(v1: float, v2: float, vH: float) -> float: ... +def rgb2hex(rgb: tuple[float, float, float], force_long: bool = False) -> str: ... +def hex2rgb(str_rgb: str) -> tuple[float, float, float]: ... +def hex2web(hex: str) -> str: ... +def web2hex(web: str, force_long: bool = False) -> str: ... + +hsl2hex: Callable[[tuple[float, float, float]], str] +hex2hsl: Callable[[str], tuple[float, float, float]] +rgb2web: Callable[[tuple[float, float, float]], str] +web2rgb: Callable[[str], tuple[float, float, float]] +web2hsl: Callable[[str], tuple[float, float, float]] +hsl2web: Callable[[tuple[float, float, float]], str] + +def color_scale( + begin_hsl: tuple[float, float, float], end_hsl: tuple[float, float, float], nb: int +) -> tuple[float, float, float]: ... +def RGB_color_picker(obj: Any) -> Color: ... + +@overload +def hash_or_str(obj: Hashable) -> int: ... +@overload +def hash_or_str(obj: object) -> str: ... # type: ignore[overload-cannot-match] + +class Color: + def __init__( + self, + color: Self | str | None = None, + pick_for: object | None = None, + picker: Callable[[object], Color] = ..., + pick_key: Callable[[object], int | str] = ..., + **kwargs: Any, + ) -> None: ... + def __getattr__(self, label: str) -> Any: ... + def __setattr__(self, label: str, value: Any) -> None: ... + def get_hsl(self) -> tuple[float, float, float]: ... + def get_hex(self) -> str: ... + def get_hex_l(self) -> str: ... + def get_rgb(self) -> tuple[float, float, float]: ... + def get_hue(self) -> float: ... + def get_saturation(self) -> float: ... + def get_luminance(self) -> float: ... + def get_red(self) -> float: ... + def get_green(self) -> float: ... + def get_blue(self) -> float: ... + def get_web(self) -> str: ... + def set_hsl(self, value: float) -> None: ... + def set_rgb(self, value: float) -> None: ... + def set_hue(self, value: float) -> None: ... + def set_saturation(self, value: float) -> None: ... + def set_luminance(self, value: float) -> None: ... + def set_red(self, value: float) -> None: ... + def set_green(self, value: float) -> None: ... + def set_blue(self, value: float) -> None: ... + def set_hex(self, value: str) -> None: ... + + set_hex_l: Callable[[str], None] = ... + + def set_web(self, value: str) -> None: ... + def range_to(self, value: str | Color | None, steps: int) -> Generator[Color]: ... + def __eq__(self, other: object) -> bool | type[NotImplemented]: ... # type: ignore[override, valid-type] # pyright: ignore[reportInvalidTypeForm] + +RGB_equivalence: Callable[[Color, Color], bool] +HSL_equivalence: Callable[[Color, Color], bool] + +def make_color_factory( + **kwargs_defaults: Any, +) -> Callable[ + [Color | str | None, object | None, Callable[[object], Color], object | None, Callable[[object], int | str]], Color +]: ... From 3c03e51e29de22432dc948c37d5160fdb2f93449 Mon Sep 17 00:00:00 2001 From: Vivid Date: Tue, 26 May 2026 21:50:46 +0000 Subject: [PATCH 2/2] Use Final --- stubs/colour/colour.pyi | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/stubs/colour/colour.pyi b/stubs/colour/colour.pyi index 4670b42b3d30..0a19cacafc43 100644 --- a/stubs/colour/colour.pyi +++ b/stubs/colour/colour.pyi @@ -1,29 +1,32 @@ import re from collections.abc import Callable, Generator, Hashable -from typing import Any, overload +from typing import Any, Final, final, overload from typing_extensions import Self -FLOAT_ERROR: float = 0.0000005 +FLOAT_ERROR: Final[float] = 0.0000005 -RGB_TO_COLOR_NAMES: dict[tuple[int, int, int], list[str]] +RGB_TO_COLOR_NAMES: Final[dict[tuple[int, int, int], list[str]]] -COLOR_NAME_TO_RGB: dict[list[str], tuple[int, int, int]] +COLOR_NAME_TO_RGB: Final[dict[list[str], tuple[int, int, int]]] -LONG_HEX_COLOR: re.Pattern[str] -SHORT_HEX_COLOR: re.Pattern[str] +LONG_HEX_COLOR: Final[re.Pattern[str]] +SHORT_HEX_COLOR: Final[re.Pattern[str]] +@final class C_HSL: def __getattr__(self, value: str) -> tuple[float, float, float]: ... +@final class C_RGB: def __getattr__(self, value: str) -> tuple[float, float, float]: ... +@final class C_HEX: def __getattr__(self, value: str) -> str: ... -HSL: C_HSL -RGB: C_RGB -HEX: C_HEX +HSL: Final[C_HSL] +RGB: Final[C_RGB] +HEX: Final[C_HEX] def hsl2rgb(hsl: tuple[float, float, float]) -> tuple[float, float, float]: ... def rgb2hsl(rgb: tuple[float, float, float]) -> tuple[float, float, float]: ... @@ -33,12 +36,12 @@ def hex2rgb(str_rgb: str) -> tuple[float, float, float]: ... def hex2web(hex: str) -> str: ... def web2hex(web: str, force_long: bool = False) -> str: ... -hsl2hex: Callable[[tuple[float, float, float]], str] -hex2hsl: Callable[[str], tuple[float, float, float]] -rgb2web: Callable[[tuple[float, float, float]], str] -web2rgb: Callable[[str], tuple[float, float, float]] -web2hsl: Callable[[str], tuple[float, float, float]] -hsl2web: Callable[[tuple[float, float, float]], str] +hsl2hex: Final[Callable[[tuple[float, float, float]], str]] +hex2hsl: Final[Callable[[str], tuple[float, float, float]]] +rgb2web: Final[Callable[[tuple[float, float, float]], str]] +web2rgb: Final[Callable[[str], tuple[float, float, float]]] +web2hsl: Final[Callable[[str], tuple[float, float, float]]] +hsl2web: Final[Callable[[tuple[float, float, float]], str]] def color_scale( begin_hsl: tuple[float, float, float], end_hsl: tuple[float, float, float], nb: int @@ -82,14 +85,14 @@ class Color: def set_blue(self, value: float) -> None: ... def set_hex(self, value: str) -> None: ... - set_hex_l: Callable[[str], None] = ... + set_hex_l: Final[Callable[[str], None]] = ... def set_web(self, value: str) -> None: ... def range_to(self, value: str | Color | None, steps: int) -> Generator[Color]: ... def __eq__(self, other: object) -> bool | type[NotImplemented]: ... # type: ignore[override, valid-type] # pyright: ignore[reportInvalidTypeForm] -RGB_equivalence: Callable[[Color, Color], bool] -HSL_equivalence: Callable[[Color, Color], bool] +RGB_equivalence: Final[Callable[[Color, Color], bool]] +HSL_equivalence: Final[Callable[[Color, Color], bool]] def make_color_factory( **kwargs_defaults: Any,