Exemple #1
0
def get_internal_fragment(
    selection_set: SelectionSetNode,
    return_type: GraphQLCompositeType,
    context: 'QueryPlanningContext',
) -> 'InternalFragment':
    # TODO: is key correct ?
    key = str(hash(selection_set))  # const key = JSON.stringify(selectionSet);
    if key not in context.internal_fragments:
        name = f'__QueryPlanFragment_{context.internal_fragment_count}'
        context.internal_fragment_count += 1

        definition = FragmentDefinitionNode(
            name=NameNode(value=name),
            type_condition=NamedTypeNode(name=NameNode(value=return_type.name)),
            selection_set=selection_set,
        )

        fragment_selection = SelectionSetNode(
            selections=[FragmentSpreadNode(name=NameNode(value=name))]
        )

        context.internal_fragments[key] = InternalFragment(
            name=name, definition=definition, selection_set=fragment_selection
        )

    return context.internal_fragments[key]
Exemple #2
0
def operation_for_entities_fetch(
    selection_set: SelectionSetNode,
    variable_usages: VariableUsages,
    internal_fragments: set[FragmentDefinitionNode],
) -> DocumentNode:
    representations_variable = VariableNode(name=NameNode(value='representations'))

    return DocumentNode(
        definitions=list(
            chain(
                [
                    OperationDefinitionNode(
                        operation=OperationType.QUERY,
                        variable_definitions=list(
                            chain(
                                [
                                    VariableDefinitionNode(
                                        variable=representations_variable,
                                        type=NonNullTypeNode(
                                            type=ListTypeNode(
                                                type=NonNullTypeNode(
                                                    type=NamedTypeNode(name=NameNode(value='_Any'))
                                                )
                                            )
                                        ),
                                    )
                                ],
                                map_fetch_node_to_variable_definitions(variable_usages),
                            )
                        ),
                        selection_set=SelectionSetNode(
                            selections=[
                                FieldNode(
                                    name=NameNode(value='_entities'),
                                    arguments=[
                                        ArgumentNode(
                                            name=NameNode(
                                                value=representations_variable.name.value
                                            ),
                                            value=representations_variable,
                                        )
                                    ],
                                    selection_set=selection_set,
                                )
                            ]
                        ),
                    ),
                ],
                internal_fragments,
            )
        )
    )
Exemple #3
0
    def args(self, **kwargs) -> "DSLField":
        r"""Set the arguments of a field

        The arguments are parsed to be stored in the AST of this field.

        .. note::
            You can also call the field directly with your arguments.
            :code:`ds.Query.human(id=1000)` is equivalent to:
            :code:`ds.Query.human.args(id=1000)`

        :param \**kwargs: the arguments (keyword=value)
        :return: itself

        :raises KeyError: if any of the provided arguments does not exist
                          for this field.
        """

        assert self.ast_field.arguments is not None

        self.ast_field.arguments = FrozenList(
            self.ast_field.arguments
            + [
                ArgumentNode(
                    name=NameNode(value=name),
                    value=ast_from_value(value, self._get_argument(name).type),
                )
                for name, value in kwargs.items()
            ]
        )

        log.debug(f"Added arguments {kwargs} in field {self!r})")

        return self
Exemple #4
0
Fichier : dsl.py Projet : tony/gql
def get_arg_serializer(arg_type, known_serializers):
    if isinstance(arg_type, GraphQLNonNull):
        return get_arg_serializer(arg_type.of_type, known_serializers)
    if isinstance(arg_type, GraphQLInputField):
        return get_arg_serializer(arg_type.type, known_serializers)
    if isinstance(arg_type, GraphQLInputObjectType):
        if arg_type in known_serializers:
            return known_serializers[arg_type]
        known_serializers[arg_type] = None
        serializers = {
            k: get_arg_serializer(v, known_serializers)
            for k, v in arg_type.fields.items()
        }
        known_serializers[arg_type] = lambda value: ObjectValueNode(
            fields=FrozenList(
                ObjectFieldNode(name=NameNode(value=k),
                                value=serializers[k](v))
                for k, v in value.items()))
        return known_serializers[arg_type]
    if isinstance(arg_type, GraphQLList):
        inner_serializer = get_arg_serializer(arg_type.of_type,
                                              known_serializers)
        return partial(serialize_list, inner_serializer)
    if isinstance(arg_type, GraphQLEnumType):
        return lambda value: EnumValueNode(value=arg_type.serialize(value))
    return lambda value: ast_from_value(arg_type.serialize(value), arg_type)
Exemple #5
0
def test_variable_to_ast_type_passing_wrapping_type():
    wrapping_type = GraphQLNonNull(GraphQLList(StarWarsSchema.get_type("ReviewInput")))
    variable = DSLVariable("review_input")
    ast = variable.to_ast_type(wrapping_type)
    assert ast == NonNullTypeNode(
        type=ListTypeNode(type=NamedTypeNode(name=NameNode(value="ReviewInput")))
    )
