First relay version

This commit is contained in:
Syrus Akbary 2015-09-25 16:35:17 -07:00
parent f2bc5eddd5
commit 9a84d595a1
12 changed files with 134 additions and 22 deletions

View File

@ -3,7 +3,7 @@ sudo: false
python:
- 2.7
install:
- pip install pytest pytest-cov coveralls flake8 six
- pip install pytest pytest-cov coveralls flake8 six blinker
- pip install git+https://github.com/dittos/graphqllib.git # Last version of graphqllib
- pip install graphql-relay
- python setup.py develop

View File

@ -26,3 +26,7 @@ from graphene.core.types import (
from graphene.decorators import (
resolve_only_args
)
from graphene.relay import (
Relay
)

View File

@ -1,4 +1,3 @@
import inspect
from graphql.core.type import (
GraphQLField,
GraphQLList,
@ -9,8 +8,8 @@ from graphql.core.type import (
GraphQLID,
GraphQLArgument,
)
from graphene.core.types import ObjectType, Interface
from graphene.utils import cached_property
from graphene.core.utils import get_object_type
class Field(object):
def __init__(self, field_type, resolve=None, null=True, args=None, description='', **extra_args):
@ -45,16 +44,11 @@ class Field(object):
@cached_property
def type(self):
field_type = self.field_type
_is_class = inspect.isclass(field_type)
if _is_class and issubclass(field_type, ObjectType):
field_type = field_type._meta.type
elif isinstance(field_type, Field):
field_type = field_type.type
elif field_type == 'self':
field_type = self.object_type._meta.type
if isinstance(self.field_type, Field):
field_type = self.field_type.type
else:
field_type = get_object_type(self.field_type, self.object_type)
field_type = self.type_wrapper(field_type)
return field_type
def type_wrapper(self, field_type):

View File

@ -1,6 +1,8 @@
from graphene.utils import cached_property
DEFAULT_NAMES = ('description', 'name', 'interface', 'type_name', 'interfaces', 'proxy')
DEFAULT_NAMES = ('description', 'name', 'interface',
'type_name', 'interfaces', 'proxy')
class Options(object):
def __init__(self, meta=None):

View File

@ -8,8 +8,10 @@ from graphql.core.type import (
)
from graphql.core import graphql
from graphene import signals
from graphene.core.options import Options
class ObjectTypeMeta(type):
def __new__(cls, name, bases, attrs):
super_new = super(ObjectTypeMeta, cls).__new__
@ -20,7 +22,10 @@ class ObjectTypeMeta(type):
module = attrs.pop('__module__')
doc = attrs.pop('__doc__', None)
new_class = super_new(cls, name, bases, {'__module__': module, '__doc__': doc})
new_class = super_new(cls, name, bases, {
'__module__': module,
'__doc__': doc
})
attr_meta = attrs.pop('Meta', None)
if not attr_meta:
meta = getattr(new_class, 'Meta', None)
@ -51,7 +56,7 @@ class ObjectTypeMeta(type):
# moment).
for field in parent_fields:
if field.field_name in field_names:
raise FieldError(
raise Exception(
'Local field %r in class %r clashes '
'with field of similar name from '
'base class %r' % (field.field_name, name, base.__name__)
@ -61,8 +66,12 @@ class ObjectTypeMeta(type):
new_class._meta.interfaces.append(base)
# new_class._meta.parents.extend(base._meta.parents)
new_class._prepare()
return new_class
def _prepare(cls):
signals.class_prepared.send(cls)
def add_to_class(cls, name, value):
# We should call the contribute_to_class method only if it's bound
if not inspect.isclass(value) and hasattr(value, 'contribute_to_class'):
@ -73,7 +82,9 @@ class ObjectTypeMeta(type):
class ObjectType(six.with_metaclass(ObjectTypeMeta)):
def __init__(self, instance=None):
signals.pre_init.send(self.__class__, instance=instance)
self.instance = instance
signals.post_init.send(self.__class__, instance=self)
def get_field(self, field):
return getattr(self.instance, field, None)

30
graphene/core/utils.py Normal file
View File

@ -0,0 +1,30 @@
import inspect
from graphene.core.types import ObjectType
from graphene import signals
registered_object_types = []
def get_object_type(field_type, object_type=None):
_is_class = inspect.isclass(field_type)
if _is_class and issubclass(field_type, ObjectType):
field_type = field_type._meta.type
elif isinstance(field_type, basestring):
if field_type == 'self':
field_type = object_type._meta.type
else:
object_type = get_registered_object_type(field_type)
field_type = object_type._meta.type
return field_type
def get_registered_object_type(name):
for object_type in registered_object_types:
if object_type._meta.type_name == name:
return object_type
return None
@signals.class_prepared.connect
def object_type_created(sender):
registered_object_types.append(sender)

View File

@ -0,0 +1,2 @@
class Relay(object):
pass

5
graphene/signals.py Normal file
View File

@ -0,0 +1,5 @@
from blinker import Signal
class_prepared = Signal()
pre_init = Signal()
post_init = Signal()

View File

@ -48,6 +48,7 @@ setup(
install_requires=[
'six',
'blinker',
'graphqllib',
'graphql-relay'
],

View File

@ -18,7 +18,7 @@ def wrap_character(character):
class Character(graphene.Interface):
id = graphene.IDField()
name = graphene.StringField()
friends = graphene.ListField('self')
friends = graphene.ListField('Character')
appearsIn = graphene.ListField(Episode)
def resolve_friends(self, args, *_):

View File

@ -0,0 +1,61 @@
import graphene
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
))
def wrap_character(character):
if isinstance(character, _Human):
return Human(character)
elif isinstance(character, _Droid):
return Droid(character)
class Character(graphene.Interface):
id = graphene.IDField()
name = graphene.StringField()
friends = graphene.ListField('self')
appearsIn = graphene.ListField(Episode)
def resolve_friends(self, args, *_):
return [wrap_character(getCharacter(f)) for f in self.instance.friends]
class Human(Character):
homePlanet = graphene.StringField()
class Droid(Character):
primaryFunction = graphene.StringField()
class Query(graphene.ObjectType):
hero = graphene.Field(Character,
episode = graphene.Argument(Episode)
)
human = graphene.Field(Human,
id = graphene.Argument(graphene.String)
)
droid = graphene.Field(Droid,
id = graphene.Argument(graphene.String)
)
@resolve_only_args
def resolve_hero(self, episode):
return wrap_character(getHero(episode))
@resolve_only_args
def resolve_human(self, id):
return wrap_character(getHuman(id))
if human:
return Human(human)
@resolve_only_args
def resolve_droid(self, id):
return wrap_character(getDroid(id))
Schema = graphene.Schema(query=Query)

View File

@ -6,6 +6,8 @@ deps=
pytest>=2.7.2
django>=1.8.0,<1.9
flake8
six
blinker
singledispatch
commands=
py.test