Пример #1
0
 def build(self) -> GraphQLSchema:
     query = self.translate_annotation_unwrapped(
         types.AClass(None, self.query, origin=None))
     mutation = self.translate_annotation_unwrapped(
         types.AClass(None, self.mutation,
                      origin=None)) if self.mutation else None
     # Interface implementations may not have been explicitly referenced in
     # the schema. But their interface must have been--so we want to
     # traverse all interfaces, find their subclasses and explicitly supply
     # them to the schema.
     #
     # To traverse all instances, we hackily construct a temporary schema,
     # then check self.type_map to see what the schema found.
     tmp_schema = GraphQLSchema(
         query=query,
         mutation=mutation,
     )
     extra_types = []
     for interface in list(self.type_map):
         if isinstance(interface, type) and issubclass(
                 interface, Interface):
             for impl in interface.__subclasses__():
                 ann = types.AClass(None, impl, origin=None)
                 extra_types.append(
                     self.translate_annotation_unwrapped(ann))
     return GraphQLSchema(query=query, mutation=mutation, types=extra_types)
 def test_when_query_is_not_subtype_then_schema_is_not_subtype(self):
     assert not is_subtype(
         GraphQLSchema(
             query=GraphQLObjectType("Object", fields={
                 "id": GraphQLField(type=GraphQLInt),
             }),
         ),
         GraphQLSchema(
             query=GraphQLObjectType("Object", fields={
                 "id": GraphQLField(type=GraphQLInt),
                 "name": GraphQLField(type=GraphQLString),
             }),
         ),
     )
Пример #3
0
def test_accepts_type_definition_with_sync_subscribe_function():
    SubscriptionType = GraphQLObjectType(
        name='Subscription',
        fields=OrderedDict([
            ('importantEmail',
             GraphQLField(
                 EmailEventType,
                 resolver=lambda *_: AsyncObservable.from_iterable([None]))),
        ]))
    test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionType)

    stream = AsyncSingleStream()
    send_important_email, subscription = create_subscription(
        stream, test_schema)

    email = Email(
        from_='*****@*****.**',
        subject='Alright',
        message='Tests are good',
        unread=True,
    )
    l = []

    fut1 = asyncio.ensure_future(p_subscribe(l, stream))
    fut2 = asyncio.ensure_future(send_important_email(email))

    asyncio.get_event_loop().run_until_complete(asyncio.gather(fut1, fut2))

    assert l  # [0].data == {'importantEmail': None}
Пример #4
0
def test_accepts_multiple_subscription_fields_defined_in_schema():
    SubscriptionTypeMultiple = GraphQLObjectType(
        name='Subscription',
        fields=OrderedDict([
            ('importantEmail', GraphQLField(EmailEventType)),
            ('nonImportantEmail', GraphQLField(EmailEventType)),
        ]))
    test_schema = GraphQLSchema(query=QueryType,
                                subscription=SubscriptionTypeMultiple)

    stream = AsyncSingleStream()
    send_important_email, subscription = create_subscription(
        stream, test_schema)

    email = Email(
        from_='*****@*****.**',
        subject='Alright',
        message='Tests are good',
        unread=True,
    )
    l = []

    fut1 = asyncio.ensure_future(p_subscribe(l, stream))
    fut2 = asyncio.ensure_future(send_important_email(email))

    asyncio.get_event_loop().run_until_complete(asyncio.gather(fut1, fut2))
    assert l[0][0] == email
