Merge branch 'master' of github.com:graphql-python/graphene

This commit is contained in:
Syrus Akbary 2015-11-18 17:55:49 -08:00
commit 1795ed516c
9 changed files with 72 additions and 31 deletions

View File

@ -17,7 +17,7 @@ class Ship(DjangoNode):
model = ShipModel model = ShipModel
@classmethod @classmethod
def get_node(cls, id): def get_node(cls, id, info):
return Ship(get_ship(id)) return Ship(get_ship(id))
@ -33,7 +33,7 @@ class Faction(DjangoNode):
model = FactionModel model = FactionModel
@classmethod @classmethod
def get_node(cls, id): def get_node(cls, id, info):
return Faction(get_faction(id)) return Faction(get_faction(id))

View File

@ -11,7 +11,7 @@ class Ship(relay.Node):
name = graphene.String(description='The name of the ship.') name = graphene.String(description='The name of the ship.')
@classmethod @classmethod
def get_node(cls, id): def get_node(cls, id, info):
return get_ship(id) return get_ship(id)
@ -27,7 +27,7 @@ class Faction(relay.Node):
return [get_ship(ship_id) for ship_id in self.ships] return [get_ship(ship_id) for ship_id in self.ships]
@classmethod @classmethod
def get_node(cls, id): def get_node(cls, id, info):
return get_faction(id) return get_faction(id)

View File

@ -10,8 +10,7 @@ from .utils import get_type_for_model, lazy_map
class DjangoConnectionField(ConnectionField): class DjangoConnectionField(ConnectionField):
def wrap_resolved(self, value, instance, args, info): def wrap_resolved(self, value, instance, args, info):
schema = info.schema.graphene_schema return lazy_map(value, self.type)
return lazy_map(value, self.type.get_object_type(schema))
class LazyListField(Field): class LazyListField(Field):
@ -20,9 +19,8 @@ class LazyListField(Field):
return List(self.type) return List(self.type)
def resolver(self, instance, args, info): def resolver(self, instance, args, info):
schema = info.schema.graphene_schema
resolved = super(LazyListField, self).resolver(instance, args, info) resolved = super(LazyListField, self).resolver(instance, args, info)
return lazy_map(resolved, self.get_object_type(schema)) return lazy_map(resolved, self.type)
class ConnectionOrListField(Field): class ConnectionOrListField(Field):
@ -30,12 +28,14 @@ class ConnectionOrListField(Field):
def internal_type(self, schema): def internal_type(self, schema):
model_field = self.type model_field = self.type
field_object_type = model_field.get_object_type(schema) field_object_type = model_field.get_object_type(schema)
if not field_object_type:
raise SkipField()
if is_node(field_object_type): if is_node(field_object_type):
field = DjangoConnectionField(model_field) field = DjangoConnectionField(field_object_type)
else: else:
field = LazyListField(model_field) field = LazyListField(field_object_type)
field.contribute_to_class(self.object_type, self.name) field.contribute_to_class(self.object_type, self.name)
return field.internal_type(schema) return schema.T(field)
class DjangoModelField(FieldType): class DjangoModelField(FieldType):

View File

@ -66,7 +66,7 @@ def test_should_node():
model = Reporter model = Reporter
@classmethod @classmethod
def get_node(cls, id): def get_node(cls, id, info):
return ReporterNode(Reporter(id=2, first_name='Cookie Monster')) return ReporterNode(Reporter(id=2, first_name='Cookie Monster'))
def resolve_articles(self, *args, **kwargs): def resolve_articles(self, *args, **kwargs):
@ -78,7 +78,7 @@ def test_should_node():
model = Article model = Article
@classmethod @classmethod
def get_node(cls, id): def get_node(cls, id, info):
return ArticleNode(Article(id=1, headline='Article node')) return ArticleNode(Article(id=1, headline='Article node'))
class Query(graphene.ObjectType): class Query(graphene.ObjectType):

View File

