diff --git a/swh/graphql/resolvers/base_node.py b/swh/graphql/resolvers/base_node.py index 21c1fd4..5d5fe72 100644 --- a/swh/graphql/resolvers/base_node.py +++ b/swh/graphql/resolvers/base_node.py @@ -1,62 +1,70 @@ from abc import ABC from collections import namedtuple from swh.graphql.errors import ObjectNotFoundError class BaseNode(ABC): """ Base class for all the Node resolvers """ def __init__(self, obj, info, node_data=None, **kwargs): self.obj = obj self.info = info self.kwargs = kwargs - self._set_node(node_data) + self._node = self._get_node(node_data) + # handle the errors, if any, after _node is set + self._handle_node_errors() - def _set_node(self, node_data): + def _get_node(self, node_data): + """ + Get the node object from the given data + if the data (node_data) is none make + a function call to get data from backend + """ if node_data is None: node_data = self._get_node_data() - self._node = self._get_node_from_data(node_data) + return self._get_node_from_data(node_data) def _get_node_from_data(self, node_data): """ - Create an object from the dict - Override to support complex data structures + Get the object from node_data + In case of a dict, covert it to an object + Override to support different data structures """ - if node_data is None: - self._handle_none_data() - if type(node_data) is dict: return namedtuple("NodeObj", node_data.keys())(*node_data.values()) return node_data - def _handle_none_data(self): + def _handle_node_errors(self): """ - raise and error in case the object returned is None - override for desired behaviour + Handle any error related to node data + + raise an error in case the object returned is None + override for specific behaviour """ - raise ObjectNotFoundError("Requested object is not available") + if self._node is None: + raise ObjectNotFoundError("Requested object is not available") def __call__(self, *args, **kw): return self def _get_node_data(self): """ Override for desired behaviour This will be called only when - node_data is not available + node_data is None """ # FIXME, make this call async (not for v1) return None def __getattr__(self, name): """ Any property defined in the sub-class will get precedence over the _node attributes """ return getattr(self._node, name) def is_type_of(self): return self.__class__.__name__ diff --git a/swh/graphql/resolvers/release.py b/swh/graphql/resolvers/release.py index 32d7e42..43ceeec 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 + 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" + 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("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 026d1be..feac370 100644 --- a/swh/graphql/resolvers/revision.py +++ b/swh/graphql/resolvers/revision.py @@ -1,97 +1,100 @@ 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 + + # FIXME, now making one db calls per parent + # Change to get the nodedata list here itself 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("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)