mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-08 08:06:36 +00:00
* ci: mypy ratchet -- keep type-clean modules clean mypy-clean.txt lists the 71 modules under src/ that type-check clean; scripts/check_types.py runs mypy (--follow-imports=silent) on exactly those files and fails on any error or a missing/unsorted/duplicate entry. A new "Type check (mypy ratchet)" CI job runs it with mypy 1.20.2 and pinned stubs; the manual pre-commit mypy hook now runs the same script (a local hook, so mypy sees the installed requirements like CI does). 35 modules were made clean with annotation-only fixes: hints, typing.cast, TYPE_CHECKING imports, implicit-Optional defaults made explicit, and annotations widened (never guards removed) where mypy called a defensive isinstance check unreachable. No runtime behaviour change. mypy.ini: numpy and orjson are treated as Any (follow_imports=skip, also for stubs). numpy 2.3+ stubs use 3.12 `type` statements that mypy won't parse at python_version 3.10, and orjson is optional, so seeing its stubs made the result depend on whether it was installed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: annotate check_types.py's list-form mypy subprocess Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
48 lines
1.6 KiB
Python
48 lines
1.6 KiB
Python
"""Marking plugin-facing core APIs for removal.
|
|
|
|
Plugins live in other repositories, so a method nothing in core calls may
|
|
still be called by a plugin nobody has checked. Such methods get
|
|
``@deprecated`` for one release before they are removed: the first call in a
|
|
process logs a warning naming the method and the release that removes it
|
|
(visible in ``journalctl -u ledmatrix``), and emits a DeprecationWarning for
|
|
tooling.
|
|
"""
|
|
|
|
import functools
|
|
import threading
|
|
import warnings
|
|
from typing import Callable, Optional, TypeVar
|
|
|
|
from src.logging_config import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
F = TypeVar("F", bound=Callable)
|
|
|
|
_warned = set()
|
|
_warned_lock = threading.Lock()
|
|
|
|
|
|
def deprecated(removal: str, alternative: Optional[str] = None) -> Callable[[F], F]:
|
|
"""Decorate a function or method that will be removed in ``removal``."""
|
|
|
|
def decorate(func: F) -> F:
|
|
message = f"{func.__qualname__}() is deprecated and will be removed in LEDMatrix {removal}"
|
|
if alternative:
|
|
message += f"; {alternative}"
|
|
|
|
@functools.wraps(func)
|
|
def wrapper(*args, **kwargs):
|
|
with _warned_lock:
|
|
first = func.__qualname__ not in _warned
|
|
_warned.add(func.__qualname__)
|
|
if first:
|
|
logger.warning(message)
|
|
warnings.warn(message, DeprecationWarning, stacklevel=2)
|
|
return func(*args, **kwargs)
|
|
|
|
wrapper.__deprecated__ = message # type: ignore[attr-defined] # functools' _Wrapped doesn't declare it
|
|
return wrapper # type: ignore[return-value]
|
|
|
|
return decorate
|