Пример #5
0
def email_schema_with_resolvers(resolve_fn=None):
    # type: (Callable) -> GraphQLSchema
    def default_resolver(root, info):
        # type: (Any, ResolveInfo) -> Union[Observable, Subject]
        func = getattr(root, "importantEmail", None)
        if func:
            func = get_unbound_function(func)
            return func()
        return Observable.empty()

    return GraphQLSchema(
        query=QueryType,
        subscription=GraphQLObjectType(
            name="Subscription",
            fields=OrderedDict(
                [
                    (
                        "importantEmail",
                        GraphQLField(
                            EmailEventType, resolver=resolve_fn or default_resolver
                        ),
                    )
                ]
            ),
        ),
    )
 def test_when_mutation_is_missing_then_is_not_subtype_of_schema_with_mutation(self):
     assert not is_subtype(
         GraphQLSchema(
             query=GraphQLObjectType("Object", fields={
                 "id": GraphQLField(type=GraphQLInt),
             }),
         ),
         GraphQLSchema(
             query=GraphQLObjectType("Object", fields={
                 "id": GraphQLField(type=GraphQLInt),
             }),
             mutation=GraphQLObjectType("Mutation", fields={
                 "id": GraphQLField(type=GraphQLInt),
             }),
         ),
     )
Пример #7
0
def test_accepts_type_definition_with_sync_subscribe_function():
    # type: () -> None
    SubscriptionType = GraphQLObjectType(
        name="Subscription",
        fields=OrderedDict([(
            "importantEmail",
            GraphQLField(EmailEventType,
                         resolver=lambda *_: Observable.from_([None])),
        )]),
    )
    test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionType)

    stream = Subject()
    send_important_email, subscription = create_subscription(
        stream, test_schema)

    email = Email(
        from_="*****@*****.**",
        subject="Alright",
        message="Tests are good",
        unread=True,
    )
    inbox = []
    subscription.subscribe(inbox.append)
    send_important_email(email)
    assert len(inbox) == 1
    assert inbox[0].data == {"importantEmail": None}
Пример #8
0
    def __init__(
            self,
            # TODO: can we make sure we only allow to pass something that has been decorated?
            query: Type,
            mutation: Optional[Type] = None,
            subscription: Optional[Type] = None,
            directives=(),
            types=(),
            extensions: Sequence[Type[Extension]] = (),
    ):
        self.extensions = extensions
        self.type_map: Dict[str, ConcreteType] = {}

        query_type = get_object_type(query, self.type_map)
        mutation_type = get_object_type(mutation,
                                        self.type_map) if mutation else None
        subscription_type = (get_object_type(subscription, self.type_map)
                             if subscription else None)

        self.middleware: List[Middleware] = [DirectivesMiddleware(directives)]

        directives = [
            get_directive_type(directive, self.type_map)
            for directive in directives
        ]

        self._schema = GraphQLSchema(
            query=query_type,
            mutation=mutation_type,
            subscription=subscription_type if subscription else None,
            directives=specified_directives + directives,
            types=[get_object_type(type, self.type_map) for type in types],
        )

        self.query = self.type_map[query_type.name]
Пример #9
0
def build_schema(base: DeclarativeMeta,
                 enable_subscription: bool = False) -> GraphQLSchema:
    """

    Args:
        base:
        enable_subscription:

    Returns: :class:`graphql:graphql.type.GraphQLSchema`

    """
    queries: GraphQLFieldMap = {}
    mutations: GraphQLFieldMap = {}

    objects: Objects = {}
    inputs: Inputs = {}

    for model in base.__subclasses__():
        build_queries(model, objects, queries, inputs)
        build_mutations(model, objects, mutations, inputs)

    return GraphQLSchema(
        GraphQLObjectType("Query", queries),
        GraphQLObjectType("Mutation", mutations),
        GraphQLObjectType("Subscription", {}) if enable_subscription else None,
    )
Пример #10
0
def test_accepts_type_definition_with_sync_subscribe_function():
    SubscriptionType = GraphQLObjectType(
        name='Subscription',
        fields=OrderedDict([
            ('importantEmail',
             GraphQLField(EmailEventType,
                          resolver=lambda *_: Observable.from_([None]))),
        ]))
    test_schema = GraphQLSchema(query=QueryType, subscription=SubscriptionType)

    stream = Subject()
    send_important_email, subscription = create_subscription(
        stream, test_schema)

    email = Email(
        from_='*****@*****.**',
        subject='Alright',
        message='Tests are good',
        unread=True,
    )
    l = []
    subscription.subscribe(l.append)
    send_important_email(email)

    assert l  # [0].data == {'importantEmail': None}
