diff --git a/graphene/core/options.py b/graphene/core/options.py index 533fe310..2d93843d 100644 --- a/graphene/core/options.py +++ b/graphene/core/options.py @@ -55,15 +55,8 @@ class Options(object): else: self.proxy = False - if self.interfaces != [] and self.interface: - raise Exception("A interface cannot inherit from interfaces") - del self.meta - @cached_property - def object(self): - return namedtuple(self.type_name, self.fields_map.keys()) - def add_field(self, field): self.local_fields.append(field) diff --git a/graphene/core/types.py b/graphene/core/types.py index e9bf78ec..aeee813a 100644 --- a/graphene/core/types.py +++ b/graphene/core/types.py @@ -132,8 +132,6 @@ class BaseObjectType(object): def __new__(cls, *args, **kwargs): if cls._meta.is_interface: raise Exception("An interface cannot be initialized") - if not args and not kwargs: - return None return super(BaseObjectType, cls).__new__(cls) def __init__(self, *args, **kwargs): diff --git a/graphene/utils/proxy_snake_dict.py b/graphene/utils/proxy_snake_dict.py index 1a5a0bce..9defd30f 100644 --- a/graphene/utils/proxy_snake_dict.py +++ b/graphene/utils/proxy_snake_dict.py @@ -24,10 +24,10 @@ class ProxySnakeDict(collections.MutableMapping): def __len__(self): return len(self.data) - def __delitem__(self): + def __delitem__(self, item): raise TypeError('ProxySnakeDict does not support item deletion') - def __setitem__(self): + def __setitem__(self, item, value): raise TypeError('ProxySnakeDict does not support item assignment') def __getitem__(self, key): @@ -59,5 +59,12 @@ class ProxySnakeDict(collections.MutableMapping): for k in self.iterkeys(): yield k, self[k] + def to_data_dict(self): + return self.data.__class__(self.iteritems()) + + def __eq__(self, other): + return self.to_data_dict() == other.to_data_dict() + def __repr__(self): - return dict(self.iteritems()).__repr__() + data_repr = self.to_data_dict().__repr__() + return ''.format(data_repr) diff --git a/tests/core/test_types.py b/tests/core/test_types.py index a8370b72..c5d09f15 100644 --- a/tests/core/test_types.py +++ b/tests/core/test_types.py @@ -34,6 +34,18 @@ class Human(Character): class Meta: type_name = 'core_Human' + @property + def readonly_prop(self): + return 'readonly' + + @property + def write_prop(self): + return self._write_prop + + @write_prop.setter + def write_prop(self, value): + self._write_prop = value + schema = Schema() @@ -44,8 +56,12 @@ def test_interface(): assert Character._meta.type_name == 'core_Character' assert object_type.description == 'Character description' assert list(object_type.get_fields().keys()) == ['name'] - # assert object_type.get_fields() == { - # 'name': Character._meta.fields_map['name'].internal_field(schema)} + + +def test_interface_cannot_initialize(): + with raises(Exception) as excinfo: + c = Character() + assert 'An interface cannot be initialized' == str(excinfo.value) def test_interface_resolve_type(): @@ -66,6 +82,27 @@ def test_object_type(): assert Human._meta.fields_map['name'].object_type == Human +def test_object_type_container(): + h = Human(name='My name') + assert h.name == 'My name' + + +def test_object_type_set_properties(): + h = Human(readonly_prop='custom', write_prop='custom') + assert h.readonly_prop == 'readonly' + assert h.write_prop == 'custom' + + +def test_object_type_container_invalid_kwarg(): + with raises(TypeError): + Human(invalid='My name') + + +def test_object_type_container_too_many_args(): + with raises(IndexError): + Human('Peter', 'No friends :(', None) + + def test_field_clashes(): with raises(Exception) as excinfo: class Droid(Character): diff --git a/tests/utils/test_misc.py b/tests/utils/test_misc.py new file mode 100644 index 00000000..a2811a11 --- /dev/null +++ b/tests/utils/test_misc.py @@ -0,0 +1,13 @@ +import collections +from graphql.core.type import GraphQLEnumType +from graphene.utils.misc import enum_to_graphql_enum + +item = collections.namedtuple('type', 'name value') + + +class MyCustomEnum(list): + __name__ = 'MyName' + + +def test_enum_to_graphql_enum(): + assert isinstance(enum_to_graphql_enum(MyCustomEnum([item('k', 'v')])), GraphQLEnumType) diff --git a/tests/utils/test_proxy_snake_dict.py b/tests/utils/test_proxy_snake_dict.py index 19d08421..0861c055 100644 --- a/tests/utils/test_proxy_snake_dict.py +++ b/tests/utils/test_proxy_snake_dict.py @@ -1,3 +1,4 @@ +from py.test import raises from graphene.utils import ProxySnakeDict @@ -8,6 +9,7 @@ def test_proxy_snake_dict(): assert 'two' in p assert 'threeOrFor' in p assert 'none' in p + assert len(p) == len(my_data) assert p['none'] is None assert p.get('none') is None assert p.get('none_existent') is None @@ -15,6 +17,11 @@ def test_proxy_snake_dict(): assert p.get('three_or_for') == 3 assert 'inside' in p assert 'other_camel_case' in p['inside'] + assert sorted(p.items()) == sorted(list([('inside', ProxySnakeDict({'other_camel_case': 3})), + ('none', None), + ('three_or_for', 3), + ('two', 2), + ('one', 1)])) def test_proxy_snake_dict_as_kwargs(): @@ -24,3 +31,22 @@ def test_proxy_snake_dict_as_kwargs(): def func(**kwargs): return kwargs.get('my_data') assert func(**p) == 1 + + +def test_proxy_snake_dict_repr(): + my_data = {'myData': 1} + p = ProxySnakeDict(my_data) + + assert repr(p) == "" + + +def test_proxy_snake_dict_set(): + p = ProxySnakeDict({}) + with raises(TypeError): + p['a'] = 2 + + +def test_proxy_snake_dict_delete(): + p = ProxySnakeDict({}) + with raises(TypeError): + del p['a']