diff --git a/swh/graphql/app.py b/swh/graphql/app.py index 3bbae03..d1574e0 100644 --- a/swh/graphql/app.py +++ b/swh/graphql/app.py @@ -1,20 +1,21 @@ from ariadne import gql, load_schema_from_path, make_executable_schema from .resolvers import resolvers, scalars type_defs = gql(load_schema_from_path("swh/graphql/schema/schema.graphql")) schema = make_executable_schema( type_defs, resolvers.query, resolvers.origin, resolvers.visit, resolvers.visit_status, resolvers.snapshot, resolvers.snapshot_branch, resolvers.branch_target, scalars.datetime_scalar, scalars.swhid_scalar, + scalars.sha1_scalar, scalars.binary_text_scalar, scalars.datetimezone_scalar, ) diff --git a/swh/graphql/resolvers/content.py b/swh/graphql/resolvers/content.py index 39bfbe1..105eb6e 100644 --- a/swh/graphql/resolvers/content.py +++ b/swh/graphql/resolvers/content.py @@ -1,23 +1,23 @@ from swh.graphql.backends import archive from swh.graphql.utils import utils from .base_node import BaseNode class BaseContentNode(BaseNode): def _get_content_by_id(self, content_id): return archive.Archive().get_content(content_id) @property def id(self): return b"test" class ContentNode(BaseContentNode): def _get_node_data(self): """ When a content is requested directly (not from a connection) with an id """ - content_id = utils.str_to_swid(self.kwargs.get("SWHId")) + content_id = utils.str_to_swid(self.kwargs.get("SWHID")) return self._get_content_by_id(content_id)[0] diff --git a/swh/graphql/resolvers/directory.py b/swh/graphql/resolvers/directory.py index a6153a9..792560d 100644 --- a/swh/graphql/resolvers/directory.py +++ b/swh/graphql/resolvers/directory.py @@ -1,42 +1,42 @@ from swh.graphql.backends import archive from swh.graphql.utils import utils from .base_node import BaseNode class BaseDirectoryNode(BaseNode): def _get_directory_by_id(self, directory_id): return archive.Archive().get_directory(directory_id) @property def entries(self): # FIXME, return a paginated list of # directory or contnet node object return self._node[0]["name"] @property def name(self): return b"test-name" @property def id(self): return b"test-id" class DirectoryNode(BaseDirectoryNode): def _get_node_data(self): """ When a directory is requested directly (not from a connection) with an id """ - directory_id = utils.str_to_swid(self.kwargs.get("SWHId")) + directory_id = utils.str_to_swid(self.kwargs.get("Sha1")) return self._get_directory_by_id(directory_id) class RevisionDirectoryNode(BaseDirectoryNode): def _get_node_data(self): """ When a directory is requested from a revision """ directory_id = self.kwargs.get("sha1") return self._get_directory_by_id(directory_id) diff --git a/swh/graphql/resolvers/release.py b/swh/graphql/resolvers/release.py index 81eb160..32d7e42 100644 --- a/swh/graphql/resolvers/release.py +++ b/swh/graphql/resolvers/release.py @@ -1,46 +1,46 @@ from swh.graphql.backends import archive from swh.graphql.utils import utils from .base_node import BaseNode class BaseReleaseNode(BaseNode): def _get_release_by_id(self, release_id): return (archive.Archive().get_release(release_id) or None)[0] @property def author(self): # return a PersoneNode object return self._node.author class ReleaseNode(BaseReleaseNode): """ When the release is requested directly (not from a connection) with an id """ def _get_node_data(self): - release_id = utils.str_to_swid(self.kwargs.get("SWHId")) + release_id = utils.str_to_swid(self.kwargs.get("Sha1")) return self._get_release_by_id(release_id) class BranchReleaseNode(BaseReleaseNode): """ When the release is requested from a snapshot branch self.obj is a branch object self.obj.target is the release id """ def _get_node_data(self): return self._get_release_by_id(self.obj.target) def is_type_of(self): """ is_type_of is required only when requesting from a connection This is for ariadne to return the right type """ return "Release" diff --git a/swh/graphql/resolvers/revision.py b/swh/graphql/resolvers/revision.py index 9910a48..9580531 100644 --- a/swh/graphql/resolvers/revision.py +++ b/swh/graphql/resolvers/revision.py @@ -1,98 +1,98 @@ from swh.graphql.backends import archive from swh.graphql.utils import utils from .base_node import BaseNode from .directory import RevisionDirectoryNode class BaseRevisionNode(BaseNode): def _get_revision_by_id(self, revision_id): # FIXME, make this call async return (archive.Archive().get_revision(revision_id) or None)[0] @property def author(self): # return a PersoneNode object return self._node.author @property def committer(self): # return a PersoneNode object return self._node.committer @property def parentIds(self): # To support the schema naming convention return self._node.parents # @paginatedlist @property def parents(self): """ Return a list of parent revisions """ # FIXME, change this to a paginated list # Storage fix or use paginatedlist decorator # change to node factory return [ ParentRevisionNode(obj=self, info=self.info, sha1=revision_id) for revision_id in self.parentIds ] @property def directoryId(self): # To support the schema naming convention """ """ return self._node.directory @property def directory(self): """ Return the """ # FIXME change to node factory return RevisionDirectoryNode(obj=self, info=self.info, sha1=self.directoryId) def is_type_of(self): """ is_type_of is required only when requesting from a connection This is for ariadne to return the correct type in schema """ return "Revision" class RevisionNode(BaseRevisionNode): """ When the revision is requested directly (not from a connection) with an id """ def _get_node_data(self): - revision_id = utils.str_to_swid(self.kwargs.get("SWHId")) + revision_id = utils.str_to_swid(self.kwargs.get("Sha1")) return self._get_revision_by_id(revision_id) class ParentRevisionNode(BaseRevisionNode): """ When a parent revision is requested """ def _get_node_data(self): revision_id = self.kwargs.get("sha1") return self._get_revision_by_id(revision_id) class BranchRevisionNode(BaseRevisionNode): """ When the revision is requested from a snapshot branch self.obj is a branch object self.obj.target is the revision id """ def _get_node_data(self): """ self.obj.target is the Revision id """ return self._get_revision_by_id(self.obj.target) diff --git a/swh/graphql/resolvers/scalars.py b/swh/graphql/resolvers/scalars.py index 9c0ce57..f1b9a6e 100644 --- a/swh/graphql/resolvers/scalars.py +++ b/swh/graphql/resolvers/scalars.py @@ -1,28 +1,34 @@ from ariadne import ScalarType datetime_scalar = ScalarType("DateTime") -swhid_scalar = ScalarType("SWHId") +swhid_scalar = ScalarType("SWHID") +sha1_scalar = ScalarType("Sha1") binary_text_scalar = ScalarType("BinaryText") datetimezone_scalar = ScalarType("DateTimeZone") @datetime_scalar.serializer def serialize_datetime(value): # FIXME, consider timezone, use core functions return value.timestamp() @swhid_scalar.serializer def serialize_swid(value): return value.hex() +@sha1_scalar.serializer +def serialize_sha1(value): + return value.hex() + + @binary_text_scalar.serializer def serialize_binary_text(value): - # FIXME, consider non utf-8 + # FIXME return value.decode("utf-8") @datetimezone_scalar.serializer def serialize_datetimezone(value): return value.to_datetime().timestamp() diff --git a/swh/graphql/resolvers/snapshot.py b/swh/graphql/resolvers/snapshot.py index e609b54..578477c 100644 --- a/swh/graphql/resolvers/snapshot.py +++ b/swh/graphql/resolvers/snapshot.py @@ -1,43 +1,43 @@ from swh.graphql.backends import archive from swh.graphql.utils import utils from .base_node import BaseNode class BaseSnapshotNode(BaseNode): def _get_snapshot_by_id(self, snapshot_id): return archive.Archive().get_snapshot(snapshot_id) class SnapshotNode(BaseSnapshotNode): """ For directly accessing a snapshot with swhid """ def _get_node_data(self): """ """ # FIXME, use methods from SWH core - snapshot_id = utils.str_to_swid(self.kwargs.get("SWHId")) + snapshot_id = utils.str_to_swid(self.kwargs.get("Sha1")) return self._get_snapshot_by_id(snapshot_id) class VisitSnapshotNode(BaseSnapshotNode): """ For accessing a snapshot from a visitstatus type """ def _get_node_data(self): """ self.obj is visitstatus here snapshot swhid is avaialbe in the parent (self.obj) """ return self._get_snapshot_by_id(self.obj.snapshot) # class SnapshotConnection(BaseConnection): # """ # To get all the snapshots under an origin # """ # _node_class = SnapshotNode diff --git a/swh/graphql/schema/schema.graphql b/swh/graphql/schema/schema.graphql index c20a37c..3078d8c 100644 --- a/swh/graphql/schema/schema.graphql +++ b/swh/graphql/schema/schema.graphql @@ -1,254 +1,260 @@ -scalar SWHId +scalar SWHID + +scalar Sha1 scalar DateTime scalar DateTimeZone scalar BinaryText interface Node { id: ID! } +interface SWHIDNode { + id: SWHID! +} + interface SWHNode { - id: SWHId! + id: Sha1! } type PageInfo { endCursor: String hasNextPage: Boolean! } type OriginConnection { edges: [OriginEdge] nodes: [Origin] pageInfo: PageInfo! totalCount: Int } type OriginEdge { cursor: String! node: Origin } type Origin implements SWHNode { - id: SWHId! # FIXME, this is not swhid + id: Sha1! url: String! visits( first: Int after: String ): VisitConnection! } type VisitConnection { edges: [VisitEdge] nodes: [Visit] pageInfo: PageInfo! totalCount: Int } type VisitEdge { cursor: String! node: Visit } type Visit implements Node { id: ID! date: DateTime! type: String status( first: Int after: String ): VisitStatusConnection # origin: Origin # FIXME, this can be added later } type VisitStatusConnection { edges: [VisitStatusEdge] nodes: [VisitStatus] pageInfo: PageInfo! totalCount: Int } type VisitStatusEdge { cursor: String! node: VisitStatus } type VisitStatus implements Node { id: ID! status: String! date: DateTime! snapshot: Snapshot type: String } # FIXME, add OriginSnapshotConnection type Snapshot implements SWHNode { - id: SWHId! + id: Sha1! branches( first: Int after: String ): BranchConnection # releases( # first: Int # after: String # ): ReleaseConnection # FIXME, add alias type as well } type BranchConnection { edges: [BranchConnectionEdge] nodes: [Branch] pageInfo: PageInfo! totalCount: Int } type BranchConnectionEdge { cursor: String! node: [Branch] } # FIXME, this could be alias or Directory as well union BranchTarget = Revision | Release type Branch implements Node { id: ID! name: BinaryText type: String # FIXME, change to an enum target: BranchTarget } # type RevisionConnection { # } # type RevisionEdge { # } type Person { email: BinaryText name: BinaryText fullname: BinaryText } type Revision implements SWHNode { - id: SWHId! + id: Sha1! message: BinaryText author: Person committer: Person date: DateTimeZone type: String - directoryId: SWHId + directoryId: Sha1 directory: Directory - parentIds: [SWHId] + parentIds: [Sha1] parents: [Revision] } # type ReleaseConnection { # } # type ReleasEdge { # } type Release implements SWHNode { - id: SWHId! + id: Sha1! name: BinaryText message: BinaryText author: Person date: DateTimeZone } type Directory implements SWHNode { - id: SWHId! + id: Sha1! name: BinaryText entries: BinaryText # FIXME, change to Union type } -type Content implements SWHNode { - id: SWHId! +type Content implements SWHIDNode { + id: SWHID! status: String } type Query { """ Get an origin with its url """ # FIXME, find some unique id to help cache # maybe base64 encode the URL origin( url: String! ): Origin """ Get a list of origins matching the given filters Can also be used to search for an origin """ # FIMXE, use Input types to make this cleaner origins( first: Int after: String ): OriginConnection """ Get a visit object with its id and/or origin and visit id """ # FIXME, find some unique id to help cache visit( originUrl: String! id: String! ): Visit """ - Get a snapshot with SWHId + Get a snapshot with SWHID """ snapshot( - SWHId: String! + Sha1: String! ): Snapshot # """ # Get all the snapshot for the given origin # """ # originSnapshot( # originUrl: String! # first: Int # after: String # ): SnapshotConnection """ Get the revision with the given swhid """ revision( - SWHId: String! + Sha1: String! ): Revision """ Get the release with the given swhid """ release( - SWHId: String! + Sha1: String! ): Release """ Get the directory with the given swhid """ directory( - SWHId: String! + Sha1: String! ): Directory """ Get the content with the given swhid """ content( - SWHId: String! + SWHID: String! ): Content # """ # Search with the given swhid # """ # searchWithSwhid }