def test_field__get_type(): field_object = FieldObject( None, ('name', CharField()), None, ) assert field_object.get_type() == String field_object = FieldObject( None, ('characters', RelatedField('self')), None, ) field_object.data[1]._self_object_type = Character assert field_object.get_type() == Character field_object = FieldObject( None, ('characters', RelatedField(Character)), None, ) assert field_object.get_type() == Character field_object = FieldObject( None, ('characters', ManyRelatedField(Character)), None, ) assert field_object.get_type() == List(Character)
class QueryRoot(Object): hero = RelatedField(Character) episodes = ManyRelatedField(Episode) episode = RelatedField(Episode, arguments={'number': Int()}) def get_hero(self): return CharacterModel.objects.get(name='R2-D2') def get_episodes(self): return EpisodeModel.objects.order_by('number') def get_episode(self, number): return EpisodeModel.objects.get(number=number)
class SchemaObject(Object): # self.data will be the query_root. object_name = '__Schema' types = ManyRelatedField(TypeObject) queryType = RelatedField(TypeObject) mutationType = RelatedField(TypeObject) directives = ManyRelatedField(DirectiveObject) def _collect_types(self, object_type, types=None): if types is None: types = set((object_type, )) for field in object_type._declared_fields.values(): if isinstance(field, RelatedField): object_type = field.object_type if object_type in types: continue types.add(object_type) self._collect_types(object_type, types) elif isinstance(field, EnumField): enum_type = field.enum if enum_type in types: continue types.add(enum_type) elif isinstance(field.type_, List): field = field.type_ elif field.type_: types.add(field.type_) return types def _type_key(self, type_): object_name = type_.object_name # Sort: defined types, introspection types, scalars, and then by name. return ( type_.kind == SCALAR, object_name.startswith('__'), object_name, ) def get_types(self): types = self._collect_types(self.data) return sorted(types, key=self._type_key) def get_queryType(self): return self.data def get_mutationType(self): return None def get_directives(self): return []
def test_field__get_type(): field_object = Field( None, ('name', CharField()), None, ) assert field_object.get_type() == String field_object = Field( None, ('characters', RelatedField('self')), None, ) field_object.data[1]._self_object_type = Character assert field_object.get_type() == Character field_object = Field( None, ('characters', RelatedField(Character)), None, ) assert field_object.get_type() == Character field_object = Field( None, ('characters', RelatedField(lambda: Character)), None, ) assert field_object.get_type() == Character field_object = Field( None, ('characters', RelatedField('test_app.schema.Character')), None, ) assert field_object.get_type() == Character field_object = Field( None, ('characters', ManyRelatedField(Character)), None, ) assert field_object.get_type() == List(Character) field_object = Field( None, ('characters', ManyRelatedField(Character, null=False)), None, ) assert field_object.get_type() == NonNull(List(Character)) field_object = Field( None, ('id', IntegerField(null=False)), None, ) assert field_object.get_type() == NonNull(Int)
def test_field__get_type_exceptions(): field_object = FieldObject( None, ('characters', RelatedField('test_app.schema.NonExistClass')), None, ) with pytest.raises(ValueError): field_object.get_type() field_object = FieldObject( None, ('characters', RelatedField('NonExistModule.NonExistClass')), None, ) with pytest.raises(ValueError): field_object.get_type()
class FieldObject(Object): # self.data will be an item from a declared fields dict object_name = '__Field' name = CharField() description = CharField() type = RelatedField(lambda: TypeObject) args = ManyRelatedField(InputValueObject) isDeprecated = BooleanField() deprecationReason = CharField() def get_name(self): return self.data[0] def get_description(self): return getattr(self.data[1], 'description', None) def get_type(self): field = self.data[1] if isinstance(field, RelatedField): type_ = field.object_type if isinstance(field.type_, List): type_ = List(type_) else: type_ = field.type_ return type_ def get_args(self): return tuple(self.data[1].arguments.items())
class Character(Object): id = IntegerField() name = CharField() friends = ManyRelatedField('self') best_friend = RelatedField('self') appears_in = ManyRelatedField(Episode) def get_best_friend(self): return self.data.friends.order_by('pk').first()
class Type(Object): # self.data will be an object or scalar object_name = '__Type' kind = EnumField(TypeKindEnum) name = CharField() description = CharField() fields = ManyRelatedField(Field) inputFields = ManyRelatedField(InputValue) interfaces = ManyRelatedField('self') possibleTypes = ManyRelatedField('self') enumValues = ManyRelatedField(EnumValue) ofType = RelatedField('self') def get_name(self): if self.data.kind in [LIST, NON_NULL]: return None return self.data.object_name def get_fields(self): if self.data.kind != OBJECT: return None return sorted( ((name, field) for name, field in self.data._declared_fields.items() if name[:2] != '__'), key=lambda item: item[0], ) def get_inputFields(self): if self.data.kind != INPUT_OBJECT: return None return [] def get_interfaces(self): if self.data.kind != OBJECT: return None return [] def get_possibleTypes(self): return None def get_enumValues(self): if self.data.kind != ENUM: return None return self.data.values def get_ofType(self): if self.data.kind in [NON_NULL, LIST]: type_ = self.data.type_ # Don't return NonNull if self is already NonNull if self.data.kind is not NON_NULL and not getattr( type_, 'null', True): return NonNull(type_) return type_ return None
class QueryRoot(Object): hero = RelatedField(Character, null=False) episodes = ManyRelatedField(Episode, arguments={'number': List(Int(null=False))}) episode = RelatedField(Episode, arguments={'number': Int(null=False)}, null=False) def get_hero(self): return CharacterModel.objects.get(name='R2-D2') def get_episodes(self, number): episodes = EpisodeModel.objects.all() if number: episodes = episodes.filter(number__in=list(number)) return episodes.order_by('number') def get_episode(self, number): return EpisodeModel.objects.get(number=number)
def register_query_root(self, BaseQueryRoot): class QueryRoot(BaseQueryRoot): def get___schema(self): return self.__class__ def get___type(self, name): schema = SchemaObject(None, self.__class__, None) for type_ in schema.get_types(): if type_.object_name == name: return type_ return None QueryRoot._declared_fields = copy.deepcopy( BaseQueryRoot._declared_fields) QueryRoot._declared_fields['__schema'] = RelatedField(SchemaObject) QueryRoot._declared_fields['__type'] = RelatedField(TypeObject, name=String()) self.query_root = QueryRoot return QueryRoot
class TypeObject(Object): # self.data will be an object or scalar object_name = '__Type' kind = EnumField(TypeKindEnum) name = CharField() description = CharField() fields = ManyRelatedField(FieldObject) inputFields = ManyRelatedField(InputValueObject) interfaces = ManyRelatedField('self') possibleTypes = ManyRelatedField('self') enumValues = ManyRelatedField(EnumValueObject) ofType = RelatedField('self') def get_name(self): if self.data.kind == LIST: return None return self.data.object_name def get_fields(self): if self.data.kind != OBJECT: return None return sorted( ((name, field) for name, field in self.data._declared_fields.items() if name[:2] != '__'), key=lambda item: item[0], ) def get_inputFields(self): if self.data.kind != INPUT_OBJECT: return None return [] def get_interfaces(self): if self.data.kind != OBJECT: return None return [] def get_possibleTypes(self): return None def get_enumValues(self): if self.data.kind != ENUM: return None return self.data.values def get_ofType(self): if self.data.kind == LIST: return self.data.type_ return None
class IntrospectionQueryRoot(Object): """ Provides basic functionality related to introspection. The query root for a graphql view should be a subclass of BaseQueryRoot. """ introspection_fields = OrderedDict(( ('__schema', RelatedField(introspection.Schema)), ('__type', RelatedField( introspection.Type, arguments={'name': String()}, )), )) def get___schema(self): return self.data def get___type(self, name): schema = introspection.Schema(None, self.data, None) for type_ in schema.get_types(): if type_.object_name == name: return type_ return None
class InputValueObject(Object): object_name = '__InputValue' name = CharField() description = CharField() type = RelatedField(lambda: TypeObject) defaultValue = CharField() def get_name(self): return self.data[0] def get_type(self): type_ = self.data[1] if isinstance(type_, List): return type_ return type_.__class__
class Episode(Object): name = CharField(description='The name of an episode') number = IntegerField() characters = ManyRelatedField(lambda: Character, types=List(String)) next = RelatedField('self') def get_next(self): return EpisodeModel.objects.filter(number=self.data.number + 1).first() def get_characters(self, types): q = Q() if types is not None: if 'human' not in types: q &= Q(human=None) if 'droid' not in types: q &= Q(droid=None) return self.data.characters.filter(q).order_by('pk')
class Episode(Object): name = CharField(description='The name of an episode') number = IntegerField() characters = ManyRelatedField( 'test_app.schema.Character', arguments={ 'types': List(String(null=False)), }, ) next = RelatedField('self') def get_next(self): return EpisodeModel.objects.filter(number=self.data.number + 1).first() def get_characters(self, types): q = Q() if types is not None: if 'human' not in types: q &= Q(human=None) if 'droid' not in types: q &= Q(droid=None) return self.data.characters.filter(q).order_by('pk')
class QueryRoot(Object): hero = RelatedField(Character) def get_hero(self): return CharacterModel.objects.get(name='R2-D2')