Page MenuHomeSoftware Heritage

D8704.diff
No OneTemporary

D8704.diff

diff --git a/swh/graphql/app.py b/swh/graphql/app.py
--- a/swh/graphql/app.py
+++ b/swh/graphql/app.py
@@ -26,15 +26,19 @@
resolvers.visit_status,
resolvers.snapshot,
resolvers.snapshot_branch,
+ resolvers.branch_target,
+ resolvers.branch_target_node,
resolvers.revision,
resolvers.release,
+ resolvers.release_target,
+ resolvers.release_target_node,
resolvers.directory,
resolvers.directory_entry,
- resolvers.search_result,
- resolvers.branch_target,
- resolvers.release_target,
resolvers.directory_entry_target,
+ resolvers.directory_entry_target_node,
+ resolvers.search_result,
resolvers.search_result_target,
+ resolvers.search_result_target_node,
resolvers.binary_string,
resolvers.date,
scalars.id_scalar,
diff --git a/swh/graphql/resolvers/content.py b/swh/graphql/resolvers/content.py
--- a/swh/graphql/resolvers/content.py
+++ b/swh/graphql/resolvers/content.py
@@ -3,7 +3,7 @@
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
-from typing import Dict, List, Optional, Union
+from typing import Dict, List, Optional
from swh.graphql.errors import DataError, InvalidInputError
from swh.model import hashutil
@@ -11,10 +11,7 @@
from .base_connection import BaseList
from .base_node import BaseSWHNode
-from .directory_entry import BaseDirectoryEntryNode
-from .release import BaseReleaseNode
-from .search import SearchResultNode
-from .snapshot_branch import BaseSnapshotBranchNode
+from .target import TargetNode
def read_and_validate_content_hashes(hashes) -> Dict[str, bytes]:
@@ -94,17 +91,12 @@
"""
_can_be_null = True
- obj: Union[
- SearchResultNode,
- BaseDirectoryEntryNode,
- BaseReleaseNode,
- BaseSnapshotBranchNode,
- ]
+ obj: TargetNode
def _get_node_data(self) -> Optional[Content]:
# FIXME, this is not considering hash collisions
# and could return a wrong object in very rare situations
- contents = self.archive.get_contents(hashes={"sha1_git": self.obj.target_hash})
+ contents = self.archive.get_contents(hashes={"sha1_git": self.obj.target_id})
# always returning the first content from the storage
return contents[0] if contents else None
diff --git a/swh/graphql/resolvers/directory.py b/swh/graphql/resolvers/directory.py
--- a/swh/graphql/resolvers/directory.py
+++ b/swh/graphql/resolvers/directory.py
@@ -3,16 +3,12 @@
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
-from typing import Union
-
from swh.model.model import Directory
from swh.model.swhids import ObjectType
from .base_node import BaseSWHNode
-from .release import BaseReleaseNode
from .revision import BaseRevisionNode
-from .search import SearchResultNode
-from .snapshot_branch import BaseSnapshotBranchNode
+from .target import TargetNode
class BaseDirectoryNode(BaseSWHNode):
@@ -65,15 +61,8 @@
Node resolver for a directory requested as a target
"""
- from .directory_entry import BaseDirectoryEntryNode
-
_can_be_null = True
- obj: Union[
- BaseSnapshotBranchNode,
- BaseReleaseNode,
- BaseDirectoryEntryNode,
- SearchResultNode,
- ]
+ obj: TargetNode
def _get_node_data(self):
- return self._get_directory_by_id(self.obj.target_hash)
+ return self._get_directory_by_id(self.obj.target_id)
diff --git a/swh/graphql/resolvers/directory_entry.py b/swh/graphql/resolvers/directory_entry.py
--- a/swh/graphql/resolvers/directory_entry.py
+++ b/swh/graphql/resolvers/directory_entry.py
@@ -12,11 +12,11 @@
class BaseDirectoryEntryNode(BaseNode):
@property
- def target_hash(self): # for DirectoryNode
+ def target_id(self):
return self._node.target
@property
- def targetType(self): # To support the schema naming convention
+ def target_type(self):
mapping = {"file": "content", "dir": "directory", "rev": "revision"}
return mapping.get(self._node.type)
diff --git a/swh/graphql/resolvers/origin.py b/swh/graphql/resolvers/origin.py
--- a/swh/graphql/resolvers/origin.py
+++ b/swh/graphql/resolvers/origin.py
@@ -8,7 +8,7 @@
from .base_connection import BaseConnection
from .base_node import BaseSWHNode
-from .search import SearchResultNode
+from .target import TargetNode
class BaseOriginNode(BaseSWHNode):
@@ -32,13 +32,13 @@
Node resolver for an origin requested as a target
"""
- obj: SearchResultNode
+ obj: TargetNode
def _get_node_data(self):
- # The target origin URL is guaranteed to exist in the archive
+ # The target origin URL (target_id here) is guaranteed to exist in the archive
# Hence returning the origin object without any explicit check in the archive
# This assumes that the search index and archive are in sync
- return Origin(self.obj.target_url)
+ return Origin(self.obj.target_id)
class OriginConnection(BaseConnection):
diff --git a/swh/graphql/resolvers/release.py b/swh/graphql/resolvers/release.py
--- a/swh/graphql/resolvers/release.py
+++ b/swh/graphql/resolvers/release.py
@@ -3,11 +3,8 @@
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
-from typing import Union
-
from .base_node import BaseSWHNode
-from .search import SearchResultNode
-from .snapshot_branch import BaseSnapshotBranchNode
+from .target import TargetNode
class BaseReleaseNode(BaseSWHNode):
@@ -19,11 +16,11 @@
return self.archive.get_releases([release_id])[0]
@property
- def target_hash(self):
+ def target_id(self):
return self._node.target
@property
- def targetType(self): # To support the schema naming convention
+ def target_type(self):
return self._node.target_type.value
def is_type_of(self):
@@ -47,8 +44,7 @@
"""
_can_be_null = True
- obj: Union[BaseSnapshotBranchNode, BaseReleaseNode, SearchResultNode]
+ obj: TargetNode
def _get_node_data(self):
- # self.obj.target_hash is the requested release id
- return self._get_release_by_id(self.obj.target_hash)
+ return self._get_release_by_id(self.obj.target_id)
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
@@ -33,7 +33,8 @@
TargetSnapshotNode,
VisitSnapshotNode,
)
-from .snapshot_branch import AliasSnapshotBranchNode, SnapshotBranchConnection
+from .snapshot_branch import SnapshotBranchConnection, TargetSnapshotBranchNode
+from .target import TargetNode
from .visit import LatestVisitNode, OriginVisitConnection, OriginVisitNode
from .visit_status import LatestVisitStatusNode, VisitStatusConnection
@@ -46,31 +47,20 @@
"latest-status": LatestVisitStatusNode,
"visit-snapshot": VisitSnapshotNode,
"snapshot": SnapshotNode,
- "branch-alias": AliasSnapshotBranchNode,
- "branch-revision": TargetRevisionNode,
- "branch-release": TargetReleaseNode,
- "branch-directory": TargetDirectoryNode,
- "branch-content": TargetContentNode,
- "branch-snapshot": TargetSnapshotNode,
"revision": RevisionNode,
"revision-directory": RevisionDirectoryNode,
"release": ReleaseNode,
- "release-revision": TargetRevisionNode,
- "release-release": TargetReleaseNode,
- "release-directory": TargetDirectoryNode,
- "release-content": TargetContentNode,
"directory": DirectoryNode,
"directory-entry": DirectoryEntryNode,
"content-by-hashes": ContentbyHashesNode,
- "dir-entry-content": TargetContentNode,
- "dir-entry-directory": TargetDirectoryNode,
- "dir-entry-revision": TargetRevisionNode,
- "search-result-origin": TargetOriginNode,
- "search-result-snapshot": TargetSnapshotNode,
- "search-result-revision": TargetRevisionNode,
- "search-result-release": TargetReleaseNode,
- "search-result-directory": TargetDirectoryNode,
- "search-result-content": TargetContentNode,
+ "target": TargetNode,
+ "target-origin": TargetOriginNode,
+ "target-snapshot": TargetSnapshotNode,
+ "target-alias": TargetSnapshotBranchNode,
+ "target-revision": TargetRevisionNode,
+ "target-release": TargetReleaseNode,
+ "target-directory": TargetDirectoryNode,
+ "target-content": TargetContentNode,
}
@classmethod
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
@@ -38,18 +38,22 @@
visit_status: ObjectType = ObjectType("VisitStatus")
snapshot: ObjectType = ObjectType("Snapshot")
snapshot_branch: ObjectType = ObjectType("Branch")
+branch_target: ObjectType = ObjectType("BranchTarget")
revision: ObjectType = ObjectType("Revision")
release: ObjectType = ObjectType("Release")
+release_target: ObjectType = ObjectType("ReleaseTarget")
directory: ObjectType = ObjectType("Directory")
directory_entry: ObjectType = ObjectType("DirectoryEntry")
+directory_entry_target: ObjectType = ObjectType("DirectoryEntryTarget")
search_result: ObjectType = ObjectType("SearchResult")
+search_result_target: ObjectType = ObjectType("SearchResultTarget")
binary_string: ObjectType = ObjectType("BinaryString")
date: ObjectType = ObjectType("Date")
-branch_target: UnionType = UnionType("BranchTarget")
-release_target: UnionType = UnionType("ReleaseTarget")
-directory_entry_target: UnionType = UnionType("DirectoryEntryTarget")
-search_result_target: UnionType = UnionType("SearchResultTarget")
+branch_target_node: UnionType = UnionType("BranchTargetNode")
+release_target_node: UnionType = UnionType("ReleaseTargetNode")
+directory_entry_target_node: UnionType = UnionType("DirectoryEntryTargetNode")
+search_result_target_node: UnionType = UnionType("SearchResultTargetNode")
# Node resolvers
# A node resolver will return either an instance of a BaseNode subclass or None
@@ -95,24 +99,6 @@
return NodeObjectFactory.create("visit-snapshot", obj, info, **kw)
-@snapshot_branch.field("target")
-def snapshot_branch_target_resolver(
- obj: rs.snapshot_branch.BaseSnapshotBranchNode, info: GraphQLResolveInfo, **kw
-) -> Union[
- rs.revision.BaseRevisionNode,
- rs.release.BaseReleaseNode,
- rs.directory.BaseDirectoryNode,
- rs.content.BaseContentNode,
- rs.snapshot.BaseSnapshotNode,
- rs.snapshot_branch.BaseSnapshotBranchNode,
-]:
- """
- Snapshot branch target can be a revision, release, directory,
- content, snapshot or a branch itself (alias type)
- """
- return NodeObjectFactory.create(f"branch-{obj.targetType}", obj, info, **kw)
-
-
@query.field("revision")
def revision_resolver(
obj: None, info: GraphQLResolveInfo, **kw
@@ -134,21 +120,6 @@
return NodeObjectFactory.create("release", obj, info, **kw)
-@release.field("target")
-def release_target_resolver(
- obj: rs.release.BaseReleaseNode, info: GraphQLResolveInfo, **kw
-) -> Union[
- rs.revision.BaseRevisionNode,
- rs.release.BaseReleaseNode,
- rs.directory.BaseDirectoryNode,
- rs.content.BaseContentNode,
-]:
- """
- Release target can be a release, revision, directory or a content
- """
- return NodeObjectFactory.create(f"release-{obj.targetType}", obj, info, **kw)
-
-
@query.field("directory")
def directory_resolver(
obj: None, info: GraphQLResolveInfo, **kw
@@ -163,23 +134,37 @@
return NodeObjectFactory.create("directory-entry", obj, info, **kw)
-@directory_entry.field("target")
-def directory_entry_target_resolver(
- obj: rs.directory_entry.BaseDirectoryEntryNode, info: GraphQLResolveInfo, **kw
-) -> Union[
- rs.revision.BaseRevisionNode,
- rs.directory.BaseDirectoryNode,
- rs.content.BaseContentNode,
-]:
- """
- DirectoryEntry target can be a directory, content or a revision
- """
- return NodeObjectFactory.create(f"dir-entry-{obj.targetType}", obj, info, **kw)
+@query.field("contentByHashes")
+def content_by_hashes_resolver(
+ obj: None, info: GraphQLResolveInfo, **kw
+) -> rs.content.ContentbyHashesNode:
+ return NodeObjectFactory.create("content-by-hashes", obj, info, **kw)
+@snapshot_branch.field("target")
+@release.field("target")
+@directory_entry.field("target")
@search_result.field("target")
-def search_result_target_resolver(
- obj: rs.search.SearchResultNode, info: GraphQLResolveInfo, **kw
+def generic_target_resolver(
+ obj: Union[
+ rs.snapshot_branch.BaseSnapshotBranchNode,
+ rs.release.BaseReleaseNode,
+ rs.directory_entry.BaseDirectoryEntryNode,
+ rs.search.SearchResultNode,
+ ],
+ info: GraphQLResolveInfo,
+ **kw,
+) -> rs.target.TargetNode:
+ # Generic resolver for all the targets
+ return NodeObjectFactory.create("target", obj, info, **kw)
+
+
+@branch_target.field("node")
+@directory_entry_target.field("node")
+@search_result_target.field("node")
+@release_target.field("node")
+def target_node_resolver(
+ obj: rs.target.TargetNode, info: GraphQLResolveInfo, **kw
) -> Union[
rs.origin.BaseOriginNode,
rs.snapshot.BaseSnapshotNode,
@@ -188,18 +173,8 @@
rs.directory.BaseDirectoryNode,
rs.content.BaseContentNode,
]:
- """
- SearchResult target can be an origin, snapshot, revision, release
- directory or a content
- """
- return NodeObjectFactory.create(f"search-result-{obj.targetType}", obj, info, **kw)
-
-
-@query.field("contentByHashes")
-def content_by_hashes_resolver(
- obj: None, info: GraphQLResolveInfo, **kw
-) -> rs.content.ContentbyHashesNode:
- return NodeObjectFactory.create("content-by-hashes", obj, info, **kw)
+ # Generic resolver for all the target nodes
+ return NodeObjectFactory.create(f"target-{obj.type}", obj, info, **kw)
# Connection resolvers
@@ -317,10 +292,10 @@
# Other resolvers
-@release_target.type_resolver
-@directory_entry_target.type_resolver
-@branch_target.type_resolver
-@search_result_target.type_resolver
+@release_target_node.type_resolver
+@directory_entry_target_node.type_resolver
+@search_result_target_node.type_resolver
+@branch_target_node.type_resolver
def union_resolver(
obj: Union[
rs.origin.BaseOriginNode,
diff --git a/swh/graphql/resolvers/revision.py b/swh/graphql/resolvers/revision.py
--- a/swh/graphql/resolvers/revision.py
+++ b/swh/graphql/resolvers/revision.py
@@ -3,8 +3,6 @@
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
-from typing import Union
-
from swh.graphql.utils import utils
from swh.model.model import Revision
from swh.model.swhids import CoreSWHID, ObjectType
@@ -12,10 +10,7 @@
from .base_connection import BaseConnection
from .base_node import BaseSWHNode
-from .directory_entry import BaseDirectoryEntryNode
-from .release import BaseReleaseNode
-from .search import SearchResultNode
-from .snapshot_branch import BaseSnapshotBranchNode
+from .target import TargetNode
class BaseRevisionNode(BaseSWHNode):
@@ -66,16 +61,10 @@
"""
_can_be_null = True
- obj: Union[
- BaseSnapshotBranchNode,
- BaseReleaseNode,
- BaseDirectoryEntryNode,
- SearchResultNode,
- ]
+ obj: TargetNode
def _get_node_data(self):
- # self.obj.target_hash is the requested revision id
- return self._get_revision_by_id(self.obj.target_hash)
+ return self._get_revision_by_id(self.obj.target_id)
class ParentRevisionConnection(BaseConnection):
diff --git a/swh/graphql/resolvers/scalars.py b/swh/graphql/resolvers/scalars.py
--- a/swh/graphql/resolvers/scalars.py
+++ b/swh/graphql/resolvers/scalars.py
@@ -4,7 +4,7 @@
# See top-level LICENSE file for more information
import datetime
-from typing import Optional
+from typing import Optional, Union
from ariadne import ScalarType
@@ -19,10 +19,10 @@
@id_scalar.serializer
-def serialize_id(value) -> str:
- if type(value) is str:
- value = value.encode()
- return value.hex()
+def serialize_id(value: Union[bytes, str]) -> str:
+ if isinstance(value, bytes):
+ return value.hex()
+ return value
@datetime_scalar.serializer
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
@@ -13,9 +13,13 @@
""" """
@property
- def targetType(self): # To support the schema naming convention
+ def target_type(self):
return self._node.type
+ @property
+ def target_id(self):
+ return self._node.target_id
+
class ResolveSwhidList(BaseList):
@@ -28,7 +32,7 @@
if self.archive.is_object_available(swhid.object_id, swhid.object_type):
results = [
{
- "target_hash": swhid.object_id,
+ "target_id": swhid.object_id,
"type": swhid.object_type.name.lower(),
}
]
@@ -48,6 +52,6 @@
# FIXME hard coding type to origin for now, as it is the only searchable object
results = [
- {"target_url": ori["url"], "type": "origin"} for ori in origins.results
+ {"target_id": ori["url"], "type": "origin"} for ori in origins.results
]
return PagedResult(results=results, next_page_token=origins.next_page_token)
diff --git a/swh/graphql/resolvers/snapshot.py b/swh/graphql/resolvers/snapshot.py
--- a/swh/graphql/resolvers/snapshot.py
+++ b/swh/graphql/resolvers/snapshot.py
@@ -3,8 +3,6 @@
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
-from typing import Union
-
from swh.graphql.errors import NullableObjectError
from swh.graphql.utils import utils
from swh.model.model import Snapshot
@@ -14,7 +12,7 @@
from .base_connection import BaseConnection
from .base_node import BaseSWHNode
from .origin import OriginNode
-from .search import SearchResultNode
+from .target import TargetNode
from .visit_status import BaseVisitStatusNode
@@ -71,13 +69,11 @@
Node resolver for a snapshot requested as a target
"""
- from .snapshot_branch import BaseSnapshotBranchNode
-
_can_be_null = True
- obj: Union[SearchResultNode, BaseSnapshotBranchNode]
+ obj: TargetNode
def _get_node_data(self):
- snapshot_id = self.obj.target_hash
+ snapshot_id = self.obj.target_id
return self._get_snapshot_by_id(snapshot_id)
diff --git a/swh/graphql/resolvers/snapshot_branch.py b/swh/graphql/resolvers/snapshot_branch.py
--- a/swh/graphql/resolvers/snapshot_branch.py
+++ b/swh/graphql/resolvers/snapshot_branch.py
@@ -11,13 +11,10 @@
from .base_connection import BaseConnection
from .base_node import BaseNode
+from .target import TargetNode
class BaseSnapshotBranchNode(BaseNode):
-
- # target field for this node is a UNION type
- # It is resolved in the top level (resolvers.resolvers.py)
-
def _get_node_from_data(self, node_data: tuple):
# node_data is a tuple as returned by _get_paged_result in
# SnapshotBranchConnection and _get_node_data in AliasSnapshotBranchNode
@@ -25,18 +22,14 @@
branch_name, branch_obj = node_data
node = {
"name": branch_name,
- "type": branch_obj.target_type.value,
- "target_hash": branch_obj.target,
+ "target_type": branch_obj.target_type.value,
+ "target_id": branch_obj.target,
}
return namedtuple("NodeObj", node.keys())(*node.values())
def is_type_of(self):
return "Branch"
- @property
- def targetType(self): # To support the schema naming convention
- return self._node.type
-
def snapshot_swhid(self):
"""
Logic to handle multiple branch alias redirects
@@ -59,13 +52,13 @@
raise ObjectNotFoundError("There is no snapshot associated with the branch")
-class AliasSnapshotBranchNode(BaseSnapshotBranchNode):
+class TargetSnapshotBranchNode(BaseSnapshotBranchNode):
- obj: BaseSnapshotBranchNode
+ obj: TargetNode
def _get_node_data(self):
snapshot_swhid = self.snapshot_swhid()
- target_branch = self.obj.target_hash
+ target_branch = self.obj.target_id
alias_branch = self.archive.get_snapshot_branches(
snapshot_swhid.object_id, first=1, name_include=target_branch
diff --git a/swh/graphql/resolvers/target.py b/swh/graphql/resolvers/target.py
new file mode 100644
--- /dev/null
+++ b/swh/graphql/resolvers/target.py
@@ -0,0 +1,41 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Union
+
+from .base_node import BaseNode
+
+if TYPE_CHECKING:
+ from .directory_entry import BaseDirectoryEntryNode # pragma: no cover
+ from .release import BaseReleaseNode # pragma: no cover
+ from .search import SearchResultNode # pragma: no cover
+ from .snapshot_branch import BaseSnapshotBranchNode # pragma: no cover
+
+
+class TargetNode(BaseNode):
+ """
+ Generic resolver for all the targets.
+ Every parent object (self.obj) must have two attributes target_type and target_id.
+ target_type is exposed as the type attribute and target_id is exposed as the identifier.
+ target_id is also used to retrieve the node object on request
+ """
+
+ # Create a subclass for specific target nodes (say with more fields)
+
+ obj: Union[
+ BaseSnapshotBranchNode,
+ BaseReleaseNode,
+ BaseDirectoryEntryNode,
+ SearchResultNode,
+ ]
+
+ def _get_node_data(self):
+ # node field of a target object is resolved in the top level resolver
+ return {
+ # field exposed in the schema
+ "type": self.obj.target_type,
+ # field exposed in the schema, the same value is used to
+ # retrieve the node object
+ "identifier": self.obj.target_id,
+ # field NOT exposed in the schema, used to retrieve the target node
+ "target_id": self.obj.target_id,
+ }
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
@@ -493,10 +493,21 @@
fullname: BinaryString
}
+
"""
-Possible branch target objects
+A snapshot branch object
"""
-union BranchTarget = Revision | Release | Branch | Content | Directory | Snapshot
+type Branch {
+ """
+ Branch name
+ """
+ name: BinaryString
+
+ """
+ Branch target object
+ """
+ target: BranchTarget
+}
"""
Possible Branch target types
@@ -511,23 +522,28 @@
}
"""
-A snapshot branch object
+Possible branch target nodes
"""
-type Branch {
+union BranchTargetNode = Revision | Release | Branch | Content | Directory | Snapshot
+
+"""
+A branch target object
+"""
+type BranchTarget {
"""
- Branch name
+ Branch target type
"""
- name: BinaryString
+ type: BranchTargetType!
"""
- Type of Branch target
+ Branch target identifier
"""
- targetType: BranchTargetType
+ identifier: ID!
"""
- Branch target object
+ Branch target node
"""
- target: BranchTarget
+ node: BranchTargetNode
}
"""
@@ -632,6 +648,7 @@
"""
The unique directory object that revision points to
"""
+ # FIXME, this field could be moved to the target structure if needed
directory: Directory
"""
@@ -666,21 +683,6 @@
): RevisionConnection
}
-"""
-Possible release target objects
-"""
-union ReleaseTarget = Release | Revision | Directory | Content
-
-"""
-Possible release target types
-"""
-enum ReleaseTargetType {
- release
- revision
- content
- directory
-}
-
"""
A release object
"""
@@ -716,14 +718,44 @@
date: Date
"""
- Type of release target
+ Release target node
+ """
+ target: ReleaseTarget
+}
+
+"""
+Possible release target types
+"""
+enum ReleaseTargetType {
+ release
+ revision
+ content
+ directory
+}
+
+"""
+Possible release target nodes
+"""
+union ReleaseTargetNode = Release | Revision | Directory | Content
+
+"""
+A release target object
+"""
+type ReleaseTarget {
+ """
+ Release target type
"""
- targetType: ReleaseTargetType
+ type: ReleaseTargetType!
"""
- Release target object
+ Release target identifier
"""
- target: ReleaseTarget
+ identifier: ID!
+
+ """
+ Release target SWH object
+ """
+ node: ReleaseTargetNode
}
"""
@@ -766,10 +798,26 @@
node: DirectoryEntry
}
+
+"""
+A directory entry object
+"""
+type DirectoryEntry {
+ """
+ The directory entry name
+ """
+ name: BinaryString
+
+ """
+ Directory entry target node
+ """
+ target: DirectoryEntryTarget
+}
+
"""
Possible directory entry target objects
"""
-union DirectoryEntryTarget = Directory | Content | Revision
+union DirectoryEntryTargetNode = Directory | Content | Revision
"""
Possible directory entry types
@@ -781,25 +829,26 @@
}
"""
-A directory entry object
+A directoryentry target object
"""
-type DirectoryEntry {
+type DirectoryEntryTarget {
"""
- The directory entry name
+ Directoryentry target type
"""
- name: BinaryString
+ type: DirectoryEntryTargetType!
"""
- Directory entry object type; can be file, dir or rev
+ Directoryentry target SWHID
"""
- targetType: DirectoryEntryTargetType
+ identifier: ID!
"""
- Directory entry target object
+ Directoryentry target SWH object
"""
- target: DirectoryEntryTarget
+ node: DirectoryEntryTargetNode
}
+
"""
A directory object
"""
@@ -974,8 +1023,20 @@
node: SearchResult
}
-union SearchResultTarget = Origin | Revision | Release | Content | Directory | Snapshot
+"""
+A SearchResult object
+"""
+type SearchResult {
+ """
+ Result target object
+ """
+ target: SearchResultTarget
+}
+
+"""
+Possible search result target types
+"""
enum SearchResultTargetType {
origin
revision
@@ -986,18 +1047,28 @@
}
"""
-A SearchResult object
+Possible search result target nodes
"""
-type SearchResult {
+union SearchResultTargetNode = Origin | Revision | Release | Content | Directory | Snapshot
+
+"""
+A search target object
+"""
+type SearchResultTarget {
"""
- Result target type
+ Search result target type
"""
- targetType: SearchResultTargetType
+ type: SearchResultTargetType
"""
- Result target object
+ Search result target identifier
"""
- target: SearchResultTarget
+ identifier: ID!
+
+ """
+ Search result target SWH object
+ """
+ node: SearchResultTargetNode
}
"""
diff --git a/swh/graphql/tests/functional/test_branch_connection.py b/swh/graphql/tests/functional/test_branch_connection.py
--- a/swh/graphql/tests/functional/test_branch_connection.py
+++ b/swh/graphql/tests/functional/test_branch_connection.py
@@ -19,31 +19,33 @@
endCursor
}
nodes {
- targetType
name {
text
}
target {
- __typename
- ...on Branch {
- name {
- text
+ type
+ node {
+ __typename
+ ...on Branch {
+ name {
+ text
+ }
+ }
+ ...on Revision {
+ swhid
+ }
+ ...on Release {
+ swhid
+ }
+ ...on Content {
+ swhid
+ }
+ ...on Directory {
+ swhid
+ }
+ ...on Snapshot {
+ swhid
}
- }
- ...on Revision {
- swhid
- }
- ...on Release {
- swhid
- }
- ...on Content {
- swhid
- }
- ...on Directory {
- swhid
- }
- ...on Snapshot {
- swhid
}
}
}
@@ -63,10 +65,12 @@
assert node == {
"name": {"text": "target/revision"},
"target": {
- "__typename": "Revision",
- "swhid": "swh:1:rev:66c7c1cd9673275037140f2abff7b7b11fc9439c",
+ "type": "revision",
+ "node": {
+ "__typename": "Revision",
+ "swhid": "swh:1:rev:66c7c1cd9673275037140f2abff7b7b11fc9439c",
+ },
},
- "targetType": "revision",
}
@@ -76,8 +80,10 @@
node = data["snapshot"]["branches"]["nodes"][0]
assert node == {
"name": {"text": "target/alias"},
- "target": {"__typename": "Branch", "name": {"text": "target/revision"}},
- "targetType": "alias",
+ "target": {
+ "type": "alias",
+ "node": {"__typename": "Branch", "name": {"text": "target/revision"}},
+ },
}
@@ -96,8 +102,8 @@
data, _ = get_branches(client, swhid=swhid, first=10, types=[filter_type])
assert len(data["snapshot"]["branches"]["nodes"]) == count
for node in data["snapshot"]["branches"]["nodes"]:
- assert node["target"]["__typename"] == target_type
- assert node["target"]["swhid"].startswith(swhid_pattern)
+ assert node["target"]["node"]["__typename"] == target_type
+ assert node["target"]["node"]["swhid"].startswith(swhid_pattern)
@pytest.mark.parametrize(
diff --git a/swh/graphql/tests/functional/test_content.py b/swh/graphql/tests/functional/test_content.py
--- a/swh/graphql/tests/functional/test_content.py
+++ b/swh/graphql/tests/functional/test_content.py
@@ -233,11 +233,14 @@
swhid
entries(first: 2) {
nodes {
- targetType
target {
- ...on Content {
- swhid
- length
+ type
+ identifier
+ node {
+ ...on Content {
+ swhid
+ length
+ }
}
}
}
@@ -248,6 +251,10 @@
data, _ = utils.get_query_response(client, query_str, swhid=directory_swhid)
content_obj = data["directory"]["entries"]["nodes"][1]["target"]
assert content_obj == {
- "length": 4,
- "swhid": "swh:1:cnt:86bc6b377e9d25f9d26777a4a28d08e63e7c5779",
+ "type": "content",
+ "identifier": "86bc6b377e9d25f9d26777a4a28d08e63e7c5779",
+ "node": {
+ "length": 4,
+ "swhid": "swh:1:cnt:86bc6b377e9d25f9d26777a4a28d08e63e7c5779",
+ },
}
diff --git a/swh/graphql/tests/functional/test_directory.py b/swh/graphql/tests/functional/test_directory.py
--- a/swh/graphql/tests/functional/test_directory.py
+++ b/swh/graphql/tests/functional/test_directory.py
@@ -65,8 +65,10 @@
release(swhid: $swhid) {
swhid
target {
- ...on Directory {
- swhid
+ node {
+ ...on Directory {
+ swhid
+ }
}
}
}
@@ -77,7 +79,7 @@
query_str,
swhid="swh:1:rel:ee4d20e80af850cc0f417d25dc5073792c5010d2",
)
- assert data["release"]["target"] == {
+ assert data["release"]["target"]["node"] == {
"swhid": "swh:1:dir:0505050505050505050505050505050505050505"
}
diff --git a/swh/graphql/tests/functional/test_directory_entry.py b/swh/graphql/tests/functional/test_directory_entry.py
--- a/swh/graphql/tests/functional/test_directory_entry.py
+++ b/swh/graphql/tests/functional/test_directory_entry.py
@@ -30,10 +30,13 @@
name {
text
}
- targetType
target {
- ...on Content {
- swhid
+ type
+ identifier
+ node {
+ ...on Content {
+ swhid
+ }
}
}
}
@@ -59,16 +62,18 @@
name {
text
}
- targetType
target {
- ...on Content {
- swhid
- }
- ...on Directory {
- swhid
- }
- ...on Revision {
- swhid
+ type
+ node {
+ ...on Content {
+ swhid
+ }
+ ...on Directory {
+ swhid
+ }
+ ...on Revision {
+ swhid
+ }
}
}
}
@@ -96,8 +101,12 @@
)
assert data["directoryEntry"] == {
"name": {"text": entry["name"].decode()},
- "target": {"swhid": str(swhid)} if swhid else None,
- "targetType": get_target_type(entry["type"]),
+ "target": {
+ "type": get_target_type(entry["type"]),
+ "node": {"swhid": str(swhid)},
+ }
+ if swhid
+ else {"type": get_target_type(entry["type"]), "node": None},
}
@@ -109,10 +118,12 @@
swhid
entries {
nodes {
- targetType
name {
text
}
+ target {
+ type
+ }
}
}
}
@@ -122,7 +133,10 @@
directory_entries = data["directory"]["entries"]["nodes"]
assert len(directory_entries) == len(directory.entries)
output = [
- {"name": {"text": de.name.decode()}, "targetType": get_target_type(de.type)}
+ {
+ "name": {"text": de.name.decode()},
+ "target": {"type": get_target_type(de.type)},
+ }
for de in directory.entries
]
for each_entry in output:
@@ -140,10 +154,12 @@
swhid
entries(nameInclude: $nameInclude) {
nodes {
- targetType
name {
text
}
+ target {
+ type
+ }
}
}
}
@@ -157,7 +173,7 @@
)
for entry in data["directory"]["entries"]["nodes"]:
assert name_include in entry["name"]["text"]
- assert entry["targetType"] == get_target_type(dir_entry["type"])
+ assert entry["target"]["type"] == get_target_type(dir_entry["type"])
def test_directory_entry_connection_filter_by_name_special_chars(client):
@@ -167,7 +183,6 @@
directory(swhid: $swhid) {
entries(nameInclude: $nameInclude) {
nodes {
- targetType
name {
text
}
@@ -184,5 +199,4 @@
)
assert data["directory"]["entries"]["nodes"][0] == {
"name": {"text": "ßßétEÉt"},
- "targetType": "content",
}
diff --git a/swh/graphql/tests/functional/test_release_node.py b/swh/graphql/tests/functional/test_release_node.py
--- a/swh/graphql/tests/functional/test_release_node.py
+++ b/swh/graphql/tests/functional/test_release_node.py
@@ -50,7 +50,9 @@
base64
}
}
- targetType
+ target {
+ type
+ }
}
}
"""
@@ -81,7 +83,9 @@
}
if release.date
else None,
- "targetType": release.target_type.value,
+ "target": {
+ "type": release.target_type.value,
+ },
}
@@ -104,19 +108,21 @@
query_str = """
query getRelease($swhid: SWHID!) {
release(swhid: $swhid) {
- targetType
target {
- ...on Revision {
- swhid
- }
- ...on Release {
- swhid
- }
- ...on Directory {
- swhid
- }
- ...on Content {
- swhid
+ type
+ node {
+ ...on Revision {
+ swhid
+ }
+ ...on Release {
+ swhid
+ }
+ ...on Directory {
+ swhid
+ }
+ ...on Content {
+ swhid
+ }
}
}
}
@@ -127,16 +133,19 @@
)
if release_with_target.target_type == ObjectType.REVISION:
- target_swhid = get_revisions()[0].swhid()
+ target = get_revisions()[0]
elif release_with_target.target_type == ObjectType.RELEASE:
- target_swhid = get_releases()[0].swhid()
+ target = get_releases()[0]
elif release_with_target.target_type == ObjectType.DIRECTORY:
- target_swhid = get_directories()[0].swhid()
+ target = get_directories()[0]
elif release_with_target.target_type == ObjectType.CONTENT:
- target_swhid = get_contents()[0].swhid()
+ target = get_contents()[0]
assert data["release"] == {
- "targetType": release_with_target.target_type.value,
- "target": {"swhid": str(target_swhid)},
+ "target": {
+ "type": release_with_target.target_type.value,
+ # "identifier": target.id.hex(),
+ "node": {"swhid": str(target.swhid())},
+ },
}
@@ -150,22 +159,25 @@
query_str = """
query getRelease($swhid: SWHID!) {
release(swhid: $swhid) {
- targetType
target {
- ...on Revision {
- swhid
- message {
- text
+ type
+ identifier
+ node {
+ ...on Revision {
+ swhid
+ message {
+ text
+ }
+ }
+ ...on Release {
+ swhid
+ }
+ ...on Directory {
+ swhid
+ }
+ ...on Content {
+ swhid
}
- }
- ...on Release {
- swhid
- }
- ...on Directory {
- swhid
- }
- ...on Content {
- swhid
}
}
}
@@ -174,10 +186,13 @@
data, _ = utils.get_query_response(client, query_str, swhid=str(swhid))
assert data["release"] == {
"target": {
- "message": {"text": "hello"},
- "swhid": str(get_revisions()[0].swhid()),
+ "type": "revision",
+ "identifier": get_revisions()[0].id.hex(),
+ "node": {
+ "message": {"text": "hello"},
+ "swhid": str(get_revisions()[0].swhid()),
+ },
},
- "targetType": "revision",
}
diff --git a/swh/graphql/tests/functional/test_revision.py b/swh/graphql/tests/functional/test_revision.py
--- a/swh/graphql/tests/functional/test_revision.py
+++ b/swh/graphql/tests/functional/test_revision.py
@@ -137,10 +137,12 @@
snapshot(swhid: $swhid) {
branches(first: 1, types: [revision]) {
nodes {
- targetType
target {
- ...on Revision {
- swhid
+ type
+ node {
+ ...on Revision {
+ swhid
+ }
}
}
}
@@ -149,7 +151,7 @@
}
"""
data, _ = utils.get_query_response(client, query_str, swhid=snapshot_swhid)
- revision_obj = data["snapshot"]["branches"]["nodes"][0]["target"]
+ revision_obj = data["snapshot"]["branches"]["nodes"][0]["target"]["node"]
assert revision_obj == {
"swhid": "swh:1:rev:66c7c1cd9673275037140f2abff7b7b11fc9439c"
}
diff --git a/swh/graphql/tests/functional/test_search.py b/swh/graphql/tests/functional/test_search.py
--- a/swh/graphql/tests/functional/test_search.py
+++ b/swh/graphql/tests/functional/test_search.py
@@ -11,12 +11,14 @@
query doSearch($query: String!, $first: Int!) {
search(query: $query, first: $first) {
nodes {
- targetType
target {
- ...on Origin {
- url
- latestVisit {
- date
+ type
+ node {
+ ...on Origin {
+ url
+ latestVisit {
+ date
+ }
}
}
}
@@ -35,10 +37,12 @@
"nodes": [
{
"target": {
- "url": "https://somewhere.org/den/fox",
- "latestVisit": {"date": "2018-11-27T17:20:39+00:00"},
+ "type": "origin",
+ "node": {
+ "url": "https://somewhere.org/den/fox",
+ "latestVisit": {"date": "2018-11-27T17:20:39+00:00"},
+ },
},
- "targetType": "origin",
}
],
"pageInfo": {"endCursor": "MQ==", "hasNextPage": True},
@@ -51,7 +55,9 @@
query doSearch($query: String!, $first: Int!) {
search(query: $query, first: $first) {
nodes {
- targetType
+ target {
+ type
+ }
}
pageInfo {
hasNextPage
diff --git a/swh/graphql/tests/functional/test_snapshot_node.py b/swh/graphql/tests/functional/test_snapshot_node.py
--- a/swh/graphql/tests/functional/test_snapshot_node.py
+++ b/swh/graphql/tests/functional/test_snapshot_node.py
@@ -18,10 +18,12 @@
swhid
branches(first:5) {
nodes {
- targetType
name {
text
}
+ target {
+ type
+ }
}
}
}
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,7 +19,9 @@
query_str = """
query resolve($swhid: SWHID!) {
resolveSWHID(swhid: $swhid) {
- targetType
+ target {
+ type
+ }
}
}
"""
@@ -43,7 +45,9 @@
query_str = """
query resolve($swhid: SWHID!) {
resolveSWHID(swhid: $swhid) {
- targetType
+ target {
+ type
+ }
}
}
"""
@@ -57,11 +61,13 @@
query_str = """
query resolve($swhid: SWHID!) {
resolveSWHID(swhid: $swhid) {
- targetType
target {
- __typename
- ... on Snapshot {
- swhid
+ type
+ node {
+ __typename
+ ... on Snapshot {
+ swhid
+ }
}
}
}
@@ -72,10 +78,12 @@
"resolveSWHID": [
{
"target": {
- "__typename": "Snapshot",
- "swhid": str(snapshot.swhid()),
+ "type": "snapshot",
+ "node": {
+ "__typename": "Snapshot",
+ "swhid": str(snapshot.swhid()),
+ },
},
- "targetType": "snapshot",
}
]
}
@@ -86,11 +94,13 @@
query_str = """
query resolve($swhid: SWHID!) {
resolveSWHID(swhid: $swhid) {
- targetType
target {
- __typename
- ... on Revision {
- swhid
+ type
+ node {
+ __typename
+ ... on Revision {
+ swhid
+ }
}
}
}
@@ -101,10 +111,12 @@
"resolveSWHID": [
{
"target": {
- "__typename": "Revision",
- "swhid": str(revision.swhid()),
- },
- "targetType": "revision",
+ "type": "revision",
+ "node": {
+ "__typename": "Revision",
+ "swhid": str(revision.swhid()),
+ },
+ }
}
]
}
@@ -115,11 +127,13 @@
query_str = """
query resolve($swhid: SWHID!) {
resolveSWHID(swhid: $swhid) {
- targetType
- target {
- __typename
- ... on Release {
- swhid
+ target {
+ type
+ node {
+ __typename
+ ... on Release {
+ swhid
+ }
}
}
}
@@ -130,10 +144,12 @@
"resolveSWHID": [
{
"target": {
- "__typename": "Release",
- "swhid": str(release.swhid()),
- },
- "targetType": "release",
+ "type": "release",
+ "node": {
+ "__typename": "Release",
+ "swhid": str(release.swhid()),
+ },
+ }
}
]
}
@@ -144,11 +160,13 @@
query_str = """
query resolve($swhid: SWHID!) {
resolveSWHID(swhid: $swhid) {
- targetType
target {
- __typename
- ... on Directory {
- swhid
+ type
+ node {
+ __typename
+ ... on Directory {
+ swhid
+ }
}
}
}
@@ -159,10 +177,12 @@
"resolveSWHID": [
{
"target": {
- "__typename": "Directory",
- "swhid": str(directory.swhid()),
- },
- "targetType": "directory",
+ "type": "directory",
+ "node": {
+ "__typename": "Directory",
+ "swhid": str(directory.swhid()),
+ },
+ }
}
]
}
@@ -173,11 +193,13 @@
query_str = """
query resolve($swhid: SWHID!) {
resolveSWHID(swhid: $swhid) {
- targetType
target {
- __typename
- ... on Content {
- swhid
+ type
+ node {
+ __typename
+ ... on Content {
+ swhid
+ }
}
}
}
@@ -188,10 +210,12 @@
"resolveSWHID": [
{
"target": {
- "__typename": "Content",
- "swhid": str(content.swhid()),
- },
- "targetType": "content",
+ "type": "content",
+ "node": {
+ "__typename": "Content",
+ "swhid": str(content.swhid()),
+ },
+ }
}
]
}
diff --git a/swh/graphql/tests/unit/resolvers/test_resolvers.py b/swh/graphql/tests/unit/resolvers/test_resolvers.py
--- a/swh/graphql/tests/unit/resolvers/test_resolvers.py
+++ b/swh/graphql/tests/unit/resolvers/test_resolvers.py
@@ -32,6 +32,7 @@
(rs.release_resolver, resolvers.release.ReleaseNode),
(rs.directory_resolver, resolvers.directory.DirectoryNode),
(rs.content_by_hashes_resolver, resolvers.content.ContentbyHashesNode),
+ (rs.generic_target_resolver, resolvers.target.TargetNode),
],
)
def test_node_resolver(self, mocker, dummy_node, resolver_func, node_cls):
@@ -65,58 +66,6 @@
# assert the right object is returned
assert isinstance(connection_obj, connection_cls)
- @pytest.mark.parametrize(
- "branch_type, node_cls",
- [
- ("revision", resolvers.revision.TargetRevisionNode),
- ("release", resolvers.release.TargetReleaseNode),
- ("directory", resolvers.directory.TargetDirectoryNode),
- ("content", resolvers.content.TargetContentNode),
- ("snapshot", resolvers.snapshot.TargetSnapshotNode),
- ],
- )
- def test_snapshot_branch_target_resolver(
- self, mocker, dummy_node, branch_type, node_cls
- ):
- obj = mocker.Mock(targetType=branch_type)
- mock_get = mocker.patch.object(node_cls, "_get_node", return_value=dummy_node)
- node_obj = rs.snapshot_branch_target_resolver(obj, None)
- assert isinstance(node_obj, node_cls)
- assert mock_get.assert_called
-
- @pytest.mark.parametrize(
- "target_type, node_cls",
- [
- ("revision", resolvers.revision.TargetRevisionNode),
- ("release", resolvers.release.TargetReleaseNode),
- ("directory", resolvers.directory.TargetDirectoryNode),
- ("content", resolvers.content.TargetContentNode),
- ],
- )
- def test_release_target_resolver(self, mocker, dummy_node, target_type, node_cls):
- obj = mocker.Mock(targetType=target_type)
- mock_get = mocker.patch.object(node_cls, "_get_node", return_value=dummy_node)
- node_obj = rs.release_target_resolver(obj, None)
- assert isinstance(node_obj, node_cls)
- assert mock_get.assert_called
-
- @pytest.mark.parametrize(
- "target_type, node_cls",
- [
- ("directory", resolvers.directory.TargetDirectoryNode),
- ("content", resolvers.content.TargetContentNode),
- ("revision", resolvers.revision.TargetRevisionNode),
- ],
- )
- def test_directory_entry_target_resolver(
- self, mocker, dummy_node, target_type, node_cls
- ):
- obj = mocker.Mock(targetType=target_type)
- mock_get = mocker.patch.object(node_cls, "_get_node", return_value=dummy_node)
- node_obj = rs.directory_entry_target_resolver(obj, None)
- assert isinstance(node_obj, node_cls)
- assert mock_get.assert_called
-
def test_union_resolver(self, mocker):
obj = mocker.Mock()
obj.is_type_of.return_value = "test"
diff --git a/swh/graphql/tests/unit/resolvers/test_scalars.py b/swh/graphql/tests/unit/resolvers/test_scalars.py
--- a/swh/graphql/tests/unit/resolvers/test_scalars.py
+++ b/swh/graphql/tests/unit/resolvers/test_scalars.py
@@ -12,7 +12,7 @@
def test_serialize_id():
- assert scalars.serialize_id("test") == "74657374"
+ assert scalars.serialize_id("test") == "test"
assert scalars.serialize_id(b"test") == "74657374"

File Metadata

Mime Type
text/plain
Expires
Tue, Dec 17, 4:11 PM (2 d, 20 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3219474

Event Timeline