Merge branch '0.4.0-cov' of github.com:graphql-python/graphene into 0.4.0-cov

This commit is contained in:
Syrus Akbary 2015-11-11 18:06:39 -08:00
commit a55222e107
10 changed files with 78 additions and 75 deletions

View File

@ -5,6 +5,7 @@ from graphene.contrib.django.fields import (ConnectionOrListField,
DjangoModelField)
from graphene.core.fields import (BooleanField, FloatField, IDField, IntField,
StringField)
from graphene.core.types.scalars import Boolean, Float, ID, Int, String
try:
UUIDField = models.UUIDField
@ -28,12 +29,12 @@ def convert_django_field(field):
@convert_django_field.register(models.URLField)
@convert_django_field.register(UUIDField)
def convert_field_to_string(field):
return StringField(description=field.help_text)
return String(description=field.help_text)
@convert_django_field.register(models.AutoField)
def convert_field_to_id(field):
return IDField(description=field.help_text)
return ID(description=field.help_text)
@convert_django_field.register(models.PositiveIntegerField)
@ -42,23 +43,23 @@ def convert_field_to_id(field):
@convert_django_field.register(models.BigIntegerField)
@convert_django_field.register(models.IntegerField)
def convert_field_to_int(field):
return IntField(description=field.help_text)
return Int(description=field.help_text)
@convert_django_field.register(models.BooleanField)
def convert_field_to_boolean(field):
return BooleanField(description=field.help_text, required=True)
return Boolean(description=field.help_text, required=True)
@convert_django_field.register(models.NullBooleanField)
def convert_field_to_nullboolean(field):
return BooleanField(description=field.help_text)
return Boolean(description=field.help_text)
@convert_django_field.register(models.DecimalField)
@convert_django_field.register(models.FloatField)
def convert_field_to_float(field):
return FloatField(description=field.help_text)
return Float(description=field.help_text)
@convert_django_field.register(models.ManyToManyField)

View File

