diff --git a/examples/starwars_relay/tests/snapshots/snap_test_objectidentification.py b/examples/starwars_relay/tests/snapshots/snap_test_objectidentification.py index 2d13cba3..cb57709a 100644 --- a/examples/starwars_relay/tests/snapshots/snap_test_objectidentification.py +++ b/examples/starwars_relay/tests/snapshots/snap_test_objectidentification.py @@ -30,21 +30,22 @@ snapshots["test_correctly_refetches_xwing 1"] = { snapshots[ "test_str_schema 1" -] = """schema { - query: Query - mutation: Mutation -} - +] = '''"""A faction in the Star Wars saga""" type Faction implements Node { + """The ID of the object""" id: ID! + + """The name of the faction.""" name: String - ships(before: String, after: String, first: Int, last: Int): ShipConnection + + """The ships used by the faction.""" + ships(before: String = null, after: String = null, first: Int = null, last: Int = null): ShipConnection } input IntroduceShipInput { shipName: String! factionId: String! - clientMutationId: String + clientMutationId: String = null } type IntroduceShipPayload { @@ -57,35 +58,60 @@ type Mutation { introduceShip(input: IntroduceShipInput!): IntroduceShipPayload } +"""An object with an ID""" interface Node { + """The ID of the object""" id: ID! } +""" +The Relay compliant `PageInfo` type, containing data necessary to paginate this connection. +""" type PageInfo { + """When paginating forwards, are there more items?""" hasNextPage: Boolean! + + """When paginating backwards, are there more items?""" hasPreviousPage: Boolean! + + """When paginating backwards, the cursor to continue.""" startCursor: String + + """When paginating forwards, the cursor to continue.""" endCursor: String } type Query { rebels: Faction empire: Faction + + """The ID of the object""" node(id: ID!): Node } +"""A ship in the Star Wars saga""" type Ship implements Node { + """The ID of the object""" id: ID! + + """The name of the ship.""" name: String } type ShipConnection { + """Pagination data for this connection.""" pageInfo: PageInfo! + + """Contains the nodes in this connection.""" edges: [ShipEdge]! } +"""A Relay edge containing a `Ship` and its cursor.""" type ShipEdge { + """The item at the end of the edge""" node: Ship + + """A cursor for use in pagination""" cursor: String! } -""" +''' diff --git a/graphene/relay/connection.py b/graphene/relay/connection.py index 047f2b4d..24804dbd 100644 --- a/graphene/relay/connection.py +++ b/graphene/relay/connection.py @@ -133,7 +133,7 @@ class IterableConnectionField(Field): ) assert issubclass(connection_type, Connection), ( - '{} type have to be a subclass of Connection. Received "{}".' + '{} type has to be a subclass of Connection. Received "{}".' ).format(self.__class__.__name__, connection_type) return type @@ -143,7 +143,7 @@ class IterableConnectionField(Field): return resolved assert isinstance(resolved, Iterable), ( - "Resolved value from the connection field have to be iterable or instance of {}. " + "Resolved value from the connection field has to be iterable or instance of {}. " 'Received "{}"' ).format(connection_type, resolved) connection = connection_from_list( diff --git a/graphene/relay/node.py b/graphene/relay/node.py index d9c4c0f6..f80db13e 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -73,7 +73,7 @@ class AbstractNode(Interface): def __init_subclass_with_meta__(cls, **options): _meta = InterfaceOptions(cls) _meta.fields = OrderedDict( - id=GlobalID(cls, description="The ID of the object.") + id=GlobalID(cls, description="The ID of the object") ) super(AbstractNode, cls).__init_subclass_with_meta__(_meta=_meta, **options) diff --git a/graphene/relay/tests/test_connection_query.py b/graphene/relay/tests/test_connection_query.py index be6ee8c7..7e6f2c4d 100644 --- a/graphene/relay/tests/test_connection_query.py +++ b/graphene/relay/tests/test_connection_query.py @@ -1,7 +1,6 @@ -from collections import OrderedDict +from pytest import mark from graphql_relay.utils import base64 -from promise import Promise from ...types import ObjectType, Schema, String from ..connection import Connection, ConnectionField, PageInfo @@ -25,15 +24,15 @@ class LetterConnection(Connection): class Query(ObjectType): letters = ConnectionField(LetterConnection) connection_letters = ConnectionField(LetterConnection) - promise_letters = ConnectionField(LetterConnection) + async_letters = ConnectionField(LetterConnection) node = Node.Field() def resolve_letters(self, info, **args): return list(letters.values()) - def resolve_promise_letters(self, info, **args): - return Promise.resolve(list(letters.values())) + async def resolve_async_letters(self, info, **args): + return list(letters.values()) def resolve_connection_letters(self, info, **args): return LetterConnection( @@ -46,9 +45,7 @@ class Query(ObjectType): schema = Schema(Query) -letters = OrderedDict() -for i, letter in enumerate(letter_chars): - letters[letter] = Letter(id=i, letter=letter) +letters = {letter: Letter(id=i, letter=letter) for i, letter in enumerate(letter_chars)} def edges(selected_letters): @@ -66,11 +63,11 @@ def cursor_for(ltr): return base64("arrayconnection:%s" % letter.id) -def execute(args=""): +async def execute(args=""): if args: args = "(" + args + ")" - return schema.execute( + return await schema.execute_async( """ { letters%s { @@ -94,8 +91,8 @@ def execute(args=""): ) -def check(args, letters, has_previous_page=False, has_next_page=False): - result = execute(args) +async def check(args, letters, has_previous_page=False, has_next_page=False): + result = await execute(args) expected_edges = edges(letters) expected_page_info = { "hasPreviousPage": has_previous_page, @@ -110,96 +107,114 @@ def check(args, letters, has_previous_page=False, has_next_page=False): } -def test_returns_all_elements_without_filters(): - check("", "ABCDE") +@mark.asyncio +async def test_returns_all_elements_without_filters(): + await check("", "ABCDE") -def test_respects_a_smaller_first(): - check("first: 2", "AB", has_next_page=True) +@mark.asyncio +async def test_respects_a_smaller_first(): + await check("first: 2", "AB", has_next_page=True) -def test_respects_an_overly_large_first(): - check("first: 10", "ABCDE") +@mark.asyncio +async def test_respects_an_overly_large_first(): + await check("first: 10", "ABCDE") -def test_respects_a_smaller_last(): - check("last: 2", "DE", has_previous_page=True) +@mark.asyncio +async def test_respects_a_smaller_last(): + await check("last: 2", "DE", has_previous_page=True) -def test_respects_an_overly_large_last(): - check("last: 10", "ABCDE") +@mark.asyncio +async def test_respects_an_overly_large_last(): + await check("last: 10", "ABCDE") -def test_respects_first_and_after(): - check('first: 2, after: "{}"'.format(cursor_for("B")), "CD", has_next_page=True) +@mark.asyncio +async def test_respects_first_and_after(): + await check('first: 2, after: "{}"'.format(cursor_for("B")), "CD", has_next_page=True) -def test_respects_first_and_after_with_long_first(): - check('first: 10, after: "{}"'.format(cursor_for("B")), "CDE") +@mark.asyncio +async def test_respects_first_and_after_with_long_first(): + await check('first: 10, after: "{}"'.format(cursor_for("B")), "CDE") -def test_respects_last_and_before(): - check('last: 2, before: "{}"'.format(cursor_for("D")), "BC", has_previous_page=True) +@mark.asyncio +async def test_respects_last_and_before(): + await check('last: 2, before: "{}"'.format(cursor_for("D")), "BC", has_previous_page=True) -def test_respects_last_and_before_with_long_last(): - check('last: 10, before: "{}"'.format(cursor_for("D")), "ABC") +@mark.asyncio +async def test_respects_last_and_before_with_long_last(): + await check('last: 10, before: "{}"'.format(cursor_for("D")), "ABC") -def test_respects_first_and_after_and_before_too_few(): - check( +@mark.asyncio +async def test_respects_first_and_after_and_before_too_few(): + await check( 'first: 2, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")), "BC", has_next_page=True, ) -def test_respects_first_and_after_and_before_too_many(): - check( +@mark.asyncio +async def test_respects_first_and_after_and_before_too_many(): + await check( 'first: 4, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")), "BCD", ) -def test_respects_first_and_after_and_before_exactly_right(): - check( +@mark.asyncio +async def test_respects_first_and_after_and_before_exactly_right(): + await check( 'first: 3, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")), "BCD", ) -def test_respects_last_and_after_and_before_too_few(): - check( +@mark.asyncio +async def test_respects_last_and_after_and_before_too_few(): + await check( 'last: 2, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")), "CD", has_previous_page=True, ) -def test_respects_last_and_after_and_before_too_many(): - check( +@mark.asyncio +async def test_respects_last_and_after_and_before_too_many(): + await check( 'last: 4, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")), "BCD", ) -def test_respects_last_and_after_and_before_exactly_right(): - check( +@mark.asyncio +async def test_respects_last_and_after_and_before_exactly_right(): + await check( 'last: 3, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")), "BCD", ) -def test_returns_no_elements_if_first_is_0(): - check("first: 0", "", has_next_page=True) +@mark.asyncio +async def test_returns_no_elements_if_first_is_0(): + await check("first: 0", "", has_next_page=True) -def test_returns_all_elements_if_cursors_are_invalid(): - check('before: "invalid" after: "invalid"', "ABCDE") +@mark.asyncio +async def test_returns_all_elements_if_cursors_are_invalid(): + await check('before: "invalid" after: "invalid"', "ABCDE") -def test_returns_all_elements_if_cursors_are_on_the_outside(): - check( +@mark.asyncio +async def test_returns_all_elements_if_cursors_are_on_the_outside(): + await check( 'before: "{}" after: "{}"'.format( base64("arrayconnection:%s" % 6), base64("arrayconnection:%s" % -1) ), @@ -207,8 +222,9 @@ def test_returns_all_elements_if_cursors_are_on_the_outside(): ) -def test_returns_no_elements_if_cursors_cross(): - check( +@mark.asyncio +async def test_returns_no_elements_if_cursors_cross(): + await check( 'before: "{}" after: "{}"'.format( base64("arrayconnection:%s" % 2), base64("arrayconnection:%s" % 4) ), @@ -216,8 +232,9 @@ def test_returns_no_elements_if_cursors_cross(): ) -def test_connection_type_nodes(): - result = schema.execute( +@mark.asyncio +async def test_connection_type_nodes(): + result = await schema.execute_async( """ { connectionLetters { @@ -248,11 +265,12 @@ def test_connection_type_nodes(): } -def test_connection_promise(): - result = schema.execute( +@mark.asyncio +async def test_connection_async(): + result = await schema.execute_async( """ { - promiseLetters(first:1) { + asyncLetters(first:1) { edges { node { id @@ -270,7 +288,7 @@ def test_connection_promise(): assert not result.errors assert result.data == { - "promiseLetters": { + "asyncLetters": { "edges": [{"node": {"id": "TGV0dGVyOjA=", "letter": "A"}}], "pageInfo": {"hasPreviousPage": False, "hasNextPage": True}, } diff --git a/graphene/relay/tests/test_mutation.py b/graphene/relay/tests/test_mutation.py index 96ddcf0c..dcafbd80 100644 --- a/graphene/relay/tests/test_mutation.py +++ b/graphene/relay/tests/test_mutation.py @@ -80,11 +80,11 @@ class OtherMutation(ClientIDMutation): @staticmethod def mutate_and_get_payload( - self, info, shared="", additional_field="", client_mutation_id=None + self, info, shared, additional_field, client_mutation_id=None ): edge_type = MyEdge return OtherMutation( - name=shared + additional_field, + name=(shared or "") + (additional_field or ""), my_node_edge=edge_type(cursor="1", node=MyNode(name="name")), ) diff --git a/graphene/relay/tests/test_node.py b/graphene/relay/tests/test_node.py index fbce1d54..be6cdc85 100644 --- a/graphene/relay/tests/test_node.py +++ b/graphene/relay/tests/test_node.py @@ -1,7 +1,7 @@ -from collections import OrderedDict - from graphql_relay import to_global_id +from graphql.pyutils import dedent + from ...types import ObjectType, Schema, String from ..node import Node, is_node @@ -70,17 +70,13 @@ def test_subclassed_node_query(): % to_global_id("MyOtherNode", 1) ) assert not executed.errors - assert executed.data == OrderedDict( - { - "node": OrderedDict( - [ - ("shared", "1"), - ("extraField", "extra field info."), - ("somethingElse", "----"), - ] - ) + assert executed.data == { + "node": { + "shared": "1", + "extraField": "extra field info.", + "somethingElse": "----" } - ) + } def test_node_requesting_non_node(): @@ -124,7 +120,7 @@ def test_node_field_only_type_wrong(): % Node.to_global_id("MyOtherNode", 1) ) assert len(executed.errors) == 1 - assert str(executed.errors[0]) == "Must receive a MyNode id." + assert str(executed.errors[0]).startswith("Must receive a MyNode id.") assert executed.data == {"onlyNode": None} @@ -143,39 +139,48 @@ def test_node_field_only_lazy_type_wrong(): % Node.to_global_id("MyOtherNode", 1) ) assert len(executed.errors) == 1 - assert str(executed.errors[0]) == "Must receive a MyNode id." + assert str(executed.errors[0]).startswith("Must receive a MyNode id.") assert executed.data == {"onlyNodeLazy": None} def test_str_schema(): - assert ( - str(schema) - == """ -schema { - query: RootQuery -} - -type MyNode implements Node { - id: ID! - name: String -} - -type MyOtherNode implements Node { - id: ID! - shared: String - somethingElse: String - extraField: String -} - -interface Node { - id: ID! -} - -type RootQuery { - first: String - node(id: ID!): Node - onlyNode(id: ID!): MyNode - onlyNodeLazy(id: ID!): MyNode -} -""".lstrip() + assert (str(schema) == dedent( + ''' + schema { + query: RootQuery + } + + type MyNode implements Node { + """The ID of the object""" + id: ID! + name: String + } + + type MyOtherNode implements Node { + """The ID of the object""" + id: ID! + shared: String + somethingElse: String + extraField: String + } + + """An object with an ID""" + interface Node { + """The ID of the object""" + id: ID! + } + + type RootQuery { + first: String + + """The ID of the object""" + node(id: ID!): Node + + """The ID of the object""" + onlyNode(id: ID!): MyNode + + """The ID of the object""" + onlyNodeLazy(id: ID!): MyNode + } + ''') ) diff --git a/graphene/relay/tests/test_node_custom.py b/graphene/relay/tests/test_node_custom.py index 07e50a1b..967bbead 100644 --- a/graphene/relay/tests/test_node_custom.py +++ b/graphene/relay/tests/test_node_custom.py @@ -1,4 +1,5 @@ -from graphql import graphql +from graphql import graphql_sync +from graphql.pyutils import dedent from ...types import Interface, ObjectType, Schema from ...types.scalars import Int, String @@ -15,7 +16,7 @@ class CustomNode(Node): @staticmethod def get_node_from_global_id(info, id, only_type=None): - assert info.schema == schema + assert info.schema is graphql_schema if id in user_data: return user_data.get(id) else: @@ -23,14 +24,14 @@ class CustomNode(Node): class BasePhoto(Interface): - width = Int() + width = Int(description="The width of the photo in pixels") class User(ObjectType): class Meta: interfaces = [CustomNode] - name = String() + name = String(description="The full name of the user") class Photo(ObjectType): @@ -48,37 +49,47 @@ class RootQuery(ObjectType): schema = Schema(query=RootQuery, types=[User, Photo]) +graphql_schema = schema.graphql_schema def test_str_schema_correct(): - assert ( - str(schema) - == """schema { - query: RootQuery -} - -interface BasePhoto { - width: Int -} - -interface Node { - id: ID! -} - -type Photo implements Node, BasePhoto { - id: ID! - width: Int -} - -type RootQuery { - node(id: ID!): Node -} - -type User implements Node { - id: ID! - name: String -} -""" + assert (str(schema) == dedent( + ''' + schema { + query: RootQuery + } + + interface BasePhoto { + """The width of the photo in pixels""" + width: Int + } + + interface Node { + """The ID of the object""" + id: ID! + } + + type Photo implements Node & BasePhoto { + """The ID of the object""" + id: ID! + + """The width of the photo in pixels""" + width: Int + } + + type RootQuery { + """The ID of the object""" + node(id: ID!): Node + } + + type User implements Node { + """The ID of the object""" + id: ID! + + """The full name of the user""" + name: String + } + ''') ) @@ -91,7 +102,7 @@ def test_gets_the_correct_id_for_users(): } """ expected = {"node": {"id": "1"}} - result = graphql(schema, query) + result = graphql_sync(graphql_schema, query) assert not result.errors assert result.data == expected @@ -105,7 +116,7 @@ def test_gets_the_correct_id_for_photos(): } """ expected = {"node": {"id": "4"}} - result = graphql(schema, query) + result = graphql_sync(graphql_schema, query) assert not result.errors assert result.data == expected @@ -122,7 +133,7 @@ def test_gets_the_correct_name_for_users(): } """ expected = {"node": {"id": "1", "name": "John Doe"}} - result = graphql(schema, query) + result = graphql_sync(graphql_schema, query) assert not result.errors assert result.data == expected @@ -139,7 +150,7 @@ def test_gets_the_correct_width_for_photos(): } """ expected = {"node": {"id": "4", "width": 400}} - result = graphql(schema, query) + result = graphql_sync(graphql_schema, query) assert not result.errors assert result.data == expected @@ -154,7 +165,7 @@ def test_gets_the_correct_typename_for_users(): } """ expected = {"node": {"id": "1", "__typename": "User"}} - result = graphql(schema, query) + result = graphql_sync(graphql_schema, query) assert not result.errors assert result.data == expected @@ -169,7 +180,7 @@ def test_gets_the_correct_typename_for_photos(): } """ expected = {"node": {"id": "4", "__typename": "Photo"}} - result = graphql(schema, query) + result = graphql_sync(graphql_schema, query) assert not result.errors assert result.data == expected @@ -186,7 +197,7 @@ def test_ignores_photo_fragments_on_user(): } """ expected = {"node": {"id": "1"}} - result = graphql(schema, query) + result = graphql_sync(graphql_schema, query) assert not result.errors assert result.data == expected @@ -200,7 +211,7 @@ def test_returns_null_for_bad_ids(): } """ expected = {"node": None} - result = graphql(schema, query) + result = graphql_sync(graphql_schema, query) assert not result.errors assert result.data == expected @@ -239,7 +250,7 @@ def test_have_correct_node_interface(): ], } } - result = graphql(schema, query) + result = graphql_sync(graphql_schema, query) assert not result.errors assert result.data == expected @@ -291,6 +302,6 @@ def test_has_correct_node_root_field(): } } } - result = graphql(schema, query) + result = graphql_sync(graphql_schema, query) assert not result.errors assert result.data == expected diff --git a/graphene/tests/issues/test_356.py b/graphene/tests/issues/test_356.py index 4571aad8..4f3e1066 100644 --- a/graphene/tests/issues/test_356.py +++ b/graphene/tests/issues/test_356.py @@ -27,6 +27,7 @@ def test_issue(): graphene.Schema(query=Query) assert str(exc_info.value) == ( - "IterableConnectionField type have to be a subclass of Connection. " - 'Received "MyUnion".' + "Query fields cannot be resolved:" + " IterableConnectionField type has to be a subclass of Connection." + ' Received "MyUnion".' ) diff --git a/graphene/types/tests/test_datetime.py b/graphene/types/tests/test_datetime.py index c08af7e7..1fd21c24 100644 --- a/graphene/types/tests/test_datetime.py +++ b/graphene/types/tests/test_datetime.py @@ -185,7 +185,6 @@ def test_bad_variables(sample_date, sample_datetime, sample_time): # when `input` is not JSON serializable formatting the error message in # `graphql.utils.is_valid_value` line 79 fails with a TypeError assert isinstance(result.errors[0], GraphQLError) - print(result.errors[0]) assert result.data is None not_a_date = dict() diff --git a/graphene/types/tests/test_query.py b/graphene/types/tests/test_query.py index f23747c0..211c2ec9 100644 --- a/graphene/types/tests/test_query.py +++ b/graphene/types/tests/test_query.py @@ -229,11 +229,11 @@ def test_query_arguments(): result = test_schema.execute("{ test }", None) assert not result.errors - assert result.data == {"test": "[null,{}]"} + assert result.data == {"test": '[null,{"a_str":null,"a_int":null}]'} result = test_schema.execute('{ test(aStr: "String!") }', "Source!") assert not result.errors - assert result.data == {"test": '["Source!",{"a_str":"String!"}]'} + assert result.data == {"test": '["Source!",{"a_str":"String!","a_int":null}]'} result = test_schema.execute('{ test(aInt: -123, aStr: "String!") }', "Source!") assert not result.errors @@ -258,18 +258,20 @@ def test_query_input_field(): result = test_schema.execute("{ test }", None) assert not result.errors - assert result.data == {"test": "[null,{}]"} + assert result.data == {"test": '[null,{"a_input":null}]'} result = test_schema.execute('{ test(aInput: {aField: "String!"} ) }', "Source!") assert not result.errors - assert result.data == {"test": '["Source!",{"a_input":{"a_field":"String!"}}]'} + assert result.data == { + "test": '["Source!",{"a_input":{"a_field":"String!","recursive_field":null}}]'} result = test_schema.execute( '{ test(aInput: {recursiveField: {aField: "String!"}}) }', "Source!" ) assert not result.errors assert result.data == { - "test": '["Source!",{"a_input":{"recursive_field":{"a_field":"String!"}}}]' + "test": '["Source!",{"a_input":{"a_field":null,"recursive_field":' + '{"a_field":"String!","recursive_field":null}}}]' } @@ -285,8 +287,7 @@ def test_query_middlewares(): return "other" def reversed_middleware(next, *args, **kwargs): - p = next(*args, **kwargs) - return p.then(lambda x: x[::-1]) + return next(*args, **kwargs)[::-1] hello_schema = Schema(Query) @@ -348,10 +349,11 @@ def test_big_list_query_compiled_query_benchmark(benchmark): return big_list hello_schema = Schema(Query) + graphql_schema = hello_schema.graphql_schema source = Source("{ allInts }") query_ast = parse(source) - big_list_query = partial(execute, hello_schema, query_ast) + big_list_query = partial(execute, graphql_schema, query_ast) result = benchmark(big_list_query) assert not result.errors assert result.data == {"allInts": list(big_list)} diff --git a/graphene/utils/thenables.py b/graphene/utils/thenables.py index a3089595..96286992 100644 --- a/graphene/utils/thenables.py +++ b/graphene/utils/thenables.py @@ -1,28 +1,15 @@ """ This file is used mainly as a bridge for thenable abstractions. -This includes: -- Promises -- Asyncio Coroutines """ -try: - from promise import Promise, is_thenable # type: ignore -except ImportError: - - class Promise(object): # type: ignore - pass - - def is_thenable(obj): # type: ignore - return False +from inspect import isawaitable -try: - from inspect import isawaitable - from .thenables_asyncio import await_and_execute -except ImportError: +def await_and_execute(obj, on_resolve): + async def build_resolve_async(): + return on_resolve(await obj) - def isawaitable(obj): # type: ignore - return False + return build_resolve_async() def maybe_thenable(obj, on_resolve): @@ -31,12 +18,8 @@ def maybe_thenable(obj, on_resolve): returning the same type of object inputed. If the object is not thenable, it should return on_resolve(obj) """ - if isawaitable(obj) and not isinstance(obj, Promise): + if isawaitable(obj): return await_and_execute(obj, on_resolve) - if is_thenable(obj): - return Promise.resolve(obj).then(on_resolve) - - # If it's not awaitable not a Promise, return - # the function executed over the object + # If it's not awaitable, return the function executed over the object return on_resolve(obj) diff --git a/graphene/utils/thenables_asyncio.py b/graphene/utils/thenables_asyncio.py deleted file mode 100644 index d5f93182..00000000 --- a/graphene/utils/thenables_asyncio.py +++ /dev/null @@ -1,5 +0,0 @@ -def await_and_execute(obj, on_resolve): - async def build_resolve_async(): - return on_resolve(await obj) - - return build_resolve_async() diff --git a/tests_asyncio/test_relay_connection.py b/tests_asyncio/test_relay_connection.py index ec86fef6..67ee2ee4 100644 --- a/tests_asyncio/test_relay_connection.py +++ b/tests_asyncio/test_relay_connection.py @@ -1,7 +1,4 @@ -import pytest - -from collections import OrderedDict -from graphql.execution.executors.asyncio import AsyncioExecutor +from pytest import mark from graphql_relay.utils import base64 @@ -27,14 +24,14 @@ class LetterConnection(Connection): class Query(ObjectType): letters = ConnectionField(LetterConnection) connection_letters = ConnectionField(LetterConnection) - promise_letters = ConnectionField(LetterConnection) + async_letters = ConnectionField(LetterConnection) node = Node.Field() def resolve_letters(self, info, **args): return list(letters.values()) - async def resolve_promise_letters(self, info, **args): + async def resolve_async_letters(self, info, **args): return list(letters.values()) def resolve_connection_letters(self, info, **args): @@ -48,9 +45,7 @@ class Query(ObjectType): schema = Schema(Query) -letters = OrderedDict() -for i, letter in enumerate(letter_chars): - letters[letter] = Letter(id=i, letter=letter) +letters = {letter: Letter(id=i, letter=letter) for i, letter in enumerate(letter_chars)} def edges(selected_letters): @@ -96,12 +91,12 @@ def execute(args=""): ) -@pytest.mark.asyncio -async def test_connection_promise(): - result = await schema.execute( +@mark.asyncio +async def test_connection_async(): + result = await schema.execute_async( """ { - promiseLetters(first:1) { + asyncLetters(first:1) { edges { node { id @@ -115,13 +110,11 @@ async def test_connection_promise(): } } """, - executor=AsyncioExecutor(), - return_promise=True, ) assert not result.errors assert result.data == { - "promiseLetters": { + "asyncLetters": { "edges": [{"node": {"id": "TGV0dGVyOjA=", "letter": "A"}}], "pageInfo": {"hasPreviousPage": False, "hasNextPage": True}, } diff --git a/tests_asyncio/test_relay_mutation.py b/tests_asyncio/test_relay_mutation.py index f63ae193..011557d5 100644 --- a/tests_asyncio/test_relay_mutation.py +++ b/tests_asyncio/test_relay_mutation.py @@ -42,11 +42,11 @@ class OtherMutation(ClientIDMutation): @staticmethod def mutate_and_get_payload( - self, info, shared="", additional_field="", client_mutation_id=None + self, info, shared, additional_field, client_mutation_id=None ): edge_type = MyEdge return OtherMutation( - name=shared + additional_field, + name=(shared or "") + (additional_field or ""), my_node_edge=edge_type(cursor="1", node=MyNode(name="name")), )