def _get_type_mapping_from_actual_type( root) -> typing.Dict[typing.Any, typing.Type]: # we map ~T to the actual type of root type_var_to_actual_type = {} for field_name, annotation in root.__annotations__.items(): # when we have a list we want to get the type of the elements contained in the # list, to do so we currently only get the first time (if the list is not empty) # this might break in more complex cases, but should suffice for now. if is_list(annotation): annotation = get_list_annotation(annotation) if is_type_var(annotation): values = getattr(root, field_name) if values: type_var_to_actual_type[annotation] = type(values[0]) elif is_type_var(annotation): type_var_to_actual_type[annotation] = type( getattr(root, field_name)) elif is_generic(annotation): type_var_to_actual_type.update( _get_type_mapping_from_actual_type(getattr(root, field_name))) return type_var_to_actual_type
def _process_type( cls, *, name: Optional[str] = None, is_input: bool = False, is_interface: bool = False, description: Optional[str] = None, federation: Optional[FederationTypeParams] = None ): name = name or to_camel_case(cls.__name__) wrapped = _wrap_dataclass(cls) interfaces = _get_interfaces(wrapped) fields = _get_fields(cls) wrapped._type_definition = TypeDefinition( name=name, is_input=is_input, is_interface=is_interface, is_generic=is_generic(cls), interfaces=interfaces, description=description, federation=federation or FederationTypeParams(), origin=cls, _fields=fields, ) return wrapped
def _resolve_type(root, info, _type): if not hasattr(root, "_type_definition"): raise WrongReturnTypeForUnion(info.field_name, str(type(root))) type_definition = root._type_definition if is_generic(type(root)): type_definition = _find_type_for_generic_union(root) returned_type = type_map[type_definition.name].implementation if returned_type not in _type.types: raise UnallowedReturnTypeForUnion(info.field_name, str(type(root)), _type.types) return returned_type
def _resolve_union_type(root: Any, info: GraphQLResolveInfo, type_: GraphQLAbstractType) -> Any: if not hasattr(root, "_type_definition"): raise WrongReturnTypeForUnion(info.field_name, str(type(root))) type_definition = root._type_definition if is_generic(type(root)): type_definition = self._find_type_for_generic_union(root) # TODO: There should be a way to do this without needing the TypeMap returned_type = type_map[type_definition.name].implementation assert isinstance(type_, GraphQLUnionType) # For mypy if returned_type not in type_.types: raise UnallowedReturnTypeForUnion(info.field_name, str(type(root)), set(type_.types)) return returned_type
def _process_type( cls, *, name: Optional[str] = None, is_input: bool = False, is_interface: bool = False, description: Optional[str] = None, federation: Optional[FederationTypeParams] = None, ): name = name or to_camel_case(cls.__name__) wrapped = _wrap_dataclass(cls) interfaces = _get_interfaces(wrapped) fields = _get_fields(cls) wrapped._type_definition = TypeDefinition( name=name, is_input=is_input, is_interface=is_interface, is_generic=is_generic(cls), interfaces=interfaces, description=description, federation=federation or FederationTypeParams(), origin=cls, _fields=fields, ) # dataclasses removes attributes from the class here: # https://github.com/python/cpython/blob/577d7c4e/Lib/dataclasses.py#L873-L880 # so we need to restore them, this will change in future, but for now this # solution should suffice for field in fields: if field.base_resolver and field.origin_name: setattr(cls, field.origin_name, field.base_resolver.wrapped_func) return wrapped
def _is_generic(cls, annotation: Any) -> bool: if hasattr(annotation, "__origin__"): return is_generic(annotation.__origin__) return False