From 87a98fc6f8a904fa575fc20946c64ad0abeae3d8 Mon Sep 17 00:00:00 2001 From: MardanovTimur Date: Fri, 22 Mar 2019 22:51:19 +0300 Subject: [PATCH] fixed custom directives --- examples/neomodel/__init__.py | 0 examples/neomodel/models.py | 0 examples/neomodel/nodes | 0 examples/neomodel/queries.py | 0 examples/neomodel/test.py | 28 +++++++++++++++ graphene_django/directives.py | 24 +++++++++++++ graphene_django/middleware.py | 68 +++++++++++++++++++++++++++++++++++ graphene_django/views.py | 7 ++++ 8 files changed, 127 insertions(+) create mode 100644 examples/neomodel/__init__.py create mode 100644 examples/neomodel/models.py create mode 100644 examples/neomodel/nodes create mode 100644 examples/neomodel/queries.py create mode 100644 examples/neomodel/test.py create mode 100644 graphene_django/directives.py create mode 100644 graphene_django/middleware.py diff --git a/examples/neomodel/__init__.py b/examples/neomodel/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/neomodel/models.py b/examples/neomodel/models.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/neomodel/nodes b/examples/neomodel/nodes new file mode 100644 index 0000000..e69de29 diff --git a/examples/neomodel/queries.py b/examples/neomodel/queries.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/neomodel/test.py b/examples/neomodel/test.py new file mode 100644 index 0000000..2baf39d --- /dev/null +++ b/examples/neomodel/test.py @@ -0,0 +1,28 @@ + +def find_brakes(self, recursion): + pass + + +REGEXES = [ + r'((?P\*+)(?P\s?\w+\s*)(?P(\{|.*|\n*|\})*))', + r'(\*node\s)*(\{(((?>[^{}]+)|(?R))*)\})', +] + +query = """ +query recursion_point { + module { + id + name + *module { + edges { + node { + id + } + } + } + } +} +""" + +if __name__ == "__main__": + diff --git a/graphene_django/directives.py b/graphene_django/directives.py new file mode 100644 index 0000000..c2a8071 --- /dev/null +++ b/graphene_django/directives.py @@ -0,0 +1,24 @@ +from .middleware import BaseCustomDirective +from graphql.type.definition import GraphQLArgument, GraphQLNonNull +from graphql.type.scalars import GraphQLString + +class DefaultDirective(BaseCustomDirective): + """ + Default to given value if None + """ + @staticmethod + def get_args(): + return { + 'to': GraphQLArgument( + type=GraphQLNonNull(GraphQLString), + description='Value to default to', + ), + } + + + @staticmethod + def process(value, directive, root, info, **kwargs): + if value is None: + to_argument = [arg for arg in directive.arguments if arg.name.value == 'to'][0] + return to_argument.value.value + return value diff --git a/graphene_django/middleware.py b/graphene_django/middleware.py new file mode 100644 index 0000000..9949cc0 --- /dev/null +++ b/graphene_django/middleware.py @@ -0,0 +1,68 @@ +import six +from graphql import DirectiveLocation, GraphQLDirective +from promise import Promise + +class DirectivesMiddleware(object): + + def resolve(self, next, root, info, **kwargs): + result = next(root, info, **kwargs) + return result.then( + lambda resolved: self.__process_value(resolved, root, info, **kwargs), + lambda error: Promise.rejected(error) + ) + + def __process_value(self, value, root, info, **kwargs): + field = info.field_asts[0] + # if field has not directive - return model-value + if not field.directives: + return value + new_value = value + # for each by field.directives + for directive in field.directives: + directive_class = CustomDirectiveMeta.REGISTRY.get(directive.name.value) + if directive_class: + # if directive class found + new_value = directive_class.process(new_value, directive, root, info, **kwargs) + return new_value + + +class CustomDirectiveMeta(type): + REGISTRY = {} + + def __new__(mcs, name, bases, attrs): + newclass = super(CustomDirectiveMeta, mcs).__new__(mcs, name, bases, attrs) + if name != 'BaseCustomDirective': + mcs.register(newclass) + return newclass + + @classmethod + def register(mcs, target): + mcs.REGISTRY[target.get_name()] = target + + @classmethod + def get_all_directives(cls): + return [d() for d in cls.REGISTRY.values()] + + +class BaseCustomDirective(six.with_metaclass(CustomDirectiveMeta, GraphQLDirective)): + __metaclass__ = CustomDirectiveMeta + + def __init__(self): + super(BaseCustomDirective, self).__init__( + name=self.get_name(), + description=self.__doc__, + args=self.get_args(), + locations=[ + DirectiveLocation.FIELD + ] + ) + + @classmethod + def get_name(cls): + return cls.__name__.replace('Directive', '').lower() + + @staticmethod + def get_args(): + return {} + +from .directives import * # define the directives diff --git a/graphene_django/views.py b/graphene_django/views.py index be7ccf9..3a0b157 100644 --- a/graphene_django/views.py +++ b/graphene_django/views.py @@ -17,6 +17,7 @@ from graphql.execution import ExecutionResult from graphql.type.schema import GraphQLSchema from .settings import graphene_settings +from .middleware import DirectivesMiddleware class HttpError(Exception): @@ -84,6 +85,7 @@ class GraphQLView(View): middleware = graphene_settings.MIDDLEWARE self.schema = self.schema or schema + middleware = self.get_directive_middleware() if middleware is not None: self.middleware = list(instantiate_middleware(middleware)) self.executor = executor @@ -98,6 +100,11 @@ class GraphQLView(View): ), "A Schema is required to be provided to GraphQLView." assert not all((graphiql, batch)), "Use either graphiql or batch processing" + + def get_directive_middleware(self, custom=True): + return [DirectivesMiddleware, ] + + # noinspection PyUnusedLocal def get_root_value(self, request): return self.root_value