943acbc573
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é.
86 lines
2.9 KiB
Python
86 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Mapping
|
|
import functools
|
|
from pathlib import Path
|
|
from typing import Any
|
|
import warnings
|
|
|
|
import pluggy
|
|
|
|
from ..compat import LEGACY_PATH
|
|
from ..compat import legacy_path
|
|
from ..deprecated import HOOK_LEGACY_PATH_ARG
|
|
|
|
|
|
# hookname: (Path, LEGACY_PATH)
|
|
imply_paths_hooks: Mapping[str, tuple[str, str]] = {
|
|
"pytest_ignore_collect": ("collection_path", "path"),
|
|
"pytest_collect_file": ("file_path", "path"),
|
|
"pytest_pycollect_makemodule": ("module_path", "path"),
|
|
"pytest_report_header": ("start_path", "startdir"),
|
|
"pytest_report_collectionfinish": ("start_path", "startdir"),
|
|
}
|
|
|
|
|
|
def _check_path(path: Path, fspath: LEGACY_PATH) -> None:
|
|
if Path(fspath) != path:
|
|
raise ValueError(
|
|
f"Path({fspath!r}) != {path!r}\n"
|
|
"if both path and fspath are given they need to be equal"
|
|
)
|
|
|
|
|
|
class PathAwareHookProxy:
|
|
"""
|
|
this helper wraps around hook callers
|
|
until pluggy supports fixingcalls, this one will do
|
|
|
|
it currently doesn't return full hook caller proxies for fixed hooks,
|
|
this may have to be changed later depending on bugs
|
|
"""
|
|
|
|
def __init__(self, hook_relay: pluggy.HookRelay) -> None:
|
|
self._hook_relay = hook_relay
|
|
|
|
def __dir__(self) -> list[str]:
|
|
return dir(self._hook_relay)
|
|
|
|
def __getattr__(self, key: str) -> pluggy.HookCaller:
|
|
hook: pluggy.HookCaller = getattr(self._hook_relay, key)
|
|
if key not in imply_paths_hooks:
|
|
self.__dict__[key] = hook
|
|
return hook
|
|
else:
|
|
path_var, fspath_var = imply_paths_hooks[key]
|
|
|
|
@functools.wraps(hook)
|
|
def fixed_hook(**kw: Any) -> Any:
|
|
path_value: Path | None = kw.pop(path_var, None)
|
|
fspath_value: LEGACY_PATH | None = kw.pop(fspath_var, None)
|
|
if fspath_value is not None:
|
|
warnings.warn(
|
|
HOOK_LEGACY_PATH_ARG.format(
|
|
pylib_path_arg=fspath_var, pathlib_path_arg=path_var
|
|
),
|
|
stacklevel=2,
|
|
)
|
|
if path_value is not None:
|
|
if fspath_value is not None:
|
|
_check_path(path_value, fspath_value)
|
|
else:
|
|
fspath_value = legacy_path(path_value)
|
|
else:
|
|
assert fspath_value is not None
|
|
path_value = Path(fspath_value)
|
|
|
|
kw[path_var] = path_value
|
|
kw[fspath_var] = fspath_value
|
|
return hook(**kw)
|
|
|
|
fixed_hook.name = hook.name # type: ignore[attr-defined]
|
|
fixed_hook.spec = hook.spec # type: ignore[attr-defined]
|
|
fixed_hook.__name__ = key
|
|
self.__dict__[key] = fixed_hook
|
|
return fixed_hook # type: ignore[return-value]
|