Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F7123024
D8704.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
49 KB
Subscribers
None
D8704.diff
View Options
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
Details
Attached
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
Attached To
D8704: [WIP] Move targets to separate objects with type and identifier
Event Timeline
Log In to Comment