Changeset View
Standalone View
swh/model/identifiers.py
Show First 20 Lines • Show All 722 Lines • ▼ Show 20 Lines | class SWHID: | ||||
metadata = attr.ib( | metadata = attr.ib( | ||||
type=ImmutableDict[str, Any], converter=ImmutableDict, default=ImmutableDict() | type=ImmutableDict[str, Any], converter=ImmutableDict, default=ImmutableDict() | ||||
) | ) | ||||
@namespace.validator | @namespace.validator | ||||
def check_namespace(self, attribute, value): | def check_namespace(self, attribute, value): | ||||
if value != SWHID_NAMESPACE: | if value != SWHID_NAMESPACE: | ||||
raise ValidationError( | raise ValidationError( | ||||
"Wrong format: only supported namespace is '%s'" % SWHID_NAMESPACE | f"Invalid SWHID: namespace is '{value}' but must be '{SWHID_NAMESPACE}'" | ||||
zack: better: "Invalid SWHID: namespace is '{value}' but must be '{SWHID_NAMESPACE}'"
(note how this… | |||||
) | ) | ||||
@scheme_version.validator | @scheme_version.validator | ||||
def check_scheme_version(self, attribute, value): | def check_scheme_version(self, attribute, value): | ||||
if value != SWHID_VERSION: | if value != SWHID_VERSION: | ||||
raise ValidationError( | raise ValidationError( | ||||
"Wrong format: only supported version is %d" % SWHID_VERSION | f"Invalid SWHID: version is {value} but must be {SWHID_VERSION}" | ||||
) | ) | ||||
Not Done Inline Actions"Invalid SWHID: version is {value} but must be {SWHID_VERSION}" zack: "Invalid SWHID: version is {value} but must be {SWHID_VERSION}" | |||||
@object_type.validator | @object_type.validator | ||||
def check_object_type(self, attribute, value): | def check_object_type(self, attribute, value): | ||||
if value not in _object_type_map: | if value not in _object_type_map: | ||||
supported_types = ", ".join(_object_type_map.keys()) | |||||
raise ValidationError( | raise ValidationError( | ||||
"Wrong input: Supported types are %s" % (list(_object_type_map.keys())) | f"Invalid SWHID: object type is {value} but must be " | ||||
Not Done Inline Actionsoops, this should be "one of" (you inherited my own typo, sorry :)) zack: oops, this should be "one of" (you inherited my own typo, sorry :)) | |||||
Done Inline Actionsyes, indeed (and the sun on my screen did not help ;) ardumont: yes, indeed (and the sun on my screen did not help ;) | |||||
f"one of {supported_types}" | |||||
) | ) | ||||
Done Inline Actions"Invalid SWHID: object type is {value} but must be one {supported_types}" (you can also move the join inside the {} and avoid an extra variable, but that's a minor detail) zack: "Invalid SWHID: object type is {value} but must be one {supported_types}"
(you can also move… | |||||
Done Inline Actionsthe intermediary variable is really for readable purpose, to avoid plenty of nested {}(). ardumont: the intermediary variable is really for readable purpose, to avoid plenty of nested {}(). | |||||
@object_id.validator | @object_id.validator | ||||
def check_object_id(self, attribute, value): | def check_object_id(self, attribute, value): | ||||
validate_sha1(value) # can raise if invalid hash | validate_sha1(value) # can raise if invalid hash | ||||
def to_dict(self) -> Dict[str, Any]: | def to_dict(self) -> Dict[str, Any]: | ||||
return attr.asdict(self) | return attr.asdict(self) | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | Returns: | ||||
a named tuple holding the parsing result | a named tuple holding the parsing result | ||||
""" | """ | ||||
# <swhid>;<contextual-information> | # <swhid>;<contextual-information> | ||||
swhid_parts = swhid.split(SWHID_CTXT_SEP) | swhid_parts = swhid.split(SWHID_CTXT_SEP) | ||||
swhid_data = swhid_parts.pop(0).split(":") | swhid_data = swhid_parts.pop(0).split(":") | ||||
if len(swhid_data) != 4: | if len(swhid_data) != 4: | ||||
raise ValidationError("Wrong format: There should be 4 mandatory values") | raise ValidationError( | ||||
Not Done Inline ActionsDuplicating the EBNF grammar here is a DRY violation, given it's already under docs/ and if you put it here too there will be two places to be changed in case of evolution. But aside from that, I think a meaningful error for users here could be much simpler, as they just need (here) to know there should be 4 values. So how about: "Invalid SWHID, format must be 'swh:1:OBJECT_TYPE:OBJECT_ID'". I think that would convey anything the user needs to know. zack: Duplicating the EBNF grammar here is a DRY violation, given it's already under docs/ and if you… | |||||
Done Inline Actionsyes, indeed. If we relax a bit the exhaustivness, your proposal is quite fine, thanks. ardumont: yes, indeed.
I did not see a simpler way though because i was set on exhaustivness...
If we… | |||||
"Invalid SWHID, format must be 'swh:1:OBJECT_TYPE:OBJECT_ID'" | |||||
) | |||||
# Checking for parsing errors | # Checking for parsing errors | ||||
_ns, _version, _type, _id = swhid_data | _ns, _version, _type, _id = swhid_data | ||||
for otype, data in _object_type_map.items(): | for otype, data in _object_type_map.items(): | ||||
if _type == data["short_name"]: | if _type == data["short_name"]: | ||||
_type = otype | _type = otype | ||||
break | break | ||||
if not _id: | if not _id: | ||||
raise ValidationError("Wrong format: Identifier should be present") | raise ValidationError( | ||||
"Invalid SWHID: missing OBJECT_ID (as a 40 hex digit string)" | |||||
Not Done Inline Actionsminor: a more canonical error message of this kind would be "Invalid SWHID: missing OBJECT_ID" zack: minor: a more canonical error message of this kind would be "Invalid SWHID: missing OBJECT_ID" | |||||
) | |||||
_metadata = {} | _metadata = {} | ||||
for part in swhid_parts: | for part in swhid_parts: | ||||
try: | try: | ||||
key, val = part.split("=") | key, val = part.split("=") | ||||
_metadata[key] = val | _metadata[key] = val | ||||
except Exception: | except Exception: | ||||
msg = "Contextual data is badly formatted, form key=val expected" | raise ValidationError( | ||||
Not Done Inline Actionsthis is a more tricky one, but my point about duplicating the grammar still applies. So, first attempt: "Invalid SWHID: contextual data must be a ;-separated list of key=value pairs." zack: this is a more tricky one, but my point about duplicating the grammar still applies. So, first… | |||||
raise ValidationError(msg) | "Invalid SWHID: contextual data must be a ;-separated list of " | ||||
" key=value pairs" | |||||
) | |||||
return SWHID( | return SWHID( | ||||
_ns, | _ns, | ||||
int(_version), | int(_version), | ||||
_type, | _type, | ||||
_id, | _id, | ||||
_metadata, # type: ignore # mypy can't properly unify types | _metadata, # type: ignore # mypy can't properly unify types | ||||
) | ) |
better: "Invalid SWHID: namespace is '{value}' but must be '{SWHID_NAMESPACE}'"
(note how this also shows where the error is)