feat: referentiel projets dynamique + validation nommage by design
Durcit la convention de nommage des projets (dérive constatée : 'Sliding Automation', 'code_versioning'... au lieu des formes canoniques). - trilium_api.py : projets_canoniques() lit le référentiel = valeurs du label projet sur les notes de type=projet (source unique, pas de constante en dur). Note-projet CodeVersioning créée (manquait). - mcp_server.py : _valider_projet() branché dans les 6 tools de création (add_decision/history/backlog, new_conversation, create_entite, add_skill). Refuse un projet non canonique (suggestion si faute) ou inconnu (renvoi au processus de création de projet). Ne verrouille pas si référentiel illisible. - lint_audit.py : VAL-nommage aligné sur le référentiel (attrape casse, espace ET snake_case ; l'ancien 'contient un espace' ratait code_versioning). - Données : 79 notes ré-étiquetées vers les 3 formes canoniques. Quality by design : l'erreur de nommage devient impossible à l'écriture, le Lint n'est plus que le filet de sécurité.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import warnings
|
||||
|
||||
from . import __version__
|
||||
|
||||
|
||||
def deprecate(
|
||||
deprecated: str,
|
||||
when: int | None,
|
||||
replacement: str | None = None,
|
||||
*,
|
||||
action: str | None = None,
|
||||
plural: bool = False,
|
||||
stacklevel: int = 3,
|
||||
) -> None:
|
||||
"""
|
||||
Deprecations helper.
|
||||
|
||||
:param deprecated: Name of thing to be deprecated.
|
||||
:param when: Pillow major version to be removed in.
|
||||
:param replacement: Name of replacement.
|
||||
:param action: Instead of "replacement", give a custom call to action
|
||||
e.g. "Upgrade to new thing".
|
||||
:param plural: if the deprecated thing is plural, needing "are" instead of "is".
|
||||
|
||||
Usually of the form:
|
||||
|
||||
"[deprecated] is deprecated and will be removed in Pillow [when] (yyyy-mm-dd).
|
||||
Use [replacement] instead."
|
||||
|
||||
You can leave out the replacement sentence:
|
||||
|
||||
"[deprecated] is deprecated and will be removed in Pillow [when] (yyyy-mm-dd)"
|
||||
|
||||
Or with another call to action:
|
||||
|
||||
"[deprecated] is deprecated and will be removed in Pillow [when] (yyyy-mm-dd).
|
||||
[action]."
|
||||
"""
|
||||
|
||||
is_ = "are" if plural else "is"
|
||||
|
||||
if when is None:
|
||||
removed = "a future version"
|
||||
elif when <= int(__version__.split(".")[0]):
|
||||
msg = f"{deprecated} {is_} deprecated and should be removed."
|
||||
raise RuntimeError(msg)
|
||||
elif when == 12:
|
||||
removed = "Pillow 12 (2025-10-15)"
|
||||
elif when == 13:
|
||||
removed = "Pillow 13 (2026-10-15)"
|
||||
else:
|
||||
msg = f"Unknown removal version: {when}. Update {__name__}?"
|
||||
raise ValueError(msg)
|
||||
|
||||
if replacement and action:
|
||||
msg = "Use only one of 'replacement' and 'action'"
|
||||
raise ValueError(msg)
|
||||
|
||||
if replacement:
|
||||
action = f". Use {replacement} instead."
|
||||
elif action:
|
||||
action = f". {action.rstrip('.')}."
|
||||
else:
|
||||
action = ""
|
||||
|
||||
warnings.warn(
|
||||
f"{deprecated} {is_} deprecated and will be removed in {removed}{action}",
|
||||
DeprecationWarning,
|
||||
stacklevel=stacklevel,
|
||||
)
|
||||
Reference in New Issue
Block a user