def parse( self, query: str, full_fragments: str = "", should_validate: bool = True, is_fragment: bool = False, ) -> ParsedQuery: query_document_ast = parse("".join([full_fragments, query])) document_ast = parse(query) if not is_fragment: operation = get_operation_ast(document_ast) if not operation.name: raise AnonymousQueryError() if should_validate: errors = validate( self.schema, query_document_ast, [rule for rule in specified_rules if rule is not NoUnusedFragmentsRule], ) if errors: raise InvalidQueryError(errors) type_info = TypeInfo(self.schema) visitor = FieldToTypeMatcherVisitor(self.schema, type_info, query) visit(document_ast, TypeInfoVisitor(type_info, visitor)) result = visitor.parsed return result
def parse_result_recursive( schema: GraphQLSchema, document: DocumentNode, node: Node, result: Optional[Dict[str, Any]], initial_type: Optional[GraphQLType] = None, inside_list_level: int = 0, visit_fragment: bool = False, operation_name: Optional[str] = None, ) -> Any: if result is None: return None type_info = TypeInfo(schema, initial_type=initial_type) visited = visit( node, TypeInfoVisitor( type_info, ParseResultVisitor( schema, document, node, result, type_info=type_info, inside_list_level=inside_list_level, visit_fragment=visit_fragment, operation_name=operation_name, ), ), visitor_keys=RESULT_DOCUMENT_KEYS, ) return visited
def parse(self, query: str, should_validate: bool = True) -> ParsedQuery: document_ast = parse(query) operation = get_operation_ast(document_ast) if not operation.name: raise AnonymousQueryError() if should_validate: errors = validate(self.schema, document_ast) if errors: raise InvalidQueryError(errors) type_info = TypeInfo(self.schema) visitor = FieldToTypeMatcherVisitor(self.schema, type_info, query) visit(document_ast, TypeInfoVisitor(type_info, visitor)) result = visitor.parsed return result
def _split_query_one_level( query_node: SubQueryNode, merged_schema_descriptor: MergedSchemaDescriptor, edge_to_stitch_fields: Dict[Tuple[str, str], Tuple[str, str]], name_assigner: IntermediateOutNameAssigner, ) -> None: """Split the query node, creating children out of all branches across cross schema edges. The input query_node will be modified. Its query_ast will be replaced by a new AST with branches leading out of cross schema edges removed, and new property fields and @output directives added as necessary. Its child_query_connections will be modified by tacking on SubQueryNodes created from these cut-off branches. Args: query_node: Query to be split into its child components. Its query_ast will be replaced (but the original AST will not be modified) and its child_query_connections will be modified. merged_schema_descriptor: The schema that the query AST contained in the input query_node targets. edge_to_stitch_fields: Mapping (type name, vertex field name) to (source field name, sink field name) used in the @stitch directive for each cross schema edge. name_assigner: Object used to generate and keep track of names of newly created @output directive. Raises: - GraphQLValidationError if the query AST contained in the input query_node is invalid, for example, having an @output directive on a cross schema edge - SchemaStructureError if the merged_schema_descriptor provided appears to be invalid or inconsistent """ type_info = TypeInfo(merged_schema_descriptor.schema) operation_definition = get_only_query_definition(query_node.query_ast, GraphQLValidationError) if not isinstance(operation_definition, OperationDefinitionNode): raise AssertionError( f"Expected operation_definition to be an OperationDefinitionNode, but it was of" f"type {type(operation_definition)}. This should be impossible.") type_info.enter(operation_definition) new_operation_definition = _split_query_ast_one_level_recursive( query_node, operation_definition, type_info, edge_to_stitch_fields, name_assigner) type_info.leave(operation_definition) if new_operation_definition is not operation_definition: query_node.query_ast = DocumentNode( definitions=[new_operation_definition]) # Check resulting AST is valid validation_errors = validate(merged_schema_descriptor.schema, query_node.query_ast) if len(validation_errors) > 0: raise AssertionError( 'The resulting split query "{}" is invalid, with the following error messages: {}' "".format(query_node.query_ast, validation_errors)) # Set schema id, check for consistency visitor = TypeInfoVisitor( type_info, SchemaIdSetterVisitor(type_info, query_node, merged_schema_descriptor.type_name_to_schema_id), ) visit(query_node.query_ast, visitor) if query_node.schema_id is None: raise AssertionError( 'Unreachable code reached. The schema id of query piece "{}" has not been ' "determined.".format(query_node.query_ast))