@ -10,12 +10,12 @@ from ..core.types.scalars import ID, Int, String
class ConnectionField(Field): class ConnectionField(Field):
def __init__(self, field_type, resolver=None, description='', def __init__(self, type, resolver=None, description='',
connection_type=None, edge_type=None, **kwargs): connection_type=None, edge_type=None, **kwargs):
super( super(
ConnectionField, ConnectionField,
self).__init__( self).__init__(
field_type, type,
resolver=resolver, resolver=resolver,
before=String(), before=String(),
after=String(), after=String(),
@ -38,7 +38,6 @@ class ConnectionField(Field):
resolved = self.wrap_resolved(resolved, instance, args, info) resolved = self.wrap_resolved(resolved, instance, args, info)
assert isinstance( assert isinstance(
resolved, Iterable), 'Resolved value from the connection field have to be iterable' resolved, Iterable), 'Resolved value from the connection field have to be iterable'
type = schema.T(self.type) type = schema.T(self.type)
node = schema.objecttype(type) node = schema.objecttype(type)
connection_type = self.get_connection_type(node) connection_type = self.get_connection_type(node)
@ -56,7 +55,8 @@ class ConnectionField(Field):
return connection_type.for_node(node, edge_type=edge_type) return connection_type.for_node(node, edge_type=edge_type)
def get_edge_type(self, node): def get_edge_type(self, node):
return self.edge_type or node.get_edge_type() edge_type = self.edge_type or node.get_edge_type()
return edge_type.for_node(node)
def get_type(self, schema): def get_type(self, schema):
from graphene.relay.utils import is_node from graphene.relay.utils import is_node
@ -65,6 +65,7 @@ class ConnectionField(Field):
assert is_node(node), 'Only nodes have connections.' assert is_node(node), 'Only nodes have connections.'
schema.register(node) schema.register(node)
connection_type = self.get_connection_type(node) connection_type = self.get_connection_type(node)
return connection_type return connection_type
@ -91,7 +92,7 @@ class NodeField(Field):
object_type != self.field_object_type): object_type != self.field_object_type):
return return
return object_type.get_node(_id) return object_type.get_node(_id, info)
def resolver(self, instance, args, info): def resolver(self, instance, args, info):
global_id = args.get('id') global_id = args.get('id')

View File

@ -1,3 +1,4 @@
import pytest
from graphql.core.type import GraphQLID, GraphQLNonNull from graphql.core.type import GraphQLID, GraphQLNonNull
import graphene import graphene
@ -15,12 +16,22 @@ class MyNode(relay.Node):
name = graphene.String() name = graphene.String()
@classmethod @classmethod
def get_node(cls, id): def get_node(cls, id, info):
return MyNode(id=id, name='mo') return MyNode(id=id, name='mo')
class SpecialNode(relay.Node):
value = graphene.String()
@classmethod
def get_node(cls, id, info):
value = "!!!" if info.request_context.get('is_special') else "???"
return SpecialNode(id=id, value=value)
class Query(graphene.ObjectType): class Query(graphene.ObjectType):
my_node = relay.NodeField(MyNode) my_node = relay.NodeField(MyNode)
special_node = relay.NodeField(SpecialNode)
all_my_nodes = relay.ConnectionField( all_my_nodes = relay.ConnectionField(
MyNode, connection_type=MyConnection, customArg=graphene.String()) MyNode, connection_type=MyConnection, customArg=graphene.String())
@ -79,6 +90,28 @@ def test_nodefield_query():
assert result.data == expected assert result.data == expected
@pytest.mark.parametrize('specialness,value', [(True, '!!!'), (False, '???')])
def test_get_node_info(specialness, value):
query = '''
query ValueQuery {
specialNode(id:"U3BlY2lhbE5vZGU6Mg==") {
id
value
}
}
'''
expected = {
'specialNode': {
'id': 'U3BlY2lhbE5vZGU6Mg==',
'value': value,
},
}
result = schema.execute(query, request_context={'is_special': specialness})
assert not result.errors
assert result.data == expected
def test_nodeidfield(): def test_nodeidfield():
id_field = MyNode._meta.fields_map['id'] id_field = MyNode._meta.fields_map['id']
id_field_type = schema.T(id_field) id_field_type = schema.T(id_field)

View File

