Page MenuHomeSoftware Heritage

D6332.diff
No OneTemporary

D6332.diff

diff --git a/swh/model/tests/test_identifiers.py b/swh/model/tests/test_identifiers.py
--- a/swh/model/tests/test_identifiers.py
+++ b/swh/model/tests/test_identifiers.py
@@ -5,15 +5,12 @@
import datetime
import hashlib
-import itertools
from typing import Dict
import unittest
-import attr
import pytest
from swh.model import git_objects, hashutil
-from swh.model.exceptions import ValidationError
from swh.model.hashutil import hash_to_bytes as _x
from swh.model.model import (
Content,
@@ -26,14 +23,6 @@
Snapshot,
TimestampWithTimezone,
)
-from swh.model.swhids import (
- SWHID_QUALIFIERS,
- CoreSWHID,
- ExtendedObjectType,
- ExtendedSWHID,
- ObjectType,
- QualifiedSWHID,
-)
def remove_id(d: Dict) -> Dict:
@@ -195,8 +184,6 @@
],
}
-dummy_qualifiers = {"origin": "https://example.com", "lines": "42"}
-
class DirectoryIdentifier(unittest.TestCase):
def setUp(self):
@@ -1186,616 +1173,6 @@
}
-# SWHIDs that are outright invalid, no matter the context
-INVALID_SWHIDS = [
- "swh:1:cnt",
- "swh:1:",
- "swh:",
- "swh:1:cnt:",
- "foo:1:cnt:abc8bc9d7a6bcf6db04f476d29314f157507d505",
- "swh:2:dir:def8bc9d7a6bcf6db04f476d29314f157507d505",
- "swh:1:foo:fed8bc9d7a6bcf6db04f476d29314f157507d505",
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;invalid;malformed",
- "swh:1:snp:gh6959356d30f1a4e9b7f6bca59b9a336464c03d",
- "swh:1:snp:foo",
- # wrong qualifier: ori should be origin
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;ori=something;anchor=1;visit=1;path=/", # noqa
- # wrong qualifier: anc should be anchor
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin=something;anc=1;visit=1;path=/", # noqa
- # wrong qualifier: vis should be visit
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin=something;anchor=1;vis=1;path=/", # noqa
- # wrong qualifier: pa should be path
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin=something;anchor=1;visit=1;pa=/", # noqa
- # wrong qualifier: line should be lines
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;line=10;origin=something;anchor=1;visit=1;path=/", # noqa
- # wrong qualifier value: it contains space before of after
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin= https://some-url", # noqa
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin=something;anchor=some-anchor ", # noqa
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin=something;anchor=some-anchor ;visit=1", # noqa
- # invalid swhid: whitespaces
- "swh :1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;ori=something;anchor=1;visit=1;path=/", # noqa
- "swh: 1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;ori=something;anchor=1;visit=1;path=/", # noqa
- "swh: 1: dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;ori=something;anchor=1;visit=1;path=/", # noqa
- "swh:1: dir: 0b6959356d30f1a4e9b7f6bca59b9a336464c03d",
- "swh:1: dir: 0b6959356d30f1a4e9b7f6bca59b9a336464c03d; origin=blah",
- "swh:1: dir: 0b6959356d30f1a4e9b7f6bca59b9a336464c03d;lines=12",
- # other whitespaces
- "swh\t:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;lines=12",
- "swh:1\n:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;lines=12",
- "swh:1:\rdir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;lines=12",
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d\f;lines=12",
- "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;lines=12\v",
-]
-
-SWHID_CLASSES = [CoreSWHID, QualifiedSWHID, ExtendedSWHID]
-
-
-@pytest.mark.parametrize(
- "invalid_swhid,swhid_class", itertools.product(INVALID_SWHIDS, SWHID_CLASSES)
-)
-def test_swhid_parsing_error(invalid_swhid, swhid_class):
- """Tests SWHID strings that are invalid for all SWHID classes do raise
- a ValidationError"""
- with pytest.raises(ValidationError):
- swhid_class.from_string(invalid_swhid)
-
-
-# string SWHIDs, and how they should be parsed by each of the classes,
-# or None if the class does not support it
-HASH = "94a9ed024d3859793618152ea559a168bbcbb5e2"
-VALID_SWHIDS = [
- (
- f"swh:1:cnt:{HASH}",
- CoreSWHID(object_type=ObjectType.CONTENT, object_id=_x(HASH),),
- QualifiedSWHID(object_type=ObjectType.CONTENT, object_id=_x(HASH),),
- ExtendedSWHID(object_type=ExtendedObjectType.CONTENT, object_id=_x(HASH),),
- ),
- (
- f"swh:1:dir:{HASH}",
- CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=_x(HASH),),
- QualifiedSWHID(object_type=ObjectType.DIRECTORY, object_id=_x(HASH),),
- ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=_x(HASH),),
- ),
- (
- f"swh:1:rev:{HASH}",
- CoreSWHID(object_type=ObjectType.REVISION, object_id=_x(HASH),),
- QualifiedSWHID(object_type=ObjectType.REVISION, object_id=_x(HASH),),
- ExtendedSWHID(object_type=ExtendedObjectType.REVISION, object_id=_x(HASH),),
- ),
- (
- f"swh:1:rel:{HASH}",
- CoreSWHID(object_type=ObjectType.RELEASE, object_id=_x(HASH),),
- QualifiedSWHID(object_type=ObjectType.RELEASE, object_id=_x(HASH),),
- ExtendedSWHID(object_type=ExtendedObjectType.RELEASE, object_id=_x(HASH),),
- ),
- (
- f"swh:1:snp:{HASH}",
- CoreSWHID(object_type=ObjectType.SNAPSHOT, object_id=_x(HASH),),
- QualifiedSWHID(object_type=ObjectType.SNAPSHOT, object_id=_x(HASH),),
- ExtendedSWHID(object_type=ExtendedObjectType.SNAPSHOT, object_id=_x(HASH),),
- ),
- (
- f"swh:1:cnt:{HASH};origin=https://github.com/python/cpython;lines=1-18",
- None, # CoreSWHID does not allow qualifiers
- QualifiedSWHID(
- object_type=ObjectType.CONTENT,
- object_id=_x(HASH),
- origin="https://github.com/python/cpython",
- lines=(1, 18),
- ),
- None, # Neither does ExtendedSWHID
- ),
- (
- f"swh:1:cnt:{HASH};origin=https://github.com/python/cpython;lines=1-18/",
- None, # likewise
- None,
- None, # likewise
- ),
- (
- f"swh:1:cnt:{HASH};origin=https://github.com/python/cpython;lines=18",
- None, # likewise
- QualifiedSWHID(
- object_type=ObjectType.CONTENT,
- object_id=_x(HASH),
- origin="https://github.com/python/cpython",
- lines=(18, None),
- ),
- None, # likewise
- ),
- (
- f"swh:1:dir:{HASH};origin=deb://Debian/packages/linuxdoc-tools",
- None, # likewise
- QualifiedSWHID(
- object_type=ObjectType.DIRECTORY,
- object_id=_x(HASH),
- origin="deb://Debian/packages/linuxdoc-tools",
- ),
- None, # likewise
- ),
- (
- f"swh:1:ori:{HASH}",
- None, # CoreSWHID does not allow origin pseudo-SWHIDs
- None, # Neither does QualifiedSWHID
- ExtendedSWHID(object_type=ExtendedObjectType.ORIGIN, object_id=_x(HASH),),
- ),
- (
- f"swh:1:emd:{HASH}",
- None, # likewise for metadata pseudo-SWHIDs
- None, # Neither does QualifiedSWHID
- ExtendedSWHID(
- object_type=ExtendedObjectType.RAW_EXTRINSIC_METADATA, object_id=_x(HASH),
- ),
- ),
- (
- f"swh:1:emd:{HASH};origin=https://github.com/python/cpython",
- None, # CoreSWHID does not allow metadata pseudo-SWHIDs or qualifiers
- None, # QualifiedSWHID does not allow metadata pseudo-SWHIDs
- None, # ExtendedSWHID does not allow qualifiers
- ),
-]
-
-
-@pytest.mark.parametrize(
- "string,core,qualified,extended",
- [
- pytest.param(string, core, qualified, extended, id=string)
- for (string, core, qualified, extended) in VALID_SWHIDS
- ],
-)
-def test_parse_unparse_swhids(string, core, qualified, extended):
- """Tests parsing and serializing valid SWHIDs with the various SWHID classes."""
- classes = [CoreSWHID, QualifiedSWHID, ExtendedSWHID]
- for (cls, parsed_swhid) in zip(classes, [core, qualified, extended]):
- if parsed_swhid is None:
- # This class should not accept this SWHID
- with pytest.raises(ValidationError) as excinfo:
- cls.from_string(string)
- # Check string serialization for exception
- assert str(excinfo.value) is not None
- else:
- # This class should
- assert cls.from_string(string) == parsed_swhid
-
- # Also check serialization
- assert string == str(parsed_swhid)
-
-
-@pytest.mark.parametrize(
- "core,extended",
- [
- pytest.param(core, extended, id=string)
- for (string, core, qualified, extended) in VALID_SWHIDS
- if core is not None
- ],
-)
-def test_core_to_extended(core, extended):
- assert core.to_extended() == extended
-
-
-@pytest.mark.parametrize(
- "ns,version,type,id,qualifiers",
- [
- ("foo", 1, ObjectType.CONTENT, "abc8bc9d7a6bcf6db04f476d29314f157507d505", {}),
- ("swh", 2, ObjectType.CONTENT, "def8bc9d7a6bcf6db04f476d29314f157507d505", {}),
- ("swh", 1, ObjectType.DIRECTORY, "aaaa", {}),
- ],
-)
-def test_QualifiedSWHID_validation_error(ns, version, type, id, qualifiers):
- with pytest.raises(ValidationError):
- QualifiedSWHID(
- namespace=ns,
- scheme_version=version,
- object_type=type,
- object_id=_x(id),
- **qualifiers,
- )
-
-
-@pytest.mark.parametrize(
- "object_type,qualifiers,expected",
- [
- # No qualifier:
- (ObjectType.CONTENT, {}, f"swh:1:cnt:{HASH}"),
- # origin:
- (ObjectType.CONTENT, {"origin": None}, f"swh:1:cnt:{HASH}"),
- (ObjectType.CONTENT, {"origin": 42}, ValueError),
- # visit:
- (
- ObjectType.CONTENT,
- {"visit": f"swh:1:snp:{HASH}"},
- f"swh:1:cnt:{HASH};visit=swh:1:snp:{HASH}",
- ),
- (
- ObjectType.CONTENT,
- {"visit": CoreSWHID(object_type=ObjectType.SNAPSHOT, object_id=_x(HASH))},
- f"swh:1:cnt:{HASH};visit=swh:1:snp:{HASH}",
- ),
- (ObjectType.CONTENT, {"visit": 42}, TypeError),
- (ObjectType.CONTENT, {"visit": f"swh:1:rel:{HASH}"}, ValidationError,),
- (
- ObjectType.CONTENT,
- {"visit": CoreSWHID(object_type=ObjectType.RELEASE, object_id=_x(HASH))},
- ValidationError,
- ),
- # anchor:
- (
- ObjectType.CONTENT,
- {"anchor": f"swh:1:snp:{HASH}"},
- f"swh:1:cnt:{HASH};anchor=swh:1:snp:{HASH}",
- ),
- (
- ObjectType.CONTENT,
- {"anchor": CoreSWHID(object_type=ObjectType.SNAPSHOT, object_id=_x(HASH))},
- f"swh:1:cnt:{HASH};anchor=swh:1:snp:{HASH}",
- ),
- (
- ObjectType.CONTENT,
- {"anchor": f"swh:1:dir:{HASH}"},
- f"swh:1:cnt:{HASH};anchor=swh:1:dir:{HASH}",
- ),
- (
- ObjectType.CONTENT,
- {"anchor": CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=_x(HASH))},
- f"swh:1:cnt:{HASH};anchor=swh:1:dir:{HASH}",
- ),
- (ObjectType.CONTENT, {"anchor": 42}, TypeError),
- (ObjectType.CONTENT, {"anchor": f"swh:1:cnt:{HASH}"}, ValidationError,),
- (
- ObjectType.CONTENT,
- {"anchor": CoreSWHID(object_type=ObjectType.CONTENT, object_id=_x(HASH))},
- ValidationError,
- ),
- # path:
- (ObjectType.CONTENT, {"path": b"/foo"}, f"swh:1:cnt:{HASH};path=/foo",),
- (
- ObjectType.CONTENT,
- {"path": b"/foo;bar"},
- f"swh:1:cnt:{HASH};path=/foo%3Bbar",
- ),
- (ObjectType.CONTENT, {"path": "/foo"}, f"swh:1:cnt:{HASH};path=/foo",),
- (
- ObjectType.CONTENT,
- {"path": "/foo;bar"},
- f"swh:1:cnt:{HASH};path=/foo%3Bbar",
- ),
- (ObjectType.CONTENT, {"path": 42}, Exception),
- # lines:
- (ObjectType.CONTENT, {"lines": (42, None)}, f"swh:1:cnt:{HASH};lines=42",),
- (ObjectType.CONTENT, {"lines": (21, 42)}, f"swh:1:cnt:{HASH};lines=21-42",),
- (ObjectType.CONTENT, {"lines": 42}, TypeError,),
- (ObjectType.CONTENT, {"lines": (None, 42)}, ValueError,),
- (ObjectType.CONTENT, {"lines": ("42", None)}, ValueError,),
- ],
-)
-def test_QualifiedSWHID_init(object_type, qualifiers, expected):
- """Tests validation and converters of qualifiers"""
- if isinstance(expected, type):
- assert issubclass(expected, Exception)
- with pytest.raises(expected):
- QualifiedSWHID(object_type=object_type, object_id=_x(HASH), **qualifiers)
- else:
- assert isinstance(expected, str)
- swhid = QualifiedSWHID(
- object_type=object_type, object_id=_x(HASH), **qualifiers
- )
-
- # Check the build object has the right serialization
- assert expected == str(swhid)
-
- # Check the internal state of the object is the same as if parsed from a string
- assert QualifiedSWHID.from_string(expected) == swhid
-
-
-def test_QualifiedSWHID_hash():
- object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
-
- assert hash(
- QualifiedSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id)
- ) == hash(QualifiedSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id))
-
- assert hash(
- QualifiedSWHID(
- object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
- )
- ) == hash(
- QualifiedSWHID(
- object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
- )
- )
-
- # Different order of the dictionary, so the underlying order of the tuple in
- # ImmutableDict is different.
- assert hash(
- QualifiedSWHID(
- object_type=ObjectType.DIRECTORY,
- object_id=object_id,
- origin="https://example.com",
- lines=(42, None),
- )
- ) == hash(
- QualifiedSWHID(
- object_type=ObjectType.DIRECTORY,
- object_id=object_id,
- lines=(42, None),
- origin="https://example.com",
- )
- )
-
-
-def test_QualifiedSWHID_eq():
- object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
-
- assert QualifiedSWHID(
- object_type=ObjectType.DIRECTORY, object_id=object_id
- ) == QualifiedSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id)
-
- assert QualifiedSWHID(
- object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
- ) == QualifiedSWHID(
- object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
- )
-
- assert QualifiedSWHID(
- object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
- ) == QualifiedSWHID(
- object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
- )
-
-
-QUALIFIED_SWHIDS = [
- # origin:
- (
- f"swh:1:cnt:{HASH};origin=https://github.com/python/cpython",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT,
- object_id=_x(HASH),
- origin="https://github.com/python/cpython",
- ),
- ),
- (
- f"swh:1:cnt:{HASH};origin=https://example.org/foo%3Bbar%25baz",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT,
- object_id=_x(HASH),
- origin="https://example.org/foo%3Bbar%25baz",
- ),
- ),
- (
- f"swh:1:cnt:{HASH};origin=https://example.org?project=test",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT,
- object_id=_x(HASH),
- origin="https://example.org?project=test",
- ),
- ),
- # visit:
- (
- f"swh:1:cnt:{HASH};visit=swh:1:snp:{HASH}",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT,
- object_id=_x(HASH),
- visit=CoreSWHID(object_type=ObjectType.SNAPSHOT, object_id=_x(HASH)),
- ),
- ),
- (f"swh:1:cnt:{HASH};visit=swh:1:rel:{HASH}", None,),
- # anchor:
- (
- f"swh:1:cnt:{HASH};anchor=swh:1:dir:{HASH}",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT,
- object_id=_x(HASH),
- anchor=CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=_x(HASH)),
- ),
- ),
- (
- f"swh:1:cnt:{HASH};anchor=swh:1:rev:{HASH}",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT,
- object_id=_x(HASH),
- anchor=CoreSWHID(object_type=ObjectType.REVISION, object_id=_x(HASH)),
- ),
- ),
- (
- f"swh:1:cnt:{HASH};anchor=swh:1:cnt:{HASH}",
- None, # 'cnt' is not valid in anchor
- ),
- (
- f"swh:1:cnt:{HASH};anchor=swh:1:ori:{HASH}",
- None, # 'ori' is not valid in a CoreSWHID
- ),
- # path:
- (
- f"swh:1:cnt:{HASH};path=/foo",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT, object_id=_x(HASH), path=b"/foo"
- ),
- ),
- (
- f"swh:1:cnt:{HASH};path=/foo%3Bbar",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT, object_id=_x(HASH), path=b"/foo;bar"
- ),
- ),
- (
- f"swh:1:cnt:{HASH};path=/foo%25bar",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT, object_id=_x(HASH), path=b"/foo%bar"
- ),
- ),
- (
- f"swh:1:cnt:{HASH};path=/foo/bar%3Dbaz",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT, object_id=_x(HASH), path=b"/foo/bar=baz"
- ),
- ),
- # lines
- (
- f"swh:1:cnt:{HASH};lines=1-18",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT, object_id=_x(HASH), lines=(1, 18),
- ),
- ),
- (
- f"swh:1:cnt:{HASH};lines=18",
- QualifiedSWHID(
- object_type=ObjectType.CONTENT, object_id=_x(HASH), lines=(18, None),
- ),
- ),
- (f"swh:1:cnt:{HASH};lines=", None,),
- (f"swh:1:cnt:{HASH};lines=aa", None,),
- (f"swh:1:cnt:{HASH};lines=18-aa", None,),
-]
-
-
-@pytest.mark.parametrize("string,parsed", QUALIFIED_SWHIDS)
-def test_QualifiedSWHID_parse_serialize_qualifiers(string, parsed):
- """Tests parsing and serializing valid SWHIDs with the various SWHID classes."""
- if parsed is None:
- with pytest.raises(ValidationError):
- print(repr(QualifiedSWHID.from_string(string)))
- else:
- assert QualifiedSWHID.from_string(string) == parsed
- assert str(parsed) == string
-
-
-def test_QualifiedSWHID_serialize_origin():
- """Checks that semicolon in origins are escaped."""
- string = f"swh:1:cnt:{HASH};origin=https://example.org/foo%3Bbar%25baz"
- swhid = QualifiedSWHID(
- object_type=ObjectType.CONTENT,
- object_id=_x(HASH),
- origin="https://example.org/foo;bar%25baz",
- )
- assert str(swhid) == string
-
-
-def test_QualifiedSWHID_attributes():
- """Checks the set of QualifiedSWHID attributes match the SWHID_QUALIFIERS
- constant."""
-
- assert set(attr.fields_dict(QualifiedSWHID)) == {
- "namespace",
- "scheme_version",
- "object_type",
- "object_id",
- *SWHID_QUALIFIERS,
- }
-
-
-@pytest.mark.parametrize(
- "ns,version,type,id",
- [
- ("foo", 1, ObjectType.CONTENT, "abc8bc9d7a6bcf6db04f476d29314f157507d505"),
- ("swh", 2, ObjectType.CONTENT, "def8bc9d7a6bcf6db04f476d29314f157507d505"),
- ("swh", 1, ObjectType.DIRECTORY, "aaaa"),
- ],
-)
-def test_CoreSWHID_validation_error(ns, version, type, id):
- with pytest.raises(ValidationError):
- CoreSWHID(
- namespace=ns, scheme_version=version, object_type=type, object_id=_x(id),
- )
-
-
-def test_CoreSWHID_hash():
- object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
-
- assert hash(
- CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id)
- ) == hash(CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id))
-
- assert hash(
- CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,)
- ) == hash(CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,))
-
- # Different order of the dictionary, so the underlying order of the tuple in
- # ImmutableDict is different.
- assert hash(
- CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,)
- ) == hash(CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,))
-
-
-def test_CoreSWHID_eq():
- object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
-
- assert CoreSWHID(
- object_type=ObjectType.DIRECTORY, object_id=object_id
- ) == CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id)
-
- assert CoreSWHID(
- object_type=ObjectType.DIRECTORY, object_id=object_id,
- ) == CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,)
-
- assert CoreSWHID(
- object_type=ObjectType.DIRECTORY, object_id=object_id,
- ) == CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,)
-
-
-@pytest.mark.parametrize(
- "ns,version,type,id",
- [
- (
- "foo",
- 1,
- ExtendedObjectType.CONTENT,
- "abc8bc9d7a6bcf6db04f476d29314f157507d505",
- ),
- (
- "swh",
- 2,
- ExtendedObjectType.CONTENT,
- "def8bc9d7a6bcf6db04f476d29314f157507d505",
- ),
- ("swh", 1, ExtendedObjectType.DIRECTORY, "aaaa"),
- ],
-)
-def test_ExtendedSWHID_validation_error(ns, version, type, id):
- with pytest.raises(ValidationError):
- ExtendedSWHID(
- namespace=ns, scheme_version=version, object_type=type, object_id=_x(id),
- )
-
-
-def test_ExtendedSWHID_hash():
- object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
-
- assert hash(
- ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id)
- ) == hash(
- ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id)
- )
-
- assert hash(
- ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
- ) == hash(
- ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
- )
-
- # Different order of the dictionary, so the underlying order of the tuple in
- # ImmutableDict is different.
- assert hash(
- ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
- ) == hash(
- ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
- )
-
-
-def test_ExtendedSWHID_eq():
- object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
-
- assert ExtendedSWHID(
- object_type=ExtendedObjectType.DIRECTORY, object_id=object_id
- ) == ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id)
-
- assert ExtendedSWHID(
- object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,
- ) == ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
-
- assert ExtendedSWHID(
- object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,
- ) == ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
-
-
def test_extid_identifier_bwcompat():
extid_dict = {
"extid_type": "test-type",
@@ -1816,9 +1193,3 @@
ExtID.from_dict({**extid_dict, "extid_version": 1}).id
!= ExtID.from_dict(extid_dict).id
)
-
-
-def test_object_types():
- """Checks ExtendedObjectType is a superset of ObjectType"""
- for member in ObjectType:
- assert getattr(ExtendedObjectType, member.name).value == member.value
diff --git a/swh/model/tests/test_swhids.py b/swh/model/tests/test_swhids.py
new file mode 100644
--- /dev/null
+++ b/swh/model/tests/test_swhids.py
@@ -0,0 +1,638 @@
+# Copyright (C) 2015-2021 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
+import itertools
+
+import attr
+import pytest
+
+from swh.model.exceptions import ValidationError
+from swh.model.hashutil import hash_to_bytes as _x
+from swh.model.swhids import (
+ SWHID_QUALIFIERS,
+ CoreSWHID,
+ ExtendedObjectType,
+ ExtendedSWHID,
+ ObjectType,
+ QualifiedSWHID,
+)
+
+dummy_qualifiers = {"origin": "https://example.com", "lines": "42"}
+
+
+# SWHIDs that are outright invalid, no matter the context
+INVALID_SWHIDS = [
+ "swh:1:cnt",
+ "swh:1:",
+ "swh:",
+ "swh:1:cnt:",
+ "foo:1:cnt:abc8bc9d7a6bcf6db04f476d29314f157507d505",
+ "swh:2:dir:def8bc9d7a6bcf6db04f476d29314f157507d505",
+ "swh:1:foo:fed8bc9d7a6bcf6db04f476d29314f157507d505",
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;invalid;malformed",
+ "swh:1:snp:gh6959356d30f1a4e9b7f6bca59b9a336464c03d",
+ "swh:1:snp:foo",
+ # wrong qualifier: ori should be origin
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;ori=something;anchor=1;visit=1;path=/", # noqa
+ # wrong qualifier: anc should be anchor
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin=something;anc=1;visit=1;path=/", # noqa
+ # wrong qualifier: vis should be visit
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin=something;anchor=1;vis=1;path=/", # noqa
+ # wrong qualifier: pa should be path
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin=something;anchor=1;visit=1;pa=/", # noqa
+ # wrong qualifier: line should be lines
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;line=10;origin=something;anchor=1;visit=1;path=/", # noqa
+ # wrong qualifier value: it contains space before of after
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin= https://some-url", # noqa
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin=something;anchor=some-anchor ", # noqa
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;origin=something;anchor=some-anchor ;visit=1", # noqa
+ # invalid swhid: whitespaces
+ "swh :1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;ori=something;anchor=1;visit=1;path=/", # noqa
+ "swh: 1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;ori=something;anchor=1;visit=1;path=/", # noqa
+ "swh: 1: dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;ori=something;anchor=1;visit=1;path=/", # noqa
+ "swh:1: dir: 0b6959356d30f1a4e9b7f6bca59b9a336464c03d",
+ "swh:1: dir: 0b6959356d30f1a4e9b7f6bca59b9a336464c03d; origin=blah",
+ "swh:1: dir: 0b6959356d30f1a4e9b7f6bca59b9a336464c03d;lines=12",
+ # other whitespaces
+ "swh\t:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;lines=12",
+ "swh:1\n:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;lines=12",
+ "swh:1:\rdir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;lines=12",
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d\f;lines=12",
+ "swh:1:dir:0b6959356d30f1a4e9b7f6bca59b9a336464c03d;lines=12\v",
+]
+
+SWHID_CLASSES = [CoreSWHID, QualifiedSWHID, ExtendedSWHID]
+
+
+@pytest.mark.parametrize(
+ "invalid_swhid,swhid_class", itertools.product(INVALID_SWHIDS, SWHID_CLASSES)
+)
+def test_swhid_parsing_error(invalid_swhid, swhid_class):
+ """Tests SWHID strings that are invalid for all SWHID classes do raise
+ a ValidationError"""
+ with pytest.raises(ValidationError):
+ swhid_class.from_string(invalid_swhid)
+
+
+# string SWHIDs, and how they should be parsed by each of the classes,
+# or None if the class does not support it
+HASH = "94a9ed024d3859793618152ea559a168bbcbb5e2"
+VALID_SWHIDS = [
+ (
+ f"swh:1:cnt:{HASH}",
+ CoreSWHID(object_type=ObjectType.CONTENT, object_id=_x(HASH),),
+ QualifiedSWHID(object_type=ObjectType.CONTENT, object_id=_x(HASH),),
+ ExtendedSWHID(object_type=ExtendedObjectType.CONTENT, object_id=_x(HASH),),
+ ),
+ (
+ f"swh:1:dir:{HASH}",
+ CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=_x(HASH),),
+ QualifiedSWHID(object_type=ObjectType.DIRECTORY, object_id=_x(HASH),),
+ ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=_x(HASH),),
+ ),
+ (
+ f"swh:1:rev:{HASH}",
+ CoreSWHID(object_type=ObjectType.REVISION, object_id=_x(HASH),),
+ QualifiedSWHID(object_type=ObjectType.REVISION, object_id=_x(HASH),),
+ ExtendedSWHID(object_type=ExtendedObjectType.REVISION, object_id=_x(HASH),),
+ ),
+ (
+ f"swh:1:rel:{HASH}",
+ CoreSWHID(object_type=ObjectType.RELEASE, object_id=_x(HASH),),
+ QualifiedSWHID(object_type=ObjectType.RELEASE, object_id=_x(HASH),),
+ ExtendedSWHID(object_type=ExtendedObjectType.RELEASE, object_id=_x(HASH),),
+ ),
+ (
+ f"swh:1:snp:{HASH}",
+ CoreSWHID(object_type=ObjectType.SNAPSHOT, object_id=_x(HASH),),
+ QualifiedSWHID(object_type=ObjectType.SNAPSHOT, object_id=_x(HASH),),
+ ExtendedSWHID(object_type=ExtendedObjectType.SNAPSHOT, object_id=_x(HASH),),
+ ),
+ (
+ f"swh:1:cnt:{HASH};origin=https://github.com/python/cpython;lines=1-18",
+ None, # CoreSWHID does not allow qualifiers
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT,
+ object_id=_x(HASH),
+ origin="https://github.com/python/cpython",
+ lines=(1, 18),
+ ),
+ None, # Neither does ExtendedSWHID
+ ),
+ (
+ f"swh:1:cnt:{HASH};origin=https://github.com/python/cpython;lines=1-18/",
+ None, # likewise
+ None,
+ None, # likewise
+ ),
+ (
+ f"swh:1:cnt:{HASH};origin=https://github.com/python/cpython;lines=18",
+ None, # likewise
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT,
+ object_id=_x(HASH),
+ origin="https://github.com/python/cpython",
+ lines=(18, None),
+ ),
+ None, # likewise
+ ),
+ (
+ f"swh:1:dir:{HASH};origin=deb://Debian/packages/linuxdoc-tools",
+ None, # likewise
+ QualifiedSWHID(
+ object_type=ObjectType.DIRECTORY,
+ object_id=_x(HASH),
+ origin="deb://Debian/packages/linuxdoc-tools",
+ ),
+ None, # likewise
+ ),
+ (
+ f"swh:1:ori:{HASH}",
+ None, # CoreSWHID does not allow origin pseudo-SWHIDs
+ None, # Neither does QualifiedSWHID
+ ExtendedSWHID(object_type=ExtendedObjectType.ORIGIN, object_id=_x(HASH),),
+ ),
+ (
+ f"swh:1:emd:{HASH}",
+ None, # likewise for metadata pseudo-SWHIDs
+ None, # Neither does QualifiedSWHID
+ ExtendedSWHID(
+ object_type=ExtendedObjectType.RAW_EXTRINSIC_METADATA, object_id=_x(HASH),
+ ),
+ ),
+ (
+ f"swh:1:emd:{HASH};origin=https://github.com/python/cpython",
+ None, # CoreSWHID does not allow metadata pseudo-SWHIDs or qualifiers
+ None, # QualifiedSWHID does not allow metadata pseudo-SWHIDs
+ None, # ExtendedSWHID does not allow qualifiers
+ ),
+]
+
+
+@pytest.mark.parametrize(
+ "string,core,qualified,extended",
+ [
+ pytest.param(string, core, qualified, extended, id=string)
+ for (string, core, qualified, extended) in VALID_SWHIDS
+ ],
+)
+def test_parse_unparse_swhids(string, core, qualified, extended):
+ """Tests parsing and serializing valid SWHIDs with the various SWHID classes."""
+ classes = [CoreSWHID, QualifiedSWHID, ExtendedSWHID]
+ for (cls, parsed_swhid) in zip(classes, [core, qualified, extended]):
+ if parsed_swhid is None:
+ # This class should not accept this SWHID
+ with pytest.raises(ValidationError) as excinfo:
+ cls.from_string(string)
+ # Check string serialization for exception
+ assert str(excinfo.value) is not None
+ else:
+ # This class should
+ assert cls.from_string(string) == parsed_swhid
+
+ # Also check serialization
+ assert string == str(parsed_swhid)
+
+
+@pytest.mark.parametrize(
+ "core,extended",
+ [
+ pytest.param(core, extended, id=string)
+ for (string, core, qualified, extended) in VALID_SWHIDS
+ if core is not None
+ ],
+)
+def test_core_to_extended(core, extended):
+ assert core.to_extended() == extended
+
+
+@pytest.mark.parametrize(
+ "ns,version,type,id,qualifiers",
+ [
+ ("foo", 1, ObjectType.CONTENT, "abc8bc9d7a6bcf6db04f476d29314f157507d505", {}),
+ ("swh", 2, ObjectType.CONTENT, "def8bc9d7a6bcf6db04f476d29314f157507d505", {}),
+ ("swh", 1, ObjectType.DIRECTORY, "aaaa", {}),
+ ],
+)
+def test_QualifiedSWHID_validation_error(ns, version, type, id, qualifiers):
+ with pytest.raises(ValidationError):
+ QualifiedSWHID(
+ namespace=ns,
+ scheme_version=version,
+ object_type=type,
+ object_id=_x(id),
+ **qualifiers,
+ )
+
+
+@pytest.mark.parametrize(
+ "object_type,qualifiers,expected",
+ [
+ # No qualifier:
+ (ObjectType.CONTENT, {}, f"swh:1:cnt:{HASH}"),
+ # origin:
+ (ObjectType.CONTENT, {"origin": None}, f"swh:1:cnt:{HASH}"),
+ (ObjectType.CONTENT, {"origin": 42}, ValueError),
+ # visit:
+ (
+ ObjectType.CONTENT,
+ {"visit": f"swh:1:snp:{HASH}"},
+ f"swh:1:cnt:{HASH};visit=swh:1:snp:{HASH}",
+ ),
+ (
+ ObjectType.CONTENT,
+ {"visit": CoreSWHID(object_type=ObjectType.SNAPSHOT, object_id=_x(HASH))},
+ f"swh:1:cnt:{HASH};visit=swh:1:snp:{HASH}",
+ ),
+ (ObjectType.CONTENT, {"visit": 42}, TypeError),
+ (ObjectType.CONTENT, {"visit": f"swh:1:rel:{HASH}"}, ValidationError,),
+ (
+ ObjectType.CONTENT,
+ {"visit": CoreSWHID(object_type=ObjectType.RELEASE, object_id=_x(HASH))},
+ ValidationError,
+ ),
+ # anchor:
+ (
+ ObjectType.CONTENT,
+ {"anchor": f"swh:1:snp:{HASH}"},
+ f"swh:1:cnt:{HASH};anchor=swh:1:snp:{HASH}",
+ ),
+ (
+ ObjectType.CONTENT,
+ {"anchor": CoreSWHID(object_type=ObjectType.SNAPSHOT, object_id=_x(HASH))},
+ f"swh:1:cnt:{HASH};anchor=swh:1:snp:{HASH}",
+ ),
+ (
+ ObjectType.CONTENT,
+ {"anchor": f"swh:1:dir:{HASH}"},
+ f"swh:1:cnt:{HASH};anchor=swh:1:dir:{HASH}",
+ ),
+ (
+ ObjectType.CONTENT,
+ {"anchor": CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=_x(HASH))},
+ f"swh:1:cnt:{HASH};anchor=swh:1:dir:{HASH}",
+ ),
+ (ObjectType.CONTENT, {"anchor": 42}, TypeError),
+ (ObjectType.CONTENT, {"anchor": f"swh:1:cnt:{HASH}"}, ValidationError,),
+ (
+ ObjectType.CONTENT,
+ {"anchor": CoreSWHID(object_type=ObjectType.CONTENT, object_id=_x(HASH))},
+ ValidationError,
+ ),
+ # path:
+ (ObjectType.CONTENT, {"path": b"/foo"}, f"swh:1:cnt:{HASH};path=/foo",),
+ (
+ ObjectType.CONTENT,
+ {"path": b"/foo;bar"},
+ f"swh:1:cnt:{HASH};path=/foo%3Bbar",
+ ),
+ (ObjectType.CONTENT, {"path": "/foo"}, f"swh:1:cnt:{HASH};path=/foo",),
+ (
+ ObjectType.CONTENT,
+ {"path": "/foo;bar"},
+ f"swh:1:cnt:{HASH};path=/foo%3Bbar",
+ ),
+ (ObjectType.CONTENT, {"path": 42}, Exception),
+ # lines:
+ (ObjectType.CONTENT, {"lines": (42, None)}, f"swh:1:cnt:{HASH};lines=42",),
+ (ObjectType.CONTENT, {"lines": (21, 42)}, f"swh:1:cnt:{HASH};lines=21-42",),
+ (ObjectType.CONTENT, {"lines": 42}, TypeError,),
+ (ObjectType.CONTENT, {"lines": (None, 42)}, ValueError,),
+ (ObjectType.CONTENT, {"lines": ("42", None)}, ValueError,),
+ ],
+)
+def test_QualifiedSWHID_init(object_type, qualifiers, expected):
+ """Tests validation and converters of qualifiers"""
+ if isinstance(expected, type):
+ assert issubclass(expected, Exception)
+ with pytest.raises(expected):
+ QualifiedSWHID(object_type=object_type, object_id=_x(HASH), **qualifiers)
+ else:
+ assert isinstance(expected, str)
+ swhid = QualifiedSWHID(
+ object_type=object_type, object_id=_x(HASH), **qualifiers
+ )
+
+ # Check the build object has the right serialization
+ assert expected == str(swhid)
+
+ # Check the internal state of the object is the same as if parsed from a string
+ assert QualifiedSWHID.from_string(expected) == swhid
+
+
+def test_QualifiedSWHID_hash():
+ object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
+
+ assert hash(
+ QualifiedSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id)
+ ) == hash(QualifiedSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id))
+
+ assert hash(
+ QualifiedSWHID(
+ object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
+ )
+ ) == hash(
+ QualifiedSWHID(
+ object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
+ )
+ )
+
+ # Different order of the dictionary, so the underlying order of the tuple in
+ # ImmutableDict is different.
+ assert hash(
+ QualifiedSWHID(
+ object_type=ObjectType.DIRECTORY,
+ object_id=object_id,
+ origin="https://example.com",
+ lines=(42, None),
+ )
+ ) == hash(
+ QualifiedSWHID(
+ object_type=ObjectType.DIRECTORY,
+ object_id=object_id,
+ lines=(42, None),
+ origin="https://example.com",
+ )
+ )
+
+
+def test_QualifiedSWHID_eq():
+ object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
+
+ assert QualifiedSWHID(
+ object_type=ObjectType.DIRECTORY, object_id=object_id
+ ) == QualifiedSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id)
+
+ assert QualifiedSWHID(
+ object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
+ ) == QualifiedSWHID(
+ object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
+ )
+
+ assert QualifiedSWHID(
+ object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
+ ) == QualifiedSWHID(
+ object_type=ObjectType.DIRECTORY, object_id=object_id, **dummy_qualifiers,
+ )
+
+
+QUALIFIED_SWHIDS = [
+ # origin:
+ (
+ f"swh:1:cnt:{HASH};origin=https://github.com/python/cpython",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT,
+ object_id=_x(HASH),
+ origin="https://github.com/python/cpython",
+ ),
+ ),
+ (
+ f"swh:1:cnt:{HASH};origin=https://example.org/foo%3Bbar%25baz",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT,
+ object_id=_x(HASH),
+ origin="https://example.org/foo%3Bbar%25baz",
+ ),
+ ),
+ (
+ f"swh:1:cnt:{HASH};origin=https://example.org?project=test",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT,
+ object_id=_x(HASH),
+ origin="https://example.org?project=test",
+ ),
+ ),
+ # visit:
+ (
+ f"swh:1:cnt:{HASH};visit=swh:1:snp:{HASH}",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT,
+ object_id=_x(HASH),
+ visit=CoreSWHID(object_type=ObjectType.SNAPSHOT, object_id=_x(HASH)),
+ ),
+ ),
+ (f"swh:1:cnt:{HASH};visit=swh:1:rel:{HASH}", None,),
+ # anchor:
+ (
+ f"swh:1:cnt:{HASH};anchor=swh:1:dir:{HASH}",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT,
+ object_id=_x(HASH),
+ anchor=CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=_x(HASH)),
+ ),
+ ),
+ (
+ f"swh:1:cnt:{HASH};anchor=swh:1:rev:{HASH}",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT,
+ object_id=_x(HASH),
+ anchor=CoreSWHID(object_type=ObjectType.REVISION, object_id=_x(HASH)),
+ ),
+ ),
+ (
+ f"swh:1:cnt:{HASH};anchor=swh:1:cnt:{HASH}",
+ None, # 'cnt' is not valid in anchor
+ ),
+ (
+ f"swh:1:cnt:{HASH};anchor=swh:1:ori:{HASH}",
+ None, # 'ori' is not valid in a CoreSWHID
+ ),
+ # path:
+ (
+ f"swh:1:cnt:{HASH};path=/foo",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT, object_id=_x(HASH), path=b"/foo"
+ ),
+ ),
+ (
+ f"swh:1:cnt:{HASH};path=/foo%3Bbar",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT, object_id=_x(HASH), path=b"/foo;bar"
+ ),
+ ),
+ (
+ f"swh:1:cnt:{HASH};path=/foo%25bar",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT, object_id=_x(HASH), path=b"/foo%bar"
+ ),
+ ),
+ (
+ f"swh:1:cnt:{HASH};path=/foo/bar%3Dbaz",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT, object_id=_x(HASH), path=b"/foo/bar=baz"
+ ),
+ ),
+ # lines
+ (
+ f"swh:1:cnt:{HASH};lines=1-18",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT, object_id=_x(HASH), lines=(1, 18),
+ ),
+ ),
+ (
+ f"swh:1:cnt:{HASH};lines=18",
+ QualifiedSWHID(
+ object_type=ObjectType.CONTENT, object_id=_x(HASH), lines=(18, None),
+ ),
+ ),
+ (f"swh:1:cnt:{HASH};lines=", None,),
+ (f"swh:1:cnt:{HASH};lines=aa", None,),
+ (f"swh:1:cnt:{HASH};lines=18-aa", None,),
+]
+
+
+@pytest.mark.parametrize("string,parsed", QUALIFIED_SWHIDS)
+def test_QualifiedSWHID_parse_serialize_qualifiers(string, parsed):
+ """Tests parsing and serializing valid SWHIDs with the various SWHID classes."""
+ if parsed is None:
+ with pytest.raises(ValidationError):
+ print(repr(QualifiedSWHID.from_string(string)))
+ else:
+ assert QualifiedSWHID.from_string(string) == parsed
+ assert str(parsed) == string
+
+
+def test_QualifiedSWHID_serialize_origin():
+ """Checks that semicolon in origins are escaped."""
+ string = f"swh:1:cnt:{HASH};origin=https://example.org/foo%3Bbar%25baz"
+ swhid = QualifiedSWHID(
+ object_type=ObjectType.CONTENT,
+ object_id=_x(HASH),
+ origin="https://example.org/foo;bar%25baz",
+ )
+ assert str(swhid) == string
+
+
+def test_QualifiedSWHID_attributes():
+ """Checks the set of QualifiedSWHID attributes match the SWHID_QUALIFIERS
+ constant."""
+
+ assert set(attr.fields_dict(QualifiedSWHID)) == {
+ "namespace",
+ "scheme_version",
+ "object_type",
+ "object_id",
+ *SWHID_QUALIFIERS,
+ }
+
+
+@pytest.mark.parametrize(
+ "ns,version,type,id",
+ [
+ ("foo", 1, ObjectType.CONTENT, "abc8bc9d7a6bcf6db04f476d29314f157507d505"),
+ ("swh", 2, ObjectType.CONTENT, "def8bc9d7a6bcf6db04f476d29314f157507d505"),
+ ("swh", 1, ObjectType.DIRECTORY, "aaaa"),
+ ],
+)
+def test_CoreSWHID_validation_error(ns, version, type, id):
+ with pytest.raises(ValidationError):
+ CoreSWHID(
+ namespace=ns, scheme_version=version, object_type=type, object_id=_x(id),
+ )
+
+
+def test_CoreSWHID_hash():
+ object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
+
+ assert hash(
+ CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id)
+ ) == hash(CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id))
+
+ assert hash(
+ CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,)
+ ) == hash(CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,))
+
+ # Different order of the dictionary, so the underlying order of the tuple in
+ # ImmutableDict is different.
+ assert hash(
+ CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,)
+ ) == hash(CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,))
+
+
+def test_CoreSWHID_eq():
+ object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
+
+ assert CoreSWHID(
+ object_type=ObjectType.DIRECTORY, object_id=object_id
+ ) == CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id)
+
+ assert CoreSWHID(
+ object_type=ObjectType.DIRECTORY, object_id=object_id,
+ ) == CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,)
+
+ assert CoreSWHID(
+ object_type=ObjectType.DIRECTORY, object_id=object_id,
+ ) == CoreSWHID(object_type=ObjectType.DIRECTORY, object_id=object_id,)
+
+
+@pytest.mark.parametrize(
+ "ns,version,type,id",
+ [
+ (
+ "foo",
+ 1,
+ ExtendedObjectType.CONTENT,
+ "abc8bc9d7a6bcf6db04f476d29314f157507d505",
+ ),
+ (
+ "swh",
+ 2,
+ ExtendedObjectType.CONTENT,
+ "def8bc9d7a6bcf6db04f476d29314f157507d505",
+ ),
+ ("swh", 1, ExtendedObjectType.DIRECTORY, "aaaa"),
+ ],
+)
+def test_ExtendedSWHID_validation_error(ns, version, type, id):
+ with pytest.raises(ValidationError):
+ ExtendedSWHID(
+ namespace=ns, scheme_version=version, object_type=type, object_id=_x(id),
+ )
+
+
+def test_ExtendedSWHID_hash():
+ object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
+
+ assert hash(
+ ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id)
+ ) == hash(
+ ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id)
+ )
+
+ assert hash(
+ ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
+ ) == hash(
+ ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
+ )
+
+ # Different order of the dictionary, so the underlying order of the tuple in
+ # ImmutableDict is different.
+ assert hash(
+ ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
+ ) == hash(
+ ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
+ )
+
+
+def test_ExtendedSWHID_eq():
+ object_id = _x("94a9ed024d3859793618152ea559a168bbcbb5e2")
+
+ assert ExtendedSWHID(
+ object_type=ExtendedObjectType.DIRECTORY, object_id=object_id
+ ) == ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id)
+
+ assert ExtendedSWHID(
+ object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,
+ ) == ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
+
+ assert ExtendedSWHID(
+ object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,
+ ) == ExtendedSWHID(object_type=ExtendedObjectType.DIRECTORY, object_id=object_id,)
+
+
+def test_object_types():
+ """Checks ExtendedObjectType is a superset of ObjectType"""
+ for member in ObjectType:
+ assert getattr(ExtendedObjectType, member.name).value == member.value

File Metadata

Mime Type
text/plain
Expires
Dec 21 2024, 9:52 PM (11 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3223623

Event Timeline