Spaces:
Sleeping
Sleeping
| """``ArtifactCachePort`` — port (Protocol) consommé par ``PipelineExecutor``. | |
| Sprint A14-S47 — inversion de dépendance pour le branchement | |
| ``ArtifactStore`` dans le pipeline. | |
| Pourquoi ce Protocol | |
| -------------------- | |
| La couche ``pipeline/`` est plus interne que ``adapters/`` dans la | |
| hiérarchie documentée du rewrite (``domain → formats → evaluation | |
| → pipeline → adapters → app → reports → interfaces``). Importer | |
| depuis ``adapters/`` dans ``pipeline/`` violerait la règle de | |
| dépendance. | |
| On applique l'inversion de dépendance (pattern hexagonal / | |
| ports-and-adapters) : | |
| - ``pipeline/`` définit le **port** ``ArtifactCachePort`` (ce | |
| module) — ce que le pipeline a besoin de consommer. | |
| - ``adapters/storage/artifact_store.ArtifactStore`` (S29) est | |
| l'**adapter** qui satisfait ce port par duck typing. | |
| - Toute autre implémentation tierce (Redis, S3, GCS, ...) qui | |
| implémente ces 5 méthodes est compatible. | |
| Convention duck typing | |
| ---------------------- | |
| ``StoredArtifact`` est aussi exposé comme Protocol minimal pour | |
| éviter d'importer la dataclass concrète depuis ``adapters/``. | |
| Les implémentations réelles fournissent une dataclass plus riche ; | |
| ``pipeline/`` ne consomme que ``stored.artifact`` et | |
| ``stored.artifact.uri``. | |
| """ | |
| from __future__ import annotations | |
| from typing import Protocol, runtime_checkable | |
| from picarones.domain.artifacts import Artifact | |
| class CachedArtifactRef(Protocol): | |
| """Port minimal consommé par ``read_cached_outputs``. | |
| Les implémentations concrètes peuvent porter des champs | |
| supplémentaires (``payload``, ``key``, …) ; ``pipeline/`` | |
| n'utilise que l'``Artifact`` reconstitué. | |
| """ | |
| def artifact(self) -> Artifact: # pragma: no cover — Protocol | |
| ... | |
| class ArtifactCachePort(Protocol): | |
| """Contrat minimal d'un cache d'artefacts consommable par | |
| ``PipelineExecutor`` pour la reprise par hash. | |
| Les méthodes correspondent **exactement** à l'API publique de | |
| ``ArtifactStore`` (S29) — ``ArtifactStore`` est donc compatible | |
| par duck typing sans rien changer. | |
| Pas d'``isinstance(store, ArtifactCachePort)`` requis : Python | |
| type-checke à l'usage (les méthodes manquantes lèvent | |
| ``AttributeError`` au runtime). Le ``@runtime_checkable`` | |
| autorise un test ``isinstance`` côté caller s'il veut une | |
| validation explicite. | |
| """ | |
| def get(self, key: str) -> CachedArtifactRef | None: # pragma: no cover | |
| ... | |
| def put( | |
| self, | |
| key: str, | |
| artifact: Artifact, | |
| payload: bytes | None = None, | |
| ) -> None: # pragma: no cover | |
| ... | |
| def __contains__(self, key: str) -> bool: # pragma: no cover | |
| ... | |
| __all__ = ["ArtifactCachePort", "CachedArtifactRef"] | |