Improved syntax using pep8 style guide

This commit is contained in:
Syrus Akbary 2015-10-02 22:17:51 -07:00
parent 9a3f11b802
commit 176696c1ac
41 changed files with 271 additions and 156 deletions

View File

@ -1,4 +1,4 @@
from graphene.contrib.django.types import (
DjangoObjectType,
DjangoNode
DjangoObjectType,
DjangoNode
)

View File

@ -11,9 +11,11 @@ from graphene.core.fields import (
)
from graphene.contrib.django.fields import ConnectionOrListField, DjangoModelField
@singledispatch
def convert_django_field(field, cls):
raise Exception("Don't know how to convert the Django field %s (%s)" % (field, field.__class__))
raise Exception(
"Don't know how to convert the Django field %s (%s)" % (field, field.__class__))
@convert_django_field.register(models.DateField)

View File

@ -16,12 +16,14 @@ def get_type_for_model(schema, model):
schema = schema
types = schema.types.values()
for _type in types:
type_model = hasattr(_type,'_meta') and getattr(_type._meta, 'model', None)
type_model = hasattr(_type, '_meta') and getattr(
_type._meta, 'model', None)
if model == type_model:
return _type
class DjangoConnectionField(relay.ConnectionField):
def wrap_resolved(self, value, instance, args, info):
if isinstance(value, (QuerySet, Manager)):
cls = instance.__class__
@ -30,6 +32,7 @@ class DjangoConnectionField(relay.ConnectionField):
class ConnectionOrListField(LazyField):
@memoize
def get_field(self, schema):
model_field = self.field_type
@ -43,6 +46,7 @@ class ConnectionOrListField(LazyField):
class DjangoModelField(Field):
def __init__(self, model, *args, **kwargs):
super(DjangoModelField, self).__init__(None, *args, **kwargs)
self.model = model
@ -55,7 +59,9 @@ class DjangoModelField(Field):
def get_object_type(self, schema):
_type = get_type_for_model(schema, self.model)
if not _type and self.object_type._meta.only_fields:
# We will only raise the exception if the related field is specified in only_fields
raise Exception("Field %s (%s) model not mapped in current schema" % (self, self.model._meta.object_name))
# We will only raise the exception if the related field is
# specified in only_fields
raise Exception("Field %s (%s) model not mapped in current schema" % (
self, self.model._meta.object_name))
return _type

View File

@ -14,6 +14,7 @@ def is_base(cls):
class DjangoOptions(Options):
def __init__(self, *args, **kwargs):
self.model = None
super(DjangoOptions, self).__init__(*args, **kwargs)
@ -25,6 +26,7 @@ class DjangoOptions(Options):
if not is_node(cls) and not is_base(cls):
return
if not self.model:
raise Exception('Django ObjectType %s must have a model in the Meta class attr' % cls)
raise Exception(
'Django ObjectType %s must have a model in the Meta class attr' % cls)
elif not inspect.isclass(self.model) or not issubclass(self.model, models.Model):
raise Exception('Provided model in %s is not a Django model' % cls)

View File

@ -42,4 +42,4 @@ class DjangoInterface(six.with_metaclass(DjangoObjectTypeMeta, BaseObjectType)):
class DjangoNode(BaseNode, DjangoInterface):
pass
pass

View File

