Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F9337315
D7887.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Subscribers
None
D7887.id.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
@@ -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
Details
Attached
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
Attached To
D7887: Possibility to search with a SWHID.
Event Timeline
Log In to Comment