Improved fields inheritance in ObjectTypes

This commit is contained in:
Syrus Akbary 2015-10-12 20:36:46 -07:00
parent 2410841753
commit 32e4a21403
4 changed files with 33 additions and 8 deletions

View File

@ -17,6 +17,10 @@ from graphene.core.types import BaseObjectType
from graphene.core.scalars import GraphQLSkipField from graphene.core.scalars import GraphQLSkipField
class Empty(object):
pass
@total_ordering @total_ordering
class Field(object): class Field(object):
SKIP = GraphQLSkipField SKIP = GraphQLSkipField
@ -142,6 +146,14 @@ class Field(object):
def __hash__(self): def __hash__(self):
return hash(self.creation_counter) return hash(self.creation_counter)
def __copy__(self):
# We need to avoid hitting __reduce__, so define this
# slightly weird copy construct.
obj = Empty()
obj.__class__ = self.__class__
obj.__dict__ = self.__dict__.copy()
return obj
class NativeField(Field): class NativeField(Field):

View File

@ -64,10 +64,7 @@ class Options(object):
@cached_property @cached_property
def fields(self): def fields(self):
fields = [] return sorted(self.local_fields)
for parent in self.parents:
fields.extend(parent._meta.fields)
return sorted(self.local_fields + fields)
@cached_property @cached_property
def fields_map(self): def fields_map(self):

View File

@ -1,5 +1,6 @@
import inspect import inspect
import six import six
import copy
from collections import OrderedDict from collections import OrderedDict
from graphql.core.type import ( from graphql.core.type import (
@ -72,13 +73,20 @@ class ObjectTypeMeta(type):
# on the base classes (we cannot handle shadowed fields at the # on the base classes (we cannot handle shadowed fields at the
# moment). # moment).
for field in parent_fields: for field in parent_fields:
if field.name in field_names and field.__class__ != field_names[field].__class__: if field.name in field_names and field.__class__ != field_names[field.name].__class__:
raise Exception( raise Exception(
'Local field %r in class %r clashes ' 'Local field %r in class %r clashes '
'with field of similar name from ' 'with field with similar name from '
'base class %r' % ( 'Interface %s (%r != %r)' % (
field.name, name, base.__name__) field.name,
new_class.__name__,
base.__name__,
field.__class__,
field_names[field.name].__class__)
) )
new_field = copy.copy(field)
new_class.add_to_class(field.field_name, new_field)
new_class._meta.parents.append(base) new_class._meta.parents.append(base)
if base._meta.interface: if base._meta.interface:
new_class._meta.interfaces.append(base) new_class._meta.interfaces.append(base)

View File

@ -3,6 +3,7 @@ from collections import namedtuple
from pytest import raises from pytest import raises
from graphene.core.fields import ( from graphene.core.fields import (
Field, Field,
IntField,
StringField, StringField,
) )
from graphql.core.type import ( from graphql.core.type import (
@ -60,3 +61,10 @@ def test_object_type():
assert object_type.get_fields() == {'name': Character._meta.fields_map['name'].internal_field( assert object_type.get_fields() == {'name': Character._meta.fields_map['name'].internal_field(
schema), 'friends': Human._meta.fields_map['friends'].internal_field(schema)} schema), 'friends': Human._meta.fields_map['friends'].internal_field(schema)}
assert object_type.get_interfaces() == [Character.internal_type(schema)] assert object_type.get_interfaces() == [Character.internal_type(schema)]
def test_field_clashes():
with raises(Exception) as excinfo:
class Droid(Character):
name = IntField()
assert 'clashes' in str(excinfo.value)