Пример #11
0
def update_schema_scalar(schema: GraphQLSchema, name: str,
                         scalar: GraphQLScalarType):
    """Update the scalar in a schema with the scalar provided.

    :param schema: the GraphQL schema
    :param name: the name of the custom scalar type in the schema
    :param scalar: a provided scalar type

    This can be used to update the default Custom Scalar implementation
    when the schema has been provided from a text file or from introspection.
    """

    if not isinstance(scalar, GraphQLScalarType):
        raise TypeError("Scalars should be instances of GraphQLScalarType.")

    schema_scalar = schema.get_type(name)

    if schema_scalar is None:
        raise KeyError(f"Scalar '{name}' not found in schema.")

    if not isinstance(schema_scalar, GraphQLScalarType):
        raise TypeError(f'The type "{name}" is not a GraphQLScalarType,'
                        f" it is a {type(schema_scalar)}")

    # Update the conversion methods
    # Using setattr because mypy has a false positive
    # https://github.com/python/mypy/issues/2427
    setattr(schema_scalar, "serialize", scalar.serialize)
    setattr(schema_scalar, "parse_value", scalar.parse_value)
    setattr(schema_scalar, "parse_literal", scalar.parse_literal)
Пример #12
0
def test_accepts_multiple_subscription_fields_defined_in_schema():
    # type: () -> None
    SubscriptionTypeMultiple = GraphQLObjectType(
        name="Subscription",
        fields=OrderedDict([
            ("importantEmail", GraphQLField(EmailEventType)),
            ("nonImportantEmail", GraphQLField(EmailEventType)),
        ]),
    )
    test_schema = GraphQLSchema(query=QueryType,
                                subscription=SubscriptionTypeMultiple)

    stream = Subject()
    send_important_email, subscription = create_subscription(
        stream, test_schema)

    email = Email(
        from_="*****@*****.**",
        subject="Alright",
        message="Tests are good",
        unread=True,
    )
    inbox = []
    stream.subscribe(inbox.append)
    send_important_email(email)
    assert len(inbox) == 1
    assert inbox[0][0] == email
Пример #13
0
    def __init__(self, edb_schema):
        '''Create a graphql schema based on edgedb schema.'''

        self.edb_schema = edb_schema
        # extract and sort modules to have a consistent type ordering
        self.modules = {
            m.name for m in
            self.edb_schema.get_modules()
        } - {'schema', 'graphql'}
        self.modules = list(self.modules)
        self.modules.sort()

        self._gql_interfaces = {}
        self._gql_objtypes = {}
        self._gql_inobjtypes = {}
        self._gql_ordertypes = {}

        self._define_types()

        query = self._gql_objtypes['Query'] = GraphQLObjectType(
            name='Query',
            fields=self.get_fields('Query'),
        )

        # get a sorted list of types relevant for the Schema
        types = [
            objt for name, objt in
            itertools.chain(self._gql_objtypes.items(),
                            self._gql_inobjtypes.items())
            # the Query is included separately
            if name != 'Query'
        ]
        types = sorted(types, key=lambda x: x.name)
        self._gql_schema = GraphQLSchema(query=query, types=types)
Пример #14
0
def _common_subtype(left, right):
    if left == right:
        return left

    elif isinstance(left, GraphQLNonNull) and isinstance(
            right, GraphQLNonNull):
        return GraphQLNonNull(_common_subtype(left.of_type, right.of_type))

    elif isinstance(left, GraphQLNonNull):
        return GraphQLNonNull(_common_subtype(left.of_type, right))

    elif isinstance(right, GraphQLNonNull):
        return GraphQLNonNull(_common_subtype(left, right.of_type))

    elif isinstance(left, GraphQLList) and isinstance(right, GraphQLList):
        return GraphQLList(_common_subtype(left.of_type, right.of_type))

    elif isinstance(left, GraphQLObjectType) and isinstance(
            right, GraphQLObjectType):
        fields = dict((field_name,
                       _common_subfield(left.fields.get(field_name),
                                        right.fields.get(field_name)))
                      for field_name in set(left.fields.keys())
                      | set(right.fields.keys()))
        return GraphQLObjectType(left.name, fields=fields)

    elif isinstance(left, GraphQLSchema) and isinstance(right, GraphQLSchema):
        return GraphQLSchema(query=_common_subtype(left.get_query_type(),
                                                   right.get_query_type()))

    else:
        raise ValueError("Cannot find common subtype")
