Skip to content

Commit 28d89a4

Browse files
committed
Improved mutations, tests and overall integration.
1 parent 6f87720 commit 28d89a4

16 files changed

+82
-410
lines changed

graphene/core/fields.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,11 @@
99
class DeprecatedField(FieldType):
1010
def __init__(self, *args, **kwargs):
1111
cls = self.__class__
12-
warnings.warn("Using {} is not longer supported".format(cls.__name__)
13-
, FutureWarning)
14-
kwargs['resolver'] = kwargs.pop('resolve', None)
15-
self.required = kwargs.pop('required', False)
12+
warnings.warn("Using {} is not longer supported".format(cls.__name__), FutureWarning)
13+
if 'resolve' in kwargs:
14+
kwargs['resolver'] = kwargs.pop('resolve')
1615
return super(DeprecatedField, self).__init__(*args, **kwargs)
1716

18-
def as_field(self):
19-
t = self
20-
if self.required:
21-
t = NonNull(t)
22-
return Field(t, _creation_counter=self.creation_counter, *self.args, **self.kwargs)
23-
2417

2518
class StringField(DeprecatedField, String):
2619
pass

graphene/core/schema.py

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from graphql.core.type import GraphQLSchema as _GraphQLSchema
99
from graphql.core.utils.introspection_query import introspection_query
1010
from graphene.core.types.base import BaseType
11+
from graphene.core.types.objecttype import BaseObjectType
1112

1213

1314
class GraphQLSchema(_GraphQLSchema):
@@ -18,7 +19,6 @@ def __init__(self, schema, *args, **kwargs):
1819

1920

2021
class Schema(object):
21-
_query = None
2222
_executor = None
2323

2424
def __init__(self, query=None, mutation=None, name='Schema', executor=None):
@@ -47,26 +47,10 @@ def T(self, object_type):
4747
else:
4848
return object_type
4949

