async def __task_receiver__(self, tasks, error_collector): for name, task in tasks.items(): task, node, field, path = task if isawaitable(task): try: result = await task except Exception as e: self.__handle_error__(e, node, path, error_collector) result = None else: result = task if not self.__check_return_type__(field.ftype, result): if result is None and error_collector: return None raise RuntimeError( f'{result} is not a valid return value to' f' {name}, please check {name}\'s type annotation', node, path) await self.__circular_resolve__(result, node, error_collector, path) self.resolve_results[name] = result return self
def __get_resover__(self, name, node, field, path): snake_cases = to_snake_case(name) if not field: raise RuntimeError( f"Cannot query field '{name}' on type '{type(self)}'.", node, path) if not isinstance(field, ResolverField): return None if '__' in snake_cases: resolver = getattr(self, f'_{self.__class__.__name__}{snake_cases}', None) else: resolver = getattr(self, snake_cases, None) if not resolver or not resolver.__is_field__: raise RuntimeError( f"Cannot query field '{name}' on type '{type(self)}'.", node, path) return resolver
def __package_args(self, node, field, path): kwargs = {} for arg in node.arguments: slot = field.params.get(to_snake_case(arg.name.value)) if not slot: raise RuntimeError( f'Can not find {arg.name.value}' f' as param in {field.name}', node, path) kwargs[to_snake_case(arg.name.value)] = load_literal_value( arg.value, slot) return kwargs
def __get_resover(self, name, node, field, path): snake_cases = to_snake_case(name) if not field: raise RuntimeError( f"Cannot query field '{name}' on type '{type(self)}'.", node, path) if not isinstance(field, ResolverField): return None if snake_cases.startswith('__'): resolver = getattr(self, f'_{snake_cases[2:]}', None) if not getattr(resolver, '__is_metafield__', False): resolver = None else: resolver = getattr(self, snake_cases, None) if not getattr(resolver, '__is_field__', False): resolver = None if not resolver: raise RuntimeError( f"Cannot query field '{name}' on type '{type(self)}'.", node, path) return resolver
async def __check_and_circular_resolve(self, tasks, error_collector): for name, task in tasks.items(): task, node, field, path = task result = self.resolve_results[self.__get_field_name(name, node)] if not self.__check_return_type(field.ftype, result): if result is None and error_collector: return False raise RuntimeError( f'{result} is not a valid return value to' f' {name}, please check {name}\'s type annotation', node, path) await self.__circular_resolve(result, node, error_collector, path) return self
async def _resolve(self, nodes, error_collector, path=[]): self.resolve_results = {} tasks = {} for node in nodes: if hasattr(node, 'name'): path = copy(path) path.append(node.name.value) returned = await self.__resolve_fragment(node, error_collector, path) if returned: continue name = node.name.value snake_cases = to_snake_case(name) field = self.__fields__.get(snake_cases) keys = self.__dataclass_fields__.keys() resolver = self.__get_resover(name, node, field, path) if not resolver: try: tasks[name] = (getattr( self, name if name in keys else snake_cases), node, field, path) except AttributeError: raise RuntimeError(f'{name} is not a valid node of {self}', node, path) else: kwargs = self.__package_args(node, field, path) try: returned = resolver(**kwargs) except Exception as e: self.__handle_error(e, node, path, error_collector) tasks[name] = (None, node, field, path) continue if isawaitable(returned): tasks[name] = (asyncio.ensure_future(returned), node, field, path) else: tasks[name] = (returned, node, field, path) return self.__task_receiver(tasks, error_collector)