Пример #15
0
def executor(root, mutation=None):
    if mutation is None:
        mutation_type = None
    else:
        mutation_type = _nullable(mutation.to_graphql_type())

    default_schema = GraphQLSchema(
        query=_nullable(root.to_graphql_type()),
        mutation=mutation_type,
    )

    def execute(query, variables=None, context=None, schema=None):
        if schema is None:
            schema = default_schema
        elif not is_subtype(default_schema, schema):
            raise ValueError(
                "schema argument must be superschema of main schema")

        return _execute(
            schema=schema,
            root=root,
            mutation=mutation,
            query=query,
            variables=variables,
            context=context,
        )

    return execute
    def test_non_nullable_list(self):

        PersonType = GraphQLObjectType(
            "Person", lambda: {"name": GraphQLField(GraphQLString)}
        )

        schema = GraphQLSchema(
            query=GraphQLObjectType(
                name="RootQueryType",
                fields={
                    "people": GraphQLField(
                        GraphQLList(GraphQLNonNull(PersonType)),
                        resolve=lambda obj, info: {"name": "eran"},
                    )
                },
            )
        )

        query = """
                query GetPeople {
                  people {
                    name
                  }
                }
            """

        parser = QueryParser(schema)
        dataclass_renderer = DataclassesRenderer(schema)

        parsed = parser.parse(query)
        rendered = dataclass_renderer.render(parsed)

        m = self.load_module(rendered)

        mock_client = MagicMock()
        mock_client.call = MagicMock(
            return_value="""
           {
               "data": {
                   "people": [
                      {
                        "name": "eran"
                      },
                      {
                        "name": "eran1"
                      }
                   ]
               }
           }
        """
        )

        result = m.GetPeople.execute(mock_client)
        assert result
        assert isinstance(result, m.GetPeople.GetPeopleData)

        assert len(result.people) == 2
        assert result.people[0].name == "eran"
        assert result.people[1].name == "eran1"
Пример #17
0
 def generate_schema(self) -> GraphQLSchema:
     """
     Finalizes the GraphQL schema by generating the GraphQLSchema
     :return: The finalized GraphQL schema
     """
     query = GraphQLObjectType("Query", self.gql_queries)
     mutation = GraphQLObjectType("Mutation", self.gql_mutations)
     return GraphQLSchema(query, mutation)
Пример #18
0
 def schema():
     Query = GraphQLObjectType('Query',
                               fields={
                                   'allInts':
                                   GraphQLField(GraphQLList(GraphQLInt),
                                                resolver=resolve_all_ints)
                               })
     return GraphQLSchema(Query)
Пример #19
0
 def compile_schema(self, schema: Schema) -> GraphQLSchema:
     return GraphQLSchema(
         query=self._compile_object_or_none(schema.query),
         mutation=self._compile_object_or_none(schema.mutation),
         subscription=self._compile_object_or_none(schema.subscription),
         directives=schema.directives,
         types=self._compile_schema_types(schema.types),
     )