Exemple #6
0
def dsl_gql(
    *operations: "DSLOperation", **operations_with_name: "DSLOperation"
) -> DocumentNode:
    r"""Given arguments instances of :class:`DSLOperation`
    containing GraphQL operations,
    generate a Document which can be executed later in a
    gql client or a gql session.

    Similar to the :func:`gql.gql` function but instead of parsing a python
    string to describe the request, we are using operations which have been generated
    dynamically using instances of :class:`DSLField`, generated
    by instances of :class:`DSLType` which themselves originated from
    a :class:`DSLSchema` class.

    :param \*operations: the GraphQL operations
    :type \*operations: DSLOperation (DSLQuery, DSLMutation, DSLSubscription)
    :param \**operations_with_name: the GraphQL operations with an operation name
    :type \**operations_with_name: DSLOperation (DSLQuery, DSLMutation, DSLSubscription)

    :return: a Document which can be later executed or subscribed by a
        :class:`Client <gql.client.Client>`, by an
        :class:`async session <gql.client.AsyncClientSession>` or by a
        :class:`sync session <gql.client.SyncClientSession>`

    :raises TypeError: if an argument is not an instance of :class:`DSLOperation`
    """

    # Concatenate operations without and with name
    all_operations: Tuple["DSLOperation", ...] = (
        *operations,
        *(operation for operation in operations_with_name.values()),
    )

    # Set the operation name
    for name, operation in operations_with_name.items():
        operation.name = name

    # Check the type
    for operation in all_operations:
        if not isinstance(operation, DSLOperation):
            raise TypeError(
                "Operations should be instances of DSLOperation "
                "(DSLQuery, DSLMutation or DSLSubscription).\n"
                f"Received: {type(operation)}."
            )

    return DocumentNode(
        definitions=[
            OperationDefinitionNode(
                operation=OperationType(operation.operation_type),
                selection_set=operation.selection_set,
                variable_definitions=FrozenList(
                    operation.variable_definitions.get_ast_definitions()
                ),
                **({"name": NameNode(value=operation.name)} if operation.name else {}),
            )
            for operation in all_operations
        ]
    )
Exemple #7
0
def ast_from_value(value: Any, type_: GraphQLInputType) -> Optional[ValueNode]:
    """
    This is a partial copy paste of the ast_from_value function in
    graphql-core utilities/ast_from_value.py

    Overwrite the if blocks that use recursion and add a new case to return a
    VariableNode when value is a DSLVariable

    Produce a GraphQL Value AST given a Python object.
    """
    if isinstance(value, DSLVariable):
        return value.set_type(type_).ast_variable

    if is_non_null_type(type_):
        type_ = cast(GraphQLNonNull, type_)
        ast_value = ast_from_value(value, type_.of_type)
        if isinstance(ast_value, NullValueNode):
            return None
        return ast_value

    # only explicit None, not Undefined or NaN
    if value is None:
        return NullValueNode()

    # undefined
    if value is Undefined:
        return None

    # Convert Python list to GraphQL list. If the GraphQLType is a list, but the value
    # is not a list, convert the value using the list's item type.
    if is_list_type(type_):
        type_ = cast(GraphQLList, type_)
        item_type = type_.of_type
        if isinstance(value, Iterable) and not isinstance(value, str):
            maybe_value_nodes = (ast_from_value(item, item_type) for item in value)
            value_nodes = filter(None, maybe_value_nodes)
            return ListValueNode(values=FrozenList(value_nodes))
        return ast_from_value(value, item_type)

    # Populate the fields of the input object by creating ASTs from each value in the
    # Python dict according to the fields in the input type.
    if is_input_object_type(type_):
        if value is None or not isinstance(value, Mapping):
            return None
        type_ = cast(GraphQLInputObjectType, type_)
        field_items = (
            (field_name, ast_from_value(value[field_name], field.type))
            for field_name, field in type_.fields.items()
            if field_name in value
        )
        field_nodes = (
            ObjectFieldNode(name=NameNode(value=field_name), value=field_value)
            for field_name, field_value in field_items
            if field_value
        )
        return ObjectValueNode(fields=FrozenList(field_nodes))

    return default_ast_from_value(value, type_)
Exemple #8
0
    def to_ast_type(
        self, type_: Union[GraphQLWrappingType, GraphQLNamedType]
    ) -> TypeNode:
        if is_wrapping_type(type_):
            if isinstance(type_, GraphQLList):
                return ListTypeNode(type=self.to_ast_type(type_.of_type))
            elif isinstance(type_, GraphQLNonNull):
                return NonNullTypeNode(type=self.to_ast_type(type_.of_type))

        type_ = assert_named_type(type_)
        return NamedTypeNode(name=NameNode(value=type_.name))
