def test_get_schema_with_macros_original_schema_unchanged(self) -> None: empty_macro_registry = get_empty_test_macro_registry() original_printed_schema = print_schema( self.macro_registry.schema_without_macros) printed_schema_with_0_macros = print_schema( get_schema_with_macros(empty_macro_registry)) printed_schema_afterwards = print_schema( self.macro_registry.schema_without_macros) self.assertEqual(original_printed_schema, printed_schema_afterwards) self.assertEqual(original_printed_schema, printed_schema_with_0_macros)
def _get_directives_in_string_form(directives): """Return a set of directives in their string form, from the native directive type.""" fake_query_type = GraphQLObjectType( "Query", fields={"foo": GraphQLField(GraphQLString)}) fake_schema = GraphQLSchema(fake_query_type, directives=directives) # Split schema on double line breaks where the following character is not a space. # It is not possible to simply split on double line breaks because print_schema puts a # double line break between GraphQLArguments. The not space character is retained and # reattached to the rest of the line. split_schema_lines = [ line.strip() for line in re.split("\n\n([^ ])", print_schema(fake_schema)) ] # Reattach the delimiter's character to the rest of the line. The first line does # not have a separated character from regular expression splitting. schema_lines = [split_schema_lines[0]] + [ delimiter_character + line for delimiter_character, line in zip(split_schema_lines[1::2], split_schema_lines[2::2]) ] return { line for line in schema_lines if line.startswith("directive") }
def test_snapshot_graphql_schema_from_orientdb_schema(self): class_to_field_type_overrides: Dict[str, Dict[str, GraphQLScalarType]] = { "UniquelyIdentifiable": {"uuid": GraphQLID} } schema, _ = generate_schema( self.orientdb_client, # type: ignore # from fixture class_to_field_type_overrides=class_to_field_type_overrides, hidden_classes={ORIENTDB_BASE_VERTEX_CLASS_NAME}, ) compare_ignoring_whitespace(self, SCHEMA_TEXT, print_schema(schema), None)
def test_meta_fields_from_constant(self): fields = schema.EXTENDED_META_FIELD_DEFINITIONS.copy() fields.update( OrderedDict(( ("foo", GraphQLField(GraphQLString)), ("bar", GraphQLField(GraphQLInt)), ))) graphql_type = GraphQLObjectType("MyType", fields) custom_schema = GraphQLSchema(graphql_type, directives=schema.DIRECTIVES) # Ensure that stringifying and parsing this schema works just fine. printed_schema = print_schema(custom_schema) expected_type_definition = """\ type MyType { _x_count: Int foo: String bar: Int }""".replace(" ", " ") # 2 space indentation instead of 4 spaces self.assertIn(expected_type_definition, printed_schema)
def __repr__(self): return print_schema(self)
def get_schema_with_macros(macro_registry): """Get a new GraphQLSchema with fields where macro edges can be used. Preconditions: 1. No macro in the registry has the same name as a field on the vertex where it applies. 2. Members of a union type do not have outgoing macros with the same name. An easy way to satisfy the preconditions is to create the macro_registry using create_macro_registry, and only update it with register_macro_edge, which does all the necessary validation. Postconditions: 1. Every GraphQLQuery that uses macros from this registry appropriately should successfully type-check against the schema generated from this function. 2. A GraphQLQuery that uses macros not present in the registry, or uses valid macros but on types they are not defined at should fail schema validation with the schema generated from this function. 3. This function is total -- A valid macro registry should not fail to create a GraphQL schema with macros. Args: macro_registry: MacroRegistry object containing a schema and macro descriptors we want to add to the schema. Returns: GraphQLSchema with additional fields where macro edges can be used. """ # The easiest way to manipulate the schema is through its AST. The easiest # way to get an AST is to print it and parse it. schema_ast = parse(print_schema(macro_registry.schema_without_macros)) fields_by_definition_name = {} for definition in schema_ast.definitions: if isinstance(definition, (ObjectTypeDefinitionNode, InterfaceTypeDefinitionNode)): # Cast to list (from FrozenList) to allow for updates. fields_by_definition_name[definition.name.value] = list(definition.fields) for class_name, macros_for_class in six.iteritems(macro_registry.macro_edges_at_class): for macro_edge_name, macro_edge_descriptor in six.iteritems(macros_for_class): list_type_at_target = ListTypeNode( type=NamedTypeNode(name=NameNode(value=macro_edge_descriptor.target_class_name)) ) arguments = [] directives = [DirectiveNode(name=NameNode(value=MacroEdgeDirective.name))] fields_by_definition_name[class_name].append( FieldDefinitionNode( name=NameNode(value=macro_edge_name), arguments=arguments, type=list_type_at_target, directives=directives, ) ) new_definitions = [] for definition in schema_ast.definitions: # Create new (Object)/(Interface)TypeDefinitionNode based on the updated fields. if isinstance(definition, ObjectTypeDefinitionNode): new_definitions.append( ObjectTypeDefinitionNode( interfaces=definition.interfaces, description=definition.description, name=definition.name, directives=definition.directives, loc=definition.loc, fields=FrozenList(fields_by_definition_name[definition.name.value]), ) ) elif isinstance(definition, InterfaceTypeDefinitionNode): new_definitions.append( InterfaceTypeDefinitionNode( description=definition.description, name=definition.name, directives=definition.directives, loc=definition.loc, fields=FrozenList(fields_by_definition_name[definition.name.value]), ) ) else: new_definitions.append(definition) new_schema_ast = DocumentNode(definitions=new_definitions) return build_ast_schema(new_schema_ast)