Improved field resolving

This commit is contained in:
Syrus Akbary 2016-06-04 03:12:09 -07:00
parent d58d1f8d89
commit 40ce604d2c
10 changed files with 94 additions and 10 deletions

View File

@ -0,0 +1,14 @@
from .types import (
ObjectType,
Interface,
implements,
Field,
Schema,
Scalar,
String, ID, Int, Float, Boolean,
List, NonNull,
Argument
)
from .utils.resolve_only_args import resolve_only_args
__all__ = ['ObjectType', 'Interface', 'implements', 'Field', 'Schema', 'Scalar', 'String', 'ID', 'Int', 'Float', 'Boolean', 'List','NonNull', 'Argument','resolve_only_args']

View File

@ -1,7 +1,9 @@
from .objecttype import ObjectType, implements from .objecttype import ObjectType, implements
from .interface import Interface from .interface import Interface
from .scalars import Scalar from .scalars import Scalar, String, ID, Int, Float, Boolean
from .schema import Schema from .schema import Schema
from .structures import List, NonNull
from .field import Field from .field import Field
from .argument import Argument
__all__ = ['ObjectType', 'Interface', 'implements', 'Field', 'Schema', 'Scalar'] __all__ = ['ObjectType', 'Interface', 'implements', 'Field', 'Schema', 'Scalar', 'String', 'ID', 'Int', 'Float', 'Boolean', 'List', 'NonNull', 'Argument']

View File

@ -6,6 +6,7 @@ from graphql.utils.assert_valid_name import assert_valid_name
from .objecttype import ObjectType from .objecttype import ObjectType
from .interface import Interface from .interface import Interface
from ..utils.orderedtype import OrderedType from ..utils.orderedtype import OrderedType
from ..utils.str_converters import to_camel_case
from .argument import to_arguments from .argument import to_arguments
@ -40,7 +41,7 @@ class Field(GraphQLField, OrderedType):
@property @property
def name(self): def name(self):
return self._name or self.attname return self._name or to_camel_case(self.attname)
@name.setter @name.setter
def name(self, name): def name(self, name):

View File

@ -57,16 +57,19 @@ class ObjectType(six.with_metaclass(ObjectTypeMeta)):
if not kwargs: if not kwargs:
for val, field in zip(args, fields_iter): for val, field in zip(args, fields_iter):
setattr(self, field.name, val) attname = getattr(field, 'attname', field.name)
setattr(self, attname, val)
else: else:
for val, field in zip(args, fields_iter): for val, field in zip(args, fields_iter):
setattr(self, field.name, val) attname = getattr(field, 'attname', field.name)
kwargs.pop(field.name, None) setattr(self, attname, val)
kwargs.pop(attname, None)
for field in fields_iter: for field in fields_iter:
try: try:
val = kwargs.pop(field.name) attname = getattr(field, 'attname', field.name)
setattr(self, field.name, val) val = kwargs.pop(attname)
setattr(self, attname, val)
except KeyError: except KeyError:
pass pass

View File

@ -1,5 +1,5 @@
import six import six
from graphql import GraphQLString, GraphQLInt, GraphQLFloat, GraphQLBoolean from graphql import GraphQLString, GraphQLInt, GraphQLFloat, GraphQLBoolean, GraphQLID
from .definitions import ClassTypeMeta, GrapheneScalarType from .definitions import ClassTypeMeta, GrapheneScalarType
from .proxy import TypeProxy from .proxy import TypeProxy
@ -52,3 +52,4 @@ String = construct_scalar_class(GraphQLString)
Int = construct_scalar_class(GraphQLInt) Int = construct_scalar_class(GraphQLInt)
Float = construct_scalar_class(GraphQLFloat) Float = construct_scalar_class(GraphQLFloat)
Boolean = construct_scalar_class(GraphQLBoolean) Boolean = construct_scalar_class(GraphQLBoolean)
ID = construct_scalar_class(GraphQLID)

View File

@ -37,7 +37,7 @@ def test_contributed_field_objecttype():
field = Field(GraphQLString) field = Field(GraphQLString)
field.contribute_to_class(MyObject, 'field_name') field.contribute_to_class(MyObject, 'field_name')
assert field.name == 'field_name' assert field.name == 'fieldName'
def test_contributed_field_non_objecttype(): def test_contributed_field_non_objecttype():

View File

@ -0,0 +1,8 @@
from functools import wraps
def resolve_only_args(func):
@wraps(func)
def inner(root, args, context, info):
return func(root, **args)
return inner

View File

@ -0,0 +1,21 @@
import re
# From this response in Stackoverflow
# http://stackoverflow.com/a/19053800/1072990
def to_camel_case(snake_str):
components = snake_str.split('_')
# We capitalize the first letter of each component except the first one
# with the 'title' method and join them together.
return components[0] + "".join(x.title() if x else '_' for x in components[1:])
# From this response in Stackoverflow
# http://stackoverflow.com/a/1176023/1072990
def to_snake_case(name):
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
def to_const(string):
return re.sub('[\W|^]+', '_', string).upper()

View File

@ -0,0 +1,12 @@
from ..resolve_only_args import resolve_only_args
def test_resolve_only_args():
def resolver(*args, **kwargs):
return kwargs
my_data = {'one': 1, 'two': 2}
wrapped = resolve_only_args(resolver)
assert wrapped(None, my_data, None, None) == my_data

View File

@ -0,0 +1,22 @@
# coding: utf-8
from ..str_converters import to_camel_case, to_const, to_snake_case
def test_snake_case():
assert to_snake_case('snakesOnAPlane') == 'snakes_on_a_plane'
assert to_snake_case('SnakesOnAPlane') == 'snakes_on_a_plane'
assert to_snake_case('SnakesOnA_Plane') == 'snakes_on_a__plane'
assert to_snake_case('snakes_on_a_plane') == 'snakes_on_a_plane'
assert to_snake_case('snakes_on_a__plane') == 'snakes_on_a__plane'
assert to_snake_case('IPhoneHysteria') == 'i_phone_hysteria'
assert to_snake_case('iPhoneHysteria') == 'i_phone_hysteria'
def test_camel_case():
assert to_camel_case('snakes_on_a_plane') == 'snakesOnAPlane'
assert to_camel_case('snakes_on_a__plane') == 'snakesOnA_Plane'
assert to_camel_case('i_phone_hysteria') == 'iPhoneHysteria'
def test_to_const():
assert to_const('snakes $1. on a "#plane') == 'SNAKES_1_ON_A_PLANE'