Changeset View
Standalone View
swh/web/common/identifiers.py
# Copyright (C) 2020 The Software Heritage developers | # Copyright (C) 2020 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU Affero General Public License version 3, or any later version | # License: GNU Affero General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
from typing import Dict, Iterable, List, Optional | from urllib.parse import quote | ||||
from typing import Any, Dict, Iterable, List, Optional | |||||
from typing_extensions import TypedDict | from typing_extensions import TypedDict | ||||
from django.http import QueryDict | from django.http import QueryDict | ||||
from swh.model.exceptions import ValidationError | from swh.model.exceptions import ValidationError | ||||
from swh.model.hashutil import hash_to_bytes | from swh.model.hashutil import hash_to_bytes | ||||
from swh.model.identifiers import ( | from swh.model.identifiers import ( | ||||
persistent_identifier, | persistent_identifier, | ||||
parse_persistent_identifier, | parse_persistent_identifier, | ||||
CONTENT, | CONTENT, | ||||
DIRECTORY, | DIRECTORY, | ||||
ORIGIN, | ORIGIN, | ||||
RELEASE, | RELEASE, | ||||
REVISION, | REVISION, | ||||
SNAPSHOT, | SNAPSHOT, | ||||
PersistentId, | PersistentId, | ||||
) | ) | ||||
from swh.web.common.exc import BadInputExc | from swh.web.common.exc import BadInputExc | ||||
from swh.web.common.typing import QueryParameters | from swh.web.common.typing import ( | ||||
from swh.web.common.utils import swh_object_icons, reverse | QueryParameters, | ||||
SnapshotContext, | |||||
SWHObjectInfo, | |||||
SWHIDInfo, | |||||
SWHIDContext, | |||||
) | |||||
from swh.web.common.utils import reverse | |||||
def get_swh_persistent_id( | def get_swh_persistent_id( | ||||
object_type: str, object_id: str, scheme_version: int = 1 | object_type: str, | ||||
object_id: str, | |||||
scheme_version: int = 1, | |||||
metadata: SWHIDContext = {}, | |||||
) -> str: | ) -> str: | ||||
""" | """ | ||||
Returns the persistent identifier for a swh object based on: | Returns the persistent identifier for a swh object based on: | ||||
* the object type | * the object type | ||||
* the object id | * the object id | ||||
* the swh identifiers scheme version | * the swh identifiers scheme version | ||||
Args: | Args: | ||||
object_type: the swh object type | object_type: the swh object type | ||||
(content/directory/release/revision/snapshot) | (content/directory/release/revision/snapshot) | ||||
object_id: the swh object id (hexadecimal representation | object_id: the swh object id (hexadecimal representation | ||||
of its hash value) | of its hash value) | ||||
scheme_version: the scheme version of the swh | scheme_version: the scheme version of the swh | ||||
persistent identifiers | persistent identifiers | ||||
Returns: | Returns: | ||||
the swh object persistent identifier | the swh object persistent identifier | ||||
Raises: | Raises: | ||||
BadInputExc: if the provided parameters do not enable to | BadInputExc: if the provided parameters do not enable to | ||||
generate a valid identifier | generate a valid identifier | ||||
""" | """ | ||||
try: | try: | ||||
swh_id = persistent_identifier(object_type, object_id, scheme_version) | swh_id = persistent_identifier(object_type, object_id, scheme_version, metadata) | ||||
except ValidationError as e: | except ValidationError as e: | ||||
raise BadInputExc( | raise BadInputExc( | ||||
"Invalid object (%s) for swh persistent id. %s" % (object_id, e) | "Invalid object (%s) for swh persistent id. %s" % (object_id, e) | ||||
) | ) | ||||
else: | else: | ||||
return swh_id | return swh_id | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | ) -> Dict[str, List[bytes]]: | ||||
for pid in persistent_ids: | for pid in persistent_ids: | ||||
obj_id = pid.object_id | obj_id = pid.object_id | ||||
obj_type = pid.object_type | obj_type = pid.object_type | ||||
pids_by_type[obj_type].append(hash_to_bytes(obj_id)) | pids_by_type[obj_type].append(hash_to_bytes(obj_id)) | ||||
return pids_by_type | return pids_by_type | ||||
def get_swh_persistent_ids(swh_objects, snapshot_context=None): | def get_swhids_info( | ||||
swh_objects: Iterable[SWHObjectInfo], | |||||
snapshot_context: Optional[SnapshotContext] = None, | |||||
extra_context: Optional[Dict[str, Any]] = None, | |||||
) -> List[SWHIDInfo]: | |||||
""" | """ | ||||
Returns a list of dict containing info related to persistent | Returns a list of dict containing info related to persistent | ||||
identifiers of swh objects. | identifiers of swh objects. | ||||
Args: | Args: | ||||
swh_objects (list): a list of dict with the following keys: | swh_objects: an iterable of dict describing archived objects | ||||
snapshot_context: optional dict parameter describing the snapshot in | |||||
* type: swh object type | which the objects have been found | ||||
(content/directory/release/revision/snapshot) | extra_context: optional dict filled with extra contextual info about | ||||
* id: swh object id | the objects | ||||
snapshot_context (dict): optional parameter describing the snapshot in | |||||
which the object has been found | |||||
Returns: | Returns: | ||||
list: a list of dict with the following keys: | a list of dict containing persistent identifiers info | ||||
* object_type: the swh object type | |||||
(content/directory/release/revision/snapshot) | |||||
* object_icon: the swh object icon to use in HTML views | |||||
* swh_id: the computed swh object persistent identifier | |||||
* swh_id_url: the url resolving the persistent identifier | |||||
* show_options: boolean indicating if the persistent id options | |||||
must be displayed in persistent ids HTML view | |||||
""" | """ | ||||
swh_ids = [] | swhids_info = [] | ||||
for swh_object in swh_objects: | for swh_object in swh_objects: | ||||
if not swh_object["id"]: | if not swh_object["object_id"]: | ||||
swhids_info.append( | |||||
SWHIDInfo( | |||||
object_type=swh_object["object_type"], | |||||
object_id="", | |||||
swhid="", | |||||
swhid_url="", | |||||
context={}, | |||||
swhid_with_context=None, | |||||
swhid_with_context_url=None, | |||||
ardumont: What is the purpose of the "empty" swh id info? | |||||
Done Inline ActionsTo handle the empty snapshot corner case when browsing the archive. But I intend to improve that later. anlambert: To handle the empty snapshot corner case when browsing the archive. But I intend to improve… | |||||
) | |||||
) | |||||
continue | continue | ||||
swh_id = get_swh_persistent_id(swh_object["type"], swh_object["id"]) | object_type = swh_object["object_type"] | ||||
show_options = swh_object["type"] == "content" or ( | object_id = swh_object["object_id"] | ||||
snapshot_context and snapshot_context["origin_info"] is not None | swhid_context: SWHIDContext = {} | ||||
if snapshot_context: | |||||
if snapshot_context["origin_info"] is not None: | |||||
swhid_context["origin"] = quote( | |||||
snapshot_context["origin_info"]["url"], safe="/?:@&" | |||||
) | |||||
if object_type != SNAPSHOT: | |||||
swhid_context["visit"] = get_swh_persistent_id( | |||||
SNAPSHOT, snapshot_context["snapshot_id"] | |||||
) | |||||
if object_type not in (RELEASE, REVISION, SNAPSHOT): | |||||
if snapshot_context["release_id"] is not None: | |||||
swhid_context["anchor"] = get_swh_persistent_id( | |||||
RELEASE, snapshot_context["release_id"] | |||||
) | |||||
elif snapshot_context["revision_id"] is not None: | |||||
swhid_context["anchor"] = get_swh_persistent_id( | |||||
REVISION, snapshot_context["revision_id"] | |||||
) | |||||
if object_type in (CONTENT, DIRECTORY): | |||||
if ( | |||||
extra_context | |||||
and "revision" in extra_context | |||||
and extra_context["revision"] | |||||
): | |||||
swhid_context["anchor"] = get_swh_persistent_id( | |||||
REVISION, extra_context["revision"] | |||||
) | |||||
elif ( | |||||
extra_context | |||||
and "root_directory" in extra_context | |||||
and extra_context["root_directory"] | |||||
and ( | |||||
object_type != DIRECTORY | |||||
or extra_context["root_directory"] != object_id | |||||
) | |||||
): | |||||
swhid_context["anchor"] = get_swh_persistent_id( | |||||
DIRECTORY, extra_context["root_directory"] | |||||
) | |||||
path = None | |||||
if extra_context and "path" in extra_context: | |||||
path = extra_context["path"] | |||||
if "filename" in extra_context and object_type == CONTENT: | |||||
path += extra_context["filename"] | |||||
if path: | |||||
swhid_context["path"] = quote(path, safe="/?:@&") | |||||
swhid = get_swh_persistent_id(object_type, object_id) | |||||
swhid_url = reverse("browse-swh-id", url_args={"swh_id": swhid}) | |||||
swhid_with_context = None | |||||
swhid_with_context_url = None | |||||
if swhid_context: | |||||
swhid_with_context = get_swh_persistent_id( | |||||
object_type, object_id, metadata=swhid_context | |||||
) | |||||
swhid_with_context_url = reverse( | |||||
"browse-swh-id", url_args={"swh_id": swhid_with_context} | |||||
) | |||||
swhids_info.append( | |||||
SWHIDInfo( | |||||
object_type=object_type, | |||||
object_id=object_id, | |||||
swhid=swhid, | |||||
swhid_url=swhid_url, | |||||
context=swhid_context, | |||||
swhid_with_context=swhid_with_context, | |||||
swhid_with_context_url=swhid_with_context_url, | |||||
) | ) | ||||
object_icon = swh_object_icons[swh_object["type"]] | |||||
swh_ids.append( | |||||
{ | |||||
"object_type": swh_object["type"], | |||||
"object_id": swh_object["id"], | |||||
"object_icon": object_icon, | |||||
"swh_id": swh_id, | |||||
"swh_id_url": reverse("browse-swh-id", url_args={"swh_id": swh_id}), | |||||
"show_options": show_options, | |||||
} | |||||
) | ) | ||||
return swh_ids | return swhids_info | ||||
Not Done Inline Actions"J'ai les fils qui se croisent ici" ;) Seriously though, i have difficulties reading the multiple conditionals. Why the apparently more complex implementation than before? ardumont: "J'ai les fils qui se croisent ici" ;)
Seriously though, i have difficulties reading the… | |||||
Done Inline ActionsSee https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html#qualifiers, there is a lot of possibilities for contextual info based on the browsing context. For instance, you can browse a content in a directory context or in a snapshot context or in an origin context. The function handles all possible cases. anlambert: See https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html#qualifiers… | |||||
Done Inline Actions
And also in a revision context ;-) anlambert: > For instance, you can browse a content in a directory context or in a snapshot context or in… | |||||
Not Done Inline ActionsThanks. ardumont: Thanks. |
What is the purpose of the "empty" swh id info?