Beispiel #1
0
        def enter(self, node, key, parent, *args):
            # type: (Any, Union[None, int, str], Any, *List[Any]) -> Optional[Any]
            parent_type = type_info.get_parent_type()
            _type = type_info.get_type()
            input_type = type_info.get_input_type()
            visited.append(
                [
                    "enter",
                    type(node).__name__,
                    node.value if type(node).__name__ == "Name" else None,
                    str(parent_type) if parent_type else None,
                    str(_type) if _type else None,
                    str(input_type) if input_type else None,
                ]
            )

            # Make a query valid by adding missing selection sets.
            if (
                type(node).__name__ == "Field"
                and not node.selection_set
                and is_composite_type(get_named_type(_type))
            ):
                return Field(
                    alias=node.alias,
                    name=node.name,
                    arguments=node.arguments,
                    directives=node.directives,
                    selection_set=SelectionSet([Field(name=Name(value="__typename"))]),
                )
Beispiel #2
0
def test_visits_edited_node():
    # type: () -> None
    added_field = Field(name=Name(value="__typename"))
    ast = parse("{ a { x } }")

    class TestVisitor(Visitor):
        def __init__(self):
            # type: () -> None
            self.did_visit_added_field = False

        def enter(self, node, *args):
            # type: (Any, *Any) -> Optional[Field]
            if isinstance(node, Field) and node.name.value == "a":
                selection_set = node.selection_set
                selections = []
                if selection_set:
                    selections = selection_set.selections
                new_selection_set = SelectionSet(selections=[added_field] + selections)
                return Field(name=None, selection_set=new_selection_set)
            if node is added_field:
                self.did_visit_added_field = True

    visitor = TestVisitor()
    visit(ast, visitor)
    assert visitor.did_visit_added_field
Beispiel #3
0
def _get_minimal_query_ast_from_macro_ast(macro_ast):
    """Get a query that should successfully compile to IR if the macro is valid."""
    ast_without_macro_directives = remove_directives_from_ast(macro_ast, {
        directive.name
        for directive in DIRECTIVES_REQUIRED_IN_MACRO_EDGE_DEFINITION
    })

    # We will add this output directive to make the ast a valid query
    output_directive = Directive(Name('output'), arguments=[
        Argument(Name('out_name'), StringValue('dummy_output_name'))
    ])

    # Shallow copy everything on the path to the first level selection list
    query_ast = copy(ast_without_macro_directives)
    root_level_selection = copy(get_only_selection_from_ast(query_ast, GraphQLInvalidMacroError))
    first_level_selections = copy(root_level_selection.selection_set.selections)

    # Add an output to a new or existing __typename field
    existing_typename_field = None
    for idx, selection in enumerate(first_level_selections):
        if isinstance(selection, Field):
            if selection.name.value == '__typename':
                # We have a copy of the list, but the elements are references to objects
                # in macro_ast that we don't want to mutate. So the following copy is necessary.
                existing_typename_field = copy(selection)
                existing_typename_field.directives = copy(existing_typename_field.directives)
                existing_typename_field.directives.append(output_directive)
                first_level_selections[idx] = existing_typename_field
    if existing_typename_field is None:
        first_level_selections.insert(0, Field(Name('__typename'), directives=[output_directive]))

    # Propagate the changes back to the result_ast
    root_level_selection.selection_set = SelectionSet(first_level_selections)
    query_ast.selection_set = SelectionSet([root_level_selection])
    return Document([query_ast])
 def enter(self, node, *args):
     if isinstance(node, Field) and node.name.value == 'a':
         selection_set = node.selection_set
         selections = []
         if selection_set:
             selections = selection_set.selections
         new_selection_set = SelectionSet(selections=[added_field] +
                                          selections)
         return Field(name=None, selection_set=new_selection_set)
     if node is added_field:
         self.did_visit_added_field = True
