Page MenuHomeSoftware Heritage

D7887.id.diff
No OneTemporary

D7887.id.diff

diff --git a/swh/graphql/app.py b/swh/graphql/app.py
--- a/swh/graphql/app.py
+++ b/swh/graphql/app.py
@@ -30,9 +30,11 @@
resolvers.release,
resolvers.directory,
resolvers.directory_entry,
+ resolvers.search_result,
resolvers.branch_target,
resolvers.release_target,
resolvers.directory_entry_target,
+ resolvers.search_result_target,
scalars.id_scalar,
scalars.string_scalar,
scalars.datetime_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
@@ -31,8 +31,10 @@
class ContentNode(BaseContentNode):
def _get_node_data(self):
"""
- When a content is requested directly
- with its SWHID
+ When a content is requested directly with its SWHID
+
+ This is also used for resolving SearchTarget when
+ searched with a content SWHID
"""
return self._get_content_by_id(self.kwargs.get("swhid").object_id)
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
@@ -24,6 +24,9 @@
def _get_node_data(self):
"""
When a directory is requested directly with its SWHID
+
+ This is also used for resolving SearchTarget when
+ searched with a directory SWHID
"""
directory_id = self.kwargs.get("swhid").object_id
# path = ""
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
@@ -13,6 +13,14 @@
def _get_node_data(self):
return archive.Archive().get_origin(self.kwargs.get("url"))
+ def is_type_of(self):
+ """
+ is_type_of is required only when resolving
+ a UNION type
+ This is for ariadne to return the right type
+ """
+ return "Origin"
+
class OriginConnection(BaseConnection):
_node_class = OriginNode
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
@@ -32,6 +32,9 @@
class ReleaseNode(BaseReleaseNode):
"""
When the release is requested directly with its SWHID
+
+ This is also used for resolving SearchTarget when
+ searched with a release SWHID
"""
def _get_node_data(self):
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
@@ -14,6 +14,7 @@
RevisionNode,
TargetRevisionNode,
)
+from .search import SearchSWHIDNode
from .snapshot import OriginSnapshotConnection, SnapshotNode, VisitSnapshotNode
from .snapshot_branch import SnapshotBranchConnection
from .visit import LatestVisitNode, OriginVisitConnection, OriginVisitNode
@@ -42,10 +43,11 @@
"content": ContentNode,
"dir-entry-dir": TargetDirectoryNode,
"dir-entry-file": TargetContentNode,
+ "resolve-swhid": SearchSWHIDNode,
}
- if resolver_type not in mapping:
+ if resolver_type.lower() not in mapping:
raise AttributeError(f"Invalid node type: {resolver_type}")
- return mapping[resolver_type]
+ return mapping[resolver_type.lower()]
def get_connection_resolver(resolver_type):
@@ -60,6 +62,6 @@
"revision-log": LogRevisionConnection,
"directory-entries": DirectoryEntryConnection,
}
- if resolver_type not in mapping:
+ if resolver_type.lower() not in mapping:
raise AttributeError(f"Invalid connection type: {resolver_type}")
- return mapping[resolver_type]
+ return mapping[resolver_type.lower()]
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
@@ -28,10 +28,12 @@
release: ObjectType = ObjectType("Release")
directory: ObjectType = ObjectType("Directory")
directory_entry: ObjectType = ObjectType("DirectoryEntry")
+search_result: ObjectType = ObjectType("SearchResult")
branch_target: UnionType = UnionType("BranchTarget")
release_target: UnionType = UnionType("ReleaseTarget")
directory_entry_target: UnionType = UnionType("DirectoryEntryTarget")
+search_result_target: UnionType = UnionType("SearchResultTarget")
# Node resolvers
# A node resolver should return an instance of BaseNode
@@ -165,6 +167,23 @@
return resolver(obj, info, **kw)()
+@query.field("resolveSWHID")
+def search_swhid_resolver(obj: None, info: GraphQLResolveInfo, **kw):
+ resolver = get_node_resolver("resolve-swhid")
+ return resolver(obj, info, **kw)
+
+
+@search_result.field("target")
+def search_swhid_target_resolver(
+ obj: rs.search.SearchSWHIDNode, info: GraphQLResolveInfo, **kw
+):
+ # Reusing the existing resolvers here (eg: RevisionNode for the rev SWHID)
+ # TODO; maybe it is better to have a separate class (eg SearchRevisionNode)
+ resolver = get_node_resolver(obj.targetType)
+ # Using the kwargs of the parent to reuse the same resolver
+ return resolver(obj, info, **obj.kwargs)
+
+
# Connection resolvers
# A connection resolver should return an instance of BaseConnection
@@ -235,6 +254,7 @@
# Any other type of resolver
+@search_result_target.type_resolver
@release_target.type_resolver
@directory_entry_target.type_resolver
@branch_target.type_resolver
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
@@ -45,6 +45,9 @@
class RevisionNode(BaseRevisionNode):
"""
When the revision is requested directly with its SWHID
+
+ This is also used for resolving SearchTarget when
+ searched with a revision SWHID
"""
def _get_node_data(self):
diff --git a/swh/graphql/resolvers/search.py b/swh/graphql/resolvers/search.py
new file mode 100644
--- /dev/null
+++ b/swh/graphql/resolvers/search.py
@@ -0,0 +1,7 @@
+from .base_node import BaseNode
+
+
+class SearchSWHIDNode(BaseNode):
+ def _get_node_data(self):
+ swhid = self.kwargs.get("swhid")
+ return {"targetType": swhid.object_type.name.lower(), "targetSWHID": swhid.object_id}
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
@@ -18,10 +18,21 @@
# Same pattern is used in directory
return Snapshot(id=snapshot_id, branches={})
+ def is_type_of(self):
+ """
+ is_type_of is required only when resolving
+ a UNION type
+ This is for ariadne to return the right type
+ """
+ return "Snapshot"
+
class SnapshotNode(BaseSnapshotNode):
"""
For directly accessing a snapshot with its SWHID
+
+ This is also used for resolving SearchTarget when
+ searched with a snapshot SWHID
"""
def _get_node_data(self):
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
@@ -789,6 +789,78 @@
status: String
}
+"""
+Connection to search results
+"""
+type SearchResultConnection {
+ """
+ List of search result edges
+ """
+ edges: [SearchResultEdge]
+
+ """
+ List of search result nodes
+ """
+ nodes: [SearchResult]
+
+ """
+ Information for pagination
+ """
+ pageInfo: PageInfo!
+
+ """
+ Total number of search result objects in the connection
+ """
+ totalCount: Int
+}
+
+"""
+Edge in search result connection
+"""
+type SearchResultEdge {
+ """
+ Cursor to request the next page after the item
+ """
+ cursor: String!
+
+ """
+ Directory entry object
+ """
+ node: SearchResult
+}
+
+"""
+Possible object types in a search result
+"""
+union SearchResultTarget = Snapshot | Revision | Release | Directory | Content | Origin
+
+"""
+Possible Search target types
+"""
+enum SearchTargetType {
+ origin
+ snapshot
+ revision
+ release
+ directory
+ content
+}
+
+"""
+A search result object
+"""
+type SearchResult {
+ """
+ Search result object type
+ """
+ targetType: SearchTargetType
+
+ """
+ Search result object
+ """
+ target: SearchResultTarget
+}
+
"""
The query root of the GraphQL interface.
"""
@@ -887,4 +959,14 @@
"""
swhid: SWHID!
): Content
+
+ """
+ Find an object with its SWHID
+ """
+ resolveSWHID(
+ """
+ Returns a single SearchResult object
+ """
+ swhid: SWHID!
+ ): SearchResult
}
diff --git a/swh/graphql/tests/unit/resolvers/test_resolver_factory.py b/swh/graphql/tests/unit/resolvers/test_resolver_factory.py
--- a/swh/graphql/tests/unit/resolvers/test_resolver_factory.py
+++ b/swh/graphql/tests/unit/resolvers/test_resolver_factory.py
@@ -31,6 +31,7 @@
("content", "ContentNode"),
("dir-entry-dir", "TargetDirectoryNode"),
("dir-entry-file", "TargetContentNode"),
+ ("resolve-swhid", "SearchSWHIDNode"),
],
)
def test_get_node_resolver(self, input_type, expected):

File Metadata

Mime Type
text/plain
Expires
Jul 3 2025, 8:00 AM (10 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3219612

Event Timeline