Пример #20
0
def test_batches_correctly(executor):

    Business = GraphQLObjectType(
        'Business', lambda: {
            'id':
            GraphQLField(GraphQLID, resolver=lambda root, info, **args: root),
        })

    Query = GraphQLObjectType(
        'Query', lambda: {
            'getBusiness':
            GraphQLField(Business,
                         args={
                             'id': GraphQLArgument(GraphQLNonNull(GraphQLID)),
                         },
                         resolver=lambda root, info, **args: info.context.
                         business_data_loader.load(args.get('id'))),
        })

    schema = GraphQLSchema(query=Query)

    doc = '''
{
    business1: getBusiness(id: "1") {
        id
    }
    business2: getBusiness(id: "2") {
        id
    }
}
    '''
    doc_ast = parse(doc)

    load_calls = []

    class BusinessDataLoader(DataLoader):
        def batch_load_fn(self, keys):
            load_calls.append(keys)
            return Promise.resolve(keys)

    class Context(object):
        business_data_loader = BusinessDataLoader()

    result = execute(schema,
                     doc_ast,
                     None,
                     context_value=Context(),
                     executor=executor)
    assert not result.errors
    assert result.data == {
        'business1': {
            'id': '1'
        },
        'business2': {
            'id': '2'
        },
    }
    assert load_calls == [['1', '2']]
Пример #21
0
def test_batches_correctly(executor):
    # type: (SyncExecutor) -> None

    Business = GraphQLObjectType(
        "Business",
        lambda: {
            "id": GraphQLField(GraphQLID,
                               resolver=lambda root, info, **args: root)
        },
    )

    Query = GraphQLObjectType(
        "Query",
        lambda: {
            "getBusiness":
            GraphQLField(
                Business,
                args={"id": GraphQLArgument(GraphQLNonNull(GraphQLID))},
                resolver=lambda root, info, **args: info.context.
                business_data_loader.load(args.get("id")),
            )
        },
    )

    schema = GraphQLSchema(query=Query)

    doc = """
{
    business1: getBusiness(id: "1") {
        id
    }
    business2: getBusiness(id: "2") {
        id
    }
}
    """
    doc_ast = parse(doc)

    load_calls = []

    class BusinessDataLoader(DataLoader):
        def batch_load_fn(self, keys):
            # type: (List[str]) -> Promise
            load_calls.append(keys)
            return Promise.resolve(keys)

    class Context(object):
        business_data_loader = BusinessDataLoader()

    result = execute(schema,
                     doc_ast,
                     None,
                     context_value=Context(),
                     executor=executor)
    assert not result.errors
    assert result.data == {"business1": {"id": "1"}, "business2": {"id": "2"}}
    assert load_calls == [["1", "2"]]
Пример #22
0
    def _bind_schema(self, schema: GraphQLSchema,
                     solutions: List[Solution]) -> GraphQLSchema:

        solutions_map = {solution.type: solution for solution in solutions}
        custom_types = [type_ for type_ in schema.to_kwargs()['types']
                        if not type_.name.startswith('__')]

        for type_ in custom_types:
            if isinstance(type_, GraphQLObjectType):
                solution = solutions_map[type_.name]
                self.logger.debug(f' Binding solution: {solution} ')
                solution_type = schema.get_type(solution.type)
                assert solution_type
                fields = getattr(solution_type, 'fields', [])
                for name, field in fields.items():
                    field.resolve = solution.resolve(name)

        return schema
Пример #23
0
 def schema():
     Query = GraphQLObjectType('Query',
                               fields={
                                   'allContainers':
                                   GraphQLField(
                                       GraphQLList(ContainerType),
                                       resolver=resolve_all_containers)
                               })
     return GraphQLSchema(Query)
Пример #24
0
    def _make_executable(self, schema: GraphQLSchema):
        for type_name, fields in self.registry.items():
            object_type = schema.get_type(type_name)
            for field_name, resolver_fn in fields.items():
                field_definition = object_type.fields.get(field_name)
                if not field_definition:
                    raise Exception(f'Invalid field {type_name}.{field_name}')

                field_definition.resolve = resolver_fn
Пример #25
0
 def test_fast_introspection_validate_schema(self) -> None:
     execution_result = try_fast_introspection(GraphQLSchema(),
                                               introspection_query)
     self.assertIsNotNone(execution_result)
     if execution_result is not None:
         self.assertIsNone(execution_result.data)
         self.assertEqual(
             execution_result.errors,
             [GraphQLError("Query root type must be provided.")])
