@@ -36,6 +36,11 @@ def __init__(self, query, mutation=None):
3636 self ._type_map = self ._build_type_map ()
3737 self ._directives = None
3838
39+ for type in self ._type_map .values ():
40+ if isinstance (type , GraphQLObjectType ):
41+ for interface in type .get_interfaces ():
42+ assert_object_implements_interface (type , interface )
43+
3944 def get_query_type (self ):
4045 return self ._query
4146
@@ -82,8 +87,8 @@ def type_map_reducer(map, type):
8287 if type .name in map :
8388 assert map [type .name ] == type , (
8489 'Schema must contain unique named types but contains multiple types named "{}".'
85- .format (type .name )
86- )
90+ ) .format (type .name )
91+
8792 return map
8893
8994 map [type .name ] = type
@@ -110,3 +115,50 @@ def type_map_reducer(map, type):
110115 reduced_map = type_map_reducer (reduced_map , getattr (field , 'type' , None ))
111116
112117 return reduced_map
118+
119+
120+ def assert_object_implements_interface (object , interface ):
121+ object_field_map = object .get_fields ()
122+ interface_field_map = interface .get_fields ()
123+
124+ for field_name , interface_field in interface_field_map .items ():
125+ object_field = object_field_map .get (field_name )
126+
127+ assert object_field , '"{}" expects field "{}" but "{}" does not provide it.' .format (
128+ interface , field_name , object
129+ )
130+
131+ assert is_equal_type (interface_field .type , object_field .type ), (
132+ '{}.{} expects type "{}" but {}.{} provides type "{}".'
133+ ).format (interface , field_name , interface_field .type , object , field_name , object_field .type )
134+
135+ object_arg_map = {arg .name : arg for arg in object_field .args }
136+ for interface_arg in interface_field .args :
137+ arg_name = interface_arg .name
138+ object_arg = object_arg_map .get (arg_name )
139+
140+ assert object_arg , (
141+ '{}.{} expects argument "{}" but {}.{} does not provide it.'
142+ ).format (interface , field_name , arg_name , object , field_name )
143+
144+ assert is_equal_type (interface_arg .type , object_arg .type ), (
145+ '{}.{}({}:) expects type "{}" but {}.{}({}:) provides type "{}".'
146+ ).format (interface , field_name , arg_name , interface_arg .type , object , field_name , arg_name , object_arg .type )
147+
148+ interface_arg_map = {arg .name : arg for arg in interface_field .args }
149+ for object_arg in object_field .args :
150+ arg_name = object_arg .name
151+ interface_arg = interface_arg_map .get (arg_name )
152+ assert interface_arg , (
153+ '{}.{} does not define argument "{}" but {}.{} provides it.'
154+ ).format (interface , field_name , arg_name , object , field_name )
155+
156+
157+ def is_equal_type (type_a , type_b ):
158+ if isinstance (type_a , GraphQLNonNull ) and isinstance (type_b , GraphQLNonNull ):
159+ return is_equal_type (type_a .of_type , type_b .of_type )
160+
161+ if isinstance (type_a , GraphQLList ) and isinstance (type_b , GraphQLList ):
162+ return is_equal_type (type_a .of_type , type_b .of_type )
163+
164+ return type_a is type_b
0 commit comments