refactor: enforce stricter type hints (#91)

LSP was screaming at me so I decided to just address it to get it off my
screen.

+ Fixed the type hints
:= Modified and added type hints for certain functions and variables in
most of the files in the utils/ folder (and some in the subcommands/
folder) for clarity and so pyright's type checker wouldn't cry.
:+ To resolve certain type issues, I had to add a bit more tiny
additional code such as, additional checks if a variable is None, a tiny
class in utils/material/generator.py to resolve the constructor usage
mismatch between what the DynamicScheme accepts and what the code
actually passes, and etc.
- Renamed certain functions and variables for clarity and also for some
to not collide with pre-existing definitions from well-known library
imports.
+ PIL has reorganized their code a bit, so the code is made to reflect
their new definitions.
= Reorganized the single import statement for "colourfulness" in
utils/wallpaper.py to be close to the top.
(I think that's it)

Side Effects?:
Everything should work the same as no logic change was done whatsover
(unless we consider the added if statements for type checking as a logic
change). I've tested it, everything seems to be in urdir.
This commit is contained in:
Kalagmitan
2026-03-15 19:56:05 +08:00
committed by GitHub
parent c930bd2604
commit b00c601d0a
12 changed files with 160 additions and 131 deletions
+25 -17
View File
@@ -11,6 +11,14 @@ from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant
from materialyoucolor.utils.math_utils import difference_degrees, rotation_direction, sanitize_degrees_double
from typing import Protocol, Any
# The base DynamicScheme class requires a 'variant' argument, but the specific
# subclasses in get_scheme() handle that internally. This Protocol tells the type
# checker to expect our specific 3-argument setup instead of the base class signature.
class SchemeConstructor(Protocol):
def __call__(self, source_color_hct: Any, is_dark: bool, contrast_level: float) -> DynamicScheme: ...
try:
from materialyoucolor.dynamiccolor.dynamic_scheme import DynamicScheme
@@ -147,7 +155,7 @@ def darken(colour: Hct, amount: float) -> Hct:
return Hct.from_hct(colour.hue, colour.chroma - diff / 5, colour.tone - diff)
def get_scheme(scheme: str) -> DynamicScheme:
def get_scheme(scheme: str) -> SchemeConstructor:
if scheme == "content":
return SchemeContent
if scheme == "expressive":
@@ -168,12 +176,12 @@ def get_scheme(scheme: str) -> DynamicScheme:
def gen_scheme(scheme, primary: Hct) -> dict[str, str]:
light = scheme.mode == "light"
is_light = scheme.mode == "light"
colours = {}
# Material colours
primary_scheme = get_scheme(scheme.variant)(primary, not light, 0)
primary_scheme = get_scheme(scheme.variant)(source_color_hct=primary, is_dark=not is_light, contrast_level=0.0)
if hasattr(MaterialDynamicColors, "all_colors"): # materialyoucolor-python >= 3.0.0
dyn_colours = MaterialDynamicColors()
for colour in dyn_colours.all_colors:
@@ -191,28 +199,28 @@ def gen_scheme(scheme, primary: Hct) -> dict[str, str]:
colours["neutral_variant_paletteKeyColor"] = colours["neutralVariantPaletteKeyColor"]
# Harmonize terminal colours
for i, hct in enumerate(light_gruvbox if light else dark_gruvbox):
for i, hct in enumerate(light_gruvbox if is_light else dark_gruvbox):
if scheme.variant == "monochrome":
colours[f"term{i}"] = grayscale(hct, light)
colours[f"term{i}"] = grayscale(hct, is_light)
else:
colours[f"term{i}"] = harmonize(
hct, colours["primary_paletteKeyColor"], (0.35 if i < 8 else 0.2) * (-1 if light else 1)
hct, colours["primary_paletteKeyColor"], (0.35 if i < 8 else 0.2) * (-1 if is_light else 1)
)
# Harmonize named colours
for i, hct in enumerate(light_catppuccin if light else dark_catppuccin):
for i, hct in enumerate(light_catppuccin if is_light else dark_catppuccin):
if scheme.variant == "monochrome":
colours[colour_names[i]] = grayscale(hct, light)
colours[colour_names[i]] = grayscale(hct, is_light)
else:
colours[colour_names[i]] = harmonize(hct, colours["primary_paletteKeyColor"], (-0.2 if light else 0.05))
colours[colour_names[i]] = harmonize(hct, colours["primary_paletteKeyColor"], (-0.2 if is_light else 0.05))
# KColours
for colour in kcolours:
colours[colour["name"]] = harmonize(colour["hct"], colours["primary"], 0.1)
colours[f"{colour['name']}Selection"] = harmonize(colour["hct"], colours["onPrimaryFixedVariant"], 0.1)
if scheme.variant == "monochrome":
colours[colour["name"]] = grayscale(colours[colour["name"]], light)
colours[f"{colour['name']}Selection"] = grayscale(colours[f"{colour['name']}Selection"], light)
colours[colour["name"]] = grayscale(colours[colour["name"]], is_light)
colours[f"{colour['name']}Selection"] = grayscale(colours[f"{colour['name']}Selection"], is_light)
if scheme.variant == "neutral":
for name, hct in colours.items():
@@ -221,8 +229,8 @@ def gen_scheme(scheme, primary: Hct) -> dict[str, str]:
# Darken surfaces for hard flavour
if scheme.flavour == "hard":
for colour in "background", *(k for k in colours.keys() if k.startswith("surface")):
colours[colour] = lighten(colours[colour], 0.4) if light else darken(colours[colour], 0.8)
colours["term0"] = lighten(colours["term0"], 0.4) if light else darken(colours["term0"], 0.9)
colours[colour] = lighten(colours[colour], 0.4) if is_light else darken(colours[colour], 0.8)
colours["term0"] = lighten(colours["term0"], 0.4) if is_light else darken(colours["term0"], 0.9)
# FIXME: deprecated stuff
colours["text"] = colours["onBackground"]
@@ -241,13 +249,13 @@ def gen_scheme(scheme, primary: Hct) -> dict[str, str]:
# More darkening if hard flavour
if scheme.flavour == "hard":
for colour in "base", "mantle", "crust":
colours[colour] = lighten(colours[colour], 0.4) if light else darken(colours[colour], 0.9)
colours[colour] = lighten(colours[colour], 0.4) if is_light else darken(colours[colour], 0.9)
for i in range(3):
colours[f"overlay{i}"] = (
lighten(colours[f"overlay{i}"], 0.4) if light else darken(colours[f"overlay{i}"], 0.8)
lighten(colours[f"overlay{i}"], 0.4) if is_light else darken(colours[f"overlay{i}"], 0.8)
)
colours[f"surface{i}"] = (
lighten(colours[f"surface{i}"], 0.4) if light else darken(colours[f"surface{i}"], 0.8)
lighten(colours[f"surface{i}"], 0.4) if is_light else darken(colours[f"surface{i}"], 0.8)
)
# For debugging
@@ -256,7 +264,7 @@ def gen_scheme(scheme, primary: Hct) -> dict[str, str]:
colours = {k: hex(v.to_int())[4:] for k, v in colours.items()}
# Extended material
if light:
if is_light:
colours["success"] = "4F6354"
colours["onSuccess"] = "FFFFFF"
colours["successContainer"] = "D1E8D5"