@ -1,4 +1,5 @@
from pytest import raises from pytest import raises
from graphql.core.type import GraphQLList
import graphene import graphene
from graphene import relay from graphene import relay
@ -31,3 +32,15 @@ def test_node_should_have_same_connection_always():
def test_node_should_have_id_field(): def test_node_should_have_id_field():
assert 'id' in OtherNode._meta.fields_map assert 'id' in OtherNode._meta.fields_map
def test_node_connection_should_have_edge():
connection = relay.Connection.for_node(OtherNode)
edge = relay.Edge.for_node(OtherNode)
connection_type = schema.T(connection)
connection_fields = connection_type.get_fields()
assert 'edges' in connection_fields
assert 'pageInfo' in connection_fields
edges_type = connection_fields['edges'].type
assert isinstance(edges_type, GraphQLList)
assert edges_type.of_type == schema.T(edge)

View File

@ -3,7 +3,6 @@ from graphql_relay.node.node import to_global_id
from ..core.types import (Boolean, Field, InputObjectType, Interface, List, from ..core.types import (Boolean, Field, InputObjectType, Interface, List,
Mutation, ObjectType, String) Mutation, ObjectType, String)
from ..core.types.argument import ArgumentsGroup from ..core.types.argument import ArgumentsGroup
from ..core.types.base import LazyType
from ..core.types.definitions import NonNull from ..core.types.definitions import NonNull
from ..utils import memoize from ..utils import memoize
from .fields import GlobalIDField from .fields import GlobalIDField
@ -24,11 +23,6 @@ class PageInfo(ObjectType):
class Edge(ObjectType): class Edge(ObjectType):
'''An edge in a connection.''' '''An edge in a connection.'''
class Meta:
type_name = 'DefaultEdge'
node = Field(LazyType(lambda object_type: object_type.node_type),
description='The item at the end of the edge')
cursor = String( cursor = String(
required=True, description='A cursor for use in pagination') required=True, description='A cursor for use in pagination')
@ -37,10 +31,11 @@ class Edge(ObjectType):
def for_node(cls, node): def for_node(cls, node):
from graphene.relay.utils import is_node from graphene.relay.utils import is_node
assert is_node(node), 'ObjectTypes in a edge have to be Nodes' assert is_node(node), 'ObjectTypes in a edge have to be Nodes'
node_field = Field(node, description='The item at the end of the edge')
return type( return type(
'%s%s' % (node._meta.type_name, cls._meta.type_name), '%s%s' % (node._meta.type_name, cls._meta.type_name),
(cls,), (cls,),
{'node_type': node}) {'node_type': node, 'node': node_field})
class Connection(ObjectType): class Connection(ObjectType):
@ -50,8 +45,6 @@ class Connection(ObjectType):
page_info = Field(PageInfo, required=True, page_info = Field(PageInfo, required=True,
description='The Information to aid in pagination') description='The Information to aid in pagination')
edges = List(LazyType(lambda object_type: object_type.edge_type),
description='Information to aid in pagination.')
_connection_data = None _connection_data = None
@ -59,12 +52,13 @@ class Connection(ObjectType):
@memoize @memoize
def for_node(cls, node, edge_type=None): def for_node(cls, node, edge_type=None):
from graphene.relay.utils import is_node from graphene.relay.utils import is_node
edge_type = edge_type or Edge edge_type = edge_type or Edge.for_node(node)
assert is_node(node), 'ObjectTypes in a connection have to be Nodes' assert is_node(node), 'ObjectTypes in a connection have to be Nodes'
edges = List(edge_type, description='Information to aid in pagination.')
return type( return type(
'%s%s' % (node._meta.type_name, cls._meta.type_name), '%s%s' % (node._meta.type_name, cls._meta.type_name),
(cls,), (cls,),
{'edge_type': edge_type.for_node(node)}) {'edge_type': edge_type, 'edges': edges})
def set_connection_data(self, data): def set_connection_data(self, data):
self._connection_data = data self._connection_data = data

View File

@ -24,7 +24,7 @@ class PyTest(TestCommand):
setup( setup(
name='graphene', name='graphene',
version='0.4.0', version='0.4.0.1',
description='Graphene: Python DSL for GraphQL', description='Graphene: Python DSL for GraphQL',
long_description=open('README.rst').read(), long_description=open('README.rst').read(),