Added abstract ObjectType definition. Fixed #55

This commit is contained in:
Syrus Akbary 2015-11-30 23:08:18 -08:00
parent c6170671c0
commit 9a198c8c86
3 changed files with 69 additions and 8 deletions

View File

@ -3,7 +3,7 @@ from collections import OrderedDict
from ..utils import cached_property from ..utils import cached_property
DEFAULT_NAMES = ('description', 'name', 'is_interface', 'is_mutation', DEFAULT_NAMES = ('description', 'name', 'is_interface', 'is_mutation',
'type_name', 'interfaces') 'type_name', 'interfaces', 'abstract')
class Options(object): class Options(object):
@ -14,6 +14,7 @@ class Options(object):
self.is_interface = False self.is_interface = False
self.is_mutation = False self.is_mutation = False
self.is_union = False self.is_union = False
self.abstract = False
self.interfaces = [] self.interfaces = []
self.parents = [] self.parents = []
self.types = [] self.types = []

View File

@ -16,6 +16,13 @@ from .base import BaseType
from .definitions import List, NonNull from .definitions import List, NonNull
def is_objecttype(cls):
if not issubclass(cls, BaseObjectType):
return False
_meta = getattr(cls, '_meta', None)
return not(_meta and (_meta.abstract or _meta.is_interface))
class ObjectTypeMeta(type): class ObjectTypeMeta(type):
options_cls = Options options_cls = Options
@ -39,19 +46,19 @@ class ObjectTypeMeta(type):
'__doc__': doc '__doc__': doc
}) })
attr_meta = attrs.pop('Meta', None) attr_meta = attrs.pop('Meta', None)
abstract = getattr(attr_meta, 'abstract', False)
if not attr_meta: if not attr_meta:
meta = None meta = getattr(new_class, 'Meta', None)
# meta = getattr(new_class, 'Meta', None)
else: else:
meta = attr_meta meta = attr_meta
getattr(new_class, '_meta', None) base_meta = getattr(new_class, '_meta', None)
new_class.add_to_class('_meta', new_class.options_cls(meta)) new_class.add_to_class('_meta', new_class.options_cls(meta))
new_class._meta.is_interface = new_class.is_interface(parents) new_class._meta.is_interface = new_class.is_interface(parents)
new_class._meta.is_mutation = new_class.is_mutation(parents) new_class._meta.is_mutation = new_class.is_mutation(parents) or (base_meta and base_meta.is_mutation)
union_types = [p for p in parents if issubclass(p, BaseObjectType)] union_types = list(filter(is_objecttype, parents))
new_class._meta.is_union = len(union_types) > 1 new_class._meta.is_union = len(union_types) > 1
new_class._meta.types = union_types new_class._meta.types = union_types
@ -66,6 +73,10 @@ class ObjectTypeMeta(type):
for obj_name, obj in attrs.items(): for obj_name, obj in attrs.items():
new_class.add_to_class(obj_name, obj) new_class.add_to_class(obj_name, obj)
if abstract:
new_class._prepare()
return new_class
if new_class._meta.is_mutation: if new_class._meta.is_mutation:
assert hasattr( assert hasattr(
new_class, 'mutate'), "All mutations must implement mutate method" new_class, 'mutate'), "All mutations must implement mutate method"
@ -138,8 +149,10 @@ class BaseObjectType(BaseType):
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
if cls._meta.is_interface: if cls._meta.is_interface:
raise Exception("An interface cannot be initialized") raise Exception("An interface cannot be initialized")
if cls._meta.is_union: elif cls._meta.is_union:
raise Exception("An union cannot be initialized") raise Exception("An union cannot be initialized")
elif cls._meta.abstract:
raise Exception("An abstract ObjectType cannot be initialized")
return super(BaseObjectType, cls).__new__(cls) return super(BaseObjectType, cls).__new__(cls)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -187,6 +200,9 @@ class BaseObjectType(BaseType):
@classmethod @classmethod
def internal_type(cls, schema): def internal_type(cls, schema):
if cls._meta.abstract:
raise Exception("Abstract ObjectTypes don't have a specific type.")
if cls._meta.is_interface: if cls._meta.is_interface:
return GraphQLInterfaceType( return GraphQLInterfaceType(
cls._meta.type_name, cls._meta.type_name,

View File

@ -5,7 +5,7 @@ from graphql.core.type import (GraphQLInterfaceType, GraphQLObjectType,
from py.test import raises from py.test import raises
from graphene.core.schema import Schema from graphene.core.schema import Schema
from graphene.core.types import Int, Interface, String from graphene.core.types import Int, Interface, ObjectType, String
class Character(Interface): class Character(Interface):
@ -148,3 +148,47 @@ def test_type_has_list():
name = String() name = String()
assert Droid.List.of_type == Droid assert Droid.List.of_type == Droid
def test_abstracttype():
class MyObject1(ObjectType):
class Meta:
abstract = True
name1 = String()
class MyObject2(ObjectType):
class Meta:
abstract = True
name2 = String()
class MyObject(MyObject1, MyObject2):
pass
object_type = schema.T(MyObject)
assert MyObject._meta.fields_map.keys() == ['name1', 'name2']
assert MyObject._meta.fields_map['name1'].object_type == MyObject
assert MyObject._meta.fields_map['name2'].object_type == MyObject
assert isinstance(object_type, GraphQLObjectType)
def test_abstracttype_initialize():
class MyAbstractObjectType(ObjectType):
class Meta:
abstract = True
with raises(Exception) as excinfo:
MyAbstractObjectType()
assert 'An abstract ObjectType cannot be initialized' == str(excinfo.value)
def test_abstracttype_type():
class MyAbstractObjectType(ObjectType):
class Meta:
abstract = True
with raises(Exception) as excinfo:
schema.T(MyAbstractObjectType)
assert 'Abstract ObjectTypes don\'t have a specific type.' == str(excinfo.value)