def _get_property_field(existing_field, field_name, directives_from_edge):
    """Return a Field object with field_name, sharing directives with any such existing field.

    Any valid directives in directives_on_edge will be transferred over to the new field.
    If there is an existing Field in selection with field_name, the returned new Field
    will also contain all directives of the existing field with that name.

    Args:
        existing_field: Field or None. If it's not None, it is a field with field_name. The
                        directives of this field will carry output to the output field
        field_name: str, the name of the output field
        directives_from_edge: List[Directive], the directives of a vertex field. The output
                              field will contain all @filter and any @optional directives
                              from this list

    Returns:
        Field object, with field_name as its name, containing directives from any field in the
        input selections with the same name and directives from the input list of directives
    """
    new_field = Field(
        name=Name(value=field_name),
        directives=[],
    )

    # Transfer directives from existing field of the same name
    if existing_field is not None:
        # Existing field, add all its directives
        directives_from_existing_field = existing_field.directives
        if directives_from_existing_field is not None:
            new_field.directives.extend(directives_from_existing_field)
    # Transfer directives from edge
    if directives_from_edge is not None:
        for directive in directives_from_edge:
            if directive.name.value == OutputDirective.name:  # output illegal on vertex field
                raise GraphQLValidationError(
                    u'Directive "{}" is not allowed on a vertex field, as @output directives '
                    u'can only exist on property fields.'.format(directive))
            elif directive.name.value == OptionalDirective.name:
                if try_get_ast_by_name_and_type(new_field.directives,
                                                OptionalDirective.name,
                                                Directive) is None:
                    # New optional directive
                    new_field.directives.append(directive)
            elif directive.name.value == FilterDirective.name:
                new_field.directives.append(directive)
            else:
                raise AssertionError(
                    u'Unreachable code reached. Directive "{}" is of an unsupported type, and '
                    u'was not caught in a prior validation step.'.format(
                        directive))

    return new_field
def _get_query_document(root_vertex_field_name, root_selections):
    """Return a Document representing a query with the specified name and selections."""
    return Document(definitions=[
        OperationDefinition(operation='query',
                            selection_set=SelectionSet(selections=[
                                Field(
                                    name=Name(value=root_vertex_field_name),
                                    selection_set=SelectionSet(
                                        selections=root_selections, ),
                                    directives=[],
                                )
                            ]))
    ])
        def enter(self, node, key, parent, *args):
            parent_type = type_info.get_parent_type()
            _type = type_info.get_type()
            input_type = type_info.get_input_type()
            visited.append([
                'enter',
                type(node).__name__,
                node.value if type(node).__name__ == "Name" else None,
                str(parent_type) if parent_type else None,
                str(_type) if _type else None,
                str(input_type) if input_type else None
            ])

            # Make a query valid by adding missing selection sets.
            if type(
                    node
            ).__name__ == "Field" and not node.selection_set and is_composite_type(
                    get_named_type(_type)):
                return Field(alias=node.alias,
                             name=node.name,
                             arguments=node.arguments,
                             directives=node.directives,
                             selection_set=SelectionSet(
                                 [Field(name=Name(value='__typename'))]))
def test_visits_edited_node():
    added_field = Field(name=Name(value='__typename'))
    ast = parse('{ a { x } }')

    class TestVisitor(Visitor):
        def __init__(self):
            self.did_visit_added_field = False

        def enter(self, node, *args):
            if isinstance(node, Field) and node.name.value == 'a':
                selection_set = node.selection_set
                selections = []
                if selection_set:
                    selections = selection_set.selections
                new_selection_set = SelectionSet(selections=[added_field] +
                                                 selections)
                return Field(name=None, selection_set=new_selection_set)
            if node is added_field:
                self.did_visit_added_field = True

    visitor = TestVisitor()
    visit(ast, visitor)
    assert visitor.did_visit_added_field
Beispiel #9
0
def test_prints_minimal_ast():
    # type: () -> None
    ast = Field(name=Name(loc=None, value="foo"))
    assert print_ast(ast) == "foo"