diff --git a/swh/model/model.py b/swh/model/model.py index c919df0d7296afa7485b209b420992489f7f25e6..0170bcaf350579c995f3f39ea36fe7ad55dd9f56 100644 --- a/swh/model/model.py +++ b/swh/model/model.py @@ -382,7 +382,7 @@ def _compute_hash_from_manifest(manifest: bytes) -> Sha1Git: return hashlib.new("sha1", manifest).digest() -class HashableObject(metaclass=ABCMeta): +class BaseHashableModel(BaseModel, metaclass=ABCMeta): """Mixin to automatically compute object identifier hash when the associated model is instantiated.""" @@ -412,14 +412,17 @@ class HashableObject(metaclass=ABCMeta): return self.id def check(self) -> None: - super().check() # type: ignore + super().check() if self.id != self.compute_hash(): raise ValueError("'id' does not match recomputed hash.") -class HashableObjectWithManifest(HashableObject): - """Derived class of HashableObject, for objects that may need to store +HashableObject = BaseHashableModel # deprecated alias + + +class HashableObjectWithManifest(BaseHashableModel): + """Derived class of BaseHashableModel, for objects that may need to store verbatim git objects as ``raw_manifest`` to preserve original hashes.""" __slots__ = () @@ -767,7 +770,7 @@ class TimestampWithTimezone(BaseModel): @attr.s(frozen=True, slots=True, field_transformer=optimize_all_validators) -class Origin(HashableObject, BaseModel): +class Origin(BaseHashableModel): """Represents a software source: a VCS and an URL.""" object_type: Final = "origin" @@ -933,7 +936,7 @@ class SnapshotBranch(BaseModel): @attr.s(frozen=True, slots=True, field_transformer=optimize_all_validators) -class Snapshot(HashableObject, BaseModel): +class Snapshot(BaseHashableModel): """Represents the full state of an origin at a given point in time.""" object_type: Final = "snapshot" @@ -1651,7 +1654,7 @@ def normalize_discovery_date(value: Any) -> datetime.datetime: @attr.s(frozen=True, slots=True, field_transformer=optimize_all_validators) -class RawExtrinsicMetadata(HashableObject, BaseModel): +class RawExtrinsicMetadata(BaseHashableModel): object_type: Final = "raw_extrinsic_metadata" # target object @@ -1897,7 +1900,7 @@ class RawExtrinsicMetadata(HashableObject, BaseModel): @attr.s(frozen=True, slots=True, field_transformer=optimize_all_validators) -class ExtID(HashableObject, BaseModel): +class ExtID(BaseHashableModel): object_type: Final = "extid" extid_type = attr.ib(type=str, validator=generic_type_validator) diff --git a/swh/model/tests/test_model.py b/swh/model/tests/test_model.py index f2adc62941d98bff9752f10f151bbb1ba87c796d..248410f99fcbce422207294493b9993c11a2106e 100644 --- a/swh/model/tests/test_model.py +++ b/swh/model/tests/test_model.py @@ -1509,9 +1509,13 @@ def test_object_type(objtype_and_obj): def test_object_type_is_final(): + checked_classes = set() object_types = set() def check_final(cls): + if cls in checked_classes: + return + checked_classes.add(cls) if hasattr(cls, "object_type"): assert cls.object_type not in object_types object_types.add(cls.object_type)