From e25a92d74a50053d650ecdbfa4e5700dcaaf48e4 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 27 Jul 2017 01:25:23 -0700 Subject: [PATCH 1/5] Added context into ResolveInfo --- graphql/execution/base.py | 5 +++-- graphql/execution/executor.py | 1 + graphql/execution/experimental/fragment.py | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/graphql/execution/base.py b/graphql/execution/base.py index ca23fed9..a68e7555 100644 --- a/graphql/execution/base.py +++ b/graphql/execution/base.py @@ -272,10 +272,10 @@ def get_field_entry_key(node): class ResolveInfo(object): __slots__ = ('field_name', 'field_asts', 'return_type', 'parent_type', - 'schema', 'fragments', 'root_value', 'operation', 'variable_values') + 'schema', 'fragments', 'root_value', 'operation', 'variable_values', 'context') def __init__(self, field_name, field_asts, return_type, parent_type, - schema, fragments, root_value, operation, variable_values): + schema, fragments, root_value, operation, variable_values, context): self.field_name = field_name self.field_asts = field_asts self.return_type = return_type @@ -285,6 +285,7 @@ def __init__(self, field_name, field_asts, return_type, parent_type, self.root_value = root_value self.operation = operation self.variable_values = variable_values + self.context = context def default_resolve_fn(source, args, context, info): diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index 699ba8e7..1516ce44 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -182,6 +182,7 @@ def resolve_field(exe_context, parent_type, source, field_asts): root_value=exe_context.root_value, operation=exe_context.operation, variable_values=exe_context.variable_values, + context=context ) executor = exe_context.executor diff --git a/graphql/execution/experimental/fragment.py b/graphql/execution/experimental/fragment.py index d6b75120..47578541 100644 --- a/graphql/execution/experimental/fragment.py +++ b/graphql/execution/experimental/fragment.py @@ -57,6 +57,7 @@ def get_resolvers(context, type, field_asts): root_value=context and context.root_value, operation=context and context.operation, variable_values=context and context.variable_values, + context=context ) if isinstance(field_base_type, GraphQLObjectType): field_fragment = Fragment( From e5ec5da87d7b0917aebf2f79e6aad630829afce4 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 27 Jul 2017 01:48:03 -0700 Subject: [PATCH 2/5] Updated resolver to use (root, info, **args) --- graphql/error/tests/test_base.py | 4 +- graphql/execution/base.py | 2 +- graphql/execution/executor.py | 17 +- graphql/execution/experimental/__init__.py | 0 graphql/execution/experimental/executor.py | 66 -- graphql/execution/experimental/fragment.py | 254 ------- graphql/execution/experimental/resolver.py | 148 ---- .../execution/experimental/tests/__init__.py | 0 .../experimental/tests/skip_test_benchmark.py | 118 ---- .../experimental/tests/skip_test_fragment.py | 197 ------ .../experimental/tests/skip_test_resolver.py | 186 ----- .../experimental/tests/test_abstract.py | 297 -------- .../experimental/tests/test_directives.py | 259 ------- .../experimental/tests/test_executor.py | 180 ----- .../experimental/tests/test_lists.py | 211 ------ .../experimental/tests/test_mutations.py | 140 ---- .../experimental/tests/test_nonnull.py | 585 --------------- .../experimental/tests/test_querybuilder.py | 168 ----- .../experimental/tests/test_resolve.py | 136 ---- .../tests/test_union_interface.py | 358 ---------- .../experimental/tests/test_variables.py | 668 ------------------ graphql/execution/experimental/tests/utils.py | 46 -- graphql/execution/experimental/utils.py | 7 - graphql/execution/tests/test_benchmark.py | 4 +- graphql/execution/tests/test_dataloader.py | 12 +- .../execution/tests/test_execute_schema.py | 4 +- graphql/execution/tests/test_executor.py | 10 +- .../execution/tests/test_executor_thread.py | 2 +- graphql/execution/tests/test_mutations.py | 8 +- graphql/execution/tests/test_resolve.py | 10 +- graphql/execution/tests/test_variables.py | 4 +- graphql/type/definition.py | 2 +- graphql/type/introspection.py | 20 +- graphql/type/tests/test_enum_type.py | 8 +- graphql/type/tests/test_introspection.py | 2 +- graphql/utils/build_client_schema.py | 2 +- 36 files changed, 50 insertions(+), 4085 deletions(-) delete mode 100644 graphql/execution/experimental/__init__.py delete mode 100644 graphql/execution/experimental/executor.py delete mode 100644 graphql/execution/experimental/fragment.py delete mode 100644 graphql/execution/experimental/resolver.py delete mode 100644 graphql/execution/experimental/tests/__init__.py delete mode 100644 graphql/execution/experimental/tests/skip_test_benchmark.py delete mode 100644 graphql/execution/experimental/tests/skip_test_fragment.py delete mode 100644 graphql/execution/experimental/tests/skip_test_resolver.py delete mode 100644 graphql/execution/experimental/tests/test_abstract.py delete mode 100644 graphql/execution/experimental/tests/test_directives.py delete mode 100644 graphql/execution/experimental/tests/test_executor.py delete mode 100644 graphql/execution/experimental/tests/test_lists.py delete mode 100644 graphql/execution/experimental/tests/test_mutations.py delete mode 100644 graphql/execution/experimental/tests/test_nonnull.py delete mode 100644 graphql/execution/experimental/tests/test_querybuilder.py delete mode 100644 graphql/execution/experimental/tests/test_resolve.py delete mode 100644 graphql/execution/experimental/tests/test_union_interface.py delete mode 100644 graphql/execution/experimental/tests/test_variables.py delete mode 100644 graphql/execution/experimental/tests/utils.py delete mode 100644 graphql/execution/experimental/utils.py diff --git a/graphql/error/tests/test_base.py b/graphql/error/tests/test_base.py index 888285c7..d51848b3 100644 --- a/graphql/error/tests/test_base.py +++ b/graphql/error/tests/test_base.py @@ -44,7 +44,7 @@ def resolver(context, *_): ('test_reraise', 'result.errors[0].reraise()'), ('reraise', 'six.reraise(type(self), self, self.stack)'), # ('reraise', 'raise value.with_traceback(tb)'), - ('resolve_or_error', 'return executor.execute(resolve_fn, source, args, context, info)'), + ('resolve_or_error', 'return executor.execute(resolve_fn, source, info, **args)'), ('execute', 'return fn(*args, **kwargs)'), ('resolver', "raise Exception('Failed')") ] # assert formatted_tb == [ @@ -52,7 +52,7 @@ def resolver(context, *_): # ('reraise', 'six.reraise(type(self), self, self.stack)'), # ('on_complete_resolver', 'result = __resolver(*args, **kwargs)'), # # ('reraise', 'raise value.with_traceback(tb)'), - # # ('resolve_or_error', 'return executor.execute(resolve_fn, source, args, context, info)'), + # # ('resolve_or_error', 'return executor.execute(resolve_fn, source, info, **args)'), # # ('execute', 'return fn(*args, **kwargs)'), # ('resolver', "raise Exception('Failed')") # ] diff --git a/graphql/execution/base.py b/graphql/execution/base.py index a68e7555..055f438b 100644 --- a/graphql/execution/base.py +++ b/graphql/execution/base.py @@ -288,7 +288,7 @@ def __init__(self, field_name, field_asts, return_type, parent_type, self.context = context -def default_resolve_fn(source, args, context, info): +def default_resolve_fn(source, info, **args): """If a resolve function is not given, then a default resolve behavior is used which takes the property of the source object of the same name as the field and returns it as the result, or if it's a function, returns the result of calling that function.""" name = info.field_name diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index 1516ce44..7784993b 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -17,25 +17,14 @@ collect_fields, default_resolve_fn, get_field_def, get_operation_root_type) from .executors.sync import SyncExecutor -from .experimental.executor import execute as experimental_execute from .middleware import MiddlewareManager logger = logging.getLogger(__name__) -use_experimental_executor = False - - def execute(schema, document_ast, root_value=None, context_value=None, variable_values=None, operation_name=None, executor=None, return_promise=False, middleware=None): - if use_experimental_executor: - return experimental_execute( - schema, document_ast, root_value, context_value, - variable_values, operation_name, executor, - return_promise, middleware - ) - assert schema, 'Must provide schema' assert isinstance(schema, GraphQLSchema), ( 'Schema must be an instance of GraphQLSchema. Also ensure that there are ' + @@ -186,7 +175,7 @@ def resolve_field(exe_context, parent_type, source, field_asts): ) executor = exe_context.executor - result = resolve_or_error(resolve_fn_middleware, source, args, context, info, executor) + result = resolve_or_error(resolve_fn_middleware, source, info, args, executor) return complete_value_catching_error( exe_context, @@ -197,9 +186,9 @@ def resolve_field(exe_context, parent_type, source, field_asts): ) -def resolve_or_error(resolve_fn, source, args, context, info, executor): +def resolve_or_error(resolve_fn, source, info, args, executor): try: - return executor.execute(resolve_fn, source, args, context, info) + return executor.execute(resolve_fn, source, info, **args) except Exception as e: logger.exception("An error occurred while resolving field {}.{}".format( info.parent_type.name, info.field_name diff --git a/graphql/execution/experimental/__init__.py b/graphql/execution/experimental/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/graphql/execution/experimental/executor.py b/graphql/execution/experimental/executor.py deleted file mode 100644 index 352418c1..00000000 --- a/graphql/execution/experimental/executor.py +++ /dev/null @@ -1,66 +0,0 @@ -from promise import Promise - -from ...type import GraphQLSchema -from ..base import ExecutionContext, ExecutionResult, get_operation_root_type -from ..executors.sync import SyncExecutor -from ..middleware import MiddlewareManager -from .fragment import Fragment - - -def execute(schema, document_ast, root_value=None, context_value=None, - variable_values=None, operation_name=None, executor=None, - return_promise=False, middleware=None): - assert schema, 'Must provide schema' - assert isinstance(schema, GraphQLSchema), ( - 'Schema must be an instance of GraphQLSchema. Also ensure that there are ' + - 'not multiple versions of GraphQL installed in your node_modules directory.' - ) - if middleware: - if not isinstance(middleware, MiddlewareManager): - middleware = MiddlewareManager(*middleware) - assert isinstance(middleware, MiddlewareManager), ( - 'middlewares have to be an instance' - ' of MiddlewareManager. Received "{}".'.format(middleware) - ) - - if executor is None: - executor = SyncExecutor() - - context = ExecutionContext( - schema, - document_ast, - root_value, - context_value, - variable_values, - operation_name, - executor, - middleware - ) - - def executor(resolve, reject): - return resolve(execute_operation(context, context.operation, root_value)) - - def on_rejected(error): - context.errors.append(error) - return None - - def on_resolve(data): - if not context.errors: - return ExecutionResult(data=data) - return ExecutionResult(data=data, errors=context.errors) - - promise = Promise(executor).catch(on_rejected).then(on_resolve) - if return_promise: - return promise - context.executor.wait_until_finished() - return promise.get() - - -def execute_operation(exe_context, operation, root_value): - type = get_operation_root_type(exe_context.schema, operation) - execute_serially = operation.operation == 'mutation' - - fragment = Fragment(type=type, field_asts=[operation], context=exe_context) - if execute_serially: - return fragment.resolve_serially(root_value) - return fragment.resolve(root_value) diff --git a/graphql/execution/experimental/fragment.py b/graphql/execution/experimental/fragment.py deleted file mode 100644 index 47578541..00000000 --- a/graphql/execution/experimental/fragment.py +++ /dev/null @@ -1,254 +0,0 @@ -import functools - -from promise import Promise, is_thenable, promise_for_dict - -from ...pyutils.cached_property import cached_property -from ...pyutils.default_ordered_dict import DefaultOrderedDict -from ...utils.undefined import Undefined -from ...type import (GraphQLInterfaceType, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLUnionType) -from ..base import ResolveInfo, collect_fields, get_field_def -from ..values import get_argument_values -from ...error import GraphQLError -try: - from itertools import izip as zip -except: - pass - - -def get_base_type(type): - if isinstance(type, (GraphQLList, GraphQLNonNull)): - return get_base_type(type.of_type) - return type - - -def get_subfield_asts(context, return_type, field_asts): - subfield_asts = DefaultOrderedDict(list) - visited_fragment_names = set() - for field_ast in field_asts: - selection_set = field_ast.selection_set - if selection_set: - subfield_asts = collect_fields( - context, return_type, selection_set, - subfield_asts, visited_fragment_names - ) - return subfield_asts - - -def get_resolvers(context, type, field_asts): - from .resolver import field_resolver - subfield_asts = get_subfield_asts(context, type, field_asts) - - for response_name, field_asts in subfield_asts.items(): - field_ast = field_asts[0] - field_name = field_ast.name.value - field_def = get_field_def(context and context.schema, type, field_name) - if not field_def: - continue - field_base_type = get_base_type(field_def.type) - field_fragment = None - info = ResolveInfo( - field_name, - field_asts, - field_base_type, - parent_type=type, - schema=context and context.schema, - fragments=context and context.fragments, - root_value=context and context.root_value, - operation=context and context.operation, - variable_values=context and context.variable_values, - context=context - ) - if isinstance(field_base_type, GraphQLObjectType): - field_fragment = Fragment( - type=field_base_type, - field_asts=field_asts, - info=info, - context=context - ) - elif isinstance(field_base_type, (GraphQLInterfaceType, GraphQLUnionType)): - field_fragment = AbstractFragment( - abstract_type=field_base_type, - field_asts=field_asts, - info=info, - context=context - ) - resolver = field_resolver(field_def, exe_context=context, info=info, fragment=field_fragment) - args = get_argument_values( - field_def.args, - field_ast.arguments, - context and context.variable_values - ) - yield (response_name, Field(resolver, args, context and context.context_value, info)) - - -class Field(object): - __slots__ = ('fn', 'args', 'context', 'info') - - def __init__(self, fn, args, context, info): - self.fn = fn - self.args = args - self.context = context - self.info = info - - def execute(self, root): - return self.fn(root, self.args, self.context, self.info) - - -class Fragment(object): - - def __init__(self, type, field_asts, context=None, info=None): - self.type = type - self.field_asts = field_asts - self.context = context - self.info = info - - @cached_property - def partial_resolvers(self): - return list(get_resolvers( - self.context, - self.type, - self.field_asts - )) - - @cached_property - def fragment_container(self): - try: - fields = next(zip(*self.partial_resolvers)) - except StopIteration: - fields = tuple() - - class FragmentInstance(dict): - # def __init__(self): - # self.fields = fields - # _fields = ('c','b','a') - set = dict.__setitem__ - # def set(self, name, value): - # self[name] = value - - def __iter__(self): - return iter(fields) - - return FragmentInstance - - def have_type(self, root): - return not self.type.is_type_of or self.type.is_type_of(root, self.context.context_value, self.info) - - def resolve(self, root): - if root and not self.have_type(root): - raise GraphQLError( - u'Expected value of type "{}" but got: {}.'.format(self.type, type(root).__name__), - self.info.field_asts - ) - - contains_promise = False - - final_results = self.fragment_container() - # return OrderedDict( - # ((field_name, field_resolver(root, field_args, context, info)) - # for field_name, field_resolver, field_args, context, info in self.partial_resolvers) - # ) - for response_name, field_resolver in self.partial_resolvers: - - result = field_resolver.execute(root) - if result is Undefined: - continue - - if not contains_promise and is_thenable(result): - contains_promise = True - - final_results[response_name] = result - - if not contains_promise: - return final_results - - return promise_for_dict(final_results) - # return { - # field_name: field_resolver(root, field_args, context, info) - # for field_name, field_resolver, field_args, context, info in self.partial_resolvers - # } - - def resolve_serially(self, root): - def execute_field_callback(results, resolver): - response_name, field_resolver = resolver - - result = field_resolver.execute(root) - - if result is Undefined: - return results - - if is_thenable(result): - def collect_result(resolved_result): - results[response_name] = resolved_result - return results - - return result.then(collect_result) - - results[response_name] = result - return results - - def execute_field(prev_promise, resolver): - return prev_promise.then(lambda results: execute_field_callback(results, resolver)) - - return functools.reduce(execute_field, self.partial_resolvers, Promise.resolve(self.fragment_container())) - - def __eq__(self, other): - return isinstance(other, Fragment) and ( - other.type == self.type and - other.field_asts == self.field_asts and - other.context == self.context and - other.info == self.info - ) - - -class AbstractFragment(object): - - def __init__(self, abstract_type, field_asts, context=None, info=None): - self.abstract_type = abstract_type - self.field_asts = field_asts - self.context = context - self.info = info - self._fragments = {} - - @cached_property - def possible_types(self): - return self.context.schema.get_possible_types(self.abstract_type) - - @cached_property - def possible_types_with_is_type_of(self): - return [ - (type, type.is_type_of) for type in self.possible_types if callable(type.is_type_of) - ] - - def get_fragment(self, type): - if isinstance(type, str): - type = self.context.schema.get_type(type) - - if type not in self._fragments: - assert type in self.possible_types, ( - 'Runtime Object type "{}" is not a possible type for "{}".' - ).format(type, self.abstract_type) - self._fragments[type] = Fragment( - type, - self.field_asts, - self.context, - self.info - ) - - return self._fragments[type] - - def resolve_type(self, result): - return_type = self.abstract_type - context = self.context.context_value - - if return_type.resolve_type: - return return_type.resolve_type(result, context, self.info) - - for type, is_type_of in self.possible_types_with_is_type_of: - if is_type_of(result, context, self.info): - return type - - def resolve(self, root): - _type = self.resolve_type(root) - fragment = self.get_fragment(_type) - return fragment.resolve(root) diff --git a/graphql/execution/experimental/resolver.py b/graphql/execution/experimental/resolver.py deleted file mode 100644 index 272eada4..00000000 --- a/graphql/execution/experimental/resolver.py +++ /dev/null @@ -1,148 +0,0 @@ -import sys -import collections -from functools import partial - -from promise import Promise, is_thenable - -from ...error import GraphQLError, GraphQLLocatedError -from ...type import (GraphQLEnumType, GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, - GraphQLUnionType) -from ..base import default_resolve_fn -from ...execution import executor -from .utils import imap, normal_map - - -def on_complete_resolver(on_error, __func, exe_context, info, __resolver, *args, **kwargs): - try: - result = __resolver(*args, **kwargs) - if is_thenable(result): - return Promise.resolve(result).then(__func).catch(on_error) - elif isinstance(result, Exception): - return on_error(result) - return __func(result) - except Exception as e: - return on_error(e) - - -def complete_list_value(inner_resolver, exe_context, info, on_error, result): - if result is None: - return None - - assert isinstance(result, collections.Iterable), \ - ('User Error: expected iterable, but did not find one ' + - 'for field {}.{}.').format(info.parent_type, info.field_name) - - completed_results = normal_map(inner_resolver, result) - - if not any(imap(is_thenable, completed_results)): - return completed_results - - return Promise.all(completed_results).catch(on_error) - - -def complete_nonnull_value(exe_context, info, result): - if result is None: - raise GraphQLError( - 'Cannot return null for non-nullable field {}.{}.'.format( - info.parent_type, info.field_name), - info.field_asts - ) - return result - - -def complete_leaf_value(serialize, result): - if result is None: - return None - return serialize(result) - - -def complete_object_value(fragment_resolve, exe_context, on_error, result): - if result is None: - return None - - result = fragment_resolve(result) - if is_thenable(result): - return result.catch(on_error) - return result - - -def field_resolver(field, fragment=None, exe_context=None, info=None): - # resolver = exe_context.get_field_resolver(field.resolver or default_resolve_fn) - resolver = field.resolver or default_resolve_fn - if exe_context: - # We decorate the resolver with the middleware - resolver = exe_context.get_field_resolver(resolver) - return type_resolver(field.type, resolver, - fragment, exe_context, info, catch_error=True) - - -def type_resolver(return_type, resolver, fragment=None, exe_context=None, info=None, catch_error=False): - if isinstance(return_type, GraphQLNonNull): - return type_resolver_non_null(return_type, resolver, fragment, exe_context, info) - - if isinstance(return_type, (GraphQLScalarType, GraphQLEnumType)): - return type_resolver_leaf(return_type, resolver, exe_context, info, catch_error) - - if isinstance(return_type, (GraphQLList)): - return type_resolver_list(return_type, resolver, fragment, exe_context, info, catch_error) - - if isinstance(return_type, (GraphQLObjectType)): - assert fragment and fragment.type == return_type, 'Fragment and return_type dont match' - return type_resolver_fragment(return_type, resolver, fragment, exe_context, info, catch_error) - - if isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)): - assert fragment, 'You need to pass a fragment to resolve a Interface or Union' - return type_resolver_fragment(return_type, resolver, fragment, exe_context, info, catch_error) - - raise Exception("The resolver have to be created for a fragment") - - -def on_error(exe_context, info, catch_error, e): - error = e - if not isinstance(e, (GraphQLLocatedError, GraphQLError)): - error = GraphQLLocatedError(info.field_asts, original_error=e) - if catch_error: - exe_context.errors.append(error) - executor.logger.exception("An error occurred while resolving field {}.{}".format( - info.parent_type.name, info.field_name - )) - error.stack = sys.exc_info()[2] - return None - raise error - - -def type_resolver_fragment(return_type, resolver, fragment, exe_context, info, catch_error): - on_complete_type_error = partial(on_error, exe_context, info, catch_error) - complete_object_value_resolve = partial( - complete_object_value, - fragment.resolve, - exe_context, - on_complete_type_error) - on_resolve_error = partial(on_error, exe_context, info, catch_error) - return partial(on_complete_resolver, on_resolve_error, complete_object_value_resolve, exe_context, info, resolver) - - -# no catch_error -def type_resolver_non_null(return_type, resolver, fragment, exe_context, info): - resolver = type_resolver( - return_type.of_type, resolver, fragment, exe_context, info) - nonnull_complete = partial(complete_nonnull_value, exe_context, info) - on_resolve_error = partial(on_error, exe_context, info, False) - return partial(on_complete_resolver, on_resolve_error, nonnull_complete, exe_context, info, resolver) - - -def type_resolver_leaf(return_type, resolver, exe_context, info, catch_error): - leaf_complete = partial(complete_leaf_value, return_type.serialize) - on_resolve_error = partial(on_error, exe_context, info, catch_error) - return partial(on_complete_resolver, on_resolve_error, leaf_complete, exe_context, info, resolver) - - -def type_resolver_list(return_type, resolver, fragment, exe_context, info, catch_error): - item_type = return_type.of_type - inner_resolver = type_resolver( - item_type, lambda item: item, fragment, exe_context, info, catch_error=True) - on_resolve_error = partial(on_error, exe_context, info, catch_error) - list_complete = partial( - complete_list_value, inner_resolver, exe_context, info, on_resolve_error) - return partial(on_complete_resolver, on_resolve_error, list_complete, exe_context, info, resolver) diff --git a/graphql/execution/experimental/tests/__init__.py b/graphql/execution/experimental/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/graphql/execution/experimental/tests/skip_test_benchmark.py b/graphql/execution/experimental/tests/skip_test_benchmark.py deleted file mode 100644 index 407a7dc1..00000000 --- a/graphql/execution/experimental/tests/skip_test_benchmark.py +++ /dev/null @@ -1,118 +0,0 @@ -# import pytest - -# from promise import Promise - -# from ....language import ast -# from ....type import (GraphQLEnumType, GraphQLField, GraphQLInt, -# GraphQLInterfaceType, GraphQLList, GraphQLNonNull, -# GraphQLObjectType, GraphQLScalarType, GraphQLSchema, -# GraphQLString, GraphQLUnionType) -# from ..fragment import Fragment -# from ..resolver import type_resolver - -# SIZE = 10000 - - -# def test_experimental_big_list_of_ints(benchmark): -# big_int_list = [x for x in range(SIZE)] - -# resolver = type_resolver(GraphQLList(GraphQLInt), lambda: big_int_list) -# result = benchmark(resolver) - -# assert result == big_int_list - - -# def test_experimental_big_list_of_nested_ints(benchmark): -# big_int_list = [x for x in range(SIZE)] - -# Node = GraphQLObjectType( -# 'Node', -# fields={ -# 'id': GraphQLField( -# GraphQLInt, -# resolver=lambda obj, -# args, -# context, -# info: obj)}) -# selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# alias=None, -# name=ast.Name(value='id'), -# arguments=[], -# directives=[], -# selection_set=None -# ) -# ]) -# fragment = Fragment(type=Node, selection_set=selection_set) -# type = GraphQLList(Node) -# resolver = type_resolver(type, lambda: big_int_list, fragment=fragment) -# resolved = benchmark(resolver) - -# assert resolved == [{ -# 'id': n -# } for n in big_int_list] - - -# def test_experimental_big_list_of_objecttypes_with_two_int_fields(benchmark): -# big_int_list = [x for x in range(SIZE)] - -# Node = GraphQLObjectType('Node', fields={ -# 'id': GraphQLField(GraphQLInt, resolver=lambda obj, args, context, info: obj), -# 'ida': GraphQLField(GraphQLInt, resolver=lambda obj, args, context, info: obj * 2) -# }) -# selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# alias=None, -# name=ast.Name(value='id'), -# arguments=[], -# directives=[], -# selection_set=None -# ), -# ast.Field( -# alias=None, -# name=ast.Name(value='ida'), -# arguments=[], -# directives=[], -# selection_set=None -# ) -# ]) -# fragment = Fragment(type=Node, selection_set=selection_set) -# type = GraphQLList(Node) -# resolver = type_resolver(type, lambda: big_int_list, fragment=fragment) -# resolved = benchmark(resolver) - -# assert resolved == [{ -# 'id': n, -# 'ida': n * 2 -# } for n in big_int_list] - - -# def test_experimental_big_list_of_objecttypes_with_one_int_field(benchmark): -# big_int_list = [x for x in range(SIZE)] -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt, resolver=lambda obj, *_, **__: obj)}) -# Query = GraphQLObjectType( -# 'Query', -# fields={ -# 'nodes': GraphQLField( -# GraphQLList(Node), -# resolver=lambda *_, -# **__: big_int_list)}) -# node_selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='nodes'), -# selection_set=node_selection_set -# ) -# ]) -# query_fragment = Fragment(type=Query, selection_set=selection_set) -# resolver = type_resolver(Query, lambda: object(), fragment=query_fragment) -# resolved = benchmark(resolver) -# assert resolved == { -# 'nodes': [{ -# 'id': n -# } for n in big_int_list] -# } diff --git a/graphql/execution/experimental/tests/skip_test_fragment.py b/graphql/execution/experimental/tests/skip_test_fragment.py deleted file mode 100644 index b891f675..00000000 --- a/graphql/execution/experimental/tests/skip_test_fragment.py +++ /dev/null @@ -1,197 +0,0 @@ -# import pytest - -# from promise import Promise - -# from ....language import ast -# from ....language.parser import parse -# from ....type import (GraphQLEnumType, GraphQLField, GraphQLInt, -# GraphQLInterfaceType, GraphQLList, GraphQLNonNull, -# GraphQLObjectType, GraphQLScalarType, GraphQLSchema, -# GraphQLString, GraphQLUnionType) -# from ...base import ExecutionContext -# from ..fragment import Fragment -# from ..resolver import type_resolver - - -# def test_fragment_equal(): -# selection1 = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# selection2 = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# assert selection1 == selection2 -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt)}) -# Node2 = GraphQLObjectType('Node2', fields={'id': GraphQLField(GraphQLInt)}) -# fragment1 = Fragment(type=Node, selection_set=selection1) -# fragment2 = Fragment(type=Node, selection_set=selection2) -# fragment3 = Fragment(type=Node2, selection_set=selection2) -# assert fragment1 == fragment2 -# assert fragment1 != fragment3 -# assert fragment1 != object() - - -# def test_fragment_resolver(): -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt, resolver=lambda obj, *_, **__: obj * 2)}) -# selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# fragment = Fragment(type=Node, selection_set=selection_set) -# assert fragment.resolve(1) == {'id': 2} -# assert fragment.resolve(2) == {'id': 4} - - -# def test_fragment_resolver_list(): -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt, resolver=lambda obj, *_, **__: obj)}) -# selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# fragment = Fragment(type=Node, selection_set=selection_set) -# type = GraphQLList(Node) - -# resolver = type_resolver(type, lambda: range(3), fragment=fragment) -# resolved = resolver() -# assert resolved == [{ -# 'id': n -# } for n in range(3)] - - -# def test_fragment_resolver_nested(): -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt, resolver=lambda obj, *_, **__: obj)}) -# Query = GraphQLObjectType('Query', fields={'node': GraphQLField(Node, resolver=lambda *_, **__: 1)}) -# node_selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='node'), -# selection_set=node_selection_set -# ) -# ]) -# # node_fragment = Fragment(type=Node, field_asts=node_field_asts) -# query_fragment = Fragment(type=Query, selection_set=selection_set) -# resolver = type_resolver(Query, lambda: object(), fragment=query_fragment) -# resolved = resolver() -# assert resolved == { -# 'node': { -# 'id': 1 -# } -# } - - -# def test_fragment_resolver_abstract(): -# Node = GraphQLInterfaceType('Node', fields={'id': GraphQLField(GraphQLInt)}) -# Person = GraphQLObjectType( -# 'Person', -# interfaces=( -# Node, -# ), -# is_type_of=lambda *_: True, -# fields={ -# 'id': GraphQLField( -# GraphQLInt, -# resolver=lambda obj, -# *_, -# **__: obj)}) -# Query = GraphQLObjectType('Query', fields={'node': GraphQLField(Node, resolver=lambda *_, **__: 1)}) -# node_selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='node'), -# selection_set=node_selection_set -# ) -# ]) -# # node_fragment = Fragment(type=Node, field_asts=node_field_asts) -# schema = GraphQLSchema(query=Query, types=[Person]) -# document_ast = parse('''{ -# node { -# id -# } -# }''') - -# root_value = None -# context_value = None -# operation_name = None -# variable_values = {} -# executor = None -# middlewares = None -# context = ExecutionContext( -# schema, -# document_ast, -# root_value, -# context_value, -# variable_values, -# operation_name, -# executor, -# middlewares -# ) - -# query_fragment = Fragment(type=Query, selection_set=selection_set, context=context) -# resolver = type_resolver(Query, lambda: object(), fragment=query_fragment) -# resolved = resolver() -# assert resolved == { -# 'node': { -# 'id': 1 -# } -# } - - -# def test_fragment_resolver_nested_list(): -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt, resolver=lambda obj, *_, **__: obj)}) -# Query = GraphQLObjectType( -# 'Query', -# fields={ -# 'nodes': GraphQLField( -# GraphQLList(Node), -# resolver=lambda *_, -# **__: range(3))}) -# node_selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# selection_set = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='nodes'), -# selection_set=node_selection_set -# ) -# ]) -# # node_fragment = Fragment(type=Node, field_asts=node_field_asts) -# query_fragment = Fragment(type=Query, selection_set=selection_set) -# resolver = type_resolver(Query, lambda: object(), fragment=query_fragment) -# resolved = resolver() -# assert resolved == { -# 'nodes': [{ -# 'id': n -# } for n in range(3)] -# } - -# # ''' -# # { -# # books { -# # title -# # author { -# # name -# # } -# # } -# # }''' -# # BooksFragment( -# # ('title', str(resolve_title())), -# # ('author', AuthorFragment( -# # ('name', str(resolve_author())) -# # )) -# # ) diff --git a/graphql/execution/experimental/tests/skip_test_resolver.py b/graphql/execution/experimental/tests/skip_test_resolver.py deleted file mode 100644 index a8ed4715..00000000 --- a/graphql/execution/experimental/tests/skip_test_resolver.py +++ /dev/null @@ -1,186 +0,0 @@ -import mock -import pytest - -from promise import Promise - -from ....error import GraphQLError, GraphQLLocatedError -from ....language import ast -from ....type import (GraphQLEnumType, GraphQLField, GraphQLInt, - GraphQLInterfaceType, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLScalarType, GraphQLSchema, - GraphQLString, GraphQLUnionType) -from ..fragment import Fragment -from ..resolver import field_resolver, type_resolver - - -@pytest.mark.parametrize("type,value,expected", [ - (GraphQLString, 1, "1"), - (GraphQLInt, "1", 1), - (GraphQLNonNull(GraphQLString), 0, "0"), - (GraphQLNonNull(GraphQLInt), 0, 0), - (GraphQLList(GraphQLString), [1, 2], ['1', '2']), - (GraphQLList(GraphQLInt), ['1', '2'], [1, 2]), - (GraphQLList(GraphQLNonNull(GraphQLInt)), [0], [0]), - (GraphQLNonNull(GraphQLList(GraphQLInt)), [], []), -]) -def test_type_resolver(type, value, expected): - resolver = type_resolver(type, lambda: value) - resolved = resolver() - assert resolved == expected - - -@pytest.mark.parametrize("type,value,expected", [ - (GraphQLString, 1, "1"), - (GraphQLInt, "1", 1), - (GraphQLNonNull(GraphQLString), 0, "0"), - (GraphQLNonNull(GraphQLInt), 0, 0), - (GraphQLList(GraphQLString), [1, 2], ['1', '2']), - (GraphQLList(GraphQLInt), ['1', '2'], [1, 2]), - (GraphQLList(GraphQLNonNull(GraphQLInt)), [0], [0]), - (GraphQLNonNull(GraphQLList(GraphQLInt)), [], []), -]) -def test_type_resolver_promise(type, value, expected): - promise_value = Promise() - resolver = type_resolver(type, lambda: promise_value) - resolved_promise = resolver() - assert not resolved_promise.is_fulfilled - promise_value.fulfill(value) - assert resolved_promise.is_fulfilled - resolved = resolved_promise.get() - assert resolved == expected - - -def raises(): - raise Exception("raises") - - -def test_resolver_exception(): - info = mock.MagicMock() - with pytest.raises(GraphQLLocatedError): - resolver = type_resolver(GraphQLString, raises, info=info) - resolver() - - -def test_field_resolver_mask_exception(): - info = mock.MagicMock() - exe_context = mock.MagicMock() - exe_context.errors = [] - field = GraphQLField(GraphQLString, resolver=raises) - resolver = field_resolver(field, info=info, exe_context=exe_context) - resolved = resolver() - assert resolved is None - assert len(exe_context.errors) == 1 - assert str(exe_context.errors[0]) == 'raises' - - -def test_nonnull_field_resolver_mask_exception(): - info = mock.MagicMock() - info.parent_type = 'parent_type' - info.field_name = 'field_name' - exe_context = mock.MagicMock() - exe_context.errors = [] - field = GraphQLField(GraphQLNonNull(GraphQLString), resolver=raises) - resolver = field_resolver(field, info=info, exe_context=exe_context) - with pytest.raises(GraphQLLocatedError) as exc_info: - resolver() - assert str(exc_info.value) == 'raises' - - -def test_nonnull_field_resolver_fails_on_null_value(): - info = mock.MagicMock() - info.parent_type = 'parent_type' - info.field_name = 'field_name' - exe_context = mock.MagicMock() - exe_context.errors = [] - field = GraphQLField(GraphQLNonNull(GraphQLString), resolver=lambda *_: None) - resolver = field_resolver(field, info=info, exe_context=exe_context) - with pytest.raises(GraphQLError) as exc_info: - resolver() - - assert str(exc_info.value) == 'Cannot return null for non-nullable field parent_type.field_name.' - - -def test_nonnull_list_field_resolver_fails_silently_on_null_value(): - info = mock.MagicMock() - info.parent_type = 'parent_type' - info.field_name = 'field_name' - exe_context = mock.MagicMock() - exe_context.errors = [] - field = GraphQLField(GraphQLList(GraphQLNonNull(GraphQLString)), resolver=lambda *_: ['1', None]) - resolver = field_resolver(field, info=info, exe_context=exe_context) - assert resolver() is None - - assert len(exe_context.errors) == 1 - assert str(exe_context.errors[0]) == 'Cannot return null for non-nullable field parent_type.field_name.' - - -def test_nonnull_list_field_resolver_fails_on_null_value_top(): - from ....pyutils.default_ordered_dict import DefaultOrderedDict - from ...base import collect_fields - - - DataType = GraphQLObjectType('DataType', { - 'nonNullString': GraphQLField(GraphQLNonNull(GraphQLString), resolver=lambda *_: None), - }) - info = mock.MagicMock() - info.parent_type = 'parent_type' - info.field_name = 'field_name' - exe_context = mock.MagicMock() - exe_context.errors = [] - field = GraphQLField(GraphQLNonNull(DataType), resolver=lambda *_: 1) - selection_set = ast.SelectionSet(selections=[ - ast.Field( - name=ast.Name(value='nonNullString'), - ) - ]) - field_asts = collect_fields( - exe_context, - DataType, - selection_set, - DefaultOrderedDict(list), - set() - ) - - # node_fragment = Fragment(type=Node, field_asts=node_field_asts) - datetype_fragment = Fragment(type=DataType, field_asts=field_asts, context=exe_context) - resolver = field_resolver(field, info=info, exe_context=exe_context, fragment=datetype_fragment) - with pytest.raises(GraphQLError) as exc_info: - resolver() - - assert not exe_context.errors - assert str(exc_info.value) == 'Cannot return null for non-nullable field parent_type.field_name.' - - -def test_nonnull_list_field_resolver_fails_on_null_value_top(): - from ....pyutils.default_ordered_dict import DefaultOrderedDict - from ...base import collect_fields - - - DataType = GraphQLObjectType('DataType', { - 'nonNullString': GraphQLField(GraphQLString, resolver=lambda *_: None), - }) - info = mock.MagicMock() - info.parent_type = 'parent_type' - info.field_name = 'field_name' - exe_context = mock.MagicMock() - exe_context.errors = [] - field = GraphQLField(GraphQLNonNull(DataType), resolver=lambda *_: 1) - selection_set = ast.SelectionSet(selections=[ - ast.Field( - name=ast.Name(value='nonNullString'), - ) - ]) - field_asts = collect_fields( - exe_context, - DataType, - selection_set, - DefaultOrderedDict(list), - set() - ) - # node_fragment = Fragment(type=Node, field_asts=node_field_asts) - datetype_fragment = Fragment(type=DataType, field_asts=field_asts, context=exe_context) - resolver = field_resolver(field, info=info, exe_context=exe_context, fragment=datetype_fragment) - data = resolver() - assert data == { - 'nonNullString': None - } diff --git a/graphql/execution/experimental/tests/test_abstract.py b/graphql/execution/experimental/tests/test_abstract.py deleted file mode 100644 index d7ca41f4..00000000 --- a/graphql/execution/experimental/tests/test_abstract.py +++ /dev/null @@ -1,297 +0,0 @@ -from graphql import graphql -from graphql.type import GraphQLBoolean, GraphQLSchema, GraphQLString -from graphql.type.definition import (GraphQLField, GraphQLInterfaceType, - GraphQLList, GraphQLObjectType, - GraphQLUnionType) - - -class Dog(object): - - def __init__(self, name, woofs): - self.name = name - self.woofs = woofs - - -class Cat(object): - - def __init__(self, name, meows): - self.name = name - self.meows = meows - - -class Human(object): - - def __init__(self, name): - self.name = name - - -is_type_of = lambda type: lambda obj, context, info: isinstance(obj, type) - - -def make_type_resolver(types): - def resolve_type(obj, context, info): - if callable(types): - t = types() - else: - t = types - - for klass, type in t: - if isinstance(obj, klass): - return type - - return None - - return resolve_type - - -def test_is_type_of_used_to_resolve_runtime_type_for_interface(): - PetType = GraphQLInterfaceType( - name='Pet', - fields={ - 'name': GraphQLField(GraphQLString) - } - ) - - DogType = GraphQLObjectType( - name='Dog', - interfaces=[PetType], - is_type_of=is_type_of(Dog), - fields={ - 'name': GraphQLField(GraphQLString), - 'woofs': GraphQLField(GraphQLBoolean) - } - ) - - CatType = GraphQLObjectType( - name='Cat', - interfaces=[PetType], - is_type_of=is_type_of(Cat), - fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean) - } - ) - - schema = GraphQLSchema( - query=GraphQLObjectType( - name='Query', - fields={ - 'pets': GraphQLField( - GraphQLList(PetType), - resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False)] - ) - } - ), - types=[CatType, DogType] - ) - - query = ''' - { - pets { - name - ... on Dog { - woofs - } - ... on Cat { - meows - } - } - } - ''' - - result = graphql(schema, query) - assert not result.errors - assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}]} - - -def test_is_type_of_used_to_resolve_runtime_type_for_union(): - DogType = GraphQLObjectType( - name='Dog', - is_type_of=is_type_of(Dog), - fields={ - 'name': GraphQLField(GraphQLString), - 'woofs': GraphQLField(GraphQLBoolean) - } - ) - - CatType = GraphQLObjectType( - name='Cat', - is_type_of=is_type_of(Cat), - fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean) - } - ) - - PetType = GraphQLUnionType( - name='Pet', - types=[CatType, DogType] - ) - - schema = GraphQLSchema( - query=GraphQLObjectType( - name='Query', - fields={ - 'pets': GraphQLField( - GraphQLList(PetType), - resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False)] - ) - } - ), - types=[CatType, DogType] - ) - - query = ''' - { - pets { - ... on Dog { - name - woofs - } - ... on Cat { - name - meows - } - } - } - ''' - - result = graphql(schema, query) - assert not result.errors - assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}]} - - -def test_resolve_type_on_interface_yields_useful_error(): - PetType = GraphQLInterfaceType( - name='Pet', - fields={ - 'name': GraphQLField(GraphQLString) - }, - resolve_type=make_type_resolver(lambda: [ - (Dog, DogType), - (Cat, CatType), - (Human, HumanType) - ]) - ) - - DogType = GraphQLObjectType( - name='Dog', - interfaces=[PetType], - fields={ - 'name': GraphQLField(GraphQLString), - 'woofs': GraphQLField(GraphQLBoolean) - } - ) - - HumanType = GraphQLObjectType( - name='Human', - fields={ - 'name': GraphQLField(GraphQLString), - } - ) - - CatType = GraphQLObjectType( - name='Cat', - interfaces=[PetType], - fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean) - } - ) - - schema = GraphQLSchema( - query=GraphQLObjectType( - name='Query', - fields={ - 'pets': GraphQLField( - GraphQLList(PetType), - resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False), Human('Jon')] - ) - } - ), - types=[DogType, CatType] - ) - - query = ''' - { - pets { - name - ... on Dog { - woofs - } - ... on Cat { - meows - } - } - } - ''' - - result = graphql(schema, query) - assert result.errors[0].message == 'Runtime Object type "Human" is not a possible type for "Pet".' - assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}, None]} - - -def test_resolve_type_on_union_yields_useful_error(): - DogType = GraphQLObjectType( - name='Dog', - fields={ - 'name': GraphQLField(GraphQLString), - 'woofs': GraphQLField(GraphQLBoolean) - } - ) - - HumanType = GraphQLObjectType( - name='Human', - fields={ - 'name': GraphQLField(GraphQLString), - } - ) - - CatType = GraphQLObjectType( - name='Cat', - fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean) - } - ) - - PetType = GraphQLUnionType( - name='Pet', - types=[DogType, CatType], - resolve_type=make_type_resolver(lambda: [ - (Dog, DogType), - (Cat, CatType), - (Human, HumanType) - ]) - ) - - schema = GraphQLSchema( - query=GraphQLObjectType( - name='Query', - fields={ - 'pets': GraphQLField( - GraphQLList(PetType), - resolver=lambda *_: [Dog('Odie', True), Cat('Garfield', False), Human('Jon')] - ) - } - ) - ) - - query = ''' - { - pets { - ... on Dog { - name - woofs - } - ... on Cat { - name - meows - } - } - } - ''' - - result = graphql(schema, query) - assert result.errors[0].message == 'Runtime Object type "Human" is not a possible type for "Pet".' - assert result.data == {'pets': [{'woofs': True, 'name': 'Odie'}, {'name': 'Garfield', 'meows': False}, None]} diff --git a/graphql/execution/experimental/tests/test_directives.py b/graphql/execution/experimental/tests/test_directives.py deleted file mode 100644 index 9d8e4aaa..00000000 --- a/graphql/execution/experimental/tests/test_directives.py +++ /dev/null @@ -1,259 +0,0 @@ -from graphql.language.parser import parse -from graphql.type import (GraphQLField, GraphQLObjectType, GraphQLSchema, - GraphQLString) - -from ..executor import execute - -schema = GraphQLSchema( - query=GraphQLObjectType( - name='TestType', - fields={ - 'a': GraphQLField(GraphQLString), - 'b': GraphQLField(GraphQLString), - } - ) -) - - -class Data(object): - a = 'a' - b = 'b' - - -def execute_test_query(doc): - return execute(schema, parse(doc), Data) - - -def test_basic_query_works(): - result = execute_test_query('{ a, b }') - assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} - - -def test_if_true_includes_scalar(): - result = execute_test_query('{ a, b @include(if: true) }') - assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} - - -def test_if_false_omits_on_scalar(): - result = execute_test_query('{ a, b @include(if: false) }') - assert not result.errors - assert result.data == {'a': 'a'} - - -def test_skip_false_includes_scalar(): - result = execute_test_query('{ a, b @skip(if: false) }') - assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} - - -def test_skip_true_omits_scalar(): - result = execute_test_query('{ a, b @skip(if: true) }') - assert not result.errors - assert result.data == {'a': 'a'} - - -def test_if_false_omits_fragment_spread(): - q = ''' - query Q { - a - ...Frag @include(if: false) - } - fragment Frag on TestType { - b - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a'} - - -def test_if_true_includes_fragment_spread(): - q = ''' - query Q { - a - ...Frag @include(if: true) - } - fragment Frag on TestType { - b - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} - - -def test_skip_false_includes_fragment_spread(): - q = ''' - query Q { - a - ...Frag @skip(if: false) - } - fragment Frag on TestType { - b - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} - - -def test_skip_true_omits_fragment_spread(): - q = ''' - query Q { - a - ...Frag @skip(if: true) - } - fragment Frag on TestType { - b - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a'} - - -def test_if_false_omits_inline_fragment(): - q = ''' - query Q { - a - ... on TestType @include(if: false) { - b - } - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a'} - - -def test_if_true_includes_inline_fragment(): - q = ''' - query Q { - a - ... on TestType @include(if: true) { - b - } - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} - - -def test_skip_false_includes_inline_fragment(): - q = ''' - query Q { - a - ... on TestType @skip(if: false) { - b - } - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} - - -def test_skip_true_omits_inline_fragment(): - q = ''' - query Q { - a - ... on TestType @skip(if: true) { - b - } - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a'} - - -def test_skip_true_omits_fragment(): - q = ''' - query Q { - a - ...Frag - } - fragment Frag on TestType @skip(if: true) { - b - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a'} - - -def test_skip_on_inline_anonymous_fragment_omits_field(): - q = ''' - query Q { - a - ... @skip(if: true) { - b - } - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a'} - - -def test_skip_on_inline_anonymous_fragment_does_not_omit_field(): - q = ''' - query Q { - a - ... @skip(if: false) { - b - } - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} - - -def test_include_on_inline_anonymous_fragment_omits_field(): - q = ''' - query Q { - a - ... @include(if: false) { - b - } - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a'} - - -def test_include_on_inline_anonymous_fragment_does_not_omit_field(): - q = ''' - query Q { - a - ... @include(if: true) { - b - } - } - ''' - result = execute_test_query(q) - assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} - - -def test_works_directives_include_and_no_skip(): - result = execute_test_query('{ a, b @include(if: true) @skip(if: false) }') - assert not result.errors - assert result.data == {'a': 'a', 'b': 'b'} - - -def test_works_directives_include_and_skip(): - result = execute_test_query('{ a, b @include(if: true) @skip(if: true) }') - assert not result.errors - assert result.data == {'a': 'a'} - - -def test_works_directives_no_include_or_skip(): - result = execute_test_query('{ a, b @include(if: false) @skip(if: false) }') - assert not result.errors - assert result.data == {'a': 'a'} diff --git a/graphql/execution/experimental/tests/test_executor.py b/graphql/execution/experimental/tests/test_executor.py deleted file mode 100644 index 7afe32a6..00000000 --- a/graphql/execution/experimental/tests/test_executor.py +++ /dev/null @@ -1,180 +0,0 @@ -from functools import partial - -import pytest - -from promise import Promise - -from ....language import ast -from ....language.parser import parse -from ....type import (GraphQLBoolean, GraphQLEnumType, GraphQLField, - GraphQLInt, GraphQLInterfaceType, GraphQLList, - GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, - GraphQLSchema, GraphQLString, GraphQLUnionType) -from ...base import ExecutionContext -from ..executor import execute -from ..fragment import Fragment -from ..resolver import type_resolver - - -# from ...executor import execute - - - -def test_fragment_resolver_abstract(benchmark): - all_slots = range(10000) - - Node = GraphQLInterfaceType('Node', fields={'id': GraphQLField(GraphQLInt)}) - Person = GraphQLObjectType('Person', interfaces=(Node, ), is_type_of=lambda *_, **__: True, fields={ - 'id': GraphQLField(GraphQLInt, resolver=lambda obj, *_, **__: obj), - 'name': GraphQLField(GraphQLString, resolver=lambda obj, *_, **__: "name:" + str(obj)) - }) - Query = GraphQLObjectType( - 'Query', - fields={ - 'nodes': GraphQLField( - GraphQLList(Node), - resolver=lambda *_, - **__: all_slots)}) - - document_ast = parse('''query { - nodes { - id - ... on Person { - name - } - } - }''') - # node_fragment = Fragment(type=Node, field_asts=node_field_asts) - schema = GraphQLSchema(query=Query, types=[Person]) - partial_execute = partial(execute, schema, document_ast) - resolved = benchmark(partial_execute) - # resolved = execute(schema, document_ast) - assert not resolved.errors - assert resolved.data == { - 'nodes': [{ - 'id': x, - 'name': 'name:' + str(x) - } for x in all_slots] - } - - -def test_fragment_resolver_context(): - Query = GraphQLObjectType('Query', fields={ - 'context': GraphQLField(GraphQLString, resolver=lambda root, args, context, info: context), - 'same_schema': GraphQLField(GraphQLBoolean, resolver=lambda root, args, context, info: info.schema == schema) - }) - - document_ast = parse('''query { - context - same_schema - }''') - # node_fragment = Fragment(type=Node, field_asts=node_field_asts) - schema = GraphQLSchema(query=Query) - # partial_execute = partial(execute, schema, document_ast, context_value="1") - # resolved = benchmark(partial_execute) - resolved = execute(schema, document_ast, context_value="1") - assert not resolved.errors - assert resolved.data == { - 'context': '1', - 'same_schema': True, - } - - -def test_fragment_resolver_fails(): - def raise_resolver(*args, **kwargs): - raise Exception("My exception") - - def succeeds_resolver(*args, **kwargs): - return True - - Query = GraphQLObjectType('Query', fields={ - 'fails': GraphQLField(GraphQLString, resolver=raise_resolver), - 'succeeds': GraphQLField(GraphQLBoolean, resolver=succeeds_resolver) - }) - - document_ast = parse('''query { - fails - succeeds - }''') - # node_fragment = Fragment(type=Node, field_asts=node_field_asts) - schema = GraphQLSchema(query=Query) - # partial_execute = partial(execute, schema, document_ast, context_value="1") - # resolved = benchmark(partial_execute) - resolved = execute(schema, document_ast, context_value="1") - assert len(resolved.errors) == 1 - assert resolved.data == { - 'fails': None, - 'succeeds': True, - } - - -def test_fragment_resolver_resolves_all_list(): - Query = GraphQLObjectType('Query', fields={ - 'ints': GraphQLField(GraphQLList(GraphQLNonNull(GraphQLInt)), resolver=lambda *args: [1, "2", "non"]), - }) - - document_ast = parse('''query { - ints - }''') - # node_fragment = Fragment(type=Node, field_asts=node_field_asts) - schema = GraphQLSchema(query=Query) - # partial_execute = partial(execute, schema, document_ast, context_value="1") - # resolved = benchmark(partial_execute) - resolved = execute(schema, document_ast) - assert len(resolved.errors) == 1 - assert str(resolved.errors[0]) == 'could not convert string to float: non' - assert resolved.data == { - 'ints': [1, 2, None] - } - - -def test_fragment_resolver_resolves_all_list(): - Person = GraphQLObjectType('Person', fields={ - 'id': GraphQLField(GraphQLInt, resolver=lambda obj, *_, **__: 1), - }) - Query = GraphQLObjectType('Query', fields={ - 'persons': GraphQLField(GraphQLList(GraphQLNonNull(Person)), resolver=lambda *args: [1, 2, None]), - }) - - document_ast = parse('''query { - persons { - id - } - }''') - # node_fragment = Fragment(type=Node, field_asts=node_field_asts) - schema = GraphQLSchema(query=Query, types=[Person]) - # partial_execute = partial(execute, schema, document_ast, context_value="1") - # resolved = benchmark(partial_execute) - resolved = execute(schema, document_ast) - assert len(resolved.errors) == 1 - assert str(resolved.errors[0]) == 'Cannot return null for non-nullable field Query.persons.' - # assert str(resolved.errors[0]) == 'could not convert string to float: non' - assert resolved.data == { - 'persons': None - } - - -def test_fragment_resolver_resolves_all_list_null(): - Person = GraphQLObjectType('Person', fields={ - 'id': GraphQLField(GraphQLInt, resolver=lambda obj, *_, **__: 1), - }) - Query = GraphQLObjectType('Query', fields={ - 'persons': GraphQLField(GraphQLList(GraphQLNonNull(Person)), resolver=lambda *args: [1, 2, None]), - }) - - document_ast = parse('''query { - persons { - id - } - }''') - # node_fragment = Fragment(type=Node, field_asts=node_field_asts) - schema = GraphQLSchema(query=Query, types=[Person]) - # partial_execute = partial(execute, schema, document_ast, context_value="1") - # resolved = benchmark(partial_execute) - resolved = execute(schema, document_ast) - assert len(resolved.errors) == 1 - assert str(resolved.errors[0]) == 'Cannot return null for non-nullable field Query.persons.' - # assert str(resolved.errors[0]) == 'could not convert string to float: non' - assert resolved.data == { - 'persons': None - } diff --git a/graphql/execution/experimental/tests/test_lists.py b/graphql/execution/experimental/tests/test_lists.py deleted file mode 100644 index 95079858..00000000 --- a/graphql/execution/experimental/tests/test_lists.py +++ /dev/null @@ -1,211 +0,0 @@ -from collections import namedtuple - -from graphql.error import format_error -from graphql.execution.experimental.executor import execute -from graphql.language.parser import parse -from graphql.type import (GraphQLField, GraphQLInt, GraphQLList, - GraphQLNonNull, GraphQLObjectType, GraphQLSchema) - -from .utils import rejected, resolved - -Data = namedtuple('Data', 'test') -ast = parse('{ nest { test } }') - - -def check(test_data, expected): - def run_check(self): - test_type = self.type - - data = Data(test=test_data) - DataType = GraphQLObjectType( - name='DataType', - fields=lambda: { - 'test': GraphQLField(test_type), - 'nest': GraphQLField(DataType, resolver=lambda *_: data) - } - ) - - schema = GraphQLSchema(query=DataType) - response = execute(schema, ast, data) - - if response.errors: - result = { - 'data': response.data, - 'errors': [format_error(e) for e in response.errors] - } - else: - result = { - 'data': response.data - } - - assert result == expected - - return run_check - - -class Test_ListOfT_Array_T: # [T] Array - type = GraphQLList(GraphQLInt) - - test_contains_values = check([1, 2], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([1, None, 2], {'data': {'nest': {'test': [1, None, 2]}}}) - test_returns_null = check(None, {'data': {'nest': {'test': None}}}) - - -class Test_ListOfT_Promise_Array_T: # [T] Promise> - type = GraphQLList(GraphQLInt) - - test_contains_values = check(resolved([1, 2]), {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check(resolved([1, None, 2]), {'data': {'nest': {'test': [1, None, 2]}}}) - test_returns_null = check(resolved(None), {'data': {'nest': {'test': None}}}) - test_rejected = check(lambda: rejected(Exception('bad')), { - 'data': {'nest': {'test': None}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], 'message': 'bad'}] - }) - - -class Test_ListOfT_Array_Promise_T: # [T] Array> - type = GraphQLList(GraphQLInt) - - test_contains_values = check([resolved(1), resolved(2)], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([resolved(1), resolved(None), resolved(2)], {'data': {'nest': {'test': [1, None, 2]}}}) - test_contains_reject = check(lambda: [resolved(1), rejected(Exception('bad')), resolved(2)], { - 'data': {'nest': {'test': [1, None, 2]}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], 'message': 'bad'}] - }) - - -class Test_NotNullListOfT_Array_T: # [T]! Array - type = GraphQLNonNull(GraphQLList(GraphQLInt)) - - test_contains_values = check(resolved([1, 2]), {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check(resolved([1, None, 2]), {'data': {'nest': {'test': [1, None, 2]}}}) - test_returns_null = check(resolved(None), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - - -class Test_NotNullListOfT_Promise_Array_T: # [T]! Promise>> - type = GraphQLNonNull(GraphQLList(GraphQLInt)) - - test_contains_values = check(resolved([1, 2]), {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check(resolved([1, None, 2]), {'data': {'nest': {'test': [1, None, 2]}}}) - test_returns_null = check(resolved(None), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - - test_rejected = check(lambda: rejected(Exception('bad')), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], 'message': 'bad'}] - }) - - -class Test_NotNullListOfT_Array_Promise_T: # [T]! Promise>> - type = GraphQLNonNull(GraphQLList(GraphQLInt)) - test_contains_values = check([resolved(1), resolved(2)], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([resolved(1), resolved(None), resolved(2)], {'data': {'nest': {'test': [1, None, 2]}}}) - test_contains_reject = check(lambda: [resolved(1), rejected(Exception('bad')), resolved(2)], { - 'data': {'nest': {'test': [1, None, 2]}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], 'message': 'bad'}] - }) - - -class TestListOfNotNullT_Array_T: # [T!] Array - type = GraphQLList(GraphQLNonNull(GraphQLInt)) - - test_contains_values = check([1, 2], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([1, None, 2], { - 'data': {'nest': {'test': None}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - test_returns_null = check(None, {'data': {'nest': {'test': None}}}) - - -class TestListOfNotNullT_Promise_Array_T: # [T!] Promise> - type = GraphQLList(GraphQLNonNull(GraphQLInt)) - - test_contains_value = check(resolved([1, 2]), {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check(resolved([1, None, 2]), { - 'data': {'nest': {'test': None}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - - test_returns_null = check(resolved(None), {'data': {'nest': {'test': None}}}) - - test_rejected = check(lambda: rejected(Exception('bad')), { - 'data': {'nest': {'test': None}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], 'message': 'bad'}] - }) - - -class TestListOfNotNullT_Array_Promise_T: # [T!] Array> - type = GraphQLList(GraphQLNonNull(GraphQLInt)) - - test_contains_values = check([resolved(1), resolved(2)], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([resolved(1), resolved(None), resolved(2)], { - 'data': {'nest': {'test': None}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - test_contains_reject = check(lambda: [resolved(1), rejected(Exception('bad')), resolved(2)], { - 'data': {'nest': {'test': None}}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], 'message': 'bad'}] - }) - - -class TestNotNullListOfNotNullT_Array_T: # [T!]! Array - type = GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLInt))) - - test_contains_values = check([1, 2], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([1, None, 2], { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - test_returns_null = check(None, { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - - -class TestNotNullListOfNotNullT_Promise_Array_T: # [T!]! Promise> - type = GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLInt))) - - test_contains_value = check(resolved([1, 2]), {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check(resolved([1, None, 2]), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - - test_returns_null = check(resolved(None), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - - test_rejected = check(lambda: rejected(Exception('bad')), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], 'message': 'bad'}] - }) - - -class TestNotNullListOfNotNullT_Array_Promise_T: # [T!]! Array> - type = GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLInt))) - - test_contains_values = check([resolved(1), resolved(2)], {'data': {'nest': {'test': [1, 2]}}}) - test_contains_null = check([resolved(1), resolved(None), resolved(2)], { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], - 'message': 'Cannot return null for non-nullable field DataType.test.'}] - }) - test_contains_reject = check(lambda: [resolved(1), rejected(Exception('bad')), resolved(2)], { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 10, 'line': 1}], 'message': 'bad'}] - }) diff --git a/graphql/execution/experimental/tests/test_mutations.py b/graphql/execution/experimental/tests/test_mutations.py deleted file mode 100644 index 431073f4..00000000 --- a/graphql/execution/experimental/tests/test_mutations.py +++ /dev/null @@ -1,140 +0,0 @@ -from graphql.language.parser import parse -from graphql.type import (GraphQLArgument, GraphQLField, GraphQLInt, - GraphQLList, GraphQLObjectType, GraphQLSchema, - GraphQLString) - -from ..executor import execute - - -class NumberHolder(object): - - def __init__(self, n): - self.theNumber = n - - -class Root(object): - - def __init__(self, n): - self.numberHolder = NumberHolder(n) - - def immediately_change_the_number(self, n): - self.numberHolder.theNumber = n - return self.numberHolder - - def promise_to_change_the_number(self, n): - # TODO: async - return self.immediately_change_the_number(n) - - def fail_to_change_the_number(self, n): - raise Exception('Cannot change the number') - - def promise_and_fail_to_change_the_number(self, n): - # TODO: async - self.fail_to_change_the_number(n) - - -NumberHolderType = GraphQLObjectType('NumberHolder', { - 'theNumber': GraphQLField(GraphQLInt) -}) - -QueryType = GraphQLObjectType('Query', { - 'numberHolder': GraphQLField(NumberHolderType) -}) - -MutationType = GraphQLObjectType('Mutation', { - 'immediatelyChangeTheNumber': GraphQLField( - NumberHolderType, - args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, args, *_: - obj.immediately_change_the_number(args['newNumber'])), - 'promiseToChangeTheNumber': GraphQLField( - NumberHolderType, - args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, args, *_: - obj.promise_to_change_the_number(args['newNumber'])), - 'failToChangeTheNumber': GraphQLField( - NumberHolderType, - args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, args, *_: - obj.fail_to_change_the_number(args['newNumber'])), - 'promiseAndFailToChangeTheNumber': GraphQLField( - NumberHolderType, - args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, args, *_: - obj.promise_and_fail_to_change_the_number(args['newNumber'])), -}) - -schema = GraphQLSchema(QueryType, MutationType) - - -def assert_evaluate_mutations_serially(executor=None): - doc = '''mutation M { - first: immediatelyChangeTheNumber(newNumber: 1) { - theNumber - }, - second: promiseToChangeTheNumber(newNumber: 2) { - theNumber - }, - third: immediatelyChangeTheNumber(newNumber: 3) { - theNumber - } - fourth: promiseToChangeTheNumber(newNumber: 4) { - theNumber - }, - fifth: immediatelyChangeTheNumber(newNumber: 5) { - theNumber - } - }''' - ast = parse(doc) - result = execute(schema, ast, Root(6), operation_name='M', executor=executor) - assert not result.errors - assert result.data == \ - { - 'first': {'theNumber': 1}, - 'second': {'theNumber': 2}, - 'third': {'theNumber': 3}, - 'fourth': {'theNumber': 4}, - 'fifth': {'theNumber': 5}, - } - - -def test_evaluates_mutations_serially(): - assert_evaluate_mutations_serially() - - -def test_evaluates_mutations_correctly_in_the_presense_of_a_failed_mutation(): - doc = '''mutation M { - first: immediatelyChangeTheNumber(newNumber: 1) { - theNumber - }, - second: promiseToChangeTheNumber(newNumber: 2) { - theNumber - }, - third: failToChangeTheNumber(newNumber: 3) { - theNumber - } - fourth: promiseToChangeTheNumber(newNumber: 4) { - theNumber - }, - fifth: immediatelyChangeTheNumber(newNumber: 5) { - theNumber - } - sixth: promiseAndFailToChangeTheNumber(newNumber: 6) { - theNumber - } - }''' - ast = parse(doc) - result = execute(schema, ast, Root(6), operation_name='M') - assert result.data == \ - { - 'first': {'theNumber': 1}, - 'second': {'theNumber': 2}, - 'third': None, - 'fourth': {'theNumber': 4}, - 'fifth': {'theNumber': 5}, - 'sixth': None, - } - assert len(result.errors) == 2 - # TODO: check error location - assert result.errors[0].message == 'Cannot change the number' - assert result.errors[1].message == 'Cannot change the number' diff --git a/graphql/execution/experimental/tests/test_nonnull.py b/graphql/execution/experimental/tests/test_nonnull.py deleted file mode 100644 index 3a40b94d..00000000 --- a/graphql/execution/experimental/tests/test_nonnull.py +++ /dev/null @@ -1,585 +0,0 @@ - -from graphql.error import format_error -from graphql.execution.experimental.executor import execute -from graphql.language.parser import parse -from graphql.type import (GraphQLField, GraphQLNonNull, GraphQLObjectType, - GraphQLSchema, GraphQLString) - -from .utils import rejected, resolved - -sync_error = Exception('sync') -non_null_sync_error = Exception('nonNullSync') -promise_error = Exception('promise') -non_null_promise_error = Exception('nonNullPromise') - - -class ThrowingData(object): - - def sync(self): - raise sync_error - - def nonNullSync(self): - raise non_null_sync_error - - def promise(self): - return rejected(promise_error) - - def nonNullPromise(self): - return rejected(non_null_promise_error) - - def nest(self): - return ThrowingData() - - def nonNullNest(self): - return ThrowingData() - - def promiseNest(self): - return resolved(ThrowingData()) - - def nonNullPromiseNest(self): - return resolved(ThrowingData()) - - -class NullingData(object): - - def sync(self): - return None - - def nonNullSync(self): - return None - - def promise(self): - return resolved(None) - - def nonNullPromise(self): - return resolved(None) - - def nest(self): - return NullingData() - - def nonNullNest(self): - return NullingData() - - def promiseNest(self): - return resolved(NullingData()) - - def nonNullPromiseNest(self): - return resolved(NullingData()) - - -DataType = GraphQLObjectType('DataType', lambda: { - 'sync': GraphQLField(GraphQLString), - 'nonNullSync': GraphQLField(GraphQLNonNull(GraphQLString)), - 'promise': GraphQLField(GraphQLString), - 'nonNullPromise': GraphQLField(GraphQLNonNull(GraphQLString)), - 'nest': GraphQLField(DataType), - 'nonNullNest': GraphQLField(GraphQLNonNull(DataType)), - 'promiseNest': GraphQLField(DataType), - 'nonNullPromiseNest': GraphQLField(GraphQLNonNull(DataType)) -}) - -schema = GraphQLSchema(DataType) - - -def order_errors(error): - locations = error['locations'] - return (locations[0]['column'], locations[0]['line']) - - -def check(doc, data, expected): - ast = parse(doc) - response = execute(schema, ast, data) - - if response.errors: - result = { - 'data': response.data, - 'errors': [format_error(e) for e in response.errors] - } - if result['errors'] != expected['errors']: - assert result['data'] == expected['data'] - # Sometimes the fields resolves asynchronously, so - # we need to check that the errors are the same, but might be - # raised in a different order. - assert sorted(result['errors'], key=order_errors) == sorted(expected['errors'], key=order_errors) - else: - assert result == expected - else: - result = { - 'data': response.data - } - - assert result == expected - - -def test_nulls_a_nullable_field_that_throws_sync(): - doc = ''' - query Q { - sync - } - ''' - - check(doc, ThrowingData(), { - 'data': {'sync': None}, - 'errors': [{'locations': [{'column': 13, 'line': 3}], 'message': str(sync_error)}] - }) - - -def test_nulls_a_nullable_field_that_throws_in_a_promise(): - doc = ''' - query Q { - promise - } - ''' - - check(doc, ThrowingData(), { - 'data': {'promise': None}, - 'errors': [{'locations': [{'column': 13, 'line': 3}], 'message': str(promise_error)}] - }) - - -def test_nulls_a_sync_returned_object_that_contains_a_non_nullable_field_that_throws(): - doc = ''' - query Q { - nest { - nonNullSync, - } - } - ''' - - check(doc, ThrowingData(), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'message': str(non_null_sync_error)}] - }) - - -def test_nulls_a_synchronously_returned_object_that_contains_a_non_nullable_field_that_throws_in_a_promise(): - doc = ''' - query Q { - nest { - nonNullPromise, - } - } - ''' - - check(doc, ThrowingData(), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'message': str(non_null_promise_error)}] - }) - - -def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_throws_synchronously(): - doc = ''' - query Q { - promiseNest { - nonNullSync, - } - } - ''' - - check(doc, ThrowingData(), { - 'data': {'promiseNest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'message': str(non_null_sync_error)}] - }) - - -def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_throws_in_a_promise(): - doc = ''' - query Q { - promiseNest { - nonNullPromise, - } - } - ''' - - check(doc, ThrowingData(), { - 'data': {'promiseNest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'message': str(non_null_promise_error)}] - }) - - -def test_nulls_a_complex_tree_of_nullable_fields_that_throw(): - doc = ''' - query Q { - nest { - sync - promise - nest { - sync - promise - } - promiseNest { - sync - promise - } - } - promiseNest { - sync - promise - nest { - sync - promise - } - promiseNest { - sync - promise - } - } - } - ''' - check(doc, ThrowingData(), { - 'data': {'nest': {'nest': {'promise': None, 'sync': None}, - 'promise': None, - 'promiseNest': {'promise': None, 'sync': None}, - 'sync': None}, - 'promiseNest': {'nest': {'promise': None, 'sync': None}, - 'promise': None, - 'promiseNest': {'promise': None, 'sync': None}, - 'sync': None}}, - 'errors': [{'locations': [{'column': 11, 'line': 4}], 'message': str(sync_error)}, - {'locations': [{'column': 11, 'line': 5}], 'message': str(promise_error)}, - {'locations': [{'column': 13, 'line': 7}], 'message': str(sync_error)}, - {'locations': [{'column': 13, 'line': 8}], 'message': str(promise_error)}, - {'locations': [{'column': 13, 'line': 11}], 'message': str(sync_error)}, - {'locations': [{'column': 13, 'line': 12}], 'message': str(promise_error)}, - {'locations': [{'column': 11, 'line': 16}], 'message': str(sync_error)}, - {'locations': [{'column': 11, 'line': 17}], 'message': str(promise_error)}, - {'locations': [{'column': 13, 'line': 19}], 'message': str(sync_error)}, - {'locations': [{'column': 13, 'line': 20}], 'message': str(promise_error)}, - {'locations': [{'column': 13, 'line': 23}], 'message': str(sync_error)}, - {'locations': [{'column': 13, 'line': 24}], 'message': str(promise_error)}] - }) - - -def test_nulls_the_first_nullable_object_after_a_field_throws_in_a_long_chain_of_fields_that_are_non_null(): - doc = ''' - query Q { - nest { - nonNullNest { - nonNullPromiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullSync - } - } - } - } - } - promiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullSync - } - } - } - } - } - anotherNest: nest { - nonNullNest { - nonNullPromiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullPromise - } - } - } - } - } - anotherPromiseNest: promiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullPromise - } - } - } - } - } - } - ''' - check(doc, ThrowingData(), { - 'data': {'nest': None, 'promiseNest': None, 'anotherNest': None, 'anotherPromiseNest': None}, - 'errors': [{'locations': [{'column': 19, 'line': 8}], - 'message': str(non_null_sync_error)}, - {'locations': [{'column': 19, 'line': 19}], - 'message': str(non_null_sync_error)}, - {'locations': [{'column': 19, 'line': 30}], - 'message': str(non_null_promise_error)}, - {'locations': [{'column': 19, 'line': 41}], - 'message': str(non_null_promise_error)}] - }) - - -def test_nulls_a_nullable_field_that_returns_null(): - doc = ''' - query Q { - sync - } - ''' - - check(doc, NullingData(), { - 'data': {'sync': None} - }) - - -def test_nulls_a_nullable_field_that_returns_null_in_a_promise(): - doc = ''' - query Q { - promise - } - ''' - - check(doc, NullingData(), { - 'data': {'promise': None} - }) - - -def test_nulls_a_sync_returned_object_that_contains_a_non_nullable_field_that_returns_null_synchronously(): - doc = ''' - query Q { - nest { - nonNullSync, - } - } - ''' - check(doc, NullingData(), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'message': 'Cannot return null for non-nullable field DataType.nonNullSync.'}] - }) - - -def test_nulls_a_synchronously_returned_object_that_contains_a_non_nullable_field_that_returns_null_in_a_promise(): - doc = ''' - query Q { - nest { - nonNullPromise, - } - } - ''' - check(doc, NullingData(), { - 'data': {'nest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'message': 'Cannot return null for non-nullable field DataType.nonNullPromise.'}] - }) - - -def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_returns_null_synchronously(): - doc = ''' - query Q { - promiseNest { - nonNullSync, - } - } - ''' - check(doc, NullingData(), { - 'data': {'promiseNest': None}, - 'errors': [{'locations': [{'column': 17, 'line': 4}], - 'message': 'Cannot return null for non-nullable field DataType.nonNullSync.'}] - }) - - -def test_nulls_an_object_returned_in_a_promise_that_contains_a_non_nullable_field_that_returns_null_ina_a_promise(): - doc = ''' - query Q { - promiseNest { - nonNullPromise - } - } - ''' - - check(doc, NullingData(), { - 'data': {'promiseNest': None}, - 'errors': [ - {'locations': [{'column': 17, 'line': 4}], - 'message': 'Cannot return null for non-nullable field DataType.nonNullPromise.'} - ] - }) - - -def test_nulls_a_complex_tree_of_nullable_fields_that_returns_null(): - doc = ''' - query Q { - nest { - sync - promise - nest { - sync - promise - } - promiseNest { - sync - promise - } - } - promiseNest { - sync - promise - nest { - sync - promise - } - promiseNest { - sync - promise - } - } - } - ''' - check(doc, NullingData(), { - 'data': { - 'nest': { - 'sync': None, - 'promise': None, - 'nest': { - 'sync': None, - 'promise': None, - }, - 'promiseNest': { - 'sync': None, - 'promise': None, - } - }, - 'promiseNest': { - 'sync': None, - 'promise': None, - 'nest': { - 'sync': None, - 'promise': None, - }, - 'promiseNest': { - 'sync': None, - 'promise': None, - } - } - } - }) - - -def test_nulls_the_first_nullable_object_after_a_field_returns_null_in_a_long_chain_of_fields_that_are_non_null(): - doc = ''' - query Q { - nest { - nonNullNest { - nonNullPromiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullSync - } - } - } - } - } - promiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullSync - } - } - } - } - } - anotherNest: nest { - nonNullNest { - nonNullPromiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullPromise - } - } - } - } - } - anotherPromiseNest: promiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullNest { - nonNullPromiseNest { - nonNullPromise - } - } - } - } - } - } - ''' - - check(doc, NullingData(), { - 'data': { - 'nest': None, - 'promiseNest': None, - 'anotherNest': None, - 'anotherPromiseNest': None - }, - 'errors': [ - {'locations': [{'column': 19, 'line': 8}], - 'message': 'Cannot return null for non-nullable field DataType.nonNullSync.'}, - {'locations': [{'column': 19, 'line': 19}], - 'message': 'Cannot return null for non-nullable field DataType.nonNullSync.'}, - {'locations': [{'column': 19, 'line': 30}], - 'message': 'Cannot return null for non-nullable field DataType.nonNullPromise.'}, - {'locations': [{'column': 19, 'line': 41}], - 'message': 'Cannot return null for non-nullable field DataType.nonNullPromise.'} - ] - }) - - -def test_nulls_the_top_level_if_sync_non_nullable_field_throws(): - doc = ''' - query Q { nonNullSync } - ''' - check(doc, ThrowingData(), { - 'data': None, - 'errors': [ - {'locations': [{'column': 19, 'line': 2}], - 'message': str(non_null_sync_error)} - ] - }) - - -def test_nulls_the_top_level_if_async_non_nullable_field_errors(): - doc = ''' - query Q { nonNullPromise } - ''' - - check(doc, ThrowingData(), { - 'data': None, - 'errors': [ - {'locations': [{'column': 19, 'line': 2}], - 'message': str(non_null_promise_error)} - ] - }) - - -def test_nulls_the_top_level_if_sync_non_nullable_field_returns_null(): - doc = ''' - query Q { nonNullSync } - ''' - check(doc, NullingData(), { - 'data': None, - 'errors': [ - {'locations': [{'column': 19, 'line': 2}], - 'message': 'Cannot return null for non-nullable field DataType.nonNullSync.'} - ] - }) - - -def test_nulls_the_top_level_if_async_non_nullable_field_resolves_null(): - doc = ''' - query Q { nonNullPromise } - ''' - check(doc, NullingData(), { - 'data': None, - 'errors': [ - {'locations': [{'column': 19, 'line': 2}], - 'message': 'Cannot return null for non-nullable field DataType.nonNullPromise.'} - ] - }) diff --git a/graphql/execution/experimental/tests/test_querybuilder.py b/graphql/execution/experimental/tests/test_querybuilder.py deleted file mode 100644 index e1c47b2a..00000000 --- a/graphql/execution/experimental/tests/test_querybuilder.py +++ /dev/null @@ -1,168 +0,0 @@ -# from ..experimental import generate_fragment, fragment_operation, experimental -# from ..fragment import Fragment - -# from ....language.parser import parse -# from ....language import ast -# from ....type import (GraphQLEnumType, GraphQLInterfaceType, GraphQLList, -# GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, -# GraphQLSchema, GraphQLUnionType, GraphQLString, GraphQLInt, GraphQLField) - - -# def test_generate_fragment(): -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt)}) -# Query = GraphQLObjectType('Query', fields={'nodes': GraphQLField(GraphQLList(Node))}) -# node_field_asts = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# query_field_asts = [ -# ast.Field( -# name=ast.Name(value='nodes'), -# selection_set=node_field_asts -# ) -# ] -# QueryFragment = generate_fragment(Query, query_field_asts) - -# assert QueryFragment == Fragment( -# Query, -# query_field_asts, -# field_fragments={ -# 'nodes': Fragment( -# Node, -# node_field_asts.selections -# ) -# }, -# ) - - -# def test_fragment_operation_query(): -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt)}) -# Query = GraphQLObjectType('Query', fields={'nodes': GraphQLField(GraphQLList(Node))}) - -# schema = GraphQLSchema(query=Query) - -# node_field_asts = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# query_field_asts = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='nodes'), -# selection_set=node_field_asts -# ) -# ]) -# operation_ast = ast.OperationDefinition( -# operation='query', -# selection_set=query_field_asts -# ) -# QueryFragment = fragment_operation(schema, operation_ast) - -# assert QueryFragment == Fragment( -# Query, -# query_field_asts.selections, -# field_fragments={ -# 'nodes': Fragment( -# Node, -# node_field_asts.selections -# ) -# }, -# ) - - -# def test_fragment_operation_mutation(): -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt)}) -# Query = GraphQLObjectType('Query', fields={'nodes': GraphQLField(GraphQLList(Node))}) - -# schema = GraphQLSchema(query=Query, mutation=Query) - -# node_field_asts = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# ) -# ]) -# query_field_asts = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='nodes'), -# selection_set=node_field_asts -# ) -# ]) -# operation_ast = ast.OperationDefinition( -# operation='mutation', -# selection_set=query_field_asts -# ) -# MutationFragment = fragment_operation(schema, operation_ast) - -# assert MutationFragment == Fragment( -# Query, -# query_field_asts.selections, -# field_fragments={ -# 'nodes': Fragment( -# Node, -# node_field_asts.selections -# ) -# }, -# execute_serially=True -# ) - - -# def test_query_builder_operation(): -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt)}) -# Query = GraphQLObjectType('Query', fields={'nodes': GraphQLField(GraphQLList(Node))}) - -# schema = GraphQLSchema(query=Query, mutation=Query) -# document_ast = parse('''query MyQuery { -# nodes { -# id -# } -# }''') -# query_builder = experimental(schema, document_ast) -# QueryFragment = query_builder.get_operation_fragment('MyQuery') -# node_field_asts = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='id'), -# arguments=[], -# directives=[], -# selection_set=None, -# ) -# ]) -# query_field_asts = ast.SelectionSet(selections=[ -# ast.Field( -# name=ast.Name(value='nodes'), -# arguments=[], -# directives=[], -# selection_set=node_field_asts -# ) -# ]) -# assert QueryFragment == Fragment( -# Query, -# query_field_asts.selections, -# field_fragments={ -# 'nodes': Fragment( -# Node, -# node_field_asts.selections -# ) -# } -# ) - - -# def test_query_builder_execution(): -# Node = GraphQLObjectType('Node', fields={'id': GraphQLField(GraphQLInt, resolver=lambda obj, **__: obj)}) -# Query = GraphQLObjectType('Query', fields={'nodes': GraphQLField(GraphQLList(Node), resolver=lambda *_, **__: range(3))}) - -# schema = GraphQLSchema(query=Query) -# document_ast = parse('''query MyQuery { -# nodes { -# id -# } -# }''') -# query_builder = experimental(schema, document_ast) -# QueryFragment = query_builder.get_operation_fragment('MyQuery') -# root = None -# expected = { -# 'nodes': [{ -# 'id': n -# } for n in range(3)] -# } -# assert QueryFragment.resolver(lambda: root) == expected diff --git a/graphql/execution/experimental/tests/test_resolve.py b/graphql/execution/experimental/tests/test_resolve.py deleted file mode 100644 index ef688003..00000000 --- a/graphql/execution/experimental/tests/test_resolve.py +++ /dev/null @@ -1,136 +0,0 @@ -import json -from collections import OrderedDict - -from graphql.type import (GraphQLArgument, GraphQLField, - GraphQLInputObjectField, GraphQLInputObjectType, - GraphQLInt, GraphQLList, GraphQLNonNull, - GraphQLObjectType, GraphQLSchema, GraphQLString) - -from ..executor import execute -from .utils import graphql - - -def _test_schema(test_field): - return GraphQLSchema( - query=GraphQLObjectType( - name='Query', - fields={ - 'test': test_field - } - ) - ) - - -def test_default_function_accesses_properties(): - schema = _test_schema(GraphQLField(GraphQLString)) - - class source: - test = 'testValue' - - result = graphql(schema, '{ test }', source) - assert not result.errors - assert result.data == {'test': 'testValue'} - - -def test_default_function_calls_methods(): - schema = _test_schema(GraphQLField(GraphQLString)) - - class source: - _secret = 'testValue' - - def test(self): - return self._secret - - result = graphql(schema, '{ test }', source()) - assert not result.errors - assert result.data == {'test': 'testValue'} - - -def test_uses_provided_resolve_function(): - def resolver(source, args, *_): - return json.dumps([source, args], separators=(',', ':')) - - schema = _test_schema(GraphQLField( - GraphQLString, - args=OrderedDict([ - ('aStr', GraphQLArgument(GraphQLString)), - ('aInt', GraphQLArgument(GraphQLInt)), - ]), - resolver=resolver - )) - - result = graphql(schema, '{ test }', None) - assert not result.errors - assert result.data == {'test': '[null,{}]'} - - result = graphql(schema, '{ test(aStr: "String!") }', 'Source!') - assert not result.errors - assert result.data == {'test': '["Source!",{"aStr":"String!"}]'} - - result = graphql(schema, '{ test(aInt: -123, aStr: "String!",) }', 'Source!') - assert not result.errors - assert result.data in [ - {'test': '["Source!",{"aStr":"String!","aInt":-123}]'}, - {'test': '["Source!",{"aInt":-123,"aStr":"String!"}]'} - ] - - -def test_maps_argument_out_names_well(): - def resolver(source, args, *_): - return json.dumps([source, args], separators=(',', ':')) - - schema = _test_schema(GraphQLField( - GraphQLString, - args=OrderedDict([ - ('aStr', GraphQLArgument(GraphQLString, out_name="a_str")), - ('aInt', GraphQLArgument(GraphQLInt, out_name="a_int")), - ]), - resolver=resolver - )) - - result = graphql(schema, '{ test }', None) - assert not result.errors - assert result.data == {'test': '[null,{}]'} - - result = graphql(schema, '{ test(aStr: "String!") }', 'Source!') - assert not result.errors - assert result.data == {'test': '["Source!",{"a_str":"String!"}]'} - - result = graphql(schema, '{ test(aInt: -123, aStr: "String!",) }', 'Source!') - assert not result.errors - assert result.data in [ - {'test': '["Source!",{"a_str":"String!","a_int":-123}]'}, - {'test': '["Source!",{"a_int":-123,"a_str":"String!"}]'} - ] - - -def test_maps_argument_out_names_well_with_input(): - def resolver(source, args, *_): - return json.dumps([source, args], separators=(',', ':')) - - TestInputObject = GraphQLInputObjectType('TestInputObject', lambda: OrderedDict([ - ('inputOne', GraphQLInputObjectField(GraphQLString, out_name="input_one")), - ('inputRecursive', GraphQLInputObjectField(TestInputObject, out_name="input_recursive")), - ])) - - schema = _test_schema(GraphQLField( - GraphQLString, - args=OrderedDict([ - ('aInput', GraphQLArgument(TestInputObject, out_name="a_input")) - ]), - resolver=resolver - )) - - result = graphql(schema, '{ test }', None) - assert not result.errors - assert result.data == {'test': '[null,{}]'} - - result = graphql(schema, '{ test(aInput: {inputOne: "String!"} ) }', 'Source!') - assert not result.errors - assert result.data == {'test': '["Source!",{"a_input":{"input_one":"String!"}}]'} - - result = graphql(schema, '{ test(aInput: {inputRecursive:{inputOne: "SourceRecursive!"}} ) }', 'Source!') - assert not result.errors - assert result.data == { - 'test': '["Source!",{"a_input":{"input_recursive":{"input_one":"SourceRecursive!"}}}]' - } diff --git a/graphql/execution/experimental/tests/test_union_interface.py b/graphql/execution/experimental/tests/test_union_interface.py deleted file mode 100644 index 2d91ebc4..00000000 --- a/graphql/execution/experimental/tests/test_union_interface.py +++ /dev/null @@ -1,358 +0,0 @@ -from graphql.language.parser import parse -from graphql.type import (GraphQLBoolean, GraphQLField, GraphQLInterfaceType, - GraphQLList, GraphQLObjectType, GraphQLSchema, - GraphQLString, GraphQLUnionType) - -from ..executor import execute - - -class Dog(object): - - def __init__(self, name, barks): - self.name = name - self.barks = barks - - -class Cat(object): - - def __init__(self, name, meows): - self.name = name - self.meows = meows - - -class Person(object): - - def __init__(self, name, pets, friends): - self.name = name - self.pets = pets - self.friends = friends - - -NamedType = GraphQLInterfaceType('Named', { - 'name': GraphQLField(GraphQLString) -}) - -DogType = GraphQLObjectType( - name='Dog', - interfaces=[NamedType], - fields={ - 'name': GraphQLField(GraphQLString), - 'barks': GraphQLField(GraphQLBoolean), - }, - is_type_of=lambda value, context, info: isinstance(value, Dog) -) - -CatType = GraphQLObjectType( - name='Cat', - interfaces=[NamedType], - fields={ - 'name': GraphQLField(GraphQLString), - 'meows': GraphQLField(GraphQLBoolean), - }, - is_type_of=lambda value, context, info: isinstance(value, Cat) -) - - -def resolve_pet_type(value, context, info): - if isinstance(value, Dog): - return DogType - if isinstance(value, Cat): - return CatType - - -PetType = GraphQLUnionType('Pet', [DogType, CatType], - resolve_type=resolve_pet_type) - -PersonType = GraphQLObjectType( - name='Person', - interfaces=[NamedType], - fields={ - 'name': GraphQLField(GraphQLString), - 'pets': GraphQLField(GraphQLList(PetType)), - 'friends': GraphQLField(GraphQLList(NamedType)), - }, - is_type_of=lambda value, context, info: isinstance(value, Person) -) - -schema = GraphQLSchema(query=PersonType, types=[PetType]) - -garfield = Cat('Garfield', False) -odie = Dog('Odie', True) -liz = Person('Liz', [], []) -john = Person('John', [garfield, odie], [liz, odie]) - - -# Execute: Union and intersection types - -def test_can_introspect_on_union_and_intersection_types(): - ast = parse(''' - { - Named: __type(name: "Named") { - kind - name - fields { name } - interfaces { name } - possibleTypes { name } - enumValues { name } - inputFields { name } - } - Pet: __type(name: "Pet") { - kind - name - fields { name } - interfaces { name } - possibleTypes { name } - enumValues { name } - inputFields { name } - } - }''') - - result = execute(schema, ast) - assert not result.errors - assert result.data == { - 'Named': { - 'enumValues': None, - 'name': 'Named', - 'kind': 'INTERFACE', - 'interfaces': None, - 'fields': [{'name': 'name'}], - 'possibleTypes': [{'name': 'Person'}, {'name': 'Dog'}, {'name': 'Cat'}], - 'inputFields': None - }, - 'Pet': { - 'enumValues': None, - 'name': 'Pet', - 'kind': 'UNION', - 'interfaces': None, - 'fields': None, - 'possibleTypes': [{'name': 'Dog'}, {'name': 'Cat'}], - 'inputFields': None - } - } - - -def test_executes_using_union_types(): - # NOTE: This is an *invalid* query, but it should be an *executable* query. - ast = parse(''' - { - __typename - name - pets { - __typename - name - barks - meows - } - } - ''') - result = execute(schema, ast, john) - - assert not result.errors - assert result.data == { - '__typename': 'Person', - 'name': 'John', - 'pets': [ - {'__typename': 'Cat', 'name': 'Garfield', 'meows': False}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ] - } - - -def test_executes_union_types_with_inline_fragment(): - # This is the valid version of the query in the above test. - ast = parse(''' - { - __typename - name - pets { - __typename - ... on Dog { - name - barks - } - ... on Cat { - name - meows - } - } - } - ''') - result = execute(schema, ast, john) - assert not result.errors - assert result.data == { - '__typename': 'Person', - 'name': 'John', - 'pets': [ - {'__typename': 'Cat', 'name': 'Garfield', 'meows': False}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ] - } - - -def test_executes_using_interface_types(): - # NOTE: This is an *invalid* query, but it should be an *executable* query. - ast = parse(''' - { - __typename - name - friends { - __typename - name - barks - meows - } - } - ''') - result = execute(schema, ast, john) - assert not result.errors - assert result.data == { - '__typename': 'Person', - 'name': 'John', - 'friends': [ - {'__typename': 'Person', 'name': 'Liz'}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ] - } - - -def test_executes_interface_types_with_inline_fragment(): - # This is the valid version of the query in the above test. - ast = parse(''' - { - __typename - name - friends { - __typename - name - ... on Dog { - barks - } - ... on Cat { - meows - } - } - } - ''') - result = execute(schema, ast, john) - assert not result.errors - assert result.data == { - '__typename': 'Person', - 'name': 'John', - 'friends': [ - {'__typename': 'Person', 'name': 'Liz'}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ] - } - - -def test_allows_fragment_conditions_to_be_abstract_types(): - ast = parse(''' - { - __typename - name - pets { ...PetFields } - friends { ...FriendFields } - } - fragment PetFields on Pet { - __typename - ... on Dog { - name - barks - } - ... on Cat { - name - meows - } - } - fragment FriendFields on Named { - __typename - name - ... on Dog { - barks - } - ... on Cat { - meows - } - } - ''') - result = execute(schema, ast, john) - assert not result.errors - assert result.data == { - '__typename': 'Person', - 'name': 'John', - 'pets': [ - {'__typename': 'Cat', 'name': 'Garfield', 'meows': False}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ], - 'friends': [ - {'__typename': 'Person', 'name': 'Liz'}, - {'__typename': 'Dog', 'name': 'Odie', 'barks': True} - ] - } - - -def test_only_include_fields_from_matching_fragment_condition(): - ast = parse(''' - { - pets { ...PetFields } - } - fragment PetFields on Pet { - __typename - ... on Dog { - name - } - } - ''') - result = execute(schema, ast, john) - assert not result.errors - assert result.data == { - 'pets': [ - {'__typename': 'Cat'}, - {'__typename': 'Dog', 'name': 'Odie'} - ], - } - - -def test_gets_execution_info_in_resolver(): - class encountered: - schema = None - root_value = None - context = None - - def resolve_type(obj, context, info): - encountered.schema = info.schema - encountered.root_value = info.root_value - encountered.context = context - return PersonType2 - - NamedType2 = GraphQLInterfaceType( - name='Named', - fields={ - 'name': GraphQLField(GraphQLString) - }, - resolve_type=resolve_type - ) - - PersonType2 = GraphQLObjectType( - name='Person', - interfaces=[NamedType2], - fields={ - 'name': GraphQLField(GraphQLString), - 'friends': GraphQLField(GraphQLList(NamedType2)) - } - ) - - schema2 = GraphQLSchema(query=PersonType2) - john2 = Person('John', [], [liz]) - context = {'hey'} - ast = parse('''{ name, friends { name } }''') - - result = execute(schema2, ast, john2, context_value=context) - assert not result.errors - assert result.data == { - 'name': 'John', 'friends': [{'name': 'Liz'}] - } - - assert encountered.schema == schema2 - assert encountered.root_value == john2 - assert encountered.context == context diff --git a/graphql/execution/experimental/tests/test_variables.py b/graphql/execution/experimental/tests/test_variables.py deleted file mode 100644 index 0bafa260..00000000 --- a/graphql/execution/experimental/tests/test_variables.py +++ /dev/null @@ -1,668 +0,0 @@ -import json -from collections import OrderedDict - -from pytest import raises - -from graphql.error import GraphQLError, format_error -from graphql.execution import execute -from graphql.language.parser import parse -from graphql.type import (GraphQLArgument, GraphQLField, - GraphQLInputObjectField, GraphQLInputObjectType, - GraphQLList, GraphQLNonNull, GraphQLObjectType, - GraphQLScalarType, GraphQLSchema, GraphQLString) - -TestComplexScalar = GraphQLScalarType( - name='ComplexScalar', - serialize=lambda v: 'SerializedValue' if v == 'DeserializedValue' else None, - parse_value=lambda v: 'DeserializedValue' if v == 'SerializedValue' else None, - parse_literal=lambda v: 'DeserializedValue' if v.value == 'SerializedValue' else None -) - -TestInputObject = GraphQLInputObjectType('TestInputObject', OrderedDict([ - ('a', GraphQLInputObjectField(GraphQLString)), - ('b', GraphQLInputObjectField(GraphQLList(GraphQLString))), - ('c', GraphQLInputObjectField(GraphQLNonNull(GraphQLString))), - ('d', GraphQLInputObjectField(TestComplexScalar)) -])) - -stringify = lambda obj: json.dumps(obj, sort_keys=True) - - -def input_to_json(obj, args, context, info): - input = args.get('input') - if input: - return stringify(input) - - -TestNestedInputObject = GraphQLInputObjectType( - name='TestNestedInputObject', - fields={ - 'na': GraphQLInputObjectField(GraphQLNonNull(TestInputObject)), - 'nb': GraphQLInputObjectField(GraphQLNonNull(GraphQLString)) - } -) - -TestType = GraphQLObjectType('TestType', { - 'fieldWithObjectInput': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(TestInputObject)}, - resolver=input_to_json), - 'fieldWithNullableStringInput': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(GraphQLString)}, - resolver=input_to_json), - 'fieldWithNonNullableStringInput': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(GraphQLNonNull(GraphQLString))}, - resolver=input_to_json), - 'fieldWithDefaultArgumentValue': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(GraphQLString, 'Hello World')}, - resolver=input_to_json), - 'fieldWithNestedInputObject': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(TestNestedInputObject, 'Hello World')}, - resolver=input_to_json), - 'list': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument(GraphQLList(GraphQLString))}, - resolver=input_to_json), - 'nnList': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument( - GraphQLNonNull(GraphQLList(GraphQLString)) - )}, - resolver=input_to_json), - 'listNN': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument( - GraphQLList(GraphQLNonNull(GraphQLString)) - )}, - resolver=input_to_json), - 'nnListNN': GraphQLField( - GraphQLString, - args={'input': GraphQLArgument( - GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLString))) - )}, - resolver=input_to_json), -}) - -schema = GraphQLSchema(TestType) - - -def check(doc, expected, args=None): - ast = parse(doc) - response = execute(schema, ast, variable_values=args) - - if response.errors: - result = { - 'data': response.data, - 'errors': [format_error(e) for e in response.errors] - } - else: - result = { - 'data': response.data - } - - assert result == expected - - -# Handles objects and nullability - -def test_inline_executes_with_complex_input(): - doc = ''' - { - fieldWithObjectInput(input: {a: "foo", b: ["bar"], c: "baz"}) - } - ''' - check(doc, { - 'data': {"fieldWithObjectInput": stringify({"a": "foo", "b": ["bar"], "c": "baz"})} - }) - - -def test_properly_parses_single_value_to_list(): - doc = ''' - { - fieldWithObjectInput(input: {a: "foo", b: "bar", c: "baz"}) - } - ''' - check(doc, { - 'data': {'fieldWithObjectInput': stringify({"a": "foo", "b": ["bar"], "c": "baz"})} - }) - - -def test_does_not_use_incorrect_value(): - doc = ''' - { - fieldWithObjectInput(input: ["foo", "bar", "baz"]) - } - ''' - check(doc, { - 'data': {'fieldWithObjectInput': None} - }) - - -def test_properly_runs_parse_literal_on_complex_scalar_types(): - doc = ''' - { - fieldWithObjectInput(input: {a: "foo", d: "SerializedValue"}) - } - ''' - check(doc, { - 'data': { - 'fieldWithObjectInput': '{"a": "foo", "d": "DeserializedValue"}', - } - }) - - -# noinspection PyMethodMayBeStatic -class TestUsingVariables: - doc = ''' - query q($input: TestInputObject) { - fieldWithObjectInput(input: $input) - } - ''' - - def test_executes_with_complex_input(self): - params = {'input': {'a': 'foo', 'b': ['bar'], 'c': 'baz'}} - check(self.doc, { - 'data': {'fieldWithObjectInput': stringify({"a": "foo", "b": ["bar"], "c": "baz"})} - }, params) - - def test_uses_default_value_when_not_provided(self): - with_defaults_doc = ''' - query q($input: TestInputObject = {a: "foo", b: ["bar"], c: "baz"}) { - fieldWithObjectInput(input: $input) - } - ''' - - check(with_defaults_doc, { - 'data': {'fieldWithObjectInput': stringify({"a": "foo", "b": ["bar"], "c": "baz"})} - }) - - def test_properly_parses_single_value_to_list(self): - params = {'input': {'a': 'foo', 'b': 'bar', 'c': 'baz'}} - check(self.doc, { - 'data': {'fieldWithObjectInput': stringify({"a": "foo", "b": ["bar"], "c": "baz"})} - }, params) - - def test_executes_with_complex_scalar_input(self): - params = {'input': {'c': 'foo', 'd': 'SerializedValue'}} - check(self.doc, { - 'data': {'fieldWithObjectInput': stringify({"c": "foo", "d": "DeserializedValue"})} - }, params) - - def test_errors_on_null_for_nested_non_null(self): - params = {'input': {'a': 'foo', 'b': 'bar', 'c': None}} - - with raises(GraphQLError) as excinfo: - check(self.doc, {}, params) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In field "c": Expected "String!", found null.'.format(stringify(params['input'])) - } - - def test_errors_on_incorrect_type(self): - params = {'input': 'foo bar'} - - with raises(GraphQLError) as excinfo: - check(self.doc, {}, params) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'Expected "TestInputObject", found not an object.'.format(stringify(params['input'])) - } - - def test_errors_on_omission_of_nested_non_null(self): - params = {'input': {'a': 'foo', 'b': 'bar'}} - - with raises(GraphQLError) as excinfo: - check(self.doc, {}, params) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In field "c": Expected "String!", found null.'.format(stringify(params['input'])) - } - - def test_errors_on_deep_nested_errors_and_with_many_errors(self): - nested_doc = ''' - query q($input: TestNestedInputObject) { - fieldWithNestedObjectInput(input: $input) - } - ''' - - params = {'input': {'na': {'a': 'foo'}}} - with raises(GraphQLError) as excinfo: - check(nested_doc, {}, params) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 19, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In field "na": In field "c": Expected "String!", found null.\n' - 'In field "nb": Expected "String!", found null.'.format(stringify(params['input'])) - } - - def test_errors_on_addition_of_input_field_of_incorrect_type(self): - params = {'input': {'a': 'foo', 'b': 'bar', 'c': 'baz', 'd': 'dog'}} - - with raises(GraphQLError) as excinfo: - check(self.doc, {}, params) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In field "d": Expected type "ComplexScalar", found "dog".'.format(stringify(params['input'])) - } - - def test_errors_on_addition_of_unknown_input_field(self): - params = {'input': {'a': 'foo', 'b': 'bar', 'c': 'baz', 'extra': 'dog'}} - - with raises(GraphQLError) as excinfo: - check(self.doc, {}, params) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In field "extra": Unknown field.'.format(stringify(params['input'])) - } - - -def test_allows_nullable_inputs_to_be_omitted(): - doc = '{ fieldWithNullableStringInput }' - check(doc, {'data': { - 'fieldWithNullableStringInput': None - }}) - - -def test_allows_nullable_inputs_to_be_omitted_in_a_variable(): - doc = ''' - query SetsNullable($value: String) { - fieldWithNullableStringInput(input: $value) - } - ''' - - check(doc, { - 'data': { - 'fieldWithNullableStringInput': None - } - }) - - -def test_allows_nullable_inputs_to_be_omitted_in_an_unlisted_variable(): - doc = ''' - query SetsNullable { - fieldWithNullableStringInput(input: $value) - } - ''' - - check(doc, { - 'data': { - 'fieldWithNullableStringInput': None - } - }) - - -def test_allows_nullable_inputs_to_be_set_to_null_in_a_variable(): - doc = ''' - query SetsNullable($value: String) { - fieldWithNullableStringInput(input: $value) - } - ''' - check(doc, { - 'data': { - 'fieldWithNullableStringInput': None - } - }, {'value': None}) - - -def test_allows_nullable_inputs_to_be_set_to_a_value_in_a_variable(): - doc = ''' - query SetsNullable($value: String) { - fieldWithNullableStringInput(input: $value) - } - ''' - - check(doc, { - 'data': { - 'fieldWithNullableStringInput': '"a"' - } - }, {'value': 'a'}) - - -def test_allows_nullable_inputs_to_be_set_to_a_value_directly(): - doc = ''' - { - fieldWithNullableStringInput(input: "a") - } - ''' - check(doc, { - 'data': { - 'fieldWithNullableStringInput': '"a"' - } - }) - - -def test_does_not_allow_non_nullable_inputs_to_be_omitted_in_a_variable(): - doc = ''' - query SetsNonNullable($value: String!) { - fieldWithNonNullableStringInput(input: $value) - } - ''' - with raises(GraphQLError) as excinfo: - check(doc, {}) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 27, 'line': 2}], - 'message': 'Variable "$value" of required type "String!" was not provided.' - } - - -def test_does_not_allow_non_nullable_inputs_to_be_set_to_null_in_a_variable(): - doc = ''' - query SetsNonNullable($value: String!) { - fieldWithNonNullableStringInput(input: $value) - } - ''' - - with raises(GraphQLError) as excinfo: - check(doc, {}, {'value': None}) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 27, 'line': 2}], - 'message': 'Variable "$value" of required type "String!" was not provided.' - } - - -def test_allows_non_nullable_inputs_to_be_set_to_a_value_in_a_variable(): - doc = ''' - query SetsNonNullable($value: String!) { - fieldWithNonNullableStringInput(input: $value) - } - ''' - - check(doc, { - 'data': { - 'fieldWithNonNullableStringInput': '"a"' - } - }, {'value': 'a'}) - - -def test_allows_non_nullable_inputs_to_be_set_to_a_value_directly(): - doc = ''' - { - fieldWithNonNullableStringInput(input: "a") - } - ''' - - check(doc, { - 'data': { - 'fieldWithNonNullableStringInput': '"a"' - } - }) - - -def test_passes_along_null_for_non_nullable_inputs_if_explcitly_set_in_the_query(): - doc = ''' - { - fieldWithNonNullableStringInput - } - ''' - - check(doc, { - 'errors': [{ - 'message': 'Argument "input" of required type String!" was not provided.' - }], - 'data': None - }) - - -def test_allows_lists_to_be_null(): - doc = ''' - query q($input: [String]) { - list(input: $input) - } - ''' - - check(doc, { - 'data': { - 'list': None - } - }) - - -def test_allows_lists_to_contain_values(): - doc = ''' - query q($input: [String]) { - list(input: $input) - } - ''' - - check(doc, { - 'data': { - 'list': stringify(['A']) - } - }, {'input': ['A']}) - - -def test_allows_lists_to_contain_null(): - doc = ''' - query q($input: [String]) { - list(input: $input) - } - ''' - - check(doc, { - 'data': { - 'list': stringify(['A', None, 'B']) - } - }, {'input': ['A', None, 'B']}) - - -def test_does_not_allow_non_null_lists_to_be_null(): - doc = ''' - query q($input: [String]!) { - nnList(input: $input) - } - ''' - - with raises(GraphQLError) as excinfo: - check(doc, {}, {'input': None}) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" of required type "[String]!" was not provided.' - } - - -def test_allows_non_null_lists_to_contain_values(): - doc = ''' - query q($input: [String]!) { - nnList(input: $input) - } - ''' - - check(doc, { - 'data': { - 'nnList': stringify(['A']) - } - }, {'input': ['A']}) - - -def test_allows_non_null_lists_to_contain_null(): - doc = ''' - query q($input: [String]!) { - nnList(input: $input) - } - ''' - - check(doc, { - 'data': { - 'nnList': stringify(['A', None, 'B']) - } - }, {'input': ['A', None, 'B']}) - - -def test_allows_lists_of_non_nulls_to_be_null(): - doc = ''' - query q($input: [String!]) { - listNN(input: $input) - } - ''' - - check(doc, { - 'data': { - 'listNN': None - } - }, {'input': None}) - - -def test_allows_lists_of_non_nulls_to_contain_values(): - doc = ''' - query q($input: [String!]) { - listNN(input: $input) - } - ''' - - check(doc, { - 'data': { - 'listNN': stringify(['A']) - } - }, {'input': ['A']}) - - -def test_does_not_allow_lists_of_non_nulls_to_contain_null(): - doc = ''' - query q($input: [String!]) { - listNN(input: $input) - } - ''' - - params = {'input': ['A', None, 'B']} - - with raises(GraphQLError) as excinfo: - check(doc, {}, params) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In element #1: Expected "String!", found null.'.format(stringify(params['input'])) - } - - -def test_does_not_allow_non_null_lists_of_non_nulls_to_be_null(): - doc = ''' - query q($input: [String!]!) { - nnListNN(input: $input) - } - ''' - with raises(GraphQLError) as excinfo: - check(doc, {}, {'input': None}) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" of required type "[String!]!" was not provided.' - } - - -def test_allows_non_null_lists_of_non_nulls_to_contain_values(): - doc = ''' - query q($input: [String!]!) { - nnListNN(input: $input) - } - ''' - - check(doc, { - 'data': { - 'nnListNN': stringify(['A']) - } - }, {'input': ['A']}) - - -def test_does_not_allow_non_null_lists_of_non_nulls_to_contain_null(): - doc = ''' - query q($input: [String!]!) { - nnListNN(input: $input) - } - ''' - - params = {'input': ['A', None, 'B']} - - with raises(GraphQLError) as excinfo: - check(doc, {}, params) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" got invalid value {}.\n' - 'In element #1: Expected "String!", found null.'.format(stringify(params['input'])) - } - - -def test_does_not_allow_invalid_types_to_be_used_as_values(): - doc = ''' - query q($input: TestType!) { - fieldWithObjectInput(input: $input) - } - ''' - params = {'input': {'list': ['A', 'B']}} - - with raises(GraphQLError) as excinfo: - check(doc, {}, params) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" expected value of type "TestType!" which cannot be used as an input type.' - } - - -def test_does_not_allow_unknown_types_to_be_used_as_values(): - doc = ''' - query q($input: UnknownType!) { - fieldWithObjectInput(input: $input) - } - ''' - params = {'input': 'whoknows'} - - with raises(GraphQLError) as excinfo: - check(doc, {}, params) - - assert format_error(excinfo.value) == { - 'locations': [{'column': 13, 'line': 2}], - 'message': 'Variable "$input" expected value of type "UnknownType!" which cannot be used as an input type.' - } - - -# noinspection PyMethodMayBeStatic -class TestUsesArgumentDefaultValues: - - def test_when_no_argument_provided(self): - check('{ fieldWithDefaultArgumentValue }', { - 'data': { - 'fieldWithDefaultArgumentValue': '"Hello World"' - } - }) - - def test_when_nullable_variable_provided(self): - check(''' - query optionalVariable($optional: String) { - fieldWithDefaultArgumentValue(input: $optional) - } - ''', { - 'data': { - 'fieldWithDefaultArgumentValue': '"Hello World"' - } - }) - - def test_when_argument_provided_cannot_be_parsed(self): - check(''' - { - fieldWithDefaultArgumentValue(input: WRONG_TYPE) - } - ''', { - 'data': { - 'fieldWithDefaultArgumentValue': '"Hello World"' - } - }) diff --git a/graphql/execution/experimental/tests/utils.py b/graphql/execution/experimental/tests/utils.py deleted file mode 100644 index 89246de1..00000000 --- a/graphql/execution/experimental/tests/utils.py +++ /dev/null @@ -1,46 +0,0 @@ -from promise import Promise - -from graphql.execution import ExecutionResult -from graphql.language.parser import parse -from graphql.language.source import Source -from graphql.validation import validate - -from ..executor import execute - - -def resolved(value): - return Promise.fulfilled(value) - - -def rejected(error): - return Promise.rejected(error) - - -def graphql(schema, request_string='', root_value=None, context_value=None, - variable_values=None, operation_name=None, executor=None, - return_promise=False, middleware=None): - try: - source = Source(request_string, 'GraphQL request') - ast = parse(source) - validation_errors = validate(schema, ast) - if validation_errors: - return ExecutionResult( - errors=validation_errors, - invalid=True, - ) - return execute( - schema, - ast, - root_value, - context_value, - operation_name=operation_name, - variable_values=variable_values or {}, - executor=executor, - return_promise=return_promise, - middleware=middleware, - ) - except Exception as e: - return ExecutionResult( - errors=[e], - invalid=True, - ) diff --git a/graphql/execution/experimental/utils.py b/graphql/execution/experimental/utils.py deleted file mode 100644 index 8aef421d..00000000 --- a/graphql/execution/experimental/utils.py +++ /dev/null @@ -1,7 +0,0 @@ -try: - from itertools import imap - normal_map = map -except: - def normal_map(func, iter): - return list(map(func, iter)) - imap = map diff --git a/graphql/execution/tests/test_benchmark.py b/graphql/execution/tests/test_benchmark.py index 7637eac6..8c5e8d75 100644 --- a/graphql/execution/tests/test_benchmark.py +++ b/graphql/execution/tests/test_benchmark.py @@ -22,11 +22,11 @@ }) -def resolve_all_containers(root, args, context, info): +def resolve_all_containers(root, info, **args): return big_container_list -def resolve_all_ints(root, args, context, info): +def resolve_all_ints(root, info, **args): return big_int_list diff --git a/graphql/execution/tests/test_dataloader.py b/graphql/execution/tests/test_dataloader.py index 24d12957..aaa01b0c 100644 --- a/graphql/execution/tests/test_dataloader.py +++ b/graphql/execution/tests/test_dataloader.py @@ -14,7 +14,7 @@ def test_batches_correctly(executor): Business = GraphQLObjectType('Business', lambda: { - 'id': GraphQLField(GraphQLID, resolver=lambda root, args, context, info: root), + 'id': GraphQLField(GraphQLID, resolver=lambda root, info, **args: root), }) Query = GraphQLObjectType('Query', lambda: { @@ -22,7 +22,7 @@ def test_batches_correctly(executor): args={ 'id': GraphQLArgument(GraphQLNonNull(GraphQLID)), }, - resolver=lambda root, args, context, info: context.business_data_loader.load(args.get('id')) + resolver=lambda root, info, **args: info.context.business_data_loader.load(args.get('id')) ), }) @@ -73,13 +73,13 @@ class Context(object): def test_batches_multiple_together(executor): Location = GraphQLObjectType('Location', lambda: { - 'id': GraphQLField(GraphQLID, resolver=lambda root, args, context, info: root), + 'id': GraphQLField(GraphQLID, resolver=lambda root, info, **args: root), }) Business = GraphQLObjectType('Business', lambda: { - 'id': GraphQLField(GraphQLID, resolver=lambda root, args, context, info: root), + 'id': GraphQLField(GraphQLID, resolver=lambda root, info, **args: root), 'location': GraphQLField(Location, - resolver=lambda root, args, context, info: context.location_data_loader.load('location-{}'.format(root)) + resolver=lambda root, info, **args: info.context.location_data_loader.load('location-{}'.format(root)) ), }) @@ -88,7 +88,7 @@ def test_batches_multiple_together(executor): args={ 'id': GraphQLArgument(GraphQLNonNull(GraphQLID)), }, - resolver=lambda root, args, context, info: context.business_data_loader.load(args.get('id')) + resolver=lambda root, info, **args: info.context.business_data_loader.load(args.get('id')) ), }) diff --git a/graphql/execution/tests/test_execute_schema.py b/graphql/execution/tests/test_execute_schema.py index a5c2a299..16e46465 100644 --- a/graphql/execution/tests/test_execute_schema.py +++ b/graphql/execution/tests/test_execute_schema.py @@ -20,7 +20,7 @@ def test_executes_using_a_schema(): 'width': GraphQLArgument(GraphQLInt), 'height': GraphQLArgument(GraphQLInt), }, - resolver=lambda obj, args, *_: + resolver=lambda obj, info, **args: obj.pic(args['width'], args['height']) ), 'recentArticle': GraphQLField(BlogArticle), @@ -39,7 +39,7 @@ def test_executes_using_a_schema(): 'article': GraphQLField( BlogArticle, args={'id': GraphQLArgument(GraphQLID)}, - resolver=lambda obj, args, *_: Article(args['id'])), + resolver=lambda obj, info, **args: Article(args['id'])), 'feed': GraphQLField( GraphQLList(BlogArticle), resolver=lambda *_: map(Article, range(1, 10 + 1))), diff --git a/graphql/execution/tests/test_executor.py b/graphql/execution/tests/test_executor.py index 9aff9362..a57b2d9c 100644 --- a/graphql/execution/tests/test_executor.py +++ b/graphql/execution/tests/test_executor.py @@ -97,7 +97,7 @@ def deeper(self): 'pic': GraphQLField( args={'size': GraphQLArgument(GraphQLInt)}, type=GraphQLString, - resolver=lambda obj, args, *_: obj.pic(args['size']), + resolver=lambda obj, info, size: obj.pic(size), ), 'deep': GraphQLField(DeepDataType), 'promise': GraphQLField(DataType), @@ -190,9 +190,9 @@ def test_correctly_threads_arguments(): } ''' - def resolver(_, args, *_args): - assert args['numArg'] == 123 - assert args['stringArg'] == 'foo' + def resolver(source, info, numArg, stringArg): + assert numArg == 123 + assert stringArg == 'foo' resolver.got_here = True resolver.got_here = False @@ -437,7 +437,7 @@ def test_does_not_include_arguments_that_were_not_set(): { 'field': GraphQLField( GraphQLString, - resolver=lambda data, args, *_: args and json.dumps(args, sort_keys=True, separators=(',', ':')), + resolver=lambda source, info, **args: args and json.dumps(args, sort_keys=True, separators=(',', ':')), args={ 'a': GraphQLArgument(GraphQLBoolean), 'b': GraphQLArgument(GraphQLBoolean), diff --git a/graphql/execution/tests/test_executor_thread.py b/graphql/execution/tests/test_executor_thread.py index 062a8e66..2838c9f2 100644 --- a/graphql/execution/tests/test_executor_thread.py +++ b/graphql/execution/tests/test_executor_thread.py @@ -98,7 +98,7 @@ def deeper(self): 'pic': GraphQLField( args={'size': GraphQLArgument(GraphQLInt)}, type=GraphQLString, - resolver=lambda obj, args, *_: obj.pic(args['size']), + resolver=lambda obj, info, **args: obj.pic(args['size']), ), 'deep': GraphQLField(DeepDataType), 'promise': GraphQLField(DataType), diff --git a/graphql/execution/tests/test_mutations.py b/graphql/execution/tests/test_mutations.py index 3a317fdf..3a71dfbb 100644 --- a/graphql/execution/tests/test_mutations.py +++ b/graphql/execution/tests/test_mutations.py @@ -44,22 +44,22 @@ def promise_and_fail_to_change_the_number(self, n): 'immediatelyChangeTheNumber': GraphQLField( NumberHolderType, args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, args, *_: + resolver=lambda obj, info, **args: obj.immediately_change_the_number(args['newNumber'])), 'promiseToChangeTheNumber': GraphQLField( NumberHolderType, args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, args, *_: + resolver=lambda obj, info, **args: obj.promise_to_change_the_number(args['newNumber'])), 'failToChangeTheNumber': GraphQLField( NumberHolderType, args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, args, *_: + resolver=lambda obj, info, **args: obj.fail_to_change_the_number(args['newNumber'])), 'promiseAndFailToChangeTheNumber': GraphQLField( NumberHolderType, args={'newNumber': GraphQLArgument(GraphQLInt)}, - resolver=lambda obj, args, *_: + resolver=lambda obj, info, **args: obj.promise_and_fail_to_change_the_number(args['newNumber'])), }) diff --git a/graphql/execution/tests/test_resolve.py b/graphql/execution/tests/test_resolve.py index 98cd09ea..0ae7fc0f 100644 --- a/graphql/execution/tests/test_resolve.py +++ b/graphql/execution/tests/test_resolve.py @@ -61,7 +61,7 @@ def test(self): def test_uses_provided_resolve_function(): - def resolver(source, args, *_): + def resolver(source, info, **args): return json.dumps([source, args], separators=(',', ':')) schema = _test_schema(GraphQLField( @@ -90,7 +90,7 @@ def resolver(source, args, *_): def test_handles_resolved_promises(): - def resolver(source, args, *_): + def resolver(source, info, **args): return Promise.resolve('foo') schema = _test_schema(GraphQLField( @@ -104,7 +104,7 @@ def resolver(source, args, *_): def test_handles_resolved_custom_promises(): - def resolver(source, args, *_): + def resolver(source, info, **args): return CustomPromise.resolve('custom_foo') schema = _test_schema(GraphQLField( @@ -118,7 +118,7 @@ def resolver(source, args, *_): def test_maps_argument_out_names_well(): - def resolver(source, args, *_): + def resolver(source, info, **args): return json.dumps([source, args], separators=(',', ':')) schema = _test_schema(GraphQLField( @@ -147,7 +147,7 @@ def resolver(source, args, *_): def test_maps_argument_out_names_well_with_input(): - def resolver(source, args, *_): + def resolver(source, info, **args): return json.dumps([source, args], separators=(',', ':')) diff --git a/graphql/execution/tests/test_variables.py b/graphql/execution/tests/test_variables.py index 36d0ba1a..f50cbb5b 100644 --- a/graphql/execution/tests/test_variables.py +++ b/graphql/execution/tests/test_variables.py @@ -38,7 +38,7 @@ class my_special_dict(dict): stringify = lambda obj: json.dumps(obj, sort_keys=True) -def input_to_json(obj, args, context, info): +def input_to_json(obj, info, **args): input = args.get('input') if input: return stringify(input) @@ -60,7 +60,7 @@ def input_to_json(obj, args, context, info): 'fieldWithCustomObjectInput': GraphQLField( GraphQLBoolean, args={'input': GraphQLArgument(TestCustomInputObject)}, - resolver=lambda root, args, context, info: isinstance(args.get('input'), my_special_dict)), + resolver=lambda root, info, **args: isinstance(args.get('input'), my_special_dict)), 'fieldWithNullableStringInput': GraphQLField( GraphQLString, args={'input': GraphQLArgument(GraphQLString)}, diff --git a/graphql/type/definition.py b/graphql/type/definition.py index e593fb23..b10a5428 100644 --- a/graphql/type/definition.py +++ b/graphql/type/definition.py @@ -147,7 +147,7 @@ class GraphQLObjectType(GraphQLType): 'street': GraphQLField(GraphQLString), 'number': GraphQLField(GraphQLInt), 'formatted': GraphQLField(GraphQLString, - resolver=lambda obj, args, context, info: obj.number + ' ' + obj.street), + resolver=lambda obj, info, **args: obj.number + ' ' + obj.street), }) When two types need to refer to each other, or a type needs to refer to diff --git a/graphql/type/introspection.py b/graphql/type/introspection.py index b2732fc8..7c44ff75 100644 --- a/graphql/type/introspection.py +++ b/graphql/type/introspection.py @@ -213,10 +213,10 @@ def kind(cls, type, *_): raise Exception('Unknown kind of type: {}'.format(type)) @staticmethod - def fields(type, args, *_): + def fields(type, info, includeDeprecated=None): if isinstance(type, (GraphQLObjectType, GraphQLInterfaceType)): fields = [] - include_deprecated = args.get('includeDeprecated') + include_deprecated = includeDeprecated for field_name, field in type.fields.items(): if field.deprecation_reason and not include_deprecated: continue @@ -231,26 +231,26 @@ def fields(type, args, *_): return None @staticmethod - def interfaces(type, *_): + def interfaces(type, info): if isinstance(type, GraphQLObjectType): return type.interfaces @staticmethod - def possible_types(type, args, context, info): + def possible_types(type, info, **args): if isinstance(type, (GraphQLInterfaceType, GraphQLUnionType)): return info.schema.get_possible_types(type) @staticmethod - def enum_values(type, args, *_): + def enum_values(type, info, includeDeprecated=None): if isinstance(type, GraphQLEnumType): values = type.values - if not args.get('includeDeprecated'): + if not includeDeprecated: values = [v for v in values if not v.deprecation_reason] return values @staticmethod - def input_fields(type, *_): + def input_fields(type, info): if isinstance(type, GraphQLInputObjectType): return input_fields_to_list(type.fields) @@ -419,7 +419,7 @@ def input_fields(type, *_): # name='__schema', type=GraphQLNonNull(__Schema), description='Access the current type schema of this server.', - resolver=lambda source, args, context, info: info.schema, + resolver=lambda source, info, **args: info.schema, args={} ) @@ -428,13 +428,13 @@ def input_fields(type, *_): # name='__type', description='Request the type information of a single type.', args={'name': GraphQLArgument(GraphQLNonNull(GraphQLString))}, - resolver=lambda source, args, context, info: info.schema.get_type(args['name']) + resolver=lambda source, info, **args: info.schema.get_type(args['name']) ) TypeNameMetaFieldDef = GraphQLField( type=GraphQLNonNull(GraphQLString), # name='__typename', description='The name of the current Object type at runtime.', - resolver=lambda source, args, context, info: info.parent_type.name, + resolver=lambda source, info, **args: info.parent_type.name, args={} ) diff --git a/graphql/type/tests/test_enum_type.py b/graphql/type/tests/test_enum_type.py index 6cf22637..2381a8c9 100644 --- a/graphql/type/tests/test_enum_type.py +++ b/graphql/type/tests/test_enum_type.py @@ -35,7 +35,7 @@ def get_first(args, *keys): 'fromInt': GraphQLArgument(GraphQLInt), 'fromString': GraphQLArgument(GraphQLString) }, - resolver=lambda value, args, context, info: get_first(args, 'fromInt', 'fromString', 'fromEnum') + resolver=lambda value, info, **args: get_first(args, 'fromInt', 'fromString', 'fromEnum') ), 'colorInt': GraphQLField( type=GraphQLInt, @@ -43,7 +43,7 @@ def get_first(args, *keys): 'fromEnum': GraphQLArgument(ColorType), 'fromInt': GraphQLArgument(GraphQLInt), }, - resolver=lambda value, args, context, info: get_first(args, 'fromInt', 'fromEnum') + resolver=lambda value, info, **args: get_first(args, 'fromInt', 'fromEnum') ) } ) @@ -56,7 +56,7 @@ def get_first(args, *keys): args={ 'color': GraphQLArgument(ColorType) }, - resolver=lambda value, args, context, info: args.get('color') + resolver=lambda value, info, **args: args.get('color') ) } ) @@ -69,7 +69,7 @@ def get_first(args, *keys): args={ 'color': GraphQLArgument(ColorType) }, - resolver=lambda value, args, context, info: args.get('color') + resolver=lambda value, info, **args: args.get('color') ) } ) diff --git a/graphql/type/tests/test_introspection.py b/graphql/type/tests/test_introspection.py index e4633763..378e0bf6 100644 --- a/graphql/type/tests/test_introspection.py +++ b/graphql/type/tests/test_introspection.py @@ -728,7 +728,7 @@ def test_introspects_on_input_object(): 'field': GraphQLField( type=GraphQLString, args={'complex': GraphQLArgument(TestInputObject)}, - resolver=lambda obj, args, context, info: json.dumps(args.get('complex')) + resolver=lambda obj, info, **args: json.dumps(args.get('complex')) ) }) schema = GraphQLSchema(TestType) diff --git a/graphql/utils/build_client_schema.py b/graphql/utils/build_client_schema.py index 116b7771..4ce0af3b 100644 --- a/graphql/utils/build_client_schema.py +++ b/graphql/utils/build_client_schema.py @@ -22,7 +22,7 @@ def _none(*_): return None -def no_execution(*args): +def no_execution(root, info, **args): raise Exception('Client Schema cannot be used for execution.') From 0d8c20dc9a3f82c58e03f5ae49a3479d8f38327a Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 27 Jul 2017 01:50:46 -0700 Subject: [PATCH 3/5] Removed context from is_type_of --- graphql/execution/executor.py | 4 ++-- graphql/execution/tests/test_abstract.py | 2 +- graphql/execution/tests/test_executor.py | 2 +- graphql/execution/tests/test_union_interface.py | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index 7784993b..c00a923c 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -356,7 +356,7 @@ def complete_abstract_value(exe_context, return_type, field_asts, info, result): def get_default_resolve_type_fn(value, context, info, abstract_type): possible_types = info.schema.get_possible_types(abstract_type) for type in possible_types: - if callable(type.is_type_of) and type.is_type_of(value, context, info): + if callable(type.is_type_of) and type.is_type_of(value, info): return type @@ -364,7 +364,7 @@ def complete_object_value(exe_context, return_type, field_asts, info, result): """ Complete an Object value by evaluating all sub-selections. """ - if return_type.is_type_of and not return_type.is_type_of(result, exe_context.context_value, info): + if return_type.is_type_of and not return_type.is_type_of(result, info): raise GraphQLError( u'Expected value of type "{}" but got: {}.'.format(return_type, type(result).__name__), field_asts diff --git a/graphql/execution/tests/test_abstract.py b/graphql/execution/tests/test_abstract.py index b58920f2..5dc7bce9 100644 --- a/graphql/execution/tests/test_abstract.py +++ b/graphql/execution/tests/test_abstract.py @@ -25,7 +25,7 @@ def __init__(self, name): self.name = name -is_type_of = lambda type: lambda obj, context, info: isinstance(obj, type) +is_type_of = lambda type: lambda obj, info: isinstance(obj, type) def make_type_resolver(types): diff --git a/graphql/execution/tests/test_executor.py b/graphql/execution/tests/test_executor.py index a57b2d9c..1ac90db5 100644 --- a/graphql/execution/tests/test_executor.py +++ b/graphql/execution/tests/test_executor.py @@ -472,7 +472,7 @@ def __init__(self, value): fields={ 'value': GraphQLField(GraphQLString), }, - is_type_of=lambda obj, context, info: isinstance(obj, Special) + is_type_of=lambda obj, info: isinstance(obj, Special) ) schema = GraphQLSchema( diff --git a/graphql/execution/tests/test_union_interface.py b/graphql/execution/tests/test_union_interface.py index 27eeedd8..2a2be2fc 100644 --- a/graphql/execution/tests/test_union_interface.py +++ b/graphql/execution/tests/test_union_interface.py @@ -38,7 +38,7 @@ def __init__(self, name, pets, friends): 'name': GraphQLField(GraphQLString), 'barks': GraphQLField(GraphQLBoolean), }, - is_type_of=lambda value, context, info: isinstance(value, Dog) + is_type_of=lambda value, info: isinstance(value, Dog) ) CatType = GraphQLObjectType( @@ -48,7 +48,7 @@ def __init__(self, name, pets, friends): 'name': GraphQLField(GraphQLString), 'meows': GraphQLField(GraphQLBoolean), }, - is_type_of=lambda value, context, info: isinstance(value, Cat) + is_type_of=lambda value, info: isinstance(value, Cat) ) @@ -70,7 +70,7 @@ def resolve_pet_type(value, context, info): 'pets': GraphQLField(GraphQLList(PetType)), 'friends': GraphQLField(GraphQLList(NamedType)), }, - is_type_of=lambda value, context, info: isinstance(value, Person) + is_type_of=lambda value, info: isinstance(value, Person) ) schema = GraphQLSchema(query=PersonType, types=[PetType]) From a3e36a588c44b182361ffbffa558ef4712ea40c9 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Thu, 27 Jul 2017 01:52:40 -0700 Subject: [PATCH 4/5] Removed context from resolve_type --- graphql/execution/executor.py | 6 +++--- graphql/execution/tests/test_abstract.py | 2 +- graphql/execution/tests/test_union_interface.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/graphql/execution/executor.py b/graphql/execution/executor.py index c00a923c..d8e4e6b8 100644 --- a/graphql/execution/executor.py +++ b/graphql/execution/executor.py @@ -324,9 +324,9 @@ def complete_abstract_value(exe_context, return_type, field_asts, info, result): # Field type must be Object, Interface or Union and expect sub-selections. if isinstance(return_type, (GraphQLInterfaceType, GraphQLUnionType)): if return_type.resolve_type: - runtime_type = return_type.resolve_type(result, exe_context.context_value, info) + runtime_type = return_type.resolve_type(result, info) else: - runtime_type = get_default_resolve_type_fn(result, exe_context.context_value, info, return_type) + runtime_type = get_default_resolve_type_fn(result, info, return_type) if isinstance(runtime_type, string_types): runtime_type = info.schema.get_type(runtime_type) @@ -353,7 +353,7 @@ def complete_abstract_value(exe_context, return_type, field_asts, info, result): return complete_object_value(exe_context, runtime_type, field_asts, info, result) -def get_default_resolve_type_fn(value, context, info, abstract_type): +def get_default_resolve_type_fn(value, info, abstract_type): possible_types = info.schema.get_possible_types(abstract_type) for type in possible_types: if callable(type.is_type_of) and type.is_type_of(value, info): diff --git a/graphql/execution/tests/test_abstract.py b/graphql/execution/tests/test_abstract.py index 5dc7bce9..0b745bc3 100644 --- a/graphql/execution/tests/test_abstract.py +++ b/graphql/execution/tests/test_abstract.py @@ -29,7 +29,7 @@ def __init__(self, name): def make_type_resolver(types): - def resolve_type(obj, context, info): + def resolve_type(obj, info): if callable(types): t = types() else: diff --git a/graphql/execution/tests/test_union_interface.py b/graphql/execution/tests/test_union_interface.py index 2a2be2fc..d45d2625 100644 --- a/graphql/execution/tests/test_union_interface.py +++ b/graphql/execution/tests/test_union_interface.py @@ -52,7 +52,7 @@ def __init__(self, name, pets, friends): ) -def resolve_pet_type(value, context, info): +def resolve_pet_type(value, info): if isinstance(value, Dog): return DogType if isinstance(value, Cat): @@ -317,7 +317,7 @@ class encountered: root_value = None context = None - def resolve_type(obj, context, info): + def resolve_type(obj, info): encountered.schema = info.schema encountered.root_value = info.root_value encountered.context = context From cece343f05e9517ac244433586ccabaea92f1bb1 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 31 Jul 2017 20:58:35 -0700 Subject: [PATCH 5/5] Fixed test starwars resolvers --- tests/starwars/starwars_schema.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/starwars/starwars_schema.py b/tests/starwars/starwars_schema.py index 52b3fb5f..74bf4364 100644 --- a/tests/starwars/starwars_schema.py +++ b/tests/starwars/starwars_schema.py @@ -45,7 +45,7 @@ description='Which movies they appear in.' ), }, - resolve_type=lambda character, *_: humanType if getHuman(character.id) else droidType, + resolve_type=lambda character, info: humanType if getHuman(character.id) else droidType, ) humanType = GraphQLObjectType( @@ -92,7 +92,7 @@ 'friends': GraphQLField( GraphQLList(characterInterface), description='The friends of the droid, or an empty list if they have none.', - resolver=lambda droid, *_: getFriends(droid), + resolver=lambda droid, info, **args: getFriends(droid), ), 'appearsIn': GraphQLField( GraphQLList(episodeEnum), @@ -118,7 +118,7 @@ type=episodeEnum, ) }, - resolver=lambda root, args, *_: getHero(args.get('episode')), + resolver=lambda root, info, **args: getHero(args.get('episode')), ), 'human': GraphQLField( humanType, @@ -128,7 +128,7 @@ type=GraphQLNonNull(GraphQLString), ) }, - resolver=lambda root, args, *_: getHuman(args['id']), + resolver=lambda root, info, **args: getHuman(args['id']), ), 'droid': GraphQLField( droidType, @@ -138,7 +138,7 @@ type=GraphQLNonNull(GraphQLString), ) }, - resolver=lambda root, args, *_: getDroid(args['id']), + resolver=lambda root, info, **args: getDroid(args['id']), ), } )