Added Field arguments.

This commit is contained in:
Syrus Akbary 2016-08-13 01:50:32 -07:00
parent 70a9de63f9
commit a7b3d193eb
7 changed files with 83 additions and 26 deletions

View File

@ -0,0 +1,33 @@
from collections import OrderedDict
from itertools import chain
from ..utils.orderedtype import OrderedType
class Argument(OrderedType):
def __init__(self, type, default_value=None, description=None, name=None, _creation_counter=None):
super(Argument, self).__init__(_creation_counter=_creation_counter)
self.name = name
self.type = type
self.default_value = default_value
self.description = description
def to_arguments(args, extra_args):
from .unmountedtype import UnmountedType
extra_args = sorted(extra_args.items(), key=lambda f: f[1])
iter_arguments = chain(args.items() + extra_args)
arguments = OrderedDict()
for default_name, arg in iter_arguments:
if isinstance(arg, UnmountedType):
arg = arg.as_argument()
if not isinstance(arg, Argument):
raise ValueError('Unknown argument "{}".'.format(default_name))
arg_name = default_name or arg.name
assert arg_name not in arguments, 'More than one Argument have same name "{}".'.format(arg.name)
arguments[arg_name] = arg
return arguments

View File

@ -1,9 +1,10 @@
import inspect
from functools import partial
from collections import OrderedDict
from collections import OrderedDict, Mapping
from ..utils.orderedtype import OrderedType
from .structures import NonNull
from .argument import to_arguments
def source_resolver(source, root, args, context, info):
@ -25,7 +26,9 @@ class Field(OrderedType):
if required:
type = NonNull(type)
self._type = type
self.args = args or OrderedDict()
if args:
assert isinstance(args, Mapping), 'Arguments in a field have to be a mapping, received "{}".'.format(args)
self.args = to_arguments(args or OrderedDict(), extra_args)
# self.args = to_arguments(args, extra_args)
assert not (source and resolver), ('A Field cannot have a source and a '
'resolver in at the same time.')

View File

@ -2,6 +2,7 @@ import pytest
from ..field import Field
from ..structures import NonNull
from ..argument import Argument
class MyInstance(object):
@ -11,7 +12,7 @@ class MyInstance(object):
def test_field_basic():
MyType = object()
args = {}
args = {'my arg': Argument(True)}
resolver = lambda: None
deprecation_reason = 'Deprecated now'
description = 'My Field'
@ -49,7 +50,22 @@ def test_field_not_source_and_resolver():
Field(MyType, source='value', resolver=lambda: None)
assert str(exc_info.value) == 'A Field cannot have a source and a resolver in at the same time.'
def test_field_source_func():
MyType = object()
field = Field(MyType, source='value_func')
assert field.resolver(MyInstance(), {}, None, None) == MyInstance.value_func()
def test_field_source_argument_as_kw():
MyType = object()
field = Field(MyType, b=NonNull(True), c=Argument(None), a=NonNull(False))
assert field.args.keys() == ['b', 'c', 'a']
assert isinstance(field.args['b'], Argument)
assert isinstance(field.args['b'].type, NonNull)
assert field.args['b'].type.of_type is True
assert isinstance(field.args['c'], Argument)
assert field.args['c'].type is None
assert isinstance(field.args['a'], Argument)
assert isinstance(field.args['a'].type, NonNull)
assert field.args['a'].type.of_type is False

View File

@ -54,7 +54,7 @@ def test_ordered_fields_in_interface():
def test_generate_interface_unmountedtype():
class MyInterface(Interface):
field = MyScalar(MyType)
field = MyScalar()
assert 'field' in MyInterface._meta.fields
assert isinstance(MyInterface._meta.fields['field'], Field)
@ -62,10 +62,10 @@ def test_generate_interface_unmountedtype():
def test_generate_interface_inherit_abstracttype():
class MyAbstractType(AbstractType):
field1 = MyScalar(MyType)
field1 = MyScalar()
class MyInterface(Interface, MyAbstractType):
field2 = MyScalar(MyType)
field2 = MyScalar()
assert MyInterface._meta.fields.keys() == ['field1', 'field2']
assert [type(x) for x in MyInterface._meta.fields.values()] == [Field, Field]
@ -73,10 +73,10 @@ def test_generate_interface_inherit_abstracttype():
def test_generate_interface_inherit_abstracttype_reversed():
class MyAbstractType(AbstractType):
field1 = MyScalar(MyType)
field1 = MyScalar()
class MyInterface(MyAbstractType, Interface):
field2 = MyScalar(MyType)
field2 = MyScalar()
assert MyInterface._meta.fields.keys() == ['field1', 'field2']
assert [type(x) for x in MyInterface._meta.fields.values()] == [Field, Field]

View File

@ -62,10 +62,10 @@ def test_ordered_fields_in_objecttype():
def test_generate_objecttype_inherit_abstracttype():
class MyAbstractType(AbstractType):
field1 = MyScalar(MyType)
field1 = MyScalar()
class MyObjectType(ObjectType, MyAbstractType):
field2 = MyScalar(MyType)
field2 = MyScalar()
assert MyObjectType._meta.fields.keys() == ['field1', 'field2']
assert [type(x) for x in MyObjectType._meta.fields.values()] == [Field, Field]
@ -73,10 +73,10 @@ def test_generate_objecttype_inherit_abstracttype():
def test_generate_objecttype_inherit_abstracttype_reversed():
class MyAbstractType(AbstractType):
field1 = MyScalar(MyType)
field1 = MyScalar()
class MyObjectType(MyAbstractType, ObjectType):
field2 = MyScalar(MyType)
field2 = MyScalar()
assert MyObjectType._meta.fields.keys() == ['field1', 'field2']
assert [type(x) for x in MyObjectType._meta.fields.values()] == [Field, Field]
@ -84,7 +84,7 @@ def test_generate_objecttype_inherit_abstracttype_reversed():
def test_generate_objecttype_unmountedtype():
class MyObjectType(ObjectType):
field = MyScalar(MyType)
field = MyScalar()
assert 'field' in MyObjectType._meta.fields
assert isinstance(MyObjectType._meta.fields['field'], Field)

View File

@ -49,13 +49,14 @@ class UnmountedType(OrderedType):
**self.kwargs
)
# def as_argument(self):
# '''
# Mount the UnmountedType as Argument
# '''
# return Argument(
# self.get_type(),
# *self.args,
# _creation_counter=self.creation_counter,
# **self.kwargs
# )
def as_argument(self):
'''
Mount the UnmountedType as Argument
'''
from .argument import Argument
return Argument(
self.get_type(),
*self.args,
_creation_counter=self.creation_counter,
**self.kwargs
)

View File

@ -54,9 +54,13 @@ def get_fields_in_type(in_type, attrs):
(attname, value)
)
elif isinstance(value, UnmountedType):
fields_with_names.append(
(attname, unmounted_field_in_type(attname, value, in_type))
)
try:
value = unmounted_field_in_type(attname, value, in_type)
fields_with_names.append(
(attname, value)
)
except Exception as e:
raise Exception('Exception while mounting the field "{}": {}'.format(attname, str(e)))
return OrderedDict(sorted(fields_with_names, key=lambda f: f[1]))