diff --git a/swh/graphql/resolvers/base_connection.py b/swh/graphql/resolvers/base_connection.py --- a/swh/graphql/resolvers/base_connection.py +++ b/swh/graphql/resolvers/base_connection.py @@ -144,3 +144,42 @@ offset_index = self._get_after_arg() or "0" index_cursor = int(offset_index) + index return utils.get_encoded_cursor(str(index_cursor)) + + +class BaseList(ABC): + """ + Base class to be used for simple lists that do not require + pagination; eg resolveSWHID entrypoint + """ + + _node_class: Optional[Type[BaseNode]] = None + + def __init__(self, obj, info, results=None, **kwargs): + self.obj: Optional[BaseNode] = obj + self.info: GraphQLResolveInfo = info + self.kwargs = kwargs + self._results: List = results + + self.archive = Archive() + + def get_results(self) -> List: + if self._results is None: + # To avoid multiple calls to the backend + self._results = self._get_results() + + if self._node_class is not None: + # convert list items to node objects + return [ + self._node_class( + obj=self.obj, info=self.info, node_data=result, **self.kwargs + ) + for result in self._results + ] + return self._results + + @abstractmethod + def _get_results(self) -> List: + """ + Override for desired behaviour + return a list of objects + """ diff --git a/swh/graphql/resolvers/resolver_factory.py b/swh/graphql/resolvers/resolver_factory.py --- a/swh/graphql/resolvers/resolver_factory.py +++ b/swh/graphql/resolvers/resolver_factory.py @@ -7,7 +7,7 @@ from swh.graphql.errors import NullableObjectError -from .base_connection import BaseConnection +from .base_connection import BaseConnection, BaseList from .base_node import BaseNode from .content import ContentNode, HashContentNode, TargetContentNode from .directory import DirectoryNode, RevisionDirectoryNode, TargetDirectoryNode @@ -20,7 +20,7 @@ RevisionNode, TargetRevisionNode, ) -from .search import ResolveSwhidConnection, SearchConnection +from .search import ResolveSwhidList, SearchConnection from .snapshot import ( OriginSnapshotConnection, SnapshotNode, @@ -91,7 +91,6 @@ "revision-parents": ParentRevisionConnection, "revision-log": LogRevisionConnection, "directory-entries": DirectoryEntryConnection, - "resolve-swhid": ResolveSwhidConnection, "search": SearchConnection, } @@ -101,3 +100,18 @@ if not resolver: raise AttributeError(f"Invalid connection type: {connection_type}") return resolver(obj, info, *args, **kw) + + +class SimpleListFactory: + mapping: ClassVar[Dict[str, Type[BaseList]]] = { + "resolve-swhid": ResolveSwhidList, + } + + @classmethod + def create(cls, list_type: str, obj, info, *args, **kw): + resolver = cls.mapping.get(list_type) + + if not resolver: + raise AttributeError(f"Invalid list type: {list_type}") + # invoke the get_results method to return the list + return resolver(obj, info, *args, **kw).get_results() diff --git a/swh/graphql/resolvers/resolvers.py b/swh/graphql/resolvers/resolvers.py --- a/swh/graphql/resolvers/resolvers.py +++ b/swh/graphql/resolvers/resolvers.py @@ -26,7 +26,11 @@ from swh.graphql.utils import utils from swh.model.model import TimestampWithTimezone -from .resolver_factory import ConnectionObjectFactory, NodeObjectFactory +from .resolver_factory import ( + ConnectionObjectFactory, + NodeObjectFactory, + SimpleListFactory, +) query: ObjectType = ObjectType("Query") origin: ObjectType = ObjectType("Origin") @@ -265,13 +269,6 @@ return ConnectionObjectFactory.create("directory-entries", obj, info, **kw) -@query.field("resolveSWHID") -def search_swhid_resolver( - obj: None, info: GraphQLResolveInfo, **kw -) -> rs.search.ResolveSwhidConnection: - return ConnectionObjectFactory.create("resolve-swhid", obj, info, **kw) - - @query.field("search") def search_resolver( obj: None, info: GraphQLResolveInfo, **kw @@ -279,6 +276,16 @@ return ConnectionObjectFactory.create("search", obj, info, **kw) +# Simple list resolvers (lists without paginations) + + +@query.field("resolveSWHID") +def search_swhid_resolver( + obj: None, info: GraphQLResolveInfo, **kw +) -> rs.search.ResolveSwhidList: + return SimpleListFactory.create("resolve-swhid", obj, info, **kw) + + # Other resolvers diff --git a/swh/graphql/resolvers/search.py b/swh/graphql/resolvers/search.py --- a/swh/graphql/resolvers/search.py +++ b/swh/graphql/resolvers/search.py @@ -5,7 +5,7 @@ from swh.storage.interface import PagedResult -from .base_connection import BaseConnection +from .base_connection import BaseConnection, BaseList from .base_node import BaseNode @@ -17,13 +17,14 @@ return self._node.type -class ResolveSwhidConnection(BaseConnection): +class ResolveSwhidList(BaseList): _node_class = SearchResultNode - def _get_paged_result(self) -> PagedResult: + def _get_results(self) -> list: swhid = self.kwargs.get("swhid") results = [] + if self.archive.is_object_available(swhid.object_id, swhid.object_type): results = [ { @@ -31,7 +32,7 @@ "type": swhid.object_type.name.lower(), } ] - return PagedResult(results=results) + return results class SearchConnection(BaseConnection): diff --git a/swh/graphql/schema/schema.graphql b/swh/graphql/schema/schema.graphql --- a/swh/graphql/schema/schema.graphql +++ b/swh/graphql/schema/schema.graphql @@ -1140,7 +1140,7 @@ SWHID to look for """ swhid: SWHID! - ): SearchResultConnection + ): [SearchResult] """ Search in SWH diff --git a/swh/graphql/tests/functional/test_swhid_resolve.py b/swh/graphql/tests/functional/test_swhid_resolve.py --- a/swh/graphql/tests/functional/test_swhid_resolve.py +++ b/swh/graphql/tests/functional/test_swhid_resolve.py @@ -19,9 +19,7 @@ query_str = """ query resolve($swhid: SWHID!) { resolveSWHID(swhid: $swhid) { - nodes { - targetType - } + targetType } } """ @@ -45,15 +43,13 @@ query_str = """ query resolve($swhid: SWHID!) { resolveSWHID(swhid: $swhid) { - nodes { - targetType - } + targetType } } """ data, _ = utils.get_query_response(client, query_str, swhid=swhid) # API will return an empty list in case of a valid, non existing SWHID - assert data == {"resolveSWHID": {"nodes": []}} + assert data == {"resolveSWHID": []} @pytest.mark.parametrize("snapshot", get_snapshots()) @@ -61,13 +57,11 @@ query_str = """ query resolve($swhid: SWHID!) { resolveSWHID(swhid: $swhid) { - nodes { - targetType - target { - __typename - ... on Snapshot { - swhid - } + targetType + target { + __typename + ... on Snapshot { + swhid } } } @@ -75,17 +69,15 @@ """ data, _ = utils.get_query_response(client, query_str, swhid=str(snapshot.swhid())) assert data == { - "resolveSWHID": { - "nodes": [ - { - "target": { - "__typename": "Snapshot", - "swhid": str(snapshot.swhid()), - }, - "targetType": "snapshot", - } - ] - } + "resolveSWHID": [ + { + "target": { + "__typename": "Snapshot", + "swhid": str(snapshot.swhid()), + }, + "targetType": "snapshot", + } + ] } @@ -94,13 +86,11 @@ query_str = """ query resolve($swhid: SWHID!) { resolveSWHID(swhid: $swhid) { - nodes { - targetType - target { - __typename - ... on Revision { - swhid - } + targetType + target { + __typename + ... on Revision { + swhid } } } @@ -108,17 +98,15 @@ """ data, _ = utils.get_query_response(client, query_str, swhid=str(revision.swhid())) assert data == { - "resolveSWHID": { - "nodes": [ - { - "target": { - "__typename": "Revision", - "swhid": str(revision.swhid()), - }, - "targetType": "revision", - } - ] - } + "resolveSWHID": [ + { + "target": { + "__typename": "Revision", + "swhid": str(revision.swhid()), + }, + "targetType": "revision", + } + ] } @@ -127,13 +115,11 @@ query_str = """ query resolve($swhid: SWHID!) { resolveSWHID(swhid: $swhid) { - nodes { - targetType - target { - __typename - ... on Release { - swhid - } + targetType + target { + __typename + ... on Release { + swhid } } } @@ -141,17 +127,15 @@ """ data, _ = utils.get_query_response(client, query_str, swhid=str(release.swhid())) assert data == { - "resolveSWHID": { - "nodes": [ - { - "target": { - "__typename": "Release", - "swhid": str(release.swhid()), - }, - "targetType": "release", - } - ] - } + "resolveSWHID": [ + { + "target": { + "__typename": "Release", + "swhid": str(release.swhid()), + }, + "targetType": "release", + } + ] } @@ -160,13 +144,11 @@ query_str = """ query resolve($swhid: SWHID!) { resolveSWHID(swhid: $swhid) { - nodes { - targetType - target { - __typename - ... on Directory { - swhid - } + targetType + target { + __typename + ... on Directory { + swhid } } } @@ -174,17 +156,15 @@ """ data, _ = utils.get_query_response(client, query_str, swhid=str(directory.swhid())) assert data == { - "resolveSWHID": { - "nodes": [ - { - "target": { - "__typename": "Directory", - "swhid": str(directory.swhid()), - }, - "targetType": "directory", - } - ] - } + "resolveSWHID": [ + { + "target": { + "__typename": "Directory", + "swhid": str(directory.swhid()), + }, + "targetType": "directory", + } + ] } @@ -193,13 +173,11 @@ query_str = """ query resolve($swhid: SWHID!) { resolveSWHID(swhid: $swhid) { - nodes { - targetType - target { - __typename - ... on Content { - swhid - } + targetType + target { + __typename + ... on Content { + swhid } } } @@ -207,15 +185,13 @@ """ data, _ = utils.get_query_response(client, query_str, swhid=str(content.swhid())) assert data == { - "resolveSWHID": { - "nodes": [ - { - "target": { - "__typename": "Content", - "swhid": str(content.swhid()), - }, - "targetType": "content", - } - ] - } + "resolveSWHID": [ + { + "target": { + "__typename": "Content", + "swhid": str(content.swhid()), + }, + "targetType": "content", + } + ] }