Exemple #9
0
 def args(self, **kwargs):
     added_args = []
     for name, value in kwargs.items():
         arg = self.field.args.get(name)
         arg_type_serializer = get_arg_serializer(arg.type)
         serialized_value = arg_type_serializer(value)
         added_args.append(
             ArgumentNode(name=NameNode(value=name),
                          value=serialized_value))
     ast_field = self.ast_field
     ast_field.arguments = FrozenList(ast_field.arguments + added_args)
     return self
Exemple #10
0
 def args(self, **kwargs):
     added_args = []
     for name, value in kwargs.items():
         arg = self.field.args.get(name)
         if not arg:
             raise KeyError(
                 f"Argument {name} does not exist in {self.field}.")
         arg_type_serializer = get_arg_serializer(arg.type)
         serialized_value = arg_type_serializer(value)
         added_args.append(
             ArgumentNode(name=NameNode(value=name),
                          value=serialized_value))
     ast_field = self.ast_field
     ast_field.arguments = FrozenList(ast_field.arguments + added_args)
     return self
Exemple #11
0
    def alias(self, alias: str) -> "DSLField":
        """Set an alias

        .. note::
            You can also pass the alias directly at the
            :meth:`select <gql.dsl.DSLField.select>` method.
            :code:`ds.Query.human.select(my_name=ds.Character.name)` is equivalent to:
            :code:`ds.Query.human.select(ds.Character.name.alias("my_name"))`

        :param alias: the alias
        :type alias: str
        :return: itself
        """

        self.ast_field.alias = NameNode(value=alias)
        return self
Exemple #12
0
def test_literal_object_input():
    assert GraphQLJSON.parse_literal(
        ObjectValueNode(
            fields=[
                ObjectFieldNode(name=NameNode(value='true'), value=BooleanValueNode(value=False)),
                ObjectFieldNode(
                    name=NameNode(value='hello'), value=VariableNode(name=NameNode(value='world'))
                ),
                ObjectFieldNode(
                    name=NameNode(value='array'),
                    value=ListValueNode(
                        values=[
                            IntValueNode(value=1),
                            FloatValueNode(value=2.0),
                            StringValueNode(value='3'),
                        ]
                    ),
                ),
                ObjectFieldNode(name=NameNode(value='maybe_null'), value=NullValueNode()),
                ObjectFieldNode(
                    name=NameNode(value='obj'),
                    value=ObjectValueNode(
                        fields=[
                            ObjectFieldNode(
                                name=NameNode(value='test'),
                                value=VariableNode(name=NameNode(value='tenet')),
                            )
                        ]
                    ),
                ),
            ]
        ),
        {
            'world': 'world',
            'tenet': 'tenet',
        },
    ) == {
        'true': False,
        'hello': 'world',
        'array': [1, 2.0, '3'],
        'maybe_null': None,
        'obj': {'test': 'tenet'},
    }
Exemple #13
0
    def __init__(
        self,
        name: str,
        graphql_type: Union[GraphQLObjectType, GraphQLInterfaceType],
        graphql_field: GraphQLField,
    ):
        """Initialize the DSLField.

        .. warning::
            Don't instantiate this class yourself.
            Use attributes of the :class:`DSLType` instead.

        :param name: the name of the field
        :param graphql_type: the GraphQL type definition from the schema
        :param graphql_field: the GraphQL field definition from the schema
        """
        self._type: Union[GraphQLObjectType, GraphQLInterfaceType] = graphql_type
        self.field: GraphQLField = graphql_field
        self.ast_field: FieldNode = FieldNode(
            name=NameNode(value=name), arguments=FrozenList()
        )
        log.debug(f"Creating {self!r}")
Exemple #14
0
 def __init__(self, name: str):
     self.type: Optional[TypeNode] = None
     self.name = name
     self.ast_variable = VariableNode(name=NameNode(value=self.name))
Exemple #15
0
 def __init__(self, name, field):
     self.field = field
     self.ast_field = FieldNode(name=NameNode(value=name),
                                arguments=FrozenList())
     self.selection_set = None
Exemple #16
0
 def alias(self, alias):
     self.ast_field.alias = NameNode(value=alias)
     return self
Exemple #17
0
from graphql_query_planner.query_plan import (
    FetchNode,
    FlattenNode,
    ParallelNode,
    PlanNode,
    QueryPlan,
    ResponsePath,
    SequenceNode,
    trim_selection_nodes,
)
from graphql_query_planner.shims import GraphQLField
from graphql_query_planner.utilities.graphql_ import get_field_def, get_response_name
from graphql_query_planner.utilities.multi_map import MultiMap
from graphql_query_planner.utilities.predicates import is_not_null_or_undefined

typename_field = FieldNode(name=NameNode(value='__typename'))


@dataclass
class OperationContext:
    schema: GraphQLSchema
    operation: OperationDefinitionNode
    fragments: 'FragmentMap'


FragmentName = str

FragmentMap = dict[FragmentName, FragmentDefinitionNode]


@dataclass