Пример #26
0
 def resolve(self, next, root, info, **kwargs):
     # Block introspection in PROD to save time unless the param forceIntrospection=true is passed
     block_introspection = True or not R.prop_or(False, 'forceIntrospection', info.context.GET) and settings.PROD
     if block_introspection and info.field_name.lower() in ['__schema', '_introspection']:
         query = GraphQLObjectType(
             "Query", lambda: {"Introspection": GraphQLField(GraphQLString, resolver=lambda *_: "Disabled")}
         )
         info.schema = GraphQLSchema(query=query)
         return next(root, info, **kwargs)
     return next(root, info, **kwargs)
Пример #27
0
 def total():
     Query = GraphQLObjectType('Query',
                               fields={
                                   'allInts':
                                   GraphQLField(GraphQLList(GraphQLInt),
                                                resolver=resolve_all_ints)
                               })
     hello_schema = GraphQLSchema(Query)
     source = Source('{ allInts }')
     ast = parse(source)
     return partial(execute, hello_schema, ast)
Пример #28
0
 def test_schema_queries_are_merged(self):
     self._assert_merge(
         [
             GraphQLSchema(
                 query=GraphQLObjectType("Object", fields={
                     "id": GraphQLField(type=GraphQLInt),
                 }),
             ),
             GraphQLSchema(
                 query=GraphQLObjectType("Object", fields={
                     "name": GraphQLField(type=GraphQLString),
                 }),
             ),
         ],
         is_schema(
             query=is_object_type(fields=has_entries({
                 "id": is_field(type=is_int),
                 "name": is_field(type=is_string),
             })),
         ),
     )
Пример #29
0
    def __init__(self, edb_schema):
        '''Create a graphql schema based on edgedb schema.'''

        self.edb_schema = edb_schema
        # extract and sort modules to have a consistent type ordering
        self.modules = {
            m.get_name(self.edb_schema)
            for m in self.edb_schema.get_objects(type=s_mod.Module)
        } - HIDDEN_MODULES
        self.modules = list(self.modules)
        self.modules.sort()

        self._gql_interfaces = {}
        self._gql_objtypes = {}
        self._gql_inobjtypes = {}
        self._gql_ordertypes = {}
        self._gql_enums = {}

        self._define_types()

        query = self._gql_objtypes['Query'] = GraphQLObjectType(
            name='Query',
            fields=self.get_fields('Query'),
        )

        # If a database only has abstract types and scalars, no
        # mutations will be possible (such as in a blank database),
        # but we would still want the reflection to work without
        # error, even if all that can be discovered through GraphQL
        # then is the schema.
        fields = self.get_fields('Mutation')
        if fields:
            mutation = self._gql_objtypes['Mutation'] = GraphQLObjectType(
                name='Mutation',
                fields=fields,
            )
        else:
            mutation = None

        # get a sorted list of types relevant for the Schema
        types = [
            objt for name, objt in itertools.chain(
                self._gql_objtypes.items(), self._gql_inobjtypes.items())
            # the Query is included separately
            if name not in TOP_LEVEL_TYPES
        ]
        types = sorted(types, key=lambda x: x.name)
        self._gql_schema = GraphQLSchema(query=query,
                                         mutation=mutation,
                                         types=types)

        # this map is used for GQL -> EQL translator needs
        self._type_map = {}
Пример #30
0
 def total():
     Query = GraphQLObjectType('Query',
                               fields={
                                   'allContainers':
                                   GraphQLField(
                                       GraphQLList(ContainerType),
                                       resolver=resolve_all_containers)
                               })
     hello_schema = GraphQLSchema(Query)
     source = Source('{ allContainers { x } }')
     ast = parse(source)
     result = partial(execute, hello_schema, ast)
def test_unicode_error_message():
    ast = parse('query Example { unicode }')

    def resolver(context, *_):
        raise Exception(u'UNIÇODÉ!')

    Type = GraphQLObjectType(
        'Type', {
            'unicode': GraphQLField(GraphQLString, resolver=resolver),
        })

    result = execute(GraphQLSchema(Type), ast)
    assert isinstance(result.errors[0], GraphQLLocatedError)