mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 12:44:15 +03:00
Improved mutations, tests and overall integration.
This commit is contained in:
parent
6f87720fc1
commit
28d89a44f1
|
@ -9,18 +9,11 @@ from .types.definitions import List, NonNull
|
||||||
class DeprecatedField(FieldType):
|
class DeprecatedField(FieldType):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
cls = self.__class__
|
cls = self.__class__
|
||||||
warnings.warn("Using {} is not longer supported".format(cls.__name__)
|
warnings.warn("Using {} is not longer supported".format(cls.__name__), FutureWarning)
|
||||||
, FutureWarning)
|
if 'resolve' in kwargs:
|
||||||
kwargs['resolver'] = kwargs.pop('resolve', None)
|
kwargs['resolver'] = kwargs.pop('resolve')
|
||||||
self.required = kwargs.pop('required', False)
|
|
||||||
return super(DeprecatedField, self).__init__(*args, **kwargs)
|
return super(DeprecatedField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def as_field(self):
|
|
||||||
t = self
|
|
||||||
if self.required:
|
|
||||||
t = NonNull(t)
|
|
||||||
return Field(t, _creation_counter=self.creation_counter, *self.args, **self.kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class StringField(DeprecatedField, String):
|
class StringField(DeprecatedField, String):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -8,6 +8,7 @@ from graphql.core.execution.middlewares.sync import \
|
||||||
from graphql.core.type import GraphQLSchema as _GraphQLSchema
|
from graphql.core.type import GraphQLSchema as _GraphQLSchema
|
||||||
from graphql.core.utils.introspection_query import introspection_query
|
from graphql.core.utils.introspection_query import introspection_query
|
||||||
from graphene.core.types.base import BaseType
|
from graphene.core.types.base import BaseType
|
||||||
|
from graphene.core.types.objecttype import BaseObjectType
|
||||||
|
|
||||||
|
|
||||||
class GraphQLSchema(_GraphQLSchema):
|
class GraphQLSchema(_GraphQLSchema):
|
||||||
|
@ -18,7 +19,6 @@ class GraphQLSchema(_GraphQLSchema):
|
||||||
|
|
||||||
|
|
||||||
class Schema(object):
|
class Schema(object):
|
||||||
_query = None
|
|
||||||
_executor = None
|
_executor = None
|
||||||
|
|
||||||
def __init__(self, query=None, mutation=None, name='Schema', executor=None):
|
def __init__(self, query=None, mutation=None, name='Schema', executor=None):
|
||||||
|
@ -47,26 +47,10 @@ class Schema(object):
|
||||||
else:
|
else:
|
||||||
return object_type
|
return object_type
|
||||||
|
|
||||||
@property
|
|
||||||
def query(self):
|
|
||||||
return self._query
|
|
||||||
|
|
||||||
@query.setter
|
|
||||||
def query(self, query):
|
|
||||||
self._query = query
|
|
||||||
|
|
||||||
@property
|
|
||||||
def mutation(self):
|
|
||||||
return self._mutation
|
|
||||||
|
|
||||||
@mutation.setter
|
|
||||||
def mutation(self, mutation):
|
|
||||||
self._mutation = mutation
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def executor(self):
|
def executor(self):
|
||||||
if not self._executor:
|
if not self._executor:
|
||||||
self.executor = Executor(
|
self._executor = Executor(
|
||||||
[SynchronousExecutionMiddleware()], map_type=OrderedDict)
|
[SynchronousExecutionMiddleware()], map_type=OrderedDict)
|
||||||
return self._executor
|
return self._executor
|
||||||
|
|
||||||
|
@ -76,18 +60,29 @@ class Schema(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def schema(self):
|
def schema(self):
|
||||||
if not self._query:
|
if not self.query:
|
||||||
raise Exception('You have to define a base query type')
|
raise Exception('You have to define a base query type')
|
||||||
return GraphQLSchema(self, query=self.T(self._query), mutation=self.T(self._mutation))
|
return GraphQLSchema(self, query=self.T(self.query), mutation=self.T(self.mutation))
|
||||||
|
|
||||||
def register(self, object_type):
|
def register(self, object_type):
|
||||||
self._types_names[object_type._meta.type_name] = object_type
|
self._types_names[object_type._meta.type_name] = object_type
|
||||||
return object_type
|
return object_type
|
||||||
|
|
||||||
|
def objecttype(self, type):
|
||||||
|
name = getattr(type, 'name', None)
|
||||||
|
if name:
|
||||||
|
objecttype = self._types_names.get(name, None)
|
||||||
|
if objecttype and inspect.isclass(objecttype) and issubclass(objecttype, BaseObjectType):
|
||||||
|
return objecttype
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
assert self.query, 'The base query type is not set'
|
||||||
|
self.T(self.query)
|
||||||
|
|
||||||
def get_type(self, type_name):
|
def get_type(self, type_name):
|
||||||
# self.schema._build_type_map()
|
self.setup()
|
||||||
if type_name not in self._types_names:
|
if type_name not in self._types_names:
|
||||||
raise Exception('Type %s not found in %r' % (type_name, self))
|
raise KeyError('Type %r not found in %r' % (type_name, self))
|
||||||
return self._types_names[type_name]
|
return self._types_names[type_name]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
import graphene
|
import graphene
|
||||||
from graphene.core.schema import Schema
|
from graphene.core.schema import Schema
|
||||||
|
|
||||||
|
@ -31,9 +30,7 @@ schema = Schema(query=Query, mutation=MyResultMutation)
|
||||||
|
|
||||||
|
|
||||||
def test_mutation_input():
|
def test_mutation_input():
|
||||||
assert ChangeNumber.input_type
|
assert schema.T(ChangeNumber.arguments).keys() == ['to']
|
||||||
assert ChangeNumber.input_type._meta.type_name == 'ChangeNumberInput'
|
|
||||||
assert list(ChangeNumber.input_type._meta.fields_map.keys()) == ['to']
|
|
||||||
|
|
||||||
|
|
||||||
def test_execute_mutations():
|
def test_execute_mutations():
|
|
@ -120,7 +120,7 @@ def test_schema_register():
|
||||||
assert schema.get_type('MyType') == MyType
|
assert schema.get_type('MyType') == MyType
|
||||||
|
|
||||||
|
|
||||||
def test_schema_register():
|
def test_schema_register_no_query_type():
|
||||||
schema = Schema(name='My own schema')
|
schema = Schema(name='My own schema')
|
||||||
|
|
||||||
@schema.register
|
@schema.register
|
||||||
|
@ -149,6 +149,7 @@ def test_lazytype():
|
||||||
|
|
||||||
t = LazyType('MyType')
|
t = LazyType('MyType')
|
||||||
|
|
||||||
|
@schema.register
|
||||||
class MyType(ObjectType):
|
class MyType(ObjectType):
|
||||||
type = StringField(resolve=lambda *_: 'Dog')
|
type = StringField(resolve=lambda *_: 'Dog')
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
from collections import OrderedDict
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from graphql.core.type import GraphQLArgument
|
from graphql.core.type import GraphQLArgument
|
||||||
|
|
||||||
from .base import OrderedType, ArgumentType
|
from .base import BaseType, OrderedType, ArgumentType
|
||||||
from ...utils import to_camel_case
|
from ...utils import to_camel_case
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,6 +22,27 @@ class Argument(OrderedType):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class ArgumentsGroup(BaseType):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
arguments = to_arguments(*args, **kwargs)
|
||||||
|
self.arguments = OrderedDict([(arg.name, arg) for arg in arguments])
|
||||||
|
|
||||||
|
def internal_type(self, schema):
|
||||||
|
return OrderedDict([(arg.name, schema.T(arg)) for arg in self.arguments.values()])
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.arguments)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self.arguments)
|
||||||
|
|
||||||
|
def __contains__(self, *args):
|
||||||
|
return self.arguments.__contains__(*args)
|
||||||
|
|
||||||
|
def __getitem__(self, *args):
|
||||||
|
return self.arguments.__getitem__(*args)
|
||||||
|
|
||||||
|
|
||||||
def to_arguments(*args, **kwargs):
|
def to_arguments(*args, **kwargs):
|
||||||
arguments = {}
|
arguments = {}
|
||||||
iter_arguments = chain(kwargs.items(), [(None, a) for a in args])
|
iter_arguments = chain(kwargs.items(), [(None, a) for a in args])
|
||||||
|
|
|
@ -11,6 +11,9 @@ class LazyType(BaseType):
|
||||||
def __init__(self, type_str):
|
def __init__(self, type_str):
|
||||||
self.type_str = type_str
|
self.type_str = type_str
|
||||||
|
|
||||||
|
def is_self(self):
|
||||||
|
return self.type_str == 'self'
|
||||||
|
|
||||||
def internal_type(self, schema):
|
def internal_type(self, schema):
|
||||||
type = schema.get_type(self.type_str)
|
type = schema.get_type(self.type_str)
|
||||||
return schema.T(type)
|
return schema.T(type)
|
||||||
|
|
|
@ -1,32 +1,35 @@
|
||||||
import six
|
import six
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from functools import wraps
|
|
||||||
|
|
||||||
from graphql.core.type import GraphQLField, GraphQLInputObjectField
|
from graphql.core.type import GraphQLField, GraphQLInputObjectField
|
||||||
|
|
||||||
from .base import LazyType, OrderedType
|
from .base import LazyType, OrderedType
|
||||||
from .argument import to_arguments
|
from .argument import ArgumentsGroup
|
||||||
|
from .definitions import NonNull
|
||||||
from ...utils import to_camel_case
|
from ...utils import to_camel_case
|
||||||
from ..types import BaseObjectType, InputObjectType
|
from ..types import BaseObjectType, InputObjectType
|
||||||
|
|
||||||
|
|
||||||
class Empty(object):
|
class Empty(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Field(OrderedType):
|
class Field(OrderedType):
|
||||||
def __init__(self, type, description=None, args=None, name=None, resolver=None, *args_list, **kwargs):
|
def __init__(self, type, description=None, args=None, name=None, resolver=None, required=False, default=None, *args_list, **kwargs):
|
||||||
_creation_counter = kwargs.pop('_creation_counter', None)
|
_creation_counter = kwargs.pop('_creation_counter', None)
|
||||||
super(Field, self).__init__(_creation_counter=_creation_counter)
|
super(Field, self).__init__(_creation_counter=_creation_counter)
|
||||||
self.name = name
|
self.name = name
|
||||||
if isinstance(type, six.string_types) and type != 'self':
|
if isinstance(type, six.string_types):
|
||||||
type = LazyType(type)
|
type = LazyType(type)
|
||||||
|
if required:
|
||||||
|
type = NonNull(type)
|
||||||
self.type = type
|
self.type = type
|
||||||
self.description = description
|
self.description = description
|
||||||
args = OrderedDict(args or {}, **kwargs)
|
args = OrderedDict(args or {}, **kwargs)
|
||||||
self.arguments = to_arguments(*args_list, **args)
|
self.arguments = ArgumentsGroup(*args_list, **args)
|
||||||
self.object_type = None
|
self.object_type = None
|
||||||
self.resolver = resolver
|
self.resolver = resolver
|
||||||
|
self.default = default
|
||||||
|
|
||||||
def contribute_to_class(self, cls, attname):
|
def contribute_to_class(self, cls, attname):
|
||||||
assert issubclass(cls, BaseObjectType), 'Field {} cannot be mounted in {}'.format(self, cls)
|
assert issubclass(cls, BaseObjectType), 'Field {} cannot be mounted in {}'.format(self, cls)
|
||||||
|
@ -34,7 +37,7 @@ class Field(OrderedType):
|
||||||
self.name = to_camel_case(attname)
|
self.name = to_camel_case(attname)
|
||||||
self.attname = attname
|
self.attname = attname
|
||||||
self.object_type = cls
|
self.object_type = cls
|
||||||
if self.type == 'self':
|
if isinstance(self.type, LazyType) and self.type.is_self():
|
||||||
self.type = cls
|
self.type = cls
|
||||||
cls._meta.add_field(self)
|
cls._meta.add_field(self)
|
||||||
|
|
||||||
|
@ -49,41 +52,29 @@ class Field(OrderedType):
|
||||||
def get_resolver_fn(self):
|
def get_resolver_fn(self):
|
||||||
resolve_fn_name = 'resolve_%s' % self.attname
|
resolve_fn_name = 'resolve_%s' % self.attname
|
||||||
if hasattr(self.object_type, resolve_fn_name):
|
if hasattr(self.object_type, resolve_fn_name):
|
||||||
resolve_fn = getattr(self.object_type, resolve_fn_name)
|
return getattr(self.object_type, resolve_fn_name)
|
||||||
|
|
||||||
@wraps(resolve_fn)
|
|
||||||
def custom_resolve_fn(instance, args, info):
|
|
||||||
return resolve_fn(instance, args, info)
|
|
||||||
return custom_resolve_fn
|
|
||||||
|
|
||||||
def default_getter(instance, args, info):
|
def default_getter(instance, args, info):
|
||||||
return getattr(instance, self.attname, None)
|
return getattr(instance, self.attname, self.default)
|
||||||
|
|
||||||
return default_getter
|
return default_getter
|
||||||
|
|
||||||
def internal_type(self, schema):
|
def internal_type(self, schema):
|
||||||
resolver = self.resolver
|
resolver = self.resolver
|
||||||
description = self.description
|
description = self.description
|
||||||
|
arguments = self.arguments
|
||||||
if not description and resolver:
|
if not description and resolver:
|
||||||
description = resolver.__doc__
|
description = resolver.__doc__
|
||||||
type = schema.T(self.type)
|
type = schema.T(self.type)
|
||||||
|
type_objecttype = schema.objecttype(type)
|
||||||
|
if type_objecttype and type_objecttype._meta.is_mutation:
|
||||||
|
assert len(arguments) == 0
|
||||||
|
arguments = type_objecttype.arguments
|
||||||
|
resolver = getattr(type_objecttype, 'mutate')
|
||||||
|
|
||||||
assert type, 'Internal type for field %s is None' % str(self)
|
assert type, 'Internal type for field %s is None' % str(self)
|
||||||
return GraphQLField(type, args=self.get_arguments(schema), resolver=resolver,
|
return GraphQLField(type, args=schema.T(arguments), resolver=resolver,
|
||||||
description=description,)
|
description=description,)
|
||||||
|
|
||||||
def get_arguments(self, schema):
|
|
||||||
if not self.arguments:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return OrderedDict([(arg.name, schema.T(arg)) for arg in self.arguments])
|
|
||||||
|
|
||||||
def __copy__(self):
|
|
||||||
obj = Empty()
|
|
||||||
obj.__class__ = self.__class__
|
|
||||||
obj.__dict__ = self.__dict__.copy()
|
|
||||||
obj.object_type = None
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
"""
|
"""
|
||||||
Displays the module, class and name of the field.
|
Displays the module, class and name of the field.
|
||||||
|
@ -103,9 +94,11 @@ class Field(OrderedType):
|
||||||
|
|
||||||
|
|
||||||
class InputField(OrderedType):
|
class InputField(OrderedType):
|
||||||
def __init__(self, type, description=None, default=None, name=None, _creation_counter=None):
|
def __init__(self, type, description=None, default=None, name=None, _creation_counter=None, required=False):
|
||||||
super(InputField, self).__init__(_creation_counter=_creation_counter)
|
super(InputField, self).__init__(_creation_counter=_creation_counter)
|
||||||
self.name = name
|
self.name = name
|
||||||
|
if required:
|
||||||
|
type = NonNull(type)
|
||||||
self.type = type
|
self.type = type
|
||||||
self.description = description
|
self.description = description
|
||||||
self.default = default
|
self.default = default
|
||||||
|
|
|
@ -8,6 +8,7 @@ import six
|
||||||
from graphene import signals
|
from graphene import signals
|
||||||
from graphene.core.options import Options
|
from graphene.core.options import Options
|
||||||
from graphene.core.types.base import BaseType
|
from graphene.core.types.base import BaseType
|
||||||
|
from graphene.core.types.argument import ArgumentsGroup
|
||||||
from graphql.core.type import (GraphQLArgument, GraphQLInputObjectType,
|
from graphql.core.type import (GraphQLArgument, GraphQLInputObjectType,
|
||||||
GraphQLInterfaceType, GraphQLObjectType)
|
GraphQLInterfaceType, GraphQLObjectType)
|
||||||
|
|
||||||
|
@ -66,9 +67,10 @@ class ObjectTypeMeta(type):
|
||||||
if input_class:
|
if input_class:
|
||||||
items = dict(input_class.__dict__)
|
items = dict(input_class.__dict__)
|
||||||
items.pop('__dict__', None)
|
items.pop('__dict__', None)
|
||||||
input_type = type('{}Input'.format(
|
items.pop('__doc__', None)
|
||||||
new_class._meta.type_name), (ObjectType, ), items)
|
items.pop('__module__', None)
|
||||||
new_class.add_to_class('input_type', input_type)
|
arguments = ArgumentsGroup(**items)
|
||||||
|
new_class.add_to_class('arguments', arguments)
|
||||||
|
|
||||||
new_class.add_extra_fields()
|
new_class.add_extra_fields()
|
||||||
|
|
||||||
|
@ -88,7 +90,7 @@ class ObjectTypeMeta(type):
|
||||||
# on the base classes (we cannot handle shadowed fields at the
|
# on the base classes (we cannot handle shadowed fields at the
|
||||||
# moment).
|
# moment).
|
||||||
for field in parent_fields:
|
for field in parent_fields:
|
||||||
if field.name in field_names and field.__class__ != field_names[field.name].__class__:
|
if field.name in field_names and field.type.__class__ != field_names[field.name].type.__class__:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Local field %r in class %r (%r) clashes '
|
'Local field %r in class %r (%r) clashes '
|
||||||
'with field with similar name from '
|
'with field with similar name from '
|
||||||
|
@ -213,14 +215,10 @@ class ObjectType(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
|
||||||
|
|
||||||
|
|
||||||
class Mutation(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
|
class Mutation(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
|
||||||
|
pass
|
||||||
@classmethod
|
|
||||||
def get_input_type(cls):
|
|
||||||
return getattr(cls, 'input_type', None)
|
|
||||||
|
|
||||||
|
|
||||||
class InputObjectType(ObjectType):
|
class InputObjectType(ObjectType):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def internal_type(cls, schema):
|
def internal_type(cls, schema):
|
||||||
fields = lambda: OrderedDict([(f.name, schema.T(f))
|
fields = lambda: OrderedDict([(f.name, schema.T(f))
|
||||||
|
|
|
@ -19,7 +19,7 @@ def test_nonnull_scalar():
|
||||||
assert type.of_type == GraphQLString
|
assert type.of_type == GraphQLString
|
||||||
|
|
||||||
|
|
||||||
def test_mixed_scalar():
|
def test_nested_scalars():
|
||||||
type = schema.T(NonNull(List(String())))
|
type = schema.T(NonNull(List(String())))
|
||||||
assert isinstance(type, GraphQLNonNull)
|
assert isinstance(type, GraphQLNonNull)
|
||||||
assert isinstance(type.of_type, GraphQLList)
|
assert isinstance(type.of_type, GraphQLList)
|
||||||
|
|
|
@ -75,12 +75,7 @@ def test_field_string_reference():
|
||||||
def test_field_custom_arguments():
|
def test_field_custom_arguments():
|
||||||
field = Field(None, name='my_customName', p=String())
|
field = Field(None, name='my_customName', p=String())
|
||||||
|
|
||||||
class MyObjectType(ObjectType):
|
args = field.arguments
|
||||||
my_field = field
|
|
||||||
|
|
||||||
schema = Schema(query=MyObjectType)
|
|
||||||
|
|
||||||
args = field.get_arguments(schema)
|
|
||||||
assert 'p' in args
|
assert 'p' in args
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from py.test import raises
|
from py.test import raises
|
||||||
from pytest import raises
|
|
||||||
|
|
||||||
from graphene.core.fields import IntField, StringField
|
from graphene.core.fields import IntField, StringField
|
||||||
from graphene.core.schema import Schema
|
from graphene.core.schema import Schema
|
||||||
|
@ -66,9 +65,6 @@ def test_object_type():
|
||||||
assert isinstance(object_type, GraphQLObjectType)
|
assert isinstance(object_type, GraphQLObjectType)
|
||||||
assert object_type.description == 'Human description'
|
assert object_type.description == 'Human description'
|
||||||
assert list(object_type.get_fields().keys()) == ['name', 'friends']
|
assert list(object_type.get_fields().keys()) == ['name', 'friends']
|
||||||
# assert object_type.get_fields() == {'name': Human._meta.fields_map['name'].internal_field(
|
|
||||||
# schema), 'friends':
|
|
||||||
# Human._meta.fields_map['friends'].internal_field(schema)}
|
|
||||||
assert object_type.get_interfaces() == [schema.T(Character)]
|
assert object_type.get_interfaces() == [schema.T(Character)]
|
||||||
assert Human._meta.fields_map['name'].object_type == Human
|
assert Human._meta.fields_map['name'].object_type == Human
|
||||||
|
|
||||||
|
@ -115,5 +111,5 @@ def test_field_mantain_resolver_tags():
|
||||||
|
|
||||||
tag_resolver(resolve_name, 'test')
|
tag_resolver(resolve_name, 'test')
|
||||||
|
|
||||||
field = Droid._meta.fields_map['name'].internal_field(schema)
|
field = schema.T(Droid._meta.fields_map['name'])
|
||||||
assert resolver_has_tag(field.resolver, 'test')
|
assert resolver_has_tag(field.resolver, 'test')
|
|
@ -1,162 +0,0 @@
|
||||||
|
|
||||||
from py.test import raises
|
|
||||||
from pytest import raises
|
|
||||||
|
|
||||||
from graphene.core.fields import Field, NonNullField, StringField
|
|
||||||
from graphene.core.options import Options
|
|
||||||
from graphene.core.schema import Schema
|
|
||||||
from graphene.core.types import ObjectType
|
|
||||||
from graphql.core.type import (GraphQLBoolean, GraphQLField, GraphQLID,
|
|
||||||
GraphQLInt, GraphQLNonNull, GraphQLString)
|
|
||||||
|
|
||||||
|
|
||||||
class ot(ObjectType):
|
|
||||||
def resolve_customdoc(self, *args, **kwargs):
|
|
||||||
'''Resolver documentation'''
|
|
||||||
return None
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "ObjectType"
|
|
||||||
|
|
||||||
schema = Schema()
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_no_contributed_raises_error():
|
|
||||||
f = Field(GraphQLString)
|
|
||||||
with raises(Exception) as excinfo:
|
|
||||||
schema.T(f)
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_type():
|
|
||||||
f = Field(GraphQLString)
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
assert isinstance(schema.T(f), GraphQLField)
|
|
||||||
assert schema.T(f).type == GraphQLString
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_name_automatic_camelcase():
|
|
||||||
f = Field(GraphQLString)
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
assert f.name == 'fieldName'
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_name_use_name_if_exists():
|
|
||||||
f = Field(GraphQLString, name='my_custom_name')
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
assert f.name == 'my_custom_name'
|
|
||||||
|
|
||||||
|
|
||||||
def test_stringfield_type():
|
|
||||||
f = StringField()
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
assert schema.T(f) == GraphQLString
|
|
||||||
|
|
||||||
|
|
||||||
def test_nonnullfield_type():
|
|
||||||
f = NonNullField(StringField())
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
assert isinstance(schema.T(f), GraphQLNonNull)
|
|
||||||
|
|
||||||
|
|
||||||
def test_stringfield_type_required():
|
|
||||||
f = Field(StringField(required=True))
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
assert isinstance(schema.T(f), GraphQLField)
|
|
||||||
assert isinstance(schema.T(f).type, GraphQLNonNull)
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_resolve():
|
|
||||||
f = StringField(required=True, resolve=lambda *args: 'RESOLVED')
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
field_type = f.internal_field(schema)
|
|
||||||
assert 'RESOLVED' == field_type.resolver(ot, None, None)
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_resolve_type_custom():
|
|
||||||
class MyCustomType(ObjectType):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class OtherType(ObjectType):
|
|
||||||
pass
|
|
||||||
|
|
||||||
s = Schema()
|
|
||||||
|
|
||||||
f = Field('MyCustomType')
|
|
||||||
f.contribute_to_class(OtherType, 'field_name')
|
|
||||||
field_type = f.get_object_type(s)
|
|
||||||
assert field_type == MyCustomType
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_resolve_type_custom():
|
|
||||||
s = Schema()
|
|
||||||
|
|
||||||
f = Field('self')
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
field_type = f.get_object_type(s)
|
|
||||||
assert field_type == ot
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_orders():
|
|
||||||
f1 = Field(None)
|
|
||||||
f2 = Field(None)
|
|
||||||
assert f1 < f2
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_orders_wrong_type():
|
|
||||||
field = Field(None)
|
|
||||||
try:
|
|
||||||
assert not field < 1
|
|
||||||
except TypeError:
|
|
||||||
# Fix exception raising in Python3+
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_eq():
|
|
||||||
f1 = Field(None)
|
|
||||||
f2 = Field(None)
|
|
||||||
assert f1 != f2
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_eq_wrong_type():
|
|
||||||
field = Field(None)
|
|
||||||
assert field != 1
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_hash():
|
|
||||||
f1 = Field(None)
|
|
||||||
f2 = Field(None)
|
|
||||||
assert hash(f1) != hash(f2)
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_none_type_raises_error():
|
|
||||||
s = Schema()
|
|
||||||
f = Field(None)
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
with raises(Exception) as excinfo:
|
|
||||||
f.internal_field(s)
|
|
||||||
assert str(
|
|
||||||
excinfo.value) == "Internal type for field ObjectType.field_name is None"
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_str():
|
|
||||||
f = StringField()
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
assert str(f) == "ObjectType.field_name"
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_repr():
|
|
||||||
f = StringField()
|
|
||||||
assert repr(f) == "<graphene.core.fields.StringField>"
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_repr_contributed():
|
|
||||||
f = StringField()
|
|
||||||
f.contribute_to_class(ot, 'field_name')
|
|
||||||
assert repr(f) == "<graphene.core.fields.StringField: field_name>"
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_resolve_objecttype_cos():
|
|
||||||
f = StringField()
|
|
||||||
f.contribute_to_class(ot, 'customdoc')
|
|
||||||
field = f.internal_field(schema)
|
|
||||||
assert field.description == 'Resolver documentation'
|
|
|
@ -1,16 +0,0 @@
|
||||||
from graphene.core.scalars import GraphQLSkipField
|
|
||||||
|
|
||||||
|
|
||||||
def test_skipfield_serialize():
|
|
||||||
f = GraphQLSkipField
|
|
||||||
assert f.serialize('a') is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_skipfield_parse_value():
|
|
||||||
f = GraphQLSkipField
|
|
||||||
assert f.parse_value('a') is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_skipfield_parse_literal():
|
|
||||||
f = GraphQLSkipField
|
|
||||||
assert f.parse_literal('a') is None
|
|
|
@ -1,143 +0,0 @@
|
||||||
|
|
||||||
from py.test import raises
|
|
||||||
from pytest import raises
|
|
||||||
|
|
||||||
from graphene import Interface, ObjectType, Schema
|
|
||||||
from graphene.core.fields import Field, ListField, StringField
|
|
||||||
from graphql.core import graphql
|
|
||||||
from graphql.core.type import (GraphQLInterfaceType, GraphQLObjectType,
|
|
||||||
GraphQLSchema)
|
|
||||||
from tests.utils import assert_equal_lists
|
|
||||||
|
|
||||||
schema = Schema(name='My own schema')
|
|
||||||
|
|
||||||
|
|
||||||
class Character(Interface):
|
|
||||||
name = StringField()
|
|
||||||
|
|
||||||
|
|
||||||
class Pet(ObjectType):
|
|
||||||
type = StringField(resolve=lambda *_: 'Dog')
|
|
||||||
|
|
||||||
|
|
||||||
class Human(Character):
|
|
||||||
friends = ListField(Character)
|
|
||||||
pet = Field(Pet)
|
|
||||||
|
|
||||||
def resolve_name(self, *args):
|
|
||||||
return 'Peter'
|
|
||||||
|
|
||||||
def resolve_friend(self, *args):
|
|
||||||
return Human(object())
|
|
||||||
|
|
||||||
def resolve_pet(self, *args):
|
|
||||||
return Pet(object())
|
|
||||||
|
|
||||||
schema.query = Human
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_registered_type():
|
|
||||||
assert schema.get_type('Character') == Character
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_unregistered_type():
|
|
||||||
with raises(Exception) as excinfo:
|
|
||||||
schema.get_type('NON_EXISTENT_MODEL')
|
|
||||||
assert 'not found' in str(excinfo.value)
|
|
||||||
|
|
||||||
|
|
||||||
def test_schema_query():
|
|
||||||
assert schema.query == Human
|
|
||||||
|
|
||||||
|
|
||||||
def test_query_schema_graphql():
|
|
||||||
object()
|
|
||||||
query = '''
|
|
||||||
{
|
|
||||||
name
|
|
||||||
pet {
|
|
||||||
type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'''
|
|
||||||
expected = {
|
|
||||||
'name': 'Peter',
|
|
||||||
'pet': {
|
|
||||||
'type': 'Dog'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = graphql(schema.schema, query, root=Human(object()))
|
|
||||||
assert not result.errors
|
|
||||||
assert result.data == expected
|
|
||||||
|
|
||||||
|
|
||||||
def test_query_schema_execute():
|
|
||||||
object()
|
|
||||||
query = '''
|
|
||||||
{
|
|
||||||
name
|
|
||||||
pet {
|
|
||||||
type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'''
|
|
||||||
expected = {
|
|
||||||
'name': 'Peter',
|
|
||||||
'pet': {
|
|
||||||
'type': 'Dog'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = schema.execute(query, root=object())
|
|
||||||
assert not result.errors
|
|
||||||
assert result.data == expected
|
|
||||||
|
|
||||||
|
|
||||||
def test_schema_get_type_map():
|
|
||||||
assert_equal_lists(
|
|
||||||
schema.schema.get_type_map().keys(),
|
|
||||||
['__Field', 'String', 'Pet', 'Character', '__InputValue', '__Directive',
|
|
||||||
'__TypeKind', '__Schema', '__Type', 'Human', '__EnumValue', 'Boolean']
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_schema_no_query():
|
|
||||||
schema = Schema(name='My own schema')
|
|
||||||
with raises(Exception) as excinfo:
|
|
||||||
schema.schema
|
|
||||||
assert 'define a base query type' in str(excinfo)
|
|
||||||
|
|
||||||
|
|
||||||
def test_schema_register():
|
|
||||||
schema = Schema(name='My own schema')
|
|
||||||
|
|
||||||
@schema.register
|
|
||||||
class MyType(ObjectType):
|
|
||||||
type = StringField(resolve=lambda *_: 'Dog')
|
|
||||||
|
|
||||||
schema.query = MyType
|
|
||||||
|
|
||||||
assert schema.get_type('MyType') == MyType
|
|
||||||
|
|
||||||
|
|
||||||
def test_schema_register():
|
|
||||||
schema = Schema(name='My own schema')
|
|
||||||
|
|
||||||
@schema.register
|
|
||||||
class MyType(ObjectType):
|
|
||||||
type = StringField(resolve=lambda *_: 'Dog')
|
|
||||||
|
|
||||||
with raises(Exception) as excinfo:
|
|
||||||
schema.get_type('MyType')
|
|
||||||
assert 'base query type' in str(excinfo.value)
|
|
||||||
|
|
||||||
|
|
||||||
def test_schema_introspect():
|
|
||||||
schema = Schema(name='My own schema')
|
|
||||||
|
|
||||||
class MyType(ObjectType):
|
|
||||||
type = StringField(resolve=lambda *_: 'Dog')
|
|
||||||
|
|
||||||
schema.query = MyType
|
|
||||||
|
|
||||||
introspection = schema.introspect()
|
|
||||||
assert '__schema' in introspection
|
|
Loading…
Reference in New Issue
Block a user