diff --git a/swh/model/hypothesis_strategies.py b/swh/model/hypothesis_strategies.py --- a/swh/model/hypothesis_strategies.py +++ b/swh/model/hypothesis_strategies.py @@ -28,12 +28,20 @@ ) from .from_disk import DentryPerms -from .identifiers import identifier_to_bytes, snapshot_identifier +from .identifiers import ( + EXTENDED_SWHID_TYPES, + SWHID_TYPES, + CoreSWHID, + ExtendedSWHID, + identifier_to_bytes, + snapshot_identifier, +) from .model import ( BaseContent, Content, Directory, DirectoryEntry, + ExtID, ObjectType, Origin, OriginVisit, @@ -143,6 +151,34 @@ ) +def core_SWHID_d(): + return builds( + dict, + namespace=just("swh"), + scheme_version=just(1), + object_type=sampled_from(SWHID_TYPES), + object_id=sha1_git(), + ) + + +def core_SWHID(): + return core_SWHID_d().map(lambda d: CoreSWHID(**d)) + + +def extended_SWHID_d(): + return builds( + dict, + namespace=just("swh"), + scheme_version=just(1), + object_type=sampled_from(EXTENDED_SWHID_TYPES), + object_id=sha1_git(), + ) + + +def extended_SWHID(): + return extended_SWHID_d().map(lambda d: ExtendedSWHID(**d)) + + def origins_d(): return builds(dict, url=urls()) @@ -290,6 +326,19 @@ return one_of(present_contents(), skipped_contents()) +def extids_d(): + return builds( + dict, + target=extended_SWHID().map(str), + extid_type=sampled_from(["hg", "git", "bzr"]), + extid=sha1(), + ) + + +def extids(): + return extids_d().map(ExtID.from_dict) + + def present_contents_d(): return builds( dict, @@ -424,6 +473,7 @@ ("release", releases), ("revision", revisions), ("directory", directories), + ("extid", extids), ] if split_content: strategies.append(("content", present_contents)) @@ -457,6 +507,7 @@ ("release", releases_d), ("revision", revisions_d), ("directory", directories_d), + ("extid", extids_d), ] if split_content: strategies.append(("content", present_contents_d)) diff --git a/swh/model/model.py b/swh/model/model.py --- a/swh/model/model.py +++ b/swh/model/model.py @@ -39,7 +39,7 @@ pass -KeyType = Union[Dict[str, str], Dict[str, bytes], bytes] +KeyType = Union[Dict[str, str], Dict[str, bytes], Tuple[Union[str, bytes], ...], bytes] """The type returned by BaseModel.unique_key().""" @@ -1093,3 +1093,25 @@ d[swhid_key] = CoreSWHID.from_string(d[swhid_key]) return super().from_dict(d) + + +@attr.s(frozen=True, slots=True) +class ExtID(BaseModel): + object_type: Final = "extid" + + extid = attr.ib(type=bytes, validator=type_validator()) + extid_type = attr.ib(type=str, validator=type_validator()) + target = attr.ib(type=ExtendedSWHID, validator=type_validator()) + + @classmethod + def from_dict(cls, d): + return super().from_dict( + dict( + extid=d["extid"], + extid_type=d["extid_type"], + target=ExtendedSWHID.from_string(d["target"]), + ) + ) + + def unique_key(self) -> KeyType: + return attr.astuple(self) diff --git a/swh/model/tests/test_hypothesis_strategies.py b/swh/model/tests/test_hypothesis_strategies.py --- a/swh/model/tests/test_hypothesis_strategies.py +++ b/swh/model/tests/test_hypothesis_strategies.py @@ -32,6 +32,7 @@ "revision", "directory", "content", + "extid", ) diff --git a/swh/model/tests/test_model.py b/swh/model/tests/test_model.py --- a/swh/model/tests/test_model.py +++ b/swh/model/tests/test_model.py @@ -1119,3 +1119,18 @@ ), **_common_metadata_fields, ) + + +@given(strategies.extids()) +def test_extid(extid): + assert extid + assert extid.unique_key() + assert extid.target.object_type.value in ( + "cnt", + "dir", + "rev", + "rel", + "snp", + "ori", + "emd", + )