WIP: Also inherit interfaces from abstract type.

This commit is contained in:
Markus Padourek 2016-08-16 19:10:46 +01:00
parent 018811036b
commit 5f573c87e4
4 changed files with 91 additions and 7 deletions

View File

@ -1,3 +1,4 @@
from collections import OrderedDict
import six import six
from ..utils.is_base_type import is_base_type from ..utils.is_base_type import is_base_type
@ -9,26 +10,59 @@ from .utils import (get_fields_in_type, get_base_fields,
class AbstractTypeMeta(type): class AbstractTypeMeta(type):
def __new__(cls, name, bases, attrs): def __new__(cls, name, bases, attrs):
from .interface import Interface
# Also ensure initialization is only performed for subclasses of # Also ensure initialization is only performed for subclasses of
# AbstractType # AbstractType
if not is_base_type(bases, AbstractTypeMeta): if not is_base_type(bases, AbstractTypeMeta):
return type.__new__(cls, name, bases, attrs) return type.__new__(cls, name, bases, attrs)
print('-----> in AbstractTypeMeta')
print(attrs.get('_meta'))
print(attrs.get('Meta'))
print(dir(attrs.get('Meta')))
for base in bases: for base in bases:
if not issubclass(base, AbstractType) and issubclass(type(base), AbstractTypeMeta): if not issubclass(base, AbstractType) and issubclass(type(base), AbstractTypeMeta):
# raise Exception('You can only extend AbstractTypes after the base definition.') # raise Exception('You can only extend AbstractTypes after the base definition.')
return type.__new__(cls, name, bases, attrs) return type.__new__(cls, name, bases, attrs)
base_fields = get_base_fields(AbstractType, bases) _meta = attrs.pop('_meta', None)
options = _meta or Options(
fields = get_fields_in_type(AbstractType, attrs) attrs.pop('Meta', None),
yank_fields_from_attrs(attrs, fields) interfaces=(),
fields=()
options = Options(
fields=merge(base_fields, fields)
) )
print('options:')
print(options)
options.base_fields = get_base_fields(AbstractType, bases)
options.local_fields = get_fields_in_type(AbstractType, attrs)
yank_fields_from_attrs(attrs, options.local_fields)
options.interface_fields = OrderedDict()
for interface in options.interfaces:
assert issubclass(interface, Interface), (
'All interfaces of {} must be a subclass of Interface. Received "{}".'
).format(name, interface)
options.interface_fields.update(interface._meta.fields)
options.fields = merge(
options.interface_fields,
options.base_fields,
options.local_fields
)
# options = Options(
# fields=merge(base_fields, fields),
# interfaces=(),
# )
cls = type.__new__(cls, name, bases, dict(attrs, _meta=options)) cls = type.__new__(cls, name, bases, dict(attrs, _meta=options))
for interface in options.interfaces:
interface.implements(cls)
return cls return cls

View File

@ -19,6 +19,10 @@ class ObjectTypeMeta(AbstractTypeMeta):
return type.__new__(cls, name, bases, attrs) return type.__new__(cls, name, bases, attrs)
_meta = attrs.pop('_meta', None) _meta = attrs.pop('_meta', None)
base_interfaces = ()
for base in bases:
if hasattr(base, '_meta') and hasattr(base._meta, 'interfaces'):
base_interfaces = base_interfaces + base._meta.interfaces
options = _meta or Options( options = _meta or Options(
attrs.pop('Meta', None), attrs.pop('Meta', None),
name=name, name=name,
@ -26,13 +30,27 @@ class ObjectTypeMeta(AbstractTypeMeta):
interfaces=(), interfaces=(),
local_fields=OrderedDict(), local_fields=OrderedDict(),
) )
options.interfaces = options.interfaces + base_interfaces
print('OPTIONS', options)
options.base_fields = get_base_fields(ObjectType, bases) options.base_fields = get_base_fields(ObjectType, bases)
print('-----> base fields: ', options.base_fields)
# from ..types import AbstractType
# inherited_bases = (AbstractType, Interface)
# for base in bases:
# if base in inherited_bases or not issubclass(base, inherited_bases):
# continue
# print(base)
# print(base())
# print(dir(base()))
# print(dir(base()._meta))
if not options.local_fields: if not options.local_fields:
options.local_fields = get_fields_in_type(ObjectType, attrs) options.local_fields = get_fields_in_type(ObjectType, attrs)
yank_fields_from_attrs(attrs, options.local_fields) yank_fields_from_attrs(attrs, options.local_fields)
options.interface_fields = OrderedDict() options.interface_fields = OrderedDict()
print('interfaces')
print(options.interfaces)
for interface in options.interfaces: for interface in options.interfaces:
assert issubclass(interface, Interface), ( assert issubclass(interface, Interface), (
'All interfaces of {} must be a subclass of Interface. Received "{}".' 'All interfaces of {} must be a subclass of Interface. Received "{}".'

View File

@ -2,6 +2,7 @@ import pytest
from ..abstracttype import AbstractType from ..abstracttype import AbstractType
from ..field import Field from ..field import Field
from ..scalars import String
from ..interface import Interface from ..interface import Interface
from ..objecttype import ObjectType from ..objecttype import ObjectType
from ..unmountedtype import UnmountedType from ..unmountedtype import UnmountedType
@ -57,6 +58,19 @@ def test_generate_objecttype_with_meta():
assert MyObjectType._meta.interfaces == (MyType, ) assert MyObjectType._meta.interfaces == (MyType, )
def test_generate_objecttype_with_interface():
class MyObjectType(ObjectType):
class Meta:
interfaces = (MyInterface, )
great_field = String()
assert MyObjectType._meta.interfaces == (MyInterface, )
assert list(MyObjectType._meta.fields.keys()) == ['ifield', 'great_field']
assert list(map(type, MyObjectType._meta.fields.values())) == [Field, Field]
def test_generate_objecttype_with_fields(): def test_generate_objecttype_with_fields():
class MyObjectType(ObjectType): class MyObjectType(ObjectType):
field = Field(MyType) field = Field(MyType)
@ -96,6 +110,20 @@ def test_generate_objecttype_inherit_abstracttype_reversed():
assert list(map(type, MyObjectType._meta.fields.values())) == [Field, Field] assert list(map(type, MyObjectType._meta.fields.values())) == [Field, Field]
def test_generate_objecttype_inherit_abstracttype_with_interface():
class MyAbstractType(AbstractType):
class Meta:
interfaces = (MyInterface, )
field1 = MyScalar()
class MyObjectType(ObjectType, MyAbstractType):
field2 = MyScalar()
assert MyObjectType._meta.interfaces == (MyInterface, )
assert list(MyObjectType._meta.fields.keys()) == ['ifield', 'field1', 'field2']
assert list(map(type, MyObjectType._meta.fields.values())) == [Field, Field, Field]
def test_generate_objecttype_unmountedtype(): def test_generate_objecttype_unmountedtype():
class MyObjectType(ObjectType): class MyObjectType(ObjectType):
field = MyScalar() field = MyScalar()

View File

@ -12,6 +12,10 @@ def merge_fields_in_attrs(bases, attrs):
for base in bases: for base in bases:
if base in inherited_bases or not issubclass(base, inherited_bases): if base in inherited_bases or not issubclass(base, inherited_bases):
continue continue
print('!!!!!!!!!!!')
print(base._meta)
print(dir(base._meta))
print(base._meta.fields.items())
for name, field in base._meta.fields.items(): for name, field in base._meta.fields.items():
if name in attrs: if name in attrs:
continue continue