Skip to content

Commit a7511d3

Browse files
committed
Added possible_types option to ObjectType.Meta
1 parent e3663d4 commit a7511d3

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

graphene/types/objecttype.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def __new__(cls, name, bases, attrs):
2424
name=name,
2525
description=trim_docstring(attrs.get('__doc__')),
2626
interfaces=(),
27+
possible_types=(),
2728
default_resolver=None,
2829
local_fields=OrderedDict(),
2930
)
@@ -55,6 +56,11 @@ def __new__(cls, name, bases, attrs):
5556

5657
cls = type.__new__(cls, name, bases, dict(attrs, _meta=options))
5758

59+
assert not (options.possible_types and cls.is_type_of), (
60+
'{}.Meta.possible_types will cause type collision with {}.is_type_of. '
61+
'Please use one or other.'
62+
).format(name, name)
63+
5864
for interface in options.interfaces:
5965
interface.implements(cls)
6066

graphene/types/tests/test_objecttype.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,27 @@ class MyObjectType(ObjectType):
184184
'''
185185

186186
assert MyObjectType._meta.description == "Documentation\n\nDocumentation line 2"
187+
188+
189+
def test_objecttype_with_possible_types():
190+
class MyObjectType(ObjectType):
191+
class Meta:
192+
possible_types = (dict, )
193+
194+
assert MyObjectType._meta.possible_types == (dict, )
195+
196+
197+
def test_objecttype_with_possible_types_and_is_type_of_should_raise():
198+
with pytest.raises(AssertionError) as excinfo:
199+
class MyObjectType(ObjectType):
200+
class Meta:
201+
possible_types = (dict, )
202+
203+
@classmethod
204+
def is_type_of(cls, root, context, info):
205+
return False
206+
207+
assert str(excinfo.value) == (
208+
'MyObjectType.Meta.possible_types will cause type collision with '
209+
'MyObjectType.is_type_of. Please use one or other.'
210+
)

graphene/types/tests/test_typemap.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,18 @@ class MyObjectType(ObjectType):
183183
assert foo_field.args == {
184184
'bar_foo': GraphQLArgument(GraphQLString, out_name='bar_foo')
185185
}
186+
187+
188+
def test_objecttype_with_possible_types():
189+
class MyObjectType(ObjectType):
190+
'''Description'''
191+
class Meta:
192+
possible_types = (dict, )
193+
194+
foo_bar = String()
195+
196+
typemap = TypeMap([MyObjectType])
197+
graphql_type = typemap['MyObjectType']
198+
assert graphql_type.is_type_of
199+
assert graphql_type.is_type_of({}, None, None) is True
200+
assert graphql_type.is_type_of(MyObjectType(), None, None) is False

graphene/types/typemap.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ def resolve_type(resolve_type_func, map, type_name, root, context, info):
5252
return _type
5353

5454

55+
def is_type_of_from_possible_types(possible_types, root, context, info):
56+
return isinstance(root, possible_types)
57+
58+
5559
class TypeMap(GraphQLTypeMap):
5660

5761
def __init__(self, types, auto_camelcase=True, schema=None):
@@ -153,12 +157,17 @@ def interfaces():
153157
interfaces.append(internal_type)
154158
return interfaces
155159

160+
if type._meta.possible_types:
161+
is_type_of = partial(is_type_of_from_possible_types, type._meta.possible_types)
162+
else:
163+
is_type_of = type.is_type_of
164+
156165
return GrapheneObjectType(
157166
graphene_type=type,
158167
name=type._meta.name,
159168
description=type._meta.description,
160169
fields=partial(self.construct_fields_for_type, map, type),
161-
is_type_of=type.is_type_of,
170+
is_type_of=is_type_of,
162171
interfaces=interfaces
163172
)
164173

0 commit comments

Comments
 (0)