diff --git a/gql/transport/local_schema.py b/gql/transport/local_schema.py index b2423346..04ed4ff1 100644 --- a/gql/transport/local_schema.py +++ b/gql/transport/local_schema.py @@ -1,3 +1,4 @@ +import asyncio from inspect import isawaitable from typing import AsyncGenerator, Awaitable, cast @@ -48,6 +49,12 @@ async def execute( return execution_result + @staticmethod + async def _await_if_necessary(obj): + """This method is necessary to work with + graphql-core versions < and >= 3.3.0a3""" + return await obj if asyncio.iscoroutine(obj) else obj + async def subscribe( self, document: DocumentNode, @@ -59,7 +66,9 @@ async def subscribe( The results are sent as an ExecutionResult object """ - subscribe_result = subscribe(self.schema, document, *args, **kwargs) + subscribe_result = await self._await_if_necessary( + subscribe(self.schema, document, *args, **kwargs) + ) if isinstance(subscribe_result, ExecutionResult): yield subscribe_result diff --git a/tests/conftest.py b/tests/conftest.py index 30c0d6f0..6a37a5d3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,6 +3,7 @@ import logging import os import pathlib +import re import ssl import sys import tempfile @@ -506,3 +507,15 @@ async def run_sync_test_inner(event_loop, server, test_function): "tests.fixtures.aws.fake_session", "tests.fixtures.aws.fake_signer", ] + + +def strip_braces_spaces(s): + """Allow to ignore differences in graphql-core syntax between versions""" + + # Strip spaces after starting braces + strip_front = s.replace("{ ", "{") + + # Strip spaces before closing braces only if one space is present + strip_back = re.sub(r"([^\s]) }", r"\1}", strip_front) + + return strip_back diff --git a/tests/custom_scalars/test_json.py b/tests/custom_scalars/test_json.py index 6276b408..d3eae3b8 100644 --- a/tests/custom_scalars/test_json.py +++ b/tests/custom_scalars/test_json.py @@ -18,6 +18,8 @@ from gql import Client, gql from gql.dsl import DSLSchema +from ..conftest import strip_braces_spaces + # Marking all tests in this file with the aiohttp marker pytestmark = pytest.mark.aiohttp @@ -201,9 +203,9 @@ def test_json_value_input_in_dsl_argument(): print(str(query)) assert ( - str(query) + strip_braces_spaces(str(query)) == """addPlayer( - player: { name: "Tim", level: 0, is_connected: false, score: 5, friends: ["Lea"] } + player: {name: "Tim", level: 0, is_connected: false, score: 5, friends: ["Lea"]} )""" ) @@ -235,8 +237,8 @@ def test_json_value_input_with_none_list_in_dsl_argument(): print(str(query)) assert ( - str(query) + strip_braces_spaces(str(query)) == """addPlayer( - player: { name: "Bob", level: 9001, is_connected: true, score: 666.66, friends: null } + player: {name: "Bob", level: 9001, is_connected: true, score: 666.66, friends: null} )""" ) diff --git a/tests/starwars/test_dsl.py b/tests/starwars/test_dsl.py index 4860e3a0..2aadf92f 100644 --- a/tests/starwars/test_dsl.py +++ b/tests/starwars/test_dsl.py @@ -37,6 +37,7 @@ ) from gql.utilities import get_introspection_query_ast, node_tree +from ..conftest import strip_braces_spaces from .schema import StarWarsSchema @@ -210,9 +211,9 @@ def test_add_variable_definitions_with_default_value_input_object(ds): query = dsl_gql(op) assert ( - print_ast(query) + strip_braces_spaces(print_ast(query)) == """ -mutation ($review: ReviewInput = { stars: 5, commentary: "Wow!" }, $episode: Episode) { +mutation ($review: ReviewInput = {stars: 5, commentary: "Wow!"}, $episode: Episode) { createReview(review: $review, episode: $episode) { stars commentary @@ -235,10 +236,10 @@ def test_add_variable_definitions_in_input_object(ds): query = dsl_gql(op) assert ( - print_ast(query) + strip_braces_spaces(print_ast(query)) == """mutation ($stars: Int, $commentary: String, $episode: Episode) { createReview( - review: { stars: $stars, commentary: $commentary } + review: {stars: $stars, commentary: $commentary} episode: $episode ) { stars @@ -565,7 +566,7 @@ def test_multiple_operations(ds): ) assert ( - print_ast(query) + strip_braces_spaces(print_ast(query)) == """query GetHeroName { hero { name @@ -575,7 +576,7 @@ def test_multiple_operations(ds): mutation CreateReviewMutation { createReview( episode: JEDI - review: { stars: 5, commentary: "This is a great movie!" } + review: {stars: 5, commentary: "This is a great movie!"} ) { stars commentary @@ -1102,7 +1103,84 @@ def test_node_tree_with_loc(ds): """.strip() - assert node_tree(document, ignore_loc=False) == node_tree_result + node_tree_result_stable = """ +DocumentNode + loc: + Location + + definitions: + OperationDefinitionNode + loc: + Location + + name: + NameNode + loc: + Location + + value: + 'GetHeroName' + directives: + empty tuple + variable_definitions: + empty tuple + selection_set: + SelectionSetNode + loc: + Location + + selections: + FieldNode + loc: + Location + + directives: + empty tuple + alias: + None + name: + NameNode + loc: + Location + + value: + 'hero' + arguments: + empty tuple + selection_set: + SelectionSetNode + loc: + Location + + selections: + FieldNode + loc: + Location + + directives: + empty tuple + alias: + None + name: + NameNode + loc: + Location + + value: + 'name' + arguments: + empty tuple + selection_set: + None + operation: + +""".strip() + + try: + assert node_tree(document, ignore_loc=False) == node_tree_result + except AssertionError: + # graphql-core version 3.2.3 + assert node_tree(document, ignore_loc=False) == node_tree_result_stable def test_legacy_fragment_with_variables(ds): diff --git a/tests/starwars/test_subscription.py b/tests/starwars/test_subscription.py index c5a50514..0f412acc 100644 --- a/tests/starwars/test_subscription.py +++ b/tests/starwars/test_subscription.py @@ -1,3 +1,5 @@ +import asyncio + import pytest from graphql import ExecutionResult, GraphQLError, subscribe @@ -17,6 +19,14 @@ """ +async def await_if_coroutine(obj): + """Function to make tests work for graphql-core versions before and after 3.3.0a3""" + if asyncio.iscoroutine(obj): + return await obj + + return obj + + @pytest.mark.asyncio async def test_subscription_support(): # reset review data for this test @@ -30,7 +40,9 @@ async def test_subscription_support(): params = {"ep": "JEDI"} expected = [{**review, "episode": "JEDI"} for review in reviews[6]] - ai = subscribe(StarWarsSchema, subs, variable_values=params) + ai = await await_if_coroutine( + subscribe(StarWarsSchema, subs, variable_values=params) + ) result = [result.data["reviewAdded"] async for result in ai] @@ -53,8 +65,8 @@ async def test_subscription_support_using_client(): async with Client(schema=StarWarsSchema) as session: results = [ result["reviewAdded"] - async for result in session.subscribe( - subs, variable_values=params, parse_result=False + async for result in await await_if_coroutine( + session.subscribe(subs, variable_values=params, parse_result=False) ) ] @@ -80,8 +92,8 @@ async def test_subscription_support_using_client_invalid_field(): # We subscribe directly from the transport to avoid local validation results = [ result - async for result in session.transport.subscribe( - subs, variable_values=params + async for result in await await_if_coroutine( + session.transport.subscribe(subs, variable_values=params) ) ] diff --git a/tests/test_aiohttp.py b/tests/test_aiohttp.py index a9b3bda6..09259e51 100644 --- a/tests/test_aiohttp.py +++ b/tests/test_aiohttp.py @@ -14,7 +14,7 @@ TransportServerError, ) -from .conftest import TemporaryFile +from .conftest import TemporaryFile, strip_braces_spaces query1_str = """ query getContinents { @@ -588,15 +588,15 @@ def test_code(): file_upload_mutation_1 = """ mutation($file: Upload!) { - uploadFile(input:{ other_var:$other_var, file:$file }) { + uploadFile(input:{other_var:$other_var, file:$file}) { success } } """ file_upload_mutation_1_operations = ( - '{"query": "mutation ($file: Upload!) {\\n uploadFile(input: { other_var: ' - '$other_var, file: $file }) {\\n success\\n }\\n}", "variables": ' + '{"query": "mutation ($file: Upload!) {\\n uploadFile(input: {other_var: ' + '$other_var, file: $file}) {\\n success\\n }\\n}", "variables": ' '{"file": null, "other_var": 42}}' ) @@ -617,7 +617,7 @@ async def single_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -679,7 +679,7 @@ async def single_upload_handler_with_content_type(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -790,7 +790,7 @@ async def binary_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -931,7 +931,7 @@ async def file_sender(file_name): file_upload_mutation_2_operations = ( '{"query": "mutation ($file1: Upload!, $file2: Upload!) {\\n ' - 'uploadFile(input: { file1: $file, file2: $file }) {\\n success\\n }\\n}", ' + 'uploadFile(input: {file1: $file, file2: $file}) {\\n success\\n }\\n}", ' '"variables": {"file1": null, "file2": null}}' ) @@ -955,7 +955,7 @@ async def handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_2_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_2_operations field_1 = await reader.next() assert field_1.name == "map" @@ -1019,7 +1019,7 @@ async def handler(request): file_upload_mutation_3 = """ mutation($files: [Upload!]!) { - uploadFiles(input:{ files:$files }) { + uploadFiles(input:{files:$files}) { success } } @@ -1027,7 +1027,7 @@ async def handler(request): file_upload_mutation_3_operations = ( '{"query": "mutation ($files: [Upload!]!) {\\n uploadFiles(' - "input: { files: $files })" + "input: {files: $files})" ' {\\n success\\n }\\n}", "variables": {"files": [null, null]}}' ) @@ -1046,7 +1046,7 @@ async def handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_3_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_3_operations field_1 = await reader.next() assert field_1.name == "map" diff --git a/tests/test_httpx.py b/tests/test_httpx.py index 56a984a4..af12f717 100644 --- a/tests/test_httpx.py +++ b/tests/test_httpx.py @@ -10,7 +10,8 @@ TransportQueryError, TransportServerError, ) -from tests.conftest import TemporaryFile + +from .conftest import TemporaryFile, strip_braces_spaces # Marking all tests in this file with the httpx marker pytestmark = pytest.mark.httpx @@ -397,15 +398,15 @@ def test_code(): file_upload_mutation_1 = """ mutation($file: Upload!) { - uploadFile(input:{ other_var:$other_var, file:$file }) { + uploadFile(input:{other_var:$other_var, file:$file}) { success } } """ file_upload_mutation_1_operations = ( - '{"query": "mutation ($file: Upload!) {\\n uploadFile(input: { other_var: ' - '$other_var, file: $file }) {\\n success\\n }\\n}", "variables": ' + '{"query": "mutation ($file: Upload!) {\\n uploadFile(input: {other_var: ' + '$other_var, file: $file}) {\\n success\\n }\\n}", "variables": ' '{"file": null, "other_var": 42}}' ) @@ -431,7 +432,7 @@ async def single_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -493,7 +494,7 @@ async def single_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -563,7 +564,7 @@ async def single_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -627,7 +628,7 @@ async def binary_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -677,7 +678,7 @@ def test_code(): file_upload_mutation_2_operations = ( '{"query": "mutation ($file1: Upload!, $file2: Upload!) {\\n ' - 'uploadFile(input: { file1: $file, file2: $file }) {\\n success\\n }\\n}", ' + 'uploadFile(input: {file1: $file, file2: $file}) {\\n success\\n }\\n}", ' '"variables": {"file1": null, "file2": null}}' ) @@ -710,7 +711,7 @@ async def handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_2_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_2_operations field_1 = await reader.next() assert field_1.name == "map" @@ -775,7 +776,7 @@ def test_code(): file_upload_mutation_3_operations = ( '{"query": "mutation ($files: [Upload!]!) {\\n uploadFiles' - "(input: { files: $files })" + "(input: {files: $files})" ' {\\n success\\n }\\n}", "variables": {"files": [null, null]}}' ) @@ -812,7 +813,7 @@ async def handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_3_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_3_operations field_1 = await reader.next() assert field_1.name == "map" diff --git a/tests/test_httpx_async.py b/tests/test_httpx_async.py index 362875de..e5be73ec 100644 --- a/tests/test_httpx_async.py +++ b/tests/test_httpx_async.py @@ -14,7 +14,7 @@ TransportServerError, ) -from .conftest import TemporaryFile, get_localhost_ssl_context +from .conftest import TemporaryFile, get_localhost_ssl_context, strip_braces_spaces query1_str = """ query getContinents { @@ -601,15 +601,15 @@ def test_code(): file_upload_mutation_1 = """ mutation($file: Upload!) { - uploadFile(input:{ other_var:$other_var, file:$file }) { + uploadFile(input:{other_var:$other_var, file:$file}) { success } } """ file_upload_mutation_1_operations = ( - '{"query": "mutation ($file: Upload!) {\\n uploadFile(input: { other_var: ' - '$other_var, file: $file }) {\\n success\\n }\\n}", "variables": ' + '{"query": "mutation ($file: Upload!) {\\n uploadFile(input: {other_var: ' + '$other_var, file: $file}) {\\n success\\n }\\n}", "variables": ' '{"file": null, "other_var": 42}}' ) @@ -630,7 +630,7 @@ async def single_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -737,7 +737,7 @@ async def binary_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -801,7 +801,7 @@ async def test_httpx_binary_file_upload(event_loop, aiohttp_server): file_upload_mutation_2_operations = ( '{"query": "mutation ($file1: Upload!, $file2: Upload!) {\\n ' - 'uploadFile(input: { file1: $file, file2: $file }) {\\n success\\n }\\n}", ' + 'uploadFile(input: {file1: $file, file2: $file}) {\\n success\\n }\\n}", ' '"variables": {"file1": null, "file2": null}}' ) @@ -826,7 +826,7 @@ async def handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_2_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_2_operations field_1 = await reader.next() assert field_1.name == "map" @@ -890,7 +890,7 @@ async def handler(request): file_upload_mutation_3 = """ mutation($files: [Upload!]!) { - uploadFiles(input:{ files:$files }) { + uploadFiles(input:{files:$files}) { success } } @@ -898,7 +898,7 @@ async def handler(request): file_upload_mutation_3_operations = ( '{"query": "mutation ($files: [Upload!]!) {\\n uploadFiles(' - "input: { files: $files })" + "input: {files: $files})" ' {\\n success\\n }\\n}", "variables": {"files": [null, null]}}' ) @@ -918,7 +918,7 @@ async def handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_3_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_3_operations field_1 = await reader.next() assert field_1.name == "map" diff --git a/tests/test_requests.py b/tests/test_requests.py index a5ff0d8b..639d2b73 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -10,7 +10,8 @@ TransportQueryError, TransportServerError, ) -from tests.conftest import TemporaryFile + +from .conftest import TemporaryFile, strip_braces_spaces # Marking all tests in this file with the requests marker pytestmark = pytest.mark.requests @@ -399,15 +400,15 @@ def test_code(): file_upload_mutation_1 = """ mutation($file: Upload!) { - uploadFile(input:{ other_var:$other_var, file:$file }) { + uploadFile(input:{other_var:$other_var, file:$file}) { success } } """ file_upload_mutation_1_operations = ( - '{"query": "mutation ($file: Upload!) {\\n uploadFile(input: { other_var: ' - '$other_var, file: $file }) {\\n success\\n }\\n}", "variables": ' + '{"query": "mutation ($file: Upload!) {\\n uploadFile(input: {other_var: ' + '$other_var, file: $file}) {\\n success\\n }\\n}", "variables": ' '{"file": null, "other_var": 42}}' ) @@ -433,7 +434,7 @@ async def single_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -495,7 +496,7 @@ async def single_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -565,7 +566,7 @@ async def single_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -629,7 +630,7 @@ async def binary_upload_handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_1_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_1_operations field_1 = await reader.next() assert field_1.name == "map" @@ -679,7 +680,7 @@ def test_code(): file_upload_mutation_2_operations = ( '{"query": "mutation ($file1: Upload!, $file2: Upload!) {\\n ' - 'uploadFile(input: { file1: $file, file2: $file }) {\\n success\\n }\\n}", ' + 'uploadFile(input: {file1: $file, file2: $file}) {\\n success\\n }\\n}", ' '"variables": {"file1": null, "file2": null}}' ) @@ -714,7 +715,7 @@ async def handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_2_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_2_operations field_1 = await reader.next() assert field_1.name == "map" @@ -779,7 +780,7 @@ def test_code(): file_upload_mutation_3_operations = ( '{"query": "mutation ($files: [Upload!]!) {\\n uploadFiles' - "(input: { files: $files })" + "(input: {files: $files})" ' {\\n success\\n }\\n}", "variables": {"files": [null, null]}}' ) @@ -816,7 +817,7 @@ async def handler(request): field_0 = await reader.next() assert field_0.name == "operations" field_0_text = await field_0.text() - assert field_0_text == file_upload_mutation_3_operations + assert strip_braces_spaces(field_0_text) == file_upload_mutation_3_operations field_1 = await reader.next() assert field_1.name == "map"