50-
@property
51-
def query(self):
52-
return self._query
53-
54-
@query.setter
55-
def query(self, query):
56-
self._query = query
57-
58-
@property
59-
def mutation(self):
60-
return self._mutation
61-
62-
@mutation.setter
63-
def mutation(self, mutation):
64-
self._mutation = mutation
65-
6650
@property
6751
def executor(self):
6852
if not self._executor:
69-
self.executor = Executor(
53+
self._executor = Executor(
7054
[SynchronousExecutionMiddleware()], map_type=OrderedDict)
7155
return self._executor
7256

@@ -76,18 +60,29 @@ def executor(self, value):
7660

7761
@property
7862
def schema(self):
79-
if not self._query:
63+
if not self.query:
8064
raise Exception('You have to define a base query type')
81-
return GraphQLSchema(self, query=self.T(self._query), mutation=self.T(self._mutation))
65+
return GraphQLSchema(self, query=self.T(self.query), mutation=self.T(self.mutation))
8266

8367
def register(self, object_type):
8468
self._types_names[object_type._meta.type_name] = object_type
8569
return object_type
8670

71+
def objecttype(self, type):
72+
name = getattr(type, 'name', None)
73+
if name:
74+
objecttype = self._types_names.get(name, None)
75+
if objecttype and inspect.isclass(objecttype) and issubclass(objecttype, BaseObjectType):
76+
return objecttype
77+
78+
def setup(self):
79+
assert self.query, 'The base query type is not set'
80+
self.T(self.query)
81+
8782
def get_type(self, type_name):
88-
# self.schema._build_type_map()
83+
self.setup()
8984
if type_name not in self._types_names:
90-
raise Exception('Type %s not found in %r' % (type_name, self))
85+
raise KeyError('Type %r not found in %r' % (type_name, self))
9186
return self._types_names[type_name]
9287

9388
@property

tests/core/test_mutations.py renamed to graphene/core/tests/test_mutations.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import graphene
32
from graphene.core.schema import Schema
43

@@ -31,9 +30,7 @@ class MyResultMutation(graphene.ObjectType):
3130

3231

3332
def test_mutation_input():
34-
assert ChangeNumber.input_type
35-
assert ChangeNumber.input_type._meta.type_name == 'ChangeNumberInput'
36-
assert list(ChangeNumber.input_type._meta.fields_map.keys()) == ['to']
33+
assert schema.T(ChangeNumber.arguments).keys() == ['to']
3734

3835

3936
def test_execute_mutations():
File renamed without changes.
File renamed without changes.

graphene/core/tests/test_schema.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class MyType(ObjectType):
120120
assert schema.get_type('MyType') == MyType
121121

122122

123-
def test_schema_register():
123+
def test_schema_register_no_query_type():
124124
schema = Schema(name='My own schema')
125125

126126
@schema.register
@@ -149,6 +149,7 @@ def test_lazytype():
149149

150150
t = LazyType('MyType')
151151

152+
@schema.register
152153
class MyType(ObjectType):
153154
type = StringField(resolve=lambda *_: 'Dog')
154155

graphene/core/types/argument.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
from collections import OrderedDict
12
from itertools import chain
23

34
from graphql.core.type import GraphQLArgument
45

5-
from .base import OrderedType, ArgumentType
6+
from .base import BaseType, OrderedType, ArgumentType
67
from ...utils import to_camel_case
78

89

@@ -21,6 +22,27 @@ def __repr__(self):
2122
return self.name
2223

2324

25+
class ArgumentsGroup(BaseType):
26+
def __init__(self, *args, **kwargs):
27+
arguments = to_arguments(*args, **kwargs)
28+
self.arguments = OrderedDict([(arg.name, arg) for arg in arguments])
29+
30+
def internal_type(self, schema):
31+
return OrderedDict([(arg.name, schema.T(arg)) for arg in self.arguments.values()])
32+
33+
def __len__(self):
34+
return len(self.arguments)
35+
36+
def __iter__(self):
37+
return iter(self.arguments)
38+
39+
def __contains__(self, *args):
40+
return self.arguments.__contains__(*args)
41+
42+
def __getitem__(self, *args):
43+
return self.arguments.__getitem__(*args)
44+
45+
2446
def to_arguments(*args, **kwargs):
2547
arguments = {}
2648
iter_arguments = chain(kwargs.items(), [(None, a) for a in args])

graphene/core/types/base.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ class LazyType(BaseType):
1111
def __init__(self, type_str):
1212
self.type_str = type_str
1313

14+
def is_self(self):
15+
return self.type_str == 'self'
16+
1417
def internal_type(self, schema):
1518
type = schema.get_type(self.type_str)
1619
return schema.T(type)

graphene/core/types/field.py

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,43 @@
11
import six
22
from collections import OrderedDict
3-
from functools import wraps
43

54
from graphql.core.type import GraphQLField, GraphQLInputObjectField
65

76
from .base import LazyType, OrderedType
8-
from .argument import to_arguments
7+
from .argument import ArgumentsGroup
8+
from .definitions import NonNull
99
from ...utils import to_camel_case
1010
from ..types import BaseObjectType, InputObjectType
1111

1212

1313
class Empty(object):
1414
pass
15-
15+
1616

1717
class Field(OrderedType):
18-
def __init__(self, type, description=None, args=None, name=None, resolver=None, *args_list, **kwargs):
18+
def __init__(self, type, description=None, args=None, name=None, resolver=None, required=False, default=None, *args_list, **kwargs):
1919
_creation_counter = kwargs.pop('_creation_counter', None)
2020
super(Field, self).__init__(_creation_counter=_creation_counter)
2121
self.name = name
22-
if isinstance(type, six.string_types) and type != 'self':
22+
if isinstance(type, six.string_types):
2323
type = LazyType(type)
24+
if required:
25+
type = NonNull(type)
2426
self.type = type
2527
self.description = description
2628
args = OrderedDict(args or {}, **kwargs)
27-
self.arguments = to_arguments(*args_list, **args)
29+
self.arguments = ArgumentsGroup(*args_list, **args)
2830
self.object_type = None
2931
self.resolver = resolver
32+
self.default = default
3033

3134
def contribute_to_class(self, cls, attname):
3235
assert issubclass(cls, BaseObjectType), 'Field {} cannot be mounted in {}'.format(self, cls)
3336
if not self.name:
3437
self.name = to_camel_case(attname)
3538
self.attname = attname
3639
self.object_type = cls
37-
if self.type == 'self':
40+
if isinstance(self.type, LazyType) and self.type.is_self():
3841
self.type = cls
3942
cls._meta.add_field(self)
4043

@@ -49,41 +52,29 @@ def resolver(self, value):
4952
def get_resolver_fn(self):
5053
resolve_fn_name = 'resolve_%s' % self.attname
5154
if hasattr(self.object_type, resolve_fn_name):
52-
resolve_fn = getattr(self.object_type, resolve_fn_name)
55+
return getattr(self.object_type, resolve_fn_name)
5356

54-
@wraps(resolve_fn)
55-
def custom_resolve_fn(instance, args, info):
56-
return resolve_fn(instance, args, info)
57-
return custom_resolve_fn
58-
5957
def default_getter(instance, args, info):
60-
return getattr(instance, self.attname, None)
61-
58+
return getattr(instance, self.attname, self.default)
6259
return default_getter
6360

6461
def internal_type(self, schema):
6562
resolver = self.resolver
6663
description = self.description
64+
arguments = self.arguments
6765
if not description and resolver:
6866
description = resolver.__doc__
6967
type = schema.T(self.type)
68+
type_objecttype = schema.objecttype(type)
69+
if type_objecttype and type_objecttype._meta.is_mutation:
70+
assert len(arguments) == 0
71+
arguments = type_objecttype.arguments
72+
resolver = getattr(type_objecttype, 'mutate')
73+
7074
assert type, 'Internal type for field %s is None' % str(self)
71-
return GraphQLField(type, args=self.get_arguments(schema), resolver=resolver,
75+
return GraphQLField(type, args=schema.T(arguments), resolver=resolver,
7276
description=description,)
7377

74-
def get_arguments(self, schema):
75-
if not self.arguments:
76-
return None
77-
78-
return OrderedDict([(arg.name, schema.T(arg)) for arg in self.arguments])
79-
80-
def __copy__(self):
81-
obj = Empty()
82-
obj.__class__ = self.__class__
83-
obj.__dict__ = self.__dict__.copy()
84-
obj.object_type = None
85-
return obj
86-
8778
def __repr__(self):
8879
"""
8980
Displays the module, class and name of the field.
@@ -103,9 +94,11 @@ def __hash__(self):
10394

10495

10596
class InputField(OrderedType):
106-
def __init__(self, type, description=None, default=None, name=None, _creation_counter=None):
97+
def __init__(self, type, description=None, default=None, name=None, _creation_counter=None, required=False):
10798
super(InputField, self).__init__(_creation_counter=_creation_counter)
10899
self.name = name
100+
if required:
101+
type = NonNull(type)
109102
self.type = type
110103
self.description = description
111104
self.default = default

graphene/core/types/objecttype.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from graphene import signals
99
from graphene.core.options import Options
1010
from graphene.core.types.base import BaseType
11+
from graphene.core.types.argument import ArgumentsGroup
1112
from graphql.core.type import (GraphQLArgument, GraphQLInputObjectType,
1213
GraphQLInterfaceType, GraphQLObjectType)
1314

@@ -66,9 +67,10 @@ def __new__(cls, name, bases, attrs):
6667
if input_class:
6768
items = dict(input_class.__dict__)
6869
items.pop('__dict__', None)
69-
input_type = type('{}Input'.format(
70-
new_class._meta.type_name), (ObjectType, ), items)
71-
new_class.add_to_class('input_type', input_type)
70+
items.pop('__doc__', None)
71+
items.pop('__module__', None)
72+
arguments = ArgumentsGroup(**items)
73+
new_class.add_to_class('arguments', arguments)
7274

7375
new_class.add_extra_fields()
7476

@@ -88,7 +90,7 @@ def __new__(cls, name, bases, attrs):
8890
# on the base classes (we cannot handle shadowed fields at the
8991
# moment).
9092
for field in parent_fields:
91-
if field.name in field_names and field.__class__ != field_names[field.name].__class__:
93+
if field.name in field_names and field.type.__class__ != field_names[field.name].type.__class__:
9294
raise Exception(
9395
'Local field %r in class %r (%r) clashes '
9496
'with field with similar name from '
@@ -213,14 +215,10 @@ class ObjectType(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
213215

214216

215217
class Mutation(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
216-
217-
@classmethod
218-
def get_input_type(cls):
219-
return getattr(cls, 'input_type', None)
218+
pass
220219

221220

222221
class InputObjectType(ObjectType):
223-
224222
@classmethod
225223
def internal_type(cls, schema):
226224
fields = lambda: OrderedDict([(f.name, schema.T(f))

0 commit comments

Comments
 (0)