@ -1,6 +1,7 @@
from graphene import relay
from graphene.contrib.django.utils import get_type_for_model, lazy_map
from graphene.core.fields import Field, LazyField, ListField
from graphene.core.fields import Field, ListField
from graphene.core.types.base import FieldType
from graphene.relay.utils import is_node
@ -8,60 +9,49 @@ class DjangoConnectionField(relay.ConnectionField):
def wrap_resolved(self, value, instance, args, info):
schema = info.schema.graphene_schema
return lazy_map(value, self.get_object_type(schema))
return lazy_map(value, self.type.get_object_type(schema))
class LazyListField(ListField):
def resolve(self, instance, args, info):
def resolver(self, instance, args, info):
schema = info.schema.graphene_schema
resolved = super(LazyListField, self).resolve(instance, args, info)
resolved = super(LazyListField, self).resolver(instance, args, info)
return lazy_map(resolved, self.get_object_type(schema))
class ConnectionOrListField(LazyField):
class ConnectionOrListField(Field):
def get_field(self, schema):
model_field = self.field_type
def internal_type(self, schema):
model_field = self.type
field_object_type = model_field.get_object_type(schema)
if is_node(field_object_type):
field = DjangoConnectionField(model_field)
else:
field = LazyListField(model_field)
field.contribute_to_class(self.object_type, self.name)
return field
return field.internal_type(schema)
class DjangoModelField(Field):
class DjangoModelField(FieldType):
def __init__(self, model, *args, **kwargs):
super(DjangoModelField, self).__init__(None, *args, **kwargs)
self.model = model
def resolve(self, instance, args, info):
resolved = super(DjangoModelField, self).resolve(instance, args, info)
schema = info.schema.graphene_schema
_type = self.get_object_type(schema)
assert _type, ("Field %s cannot be retrieved as the "
"ObjectType is not registered by the schema" % (
self.attname
))
return _type(resolved)
super(DjangoModelField, self).__init__(*args, **kwargs)
def internal_type(self, schema):
_type = self.get_object_type(schema)
if not _type and self.object_type._meta.only_fields:
if not _type and self.parent._meta.only_fields:
raise Exception(
"Model %r is not accessible by the schema. "
"You can either register the type manually "
"using @schema.register. "
"Or disable the field %s in %s" % (
"Or disable the field in %s" % (
self.model,
self.attname,
self.object_type
self.parent,
)
)
return schema.T(_type) or Field.SKIP
return schema.T(_type)
def get_object_type(self, schema):
return get_type_for_model(schema, self.model)

View File

@ -40,9 +40,9 @@ class Schema(object):
if object_type not in self._types:
internal_type = object_type.internal_type(self)
self._types[object_type] = internal_type
name = getattr(internal_type, 'name', None)
if name:
self._types_names[name] = object_type
is_objecttype = inspect.isclass(object_type) and issubclass(object_type, BaseObjectType)
if is_objecttype:
self.register(object_type)
return self._types[object_type]
else:
return object_type
@ -65,6 +65,10 @@ class Schema(object):
return GraphQLSchema(self, query=self.T(self.query), mutation=self.T(self.mutation))
def register(self, object_type):
type_name = object_type._meta.type_name
registered_object_type = self._types_names.get(type_name, None)
if registered_object_type:
assert registered_object_type == object_type, 'Type {} already registered with other object type'.format(type_name)
self._types_names[object_type._meta.type_name] = object_type
return object_type

View File

@ -31,14 +31,12 @@ class Field(OrderedType):
if isinstance(type, six.string_types):
type = LazyType(type)
self.required = required
if self.required:
type = NonNull(type)
self.type = type
self.description = description
args = OrderedDict(args or {}, **kwargs)
self.arguments = ArgumentsGroup(*args_list, **args)
self.object_type = None
self.resolver = resolver
self.resolver_fn = resolver
self.default = default
def contribute_to_class(self, cls, attname):
@ -54,11 +52,11 @@ class Field(OrderedType):
@property
def resolver(self):
return self._resolver or self.get_resolver_fn()
return self.resolver_fn or self.get_resolver_fn()
@resolver.setter
def resolver(self, value):
self._resolver = value
self.resolver_fn = value
def get_resolver_fn(self):
resolve_fn_name = 'resolve_%s' % self.attname
@ -70,6 +68,8 @@ class Field(OrderedType):
return default_getter
def get_type(self, schema):
if self.required:
return NonNull(self.type)
return self.type
def internal_type(self, schema):

View File

@ -1,7 +1,7 @@
from collections import Iterable
from graphene.core.fields import Field, IDField
from graphene.core.types.scalars import String, ID
from graphene.core.types.scalars import String, ID, Int
from graphql.core.type import GraphQLArgument, GraphQLID, GraphQLNonNull
from graphql_relay.connection.arrayconnection import connection_from_list
from graphql_relay.node.node import from_global_id
@ -14,8 +14,8 @@ class ConnectionField(Field):
super(ConnectionField, self).__init__(field_type, resolver=resolver,
before=String(),
after=String(),
first=String(),
last=String(),
first=Int(),
last=Int(),
description=description, **kwargs)
self.connection_type = connection_type
self.edge_type = edge_type
@ -24,17 +24,18 @@ class ConnectionField(Field):
return value
def resolve(self, instance, args, info):
def resolver(self, instance, args, info):
from graphene.relay.types import PageInfo
schema = info.schema.graphene_schema
resolved = super(ConnectionField, self).resolve(instance, args, info)
resolved = super(ConnectionField, self).resolver(instance, args, info)
if resolved:
resolved = self.wrap_resolved(resolved, instance, args, info)
assert isinstance(
resolved, Iterable), 'Resolved value from the connection field have to be iterable'
node = self.get_object_type(schema)
type = schema.T(self.type)
node = schema.objecttype(type)
connection_type = self.get_connection_type(node)
edge_type = self.get_edge_type(node)
@ -81,14 +82,16 @@ class NodeField(Field):
return object_type.get_node(_id)
def resolve(self, instance, args, info):
def resolver(self, instance, args, info):
global_id = args.get('id')
return self.id_fetcher(global_id, info)
class GlobalIDField(IDField):
class GlobalIDField(Field):
'''The ID of an object'''
required = True
def __init__(self, *args, **kwargs):
super(GlobalIDField, self).__init__(ID(), *args, **kwargs)
self.required = True
def contribute_to_class(self, cls, name):
from graphene.relay.utils import is_node, is_node_type
@ -96,5 +99,5 @@ class GlobalIDField(IDField):
assert in_node, 'GlobalIDField could only be inside a Node, but got %r' % cls
super(GlobalIDField, self).contribute_to_class(cls, name)
def resolve(self, instance, args, info):
def resolver(self, instance, args, info):
return self.object_type.to_global_id(instance, args, info)

View File

@ -15,7 +15,7 @@ class MyNode(relay.Node):
@classmethod
def get_node(cls, id):
return MyNode(name='mo')
return MyNode(id=id, name='mo')
class Query(graphene.ObjectType):
@ -35,6 +35,7 @@ def test_nodefield_query():
query = '''
query RebelsShipsQuery {
myNode(id:"TXlOb2RlOjE=") {
id
name
},
allMyNodes (customArg:"1") {
@ -52,6 +53,7 @@ def test_nodefield_query():
'''
expected = {
'myNode': {
'id': 'TXlOb2RlOjE=',
'name': 'mo'
},
'allMyNodes': {

View File

@ -15,8 +15,9 @@ def assert_conversion(django_field, graphene_field, *args):
field = django_field(*args, help_text='Custom Help Text')
graphene_type = convert_django_field(field)
assert isinstance(graphene_type, graphene_field)
assert graphene_type.description == 'Custom Help Text'
return graphene_type
field = graphene_type.as_field()
assert field.description == 'Custom Help Text'
return field
def test_should_unknown_django_field_raise_exception():
@ -26,86 +27,86 @@ def test_should_unknown_django_field_raise_exception():
def test_should_date_convert_string():
assert_conversion(models.DateField, graphene.StringField)
assert_conversion(models.DateField, graphene.String)
def test_should_char_convert_string():
assert_conversion(models.CharField, graphene.StringField)
assert_conversion(models.CharField, graphene.String)
def test_should_text_convert_string():
assert_conversion(models.TextField, graphene.StringField)
assert_conversion(models.TextField, graphene.String)
def test_should_email_convert_string():
assert_conversion(models.EmailField, graphene.StringField)
assert_conversion(models.EmailField, graphene.String)
def test_should_slug_convert_string():
assert_conversion(models.SlugField, graphene.StringField)
assert_conversion(models.SlugField, graphene.String)
def test_should_url_convert_string():
assert_conversion(models.URLField, graphene.StringField)
assert_conversion(models.URLField, graphene.String)
def test_should_auto_convert_id():
assert_conversion(models.AutoField, graphene.IDField)
assert_conversion(models.AutoField, graphene.ID)
def test_should_positive_integer_convert_int():
assert_conversion(models.PositiveIntegerField, graphene.IntField)
assert_conversion(models.PositiveIntegerField, graphene.Int)
def test_should_positive_small_convert_int():
assert_conversion(models.PositiveSmallIntegerField, graphene.IntField)
assert_conversion(models.PositiveSmallIntegerField, graphene.Int)
def test_should_small_integer_convert_int():
assert_conversion(models.SmallIntegerField, graphene.IntField)
assert_conversion(models.SmallIntegerField, graphene.Int)
def test_should_big_integer_convert_int():
assert_conversion(models.BigIntegerField, graphene.IntField)
assert_conversion(models.BigIntegerField, graphene.Int)
def test_should_integer_convert_int():
assert_conversion(models.IntegerField, graphene.IntField)
assert_conversion(models.IntegerField, graphene.Int)
def test_should_boolean_convert_boolean():
field = assert_conversion(models.BooleanField, graphene.BooleanField)
field = assert_conversion(models.BooleanField, graphene.Boolean)
assert field.required is True
def test_should_nullboolean_convert_boolean():
field = assert_conversion(models.NullBooleanField, graphene.BooleanField)
field = assert_conversion(models.NullBooleanField, graphene.Boolean)
assert field.required is False
def test_should_float_convert_float():
assert_conversion(models.FloatField, graphene.FloatField)
assert_conversion(models.FloatField, graphene.Float)
def test_should_manytomany_convert_connectionorlist():
graphene_type = convert_django_field(Reporter._meta.local_many_to_many[0])
assert isinstance(graphene_type, ConnectionOrListField)
assert isinstance(graphene_type.field_type, DjangoModelField)
assert graphene_type.field_type.model == Reporter
assert isinstance(graphene_type.type, DjangoModelField)
assert graphene_type.type.model == Reporter
def test_should_manytoone_convert_connectionorlist():
graphene_type = convert_django_field(Reporter.articles.related)
assert isinstance(graphene_type, ConnectionOrListField)
assert isinstance(graphene_type.field_type, DjangoModelField)
assert graphene_type.field_type.model == Article
assert isinstance(graphene_type.type, DjangoModelField)
assert graphene_type.type.model == Article
def test_should_onetoone_convert_model():
field = assert_conversion(models.OneToOneField, DjangoModelField, Article)
assert field.model == Article
assert field.type.model == Article
def test_should_foreignkey_convert_model():
field = assert_conversion(models.ForeignKey, DjangoModelField, Article)
assert field.model == Article
assert field.type.model == Article

View File

@ -2,7 +2,8 @@
from graphene import Schema
from graphene.contrib.django.types import DjangoInterface, DjangoNode
from graphene.core.fields import IntField
from graphene.core.fields import IntField, Field
from graphene.core.types.scalars import String, Int
from graphene.relay.fields import GlobalIDField
from graphql.core.type import GraphQLInterfaceType, GraphQLObjectType
from tests.utils import assert_equal_lists
@ -57,7 +58,8 @@ def test_node_idfield():
def test_node_replacedfield():
idfield = Human._meta.fields_map['pub_date']
assert isinstance(idfield, IntField)
assert isinstance(idfield, Field)
assert schema.T(idfield).type == schema.T(Int())
def test_interface_resolve_type():