@ -13,7 +13,9 @@ from graphql.core.type import (
from graphene.utils import cached_property, memoize
from graphene.core.types import BaseObjectType
class Field(object):
def __init__(self, field_type, resolve=None, null=True, args=None, description='', **extra_args):
self.field_type = field_type
self.resolve_fn = resolve
@ -41,7 +43,8 @@ class Field(object):
if self.resolve_fn:
resolve_fn = self.resolve_fn
else:
resolve_fn = lambda root, args, info: root.resolve(self.field_name, args, info)
resolve_fn = lambda root, args, info: root.resolve(
self.field_name, args, info)
return resolve_fn(instance, args, info)
def get_object_type(self, schema):
@ -78,7 +81,8 @@ class Field(object):
@memoize
def internal_field(self, schema):
if not self.object_type:
raise Exception('Field could not be constructed in a non graphene.Type or graphene.Interface')
raise Exception(
'Field could not be constructed in a non graphene.Type or graphene.Interface')
extra_args = self.extra_args.copy()
for arg_name, arg_value in extra_args.items():
@ -118,6 +122,7 @@ class Field(object):
class NativeField(Field):
def __init__(self, field=None):
super(NativeField, self).__init__(None)
self.field = field
@ -135,6 +140,7 @@ class NativeField(Field):
class LazyField(Field):
@memoize
def inner_field(self, schema):
return self.get_field(schema)
@ -147,11 +153,13 @@ class LazyField(Field):
class LazyNativeField(NativeField):
def __init__(self, *args, **kwargs):
super(LazyNativeField, self).__init__(None, *args, **kwargs)
def get_field(self, schema):
raise NotImplementedError("get_field function not implemented for %s LazyField" % self.__class__)
raise NotImplementedError(
"get_field function not implemented for %s LazyField" % self.__class__)
@memoize
def internal_field(self, schema):
@ -163,6 +171,7 @@ class LazyNativeField(NativeField):
class TypeField(Field):
def __init__(self, *args, **kwargs):
super(TypeField, self).__init__(self.field_type, *args, **kwargs)
@ -188,10 +197,12 @@ class FloatField(TypeField):
class ListField(Field):
def type_wrapper(self, field_type):
return GraphQLList(field_type)
class NonNullField(Field):
def type_wrapper(self, field_type):
return GraphQLNonNull(field_type)

View File

@ -5,6 +5,7 @@ DEFAULT_NAMES = ('description', 'name', 'interface',
class Options(object):
def __init__(self, meta=None):
self.meta = meta
self.local_fields = []
@ -13,7 +14,7 @@ class Options(object):
self.interfaces = []
self.parents = []
self.valid_attrs = DEFAULT_NAMES
def contribute_to_class(self, cls, name):
cls._meta = self
self.parent = cls
@ -47,7 +48,8 @@ class Options(object):
# Any leftover attributes must be invalid.
if meta_attrs != {}:
raise TypeError("'class Meta' got invalid attribute(s): %s" % ','.join(meta_attrs.keys()))
raise TypeError(
"'class Meta' got invalid attribute(s): %s" % ','.join(meta_attrs.keys()))
else:
self.proxy = False

View File

@ -49,7 +49,7 @@ class Schema(object):
@property
def types(self):
return self._internal_types
def execute(self, request='', root=None, vars=None, operation_name=None):
root = root or object()
return graphql(
@ -63,6 +63,7 @@ class Schema(object):
def introspect(self):
return self._schema.get_type_map()
def register_internal_type(fun):
@wraps(fun)
def wrapper(cls, schema):

View File

@ -11,6 +11,7 @@ from graphene.core.options import Options
from graphene.utils import memoize
from graphene.core.schema import register_internal_type
class ObjectTypeMeta(type):
options_cls = Options
@ -40,7 +41,7 @@ class ObjectTypeMeta(type):
base_meta = getattr(new_class, '_meta', None)
new_class.add_to_class('_meta', new_class.options_cls(meta))
new_class._meta.interface = new_class.is_interface(parents)
# Add all attributes to the class.
for obj_name, obj in attrs.items():
@ -68,7 +69,8 @@ class ObjectTypeMeta(type):
raise Exception(
'Local field %r in class %r clashes '
'with field of similar name from '
'base class %r' % (field.field_name, name, base.__name__)
'base class %r' % (
field.field_name, name, base.__name__)
)
new_class._meta.parents.append(base)
if base._meta.interface:
@ -93,6 +95,7 @@ class ObjectTypeMeta(type):
class BaseObjectType(object):
def __new__(cls, instance=None, *args, **kwargs):
if cls._meta.interface:
raise Exception("An interface cannot be initialized")
@ -143,7 +146,8 @@ class BaseObjectType(object):
return GraphQLInterfaceType(
cls._meta.type_name,
description=cls._meta.description,
resolve_type=lambda *args, **kwargs: cls.resolve_type(schema, *args, **kwargs),
resolve_type=lambda *
args, **kwargs: cls.resolve_type(schema, *args, **kwargs),
fields=fields
)
return GraphQLObjectType(
@ -157,5 +161,6 @@ class BaseObjectType(object):
class ObjectType(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
pass
class Interface(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
pass

View File

@ -4,5 +4,5 @@ from functools import wraps
def resolve_only_args(func):
@wraps(func)
def inner(self, args, info):
return func(self, **args)
return inner
return func(self, **args)
return inner

View File

@ -2,8 +2,9 @@ from graphene.core.schema import Schema
_global_schema = None
def get_global_schema():
global _global_schema
if not _global_schema:
_global_schema = Schema(name='Global Schema')
return _global_schema
global _global_schema
if not _global_schema:
_global_schema = Schema(name='Global Schema')
return _global_schema

View File

@ -1,12 +1,12 @@
from graphene.relay.fields import (
ConnectionField,
NodeField
ConnectionField,
NodeField
)
import graphene.relay.connections
from graphene.relay.types import (
Node
Node
)
from graphene.relay.utils import is_node

View File

@ -13,4 +13,5 @@ def object_type_created(object_type):
type_name = object_type._meta.type_name
field = NodeIDField()
object_type.add_to_class('id', field)
assert hasattr(object_type, 'get_node'), 'get_node classmethod not found in %s Node' % type_name
assert hasattr(
object_type, 'get_node'), 'get_node classmethod not found in %s Node' % type_name

View File

@ -16,8 +16,9 @@ from graphene.utils import memoize
class ConnectionField(Field):
def __init__(self, field_type, resolve=None, description=''):
super(ConnectionField, self).__init__(field_type, resolve=resolve,
super(ConnectionField, self).__init__(field_type, resolve=resolve,
args=connectionArgs, description=description)
def wrap_resolved(self, value, instance, args, info):
@ -27,23 +28,27 @@ class ConnectionField(Field):
resolved = super(ConnectionField, self).resolve(instance, args, info)
if resolved:
resolved = self.wrap_resolved(resolved, instance, args, info)
assert isinstance(resolved, collections.Iterable), 'Resolved value from the connection field have to be iterable'
assert isinstance(
resolved, collections.Iterable), 'Resolved value from the connection field have to be iterable'
return connectionFromArray(resolved, args)
@memoize
def internal_type(self, schema):
from graphene.relay.types import BaseNode
object_type = self.get_object_type(schema)
assert issubclass(object_type, BaseNode), 'Only nodes have connections.'
assert issubclass(
object_type, BaseNode), 'Only nodes have connections.'
return object_type.get_connection(schema)
class NodeField(LazyNativeField):
def get_field(self, schema):
from graphene.relay.types import BaseNode
return BaseNode.get_definitions(schema).nodeField
class NodeIDField(LazyNativeField):
def get_field(self, schema):
return globalIdField(self.object_type._meta.type_name)

View File

@ -23,6 +23,7 @@ def get_node(schema, globalId, *args):
class BaseNode(object):
@classmethod
@memoize
def get_definitions(cls, schema):

View File

@ -1,7 +1,9 @@
from graphene.relay.types import BaseNode
def is_node(object_type):
return issubclass(object_type, BaseNode) and not is_node_type(object_type)
return issubclass(object_type, BaseNode) and not is_node_type(object_type)
def is_node_type(object_type):
return BaseNode in object_type.__bases__
return BaseNode in object_type.__bases__

View File

@ -1,6 +1,8 @@
from functools import wraps
class cached_property(object):
"""
A property that is only computed once per instance and then replaces itself
with an ordinary attribute. Deleting the attribute resets the property.

View File

@ -17,7 +17,7 @@ class PyTest(TestCommand):
self.test_suite = True
def run_tests(self):
#import here, cause outside the eggs aren't loaded
# import here, cause outside the eggs aren't loaded
import pytest
errno = pytest.main(self.pytest_args)
sys.exit(errno)

View File

@ -8,10 +8,12 @@ r.save()
r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
r2.save()
a = Article(id=None, headline="This is a test", pub_date=date(2005, 7, 27), reporter=r)
a = Article(id=None, headline="This is a test",
pub_date=date(2005, 7, 27), reporter=r)
a.save()
new_article = r.articles.create(headline="John's second story", pub_date=date(2005, 7, 29))
new_article = r.articles.create(
headline="John's second story", pub_date=date(2005, 7, 29))
new_article2 = Article(headline="Paul's story", pub_date=date(2006, 1, 17))
r.articles.add(new_article2)

View File

@ -1,6 +1,7 @@
from __future__ import absolute_import
from django.db import models
class Reporter(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
@ -12,6 +13,7 @@ class Reporter(models.Model):
class Meta:
app_label = 'contrib_django'
class Article(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateField()

View File

@ -20,6 +20,7 @@ def test_should_raise_if_no_model():
def test_should_raise_if_model_is_invalid():
with raises(Exception) as excinfo:
class Character2(DjangoObjectType):
class Meta:
model = 1
assert 'not a Django model' in str(excinfo.value)
@ -28,6 +29,7 @@ def test_should_raise_if_model_is_invalid():
def test_should_raise_if_model_is_invalid():
with raises(Exception) as excinfo:
class ReporterTypeError(DjangoObjectType):
class Meta:
model = Reporter
only_fields = ('articles', )
@ -41,18 +43,22 @@ def test_should_raise_if_model_is_invalid():
result = schema.execute(query)
assert not result.errors
assert 'articles (Article) model not mapped in current schema' in str(excinfo.value)
assert 'articles (Article) model not mapped in current schema' in str(
excinfo.value)
def test_should_map_fields_correctly():
class ReporterType2(DjangoObjectType):
class Meta:
model = Reporter
assert ReporterType2._meta.fields_map.keys() == ['articles', 'first_name', 'last_name', 'id', 'email']
assert ReporterType2._meta.fields_map.keys(
) == ['articles', 'first_name', 'last_name', 'id', 'email']
def test_should_map_fields():
class ReporterType(DjangoObjectType):
class Meta:
model = Reporter
@ -86,13 +92,16 @@ def test_should_map_fields():
def test_should_map_only_few_fields():
class Reporter2(DjangoObjectType):
class Meta:
model = Reporter
only_fields = ('id', 'email')
assert Reporter2._meta.fields_map.keys() == ['id', 'email']
def test_should_node():
class ReporterNodeType(DjangoNode):
class Meta:
model = Reporter
@ -104,6 +113,7 @@ def test_should_node():
return [ArticleNodeType(Article(headline='Hi!'))]
class ArticleNodeType(DjangoNode):
class Meta:
model = Article
@ -152,11 +162,11 @@ def test_should_node():
'last_name': 'X',
'email': '',
'articles': {
'edges': [{
'node': {
'headline': 'Hi!'
}
}]
'edges': [{
'node': {
'headline': 'Hi!'
}
}]
},
},
'my_article': {

View File

@ -20,13 +20,16 @@ from .models import Reporter, Article
class Character(DjangoInterface):
'''Character description'''
class Meta:
model = Reporter
class Human(DjangoNode):
'''Human description'''
def get_node(self, id):
pass
@ -39,12 +42,14 @@ schema = Schema()
def test_django_interface():
assert DjangoNode._meta.interface == True
def test_pseudo_interface():
object_type = Character.internal_type(schema)
assert Character._meta.interface == True
assert isinstance(object_type, GraphQLInterfaceType)
assert Character._meta.model == Reporter
assert object_type.get_fields().keys() == ['articles', 'first_name', 'last_name', 'id', 'email']
assert object_type.get_fields().keys() == [
'articles', 'first_name', 'last_name', 'id', 'email']
def test_interface_resolve_type():

View File

@ -17,10 +17,13 @@ from graphql.core.type import (
GraphQLID,
)
class ObjectType(object):
_meta = Options()
def resolve(self, *args, **kwargs):
return None
def can_resolve(self, *args):
return True
@ -28,11 +31,13 @@ ot = ObjectType()
ObjectType._meta.contribute_to_class(ObjectType, '_meta')
class Schema(object):
pass
schema = Schema()
def test_field_no_contributed_raises_error():
f = Field(GraphQLString)
with raises(Exception) as excinfo:
@ -60,10 +65,10 @@ def test_stringfield_type_null():
def test_field_resolve():
f = StringField(null=False, resolve=lambda *args:'RESOLVED')
f = StringField(null=False, resolve=lambda *args: 'RESOLVED')
f.contribute_to_class(ot, 'field_name')
field_type = f.internal_field(schema)
assert 'RESOLVED' == field_type.resolver(ot,2,3)
assert 'RESOLVED' == field_type.resolver(ot, 2, 3)
def test_field_resolve_type_custom():
@ -71,6 +76,7 @@ def test_field_resolve_type_custom():
pass
class Schema(object):
def get_type(self, name):
if name == 'MyCustomType':
return MyCustomType

View File

@ -8,13 +8,16 @@ from graphene.core.fields import (
from graphene.core.options import Options
class Meta:
interface = True
type_name = 'Character'
class InvalidMeta:
other_value = True
def test_field_added_in_meta():
opt = Options(Meta)
@ -27,6 +30,7 @@ def test_field_added_in_meta():
opt.add_field(f)
assert f in opt.fields
def test_options_contribute():
opt = Options(Meta)
@ -36,6 +40,7 @@ def test_options_contribute():
opt.contribute_to_class(ObjectType, '_meta')
assert ObjectType._meta == opt
def test_options_typename():
opt = Options(Meta)
@ -45,16 +50,19 @@ def test_options_typename():
opt.contribute_to_class(ObjectType, '_meta')
assert opt.type_name == 'Character'
def test_options_description():
opt = Options(Meta)
class ObjectType(object):
'''False description'''
pass
opt.contribute_to_class(ObjectType, '_meta')
assert opt.description == 'False description'
def test_field_no_contributed_raises_error():
opt = Options(InvalidMeta)

View File

@ -24,7 +24,7 @@ class Character(Interface):
class Pet(ObjectType):
type = StringField(resolve=lambda *_:'Dog')
type = StringField(resolve=lambda *_: 'Dog')
class Human(Character):
@ -33,7 +33,7 @@ class Human(Character):
def resolve_name(self, *args):
return 'Peter'
def resolve_friend(self, *args):
return Human(object())
@ -60,7 +60,7 @@ def test_query():
expected = {
'name': 'Peter',
'pet': {
'type':'Dog'
'type': 'Dog'
}
}
result = graphql(schema, query, root=Human(object()))

View File

@ -28,7 +28,7 @@ class Character(Interface):
class Pet(ObjectType):
type = StringField(resolve=lambda *_:'Dog')
type = StringField(resolve=lambda *_: 'Dog')
class Human(Character):
@ -37,7 +37,7 @@ class Human(Character):
def resolve_name(self, *args):
return 'Peter'
def resolve_friend(self, *args):
return Human(object())
@ -46,17 +46,21 @@ class Human(Character):
schema.query = Human
def test_get_registered_type():
assert schema.get_type('Character') == Character
def test_get_unregistered_type():
with raises(Exception) as excinfo:
schema.get_type('NON_EXISTENT_MODEL')
assert 'not found' in str(excinfo.value)
def test_schema_query():
assert schema.query == Human
def test_query_schema_graphql():
a = object()
query = '''
@ -70,7 +74,7 @@ def test_query_schema_graphql():
expected = {
'name': 'Peter',
'pet': {
'type':'Dog'
'type': 'Dog'
}
}
result = graphql(schema.schema, query, root=Human(object()))
@ -91,7 +95,7 @@ def test_query_schema_execute():
expected = {
'name': 'Peter',
'pet': {
'type':'Dog'
'type': 'Dog'
}
}
result = schema.execute(query, root=object())
@ -100,4 +104,5 @@ def test_query_schema_execute():
def test_schema_get_type_map():
assert schema.schema.get_type_map().keys() == ['__Field', 'String', 'Pet', 'Character', '__InputValue', '__Directive', '__TypeKind', '__Schema', '__Type', 'Human', '__EnumValue', 'Boolean']
assert schema.schema.get_type_map().keys() == [
'__Field', 'String', 'Pet', 'Character', '__InputValue', '__Directive', '__TypeKind', '__Schema', '__Type', 'Human', '__EnumValue', 'Boolean']

View File

@ -17,13 +17,16 @@ from graphene.core.types import (
class Character(Interface):
'''Character description'''
name = StringField()
class Meta:
type_name = 'core.Character'
class Human(Character):
'''Human description'''
friends = StringField()
@ -39,7 +42,8 @@ def test_interface():
assert isinstance(object_type, GraphQLInterfaceType)
assert Character._meta.type_name == 'core.Character'
assert object_type.description == 'Character description'
assert object_type.get_fields() == {'name': Character._meta.fields_map['name'].internal_field(schema)}
assert object_type.get_fields() == {
'name': Character._meta.fields_map['name'].internal_field(schema)}
def test_interface_resolve_type():
@ -53,5 +57,6 @@ def test_object_type():
assert Human._meta.type_name == 'core.Human'
assert isinstance(object_type, GraphQLObjectType)
assert object_type.description == 'Human description'
assert object_type.get_fields() == {'name': Character._meta.fields_map['name'].internal_field(schema), 'friends': Human._meta.fields_map['friends'].internal_field(schema)}
assert object_type.get_fields() == {'name': Character._meta.fields_map['name'].internal_field(
schema), 'friends': Human._meta.fields_map['friends'].internal_field(schema)}
assert object_type.get_interfaces() == [Character.internal_type(schema)]

View File

@ -6,7 +6,7 @@ INSTALLED_APPS = [
'tests.contrib_django',
]
DATABASES={
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'tests/django.sqlite',

View File

@ -5,6 +5,7 @@ from graphene import relay
schema = graphene.Schema()
class OtherNode(relay.Node):
name = graphene.StringField()

View File

@ -5,40 +5,40 @@ Human = namedtuple('Human', 'id name friends appearsIn homePlanet')
luke = Human(
id='1000',
name='Luke Skywalker',
friends=[ '1002', '1003', '2000', '2001' ],
appearsIn=[ 4, 5, 6 ],
friends=['1002', '1003', '2000', '2001'],
appearsIn=[4, 5, 6],
homePlanet='Tatooine',
)
vader = Human(
id='1001',
name='Darth Vader',
friends=[ '1004' ],
appearsIn=[ 4, 5, 6 ],
friends=['1004'],
appearsIn=[4, 5, 6],
homePlanet='Tatooine',
)
han = Human(
id='1002',
name='Han Solo',
friends=[ '1000', '1003', '2001' ],
appearsIn=[ 4, 5, 6 ],
friends=['1000', '1003', '2001'],
appearsIn=[4, 5, 6],
homePlanet=None,
)
leia = Human(
id='1003',
name='Leia Organa',
friends=[ '1000', '1002', '2000', '2001' ],
appearsIn=[ 4, 5, 6 ],
friends=['1000', '1002', '2000', '2001'],
appearsIn=[4, 5, 6],
homePlanet='Alderaan',
)
tarkin = Human(
id='1004',
name='Wilhuff Tarkin',
friends=[ '1001' ],
appearsIn=[ 4 ],
friends=['1001'],
appearsIn=[4],
homePlanet=None,
)
@ -55,16 +55,16 @@ Droid = namedtuple('Droid', 'id name friends appearsIn primaryFunction')
threepio = Droid(
id='2000',
name='C-3PO',
friends=[ '1000', '1002', '1003', '2001' ],
appearsIn=[ 4, 5, 6 ],
friends=['1000', '1002', '1003', '2001'],
appearsIn=[4, 5, 6],
primaryFunction='Protocol',
)
artoo = Droid(
id='2001',
name='R2-D2',
friends=[ '1000', '1002', '1003' ],
appearsIn=[ 4, 5, 6 ],
friends=['1000', '1002', '1003'],
appearsIn=[4, 5, 6],
primaryFunction='Astromech',
)
@ -73,6 +73,7 @@ droidData = {
'2001': artoo,
}
def getCharacter(id):
return humanData.get(id) or droidData.get(id)

View File

@ -4,14 +4,14 @@ from graphene import resolve_only_args
from .data import getHero, getHuman, getCharacter, getDroid, Human as _Human, Droid as _Droid
Episode = graphene.Enum('Episode', dict(
NEWHOPE = 4,
EMPIRE = 5,
JEDI = 6
NEWHOPE=4,
EMPIRE=5,
JEDI=6
))
def wrap_character(character):
if isinstance(character, _Human):
if isinstance(character, _Human):
return Human(character)
elif isinstance(character, _Droid):
return Droid(character)
@ -37,14 +37,14 @@ class Droid(Character):
class Query(graphene.ObjectType):
hero = graphene.Field(Character,
episode = graphene.Argument(Episode)
)
episode=graphene.Argument(Episode)
)
human = graphene.Field(Human,
id = graphene.Argument(graphene.String)
)
id=graphene.Argument(graphene.String)
)
droid = graphene.Field(Droid,
id = graphene.Argument(graphene.String)
)
id=graphene.Argument(graphene.String)
)
class Meta:
type_name = 'core.Query'

View File

@ -69,7 +69,7 @@ def test_nested_query():
'friends': [
{
'name': 'Luke Skywalker',
'appearsIn': [ 'NEWHOPE', 'EMPIRE', 'JEDI' ],
'appearsIn': ['NEWHOPE', 'EMPIRE', 'JEDI'],
'friends': [
{
'name': 'Han Solo',
@ -87,7 +87,7 @@ def test_nested_query():
},
{
'name': 'Han Solo',
'appearsIn': [ 'NEWHOPE', 'EMPIRE', 'JEDI' ],
'appearsIn': ['NEWHOPE', 'EMPIRE', 'JEDI'],
'friends': [
{
'name': 'Luke Skywalker',
@ -102,7 +102,7 @@ def test_nested_query():
},
{
'name': 'Leia Organa',
'appearsIn': [ 'NEWHOPE', 'EMPIRE', 'JEDI' ],
'appearsIn': ['NEWHOPE', 'EMPIRE', 'JEDI'],
'friends': [
{
'name': 'Luke Skywalker',
@ -264,11 +264,11 @@ def test_duplicate_fields():
'luke': {
'name': 'Luke Skywalker',
'homePlanet': 'Tatooine',
},
},
'leia': {
'name': 'Leia Organa',
'homePlanet': 'Alderaan',
}
}
}
result = Schema.execute(query)
assert not result.errors
@ -294,11 +294,11 @@ def test_use_fragment():
'luke': {
'name': 'Luke Skywalker',
'homePlanet': 'Tatooine',
},
},
'leia': {
'name': 'Leia Organa',
'homePlanet': 'Alderaan',
}
}
}
result = Schema.execute(query)
assert not result.errors

View File

@ -2,6 +2,7 @@ from collections import namedtuple
from .models import Ship, Faction
def initialize():
rebels = Faction(
id='1',
@ -15,7 +16,6 @@ def initialize():
)
empire.save()
xwing = Ship(
id='1',
name='X-Wing',
@ -88,14 +88,18 @@ def createShip(shipName, factionId):
def getShip(_id):
return Ship.objects.get(id=_id)
def getShips():
return Ship.objects.all()
def getFaction(_id):
return Faction.objects.get(id=_id)
def getRebels():
return getFaction(1)
def getEmpire():
return getFaction(2)

View File

@ -15,17 +15,21 @@ from .data import (
schema = graphene.Schema(name='Starwars Django Relay Schema')
class Ship(DjangoNode):
class Meta:
model = ShipModel
model = ShipModel
@classmethod
def get_node(cls, id):
return Ship(getShip(id))
class Faction(DjangoNode):
class Meta:
model = FactionModel
model = FactionModel
@classmethod
def get_node(cls, id):

View File

@ -7,6 +7,7 @@ from .data import initialize
pytestmark = pytest.mark.django_db
def test_correct_fetch_first_ship_rebels():
initialize()
query = '''
@ -24,18 +25,18 @@ def test_correct_fetch_first_ship_rebels():
}
'''
expected = {
'rebels': {
'name': 'Alliance to Restore the Republic',
'ships': {
'edges': [
{
'node': {
'name': 'X-Wing'
}
'rebels': {
'name': 'Alliance to Restore the Republic',
'ships': {
'edges': [
{
'node': {
'name': 'X-Wing'
}
}
]
}
]
}
}
}
result = schema.execute(query)
assert not result.errors

View File

@ -7,6 +7,7 @@ from .schema import schema
pytestmark = pytest.mark.django_db
def test_correctly_fetches_id_name_rebels():
initialize()
query = '''
@ -18,15 +19,16 @@ def test_correctly_fetches_id_name_rebels():
}
'''
expected = {
'rebels': {
'id': 'RmFjdGlvbjox',
'name': 'Alliance to Restore the Republic'
}
'rebels': {
'id': 'RmFjdGlvbjox',
'name': 'Alliance to Restore the Republic'
}
}
result = schema.execute(query)
assert not result.errors
assert result.data == expected
def test_correctly_refetches_rebels():
initialize()
query = '''
@ -40,15 +42,16 @@ def test_correctly_refetches_rebels():
}
'''
expected = {
'node': {
'id': 'RmFjdGlvbjox',
'name': 'Alliance to Restore the Republic'
}
'node': {
'id': 'RmFjdGlvbjox',
'name': 'Alliance to Restore the Republic'
}
}
result = schema.execute(query)
assert not result.errors
assert result.data == expected
def test_correctly_fetches_id_name_empire():
initialize()
query = '''
@ -60,15 +63,16 @@ def test_correctly_fetches_id_name_empire():
}
'''
expected = {
'empire': {
'id': 'RmFjdGlvbjoy',
'name': 'Galactic Empire'
}
'empire': {
'id': 'RmFjdGlvbjoy',
'name': 'Galactic Empire'
}
}
result = schema.execute(query)
assert not result.errors
assert result.data == expected
def test_correctly_refetches_empire():
initialize()
query = '''
@ -82,15 +86,16 @@ def test_correctly_refetches_empire():
}
'''
expected = {
'node': {
'id': 'RmFjdGlvbjoy',
'name': 'Galactic Empire'
}
'node': {
'id': 'RmFjdGlvbjoy',
'name': 'Galactic Empire'
}
}
result = schema.execute(query)
assert not result.errors
assert result.data == expected
def test_correctly_refetches_xwing():
initialize()
query = '''
@ -104,10 +109,10 @@ def test_correctly_refetches_xwing():
}
'''
expected = {
'node': {
'id': 'U2hpcDox',
'name': 'X-Wing'
}
'node': {
'id': 'U2hpcDox',
'name': 'X-Wing'
}
}
result = schema.execute(query)
assert not result.errors

View File

@ -1,7 +1,7 @@
from collections import namedtuple
Ship = namedtuple('Ship',['id', 'name'])
Faction = namedtuple('Faction',['id', 'name', 'ships'])
Ship = namedtuple('Ship', ['id', 'name'])
Faction = namedtuple('Faction', ['id', 'name', 'ships'])
xwing = Ship(
id='1',
@ -54,7 +54,7 @@ rebels = Faction(
empire = Faction(
id='2',
name='Galactic Empire',
ships= ['6', '7', '8']
ships=['6', '7', '8']
)
data = {
@ -74,6 +74,7 @@ data = {
}
}
def createShip(shipName, factionId):
nextShip = len(data['Ship'].keys())+1
newShip = Ship(
@ -88,11 +89,14 @@ def createShip(shipName, factionId):
def getShip(_id):
return data['Ship'][_id]
def getFaction(_id):
return data['Faction'][_id]
def getRebels():
return rebels
def getEmpire():
return empire

View File

@ -10,7 +10,9 @@ from .data import (
schema = graphene.Schema(name='Starwars Relay Schema')
class Ship(relay.Node):
'''A ship in the Star Wars saga'''
name = graphene.StringField(description='The name of the ship.')
@ -20,9 +22,11 @@ class Ship(relay.Node):
class Faction(relay.Node):
'''A faction in the Star Wars saga'''
name = graphene.StringField(description='The name of the faction.')
ships = relay.ConnectionField(Ship, description='The ships used by the faction.')
ships = relay.ConnectionField(
Ship, description='The ships used by the faction.')
@resolve_only_args
def resolve_ships(self, **kwargs):

View File

@ -11,6 +11,7 @@ Episode = graphene.Enum('Episode', dict(
JEDI=6
))
def wrap_character(character):
if isinstance(character, _Human):
return Human(character)

View File

@ -3,6 +3,7 @@ from graphql.core import graphql
from .schema import schema
def test_correct_fetch_first_ship_rebels():
query = '''
query RebelsShipsQuery {
@ -19,18 +20,18 @@ def test_correct_fetch_first_ship_rebels():
}
'''
expected = {
'rebels': {
'name': 'Alliance to Restore the Republic',
'ships': {
'edges': [
{
'node': {
'name': 'X-Wing'
}
'rebels': {
'name': 'Alliance to Restore the Republic',
'ships': {
'edges': [
{
'node': {
'name': 'X-Wing'
}
}
]
}
]
}
}
}
result = schema.execute(query)
assert not result.errors

View File

@ -3,6 +3,7 @@ from graphql.core import graphql
from .schema import schema
def test_correctly_fetches_id_name_rebels():
query = '''
query RebelsQuery {
@ -13,15 +14,16 @@ def test_correctly_fetches_id_name_rebels():
}
'''
expected = {
'rebels': {
'id': 'RmFjdGlvbjox',
'name': 'Alliance to Restore the Republic'
}
'rebels': {
'id': 'RmFjdGlvbjox',
'name': 'Alliance to Restore the Republic'
}
}
result = schema.execute(query)
assert not result.errors
assert result.data == expected
def test_correctly_refetches_rebels():
query = '''
query RebelsRefetchQuery {
@ -34,15 +36,16 @@ def test_correctly_refetches_rebels():
}
'''
expected = {
'node': {
'id': 'RmFjdGlvbjox',
'name': 'Alliance to Restore the Republic'
}
'node': {
'id': 'RmFjdGlvbjox',
'name': 'Alliance to Restore the Republic'
}
}
result = schema.execute(query)
assert not result.errors
assert result.data == expected
def test_correctly_fetches_id_name_empire():
query = '''
query EmpireQuery {
@ -53,15 +56,16 @@ def test_correctly_fetches_id_name_empire():
}
'''
expected = {
'empire': {
'id': 'RmFjdGlvbjoy',
'name': 'Galactic Empire'
}
'empire': {
'id': 'RmFjdGlvbjoy',
'name': 'Galactic Empire'
}
}
result = schema.execute(query)
assert not result.errors
assert result.data == expected
def test_correctly_refetches_empire():
query = '''
query EmpireRefetchQuery {
@ -74,15 +78,16 @@ def test_correctly_refetches_empire():
}
'''
expected = {
'node': {
'id': 'RmFjdGlvbjoy',
'name': 'Galactic Empire'
}
'node': {
'id': 'RmFjdGlvbjoy',
'name': 'Galactic Empire'
}
}
result = schema.execute(query)
assert not result.errors
assert result.data == expected
def test_correctly_refetches_xwing():
query = '''
query XWingRefetchQuery {
@ -95,10 +100,10 @@ def test_correctly_refetches_xwing():
}
'''
expected = {
'node': {
'id': 'U2hpcDox',
'name': 'X-Wing'
}
'node': {
'id': 'U2hpcDox',
'name': 'X-Wing'
}
}
result = schema.execute(query)
assert not result.errors