From f6b85ae7cb86cddbda4cb82acebdf51b598cb1d9 Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 13:02:57 +0100 Subject: [PATCH 01/11] Support Python 3.10 and move dev status to beta --- setup.py | 4 +++- tox.ini | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 94f3a9ee..e1cdade2 100644 --- a/setup.py +++ b/setup.py @@ -67,14 +67,16 @@ author_email="me@syrusakbary.com", license="MIT", classifiers=[ - "Development Status :: 3 - Alpha", + "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries", "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Programming Language :: Python :: Implementation :: PyPy", ], keywords="api graphql protocol rest relay gql client", diff --git a/tox.ini b/tox.ini index 414f083b..2699744c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] envlist = black,flake8,import-order,mypy,manifest, - py{36,37,38,39,py3} + py{36,37,38,39,310,py3} [pytest] markers = asyncio @@ -12,6 +12,7 @@ python = 3.7: py37 3.8: py38 3.9: py39 + 3.10: py310 pypy3: pypy3 [testenv] @@ -30,7 +31,7 @@ deps = -e.[test] commands = pip install -U setuptools ; run "tox -- tests -s" to show output for debugging - py{36,37,39,py3}: pytest {posargs:tests} + py{36,37,39,310,py3}: pytest {posargs:tests} py{38}: pytest {posargs:tests --cov-report=term-missing --cov=gql} [testenv:black] From 3d786a22adc4897cdee8abbd2bf2d542bf582d39 Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 13:05:41 +0100 Subject: [PATCH 02/11] Add Python 3.10 test with GitHub actions --- .github/workflows/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8326a645..870493aa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "pypy3"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "pypy3"] os: [ubuntu-latest, windows-latest] exclude: - os: windows-latest @@ -17,6 +17,8 @@ jobs: python-version: "3.7" - os: windows-latest python-version: "3.9" + - os: windows-latest + python-version: "3.10" - os: windows-latest python-version: "pypy3" From c22e9320fe428e2dfc18a21a6875d3e1fb04cc40 Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 14:12:52 +0100 Subject: [PATCH 03/11] Update pytest and websockets --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index e1cdade2..283f64a0 100644 --- a/setup.py +++ b/setup.py @@ -13,9 +13,9 @@ tests_requires = [ "parse==1.15.0", - "pytest==5.4.2", - "pytest-asyncio==0.11.0", - "pytest-cov==2.8.1", + "pytest==6.2.5", + "pytest-asyncio==0.16.0", + "pytest-cov==3.0.0", "mock==4.0.2", "vcrpy==4.0.2", "aiofiles", @@ -43,7 +43,7 @@ ] install_websockets_requires = [ - "websockets>=9,<10", + "websockets>=10,<11", ] install_all_requires = ( From 2a4b4e8d0f7b73a11030d8904ba88f6fcb901793 Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 14:58:51 +0100 Subject: [PATCH 04/11] Remove Client type_def obsolete argument (#262) --- gql/client.py | 15 --------------- tests/test_async_client_validation.py | 21 +++------------------ 2 files changed, 3 insertions(+), 33 deletions(-) diff --git a/gql/client.py b/gql/client.py index c39da95b..fc686c16 100644 --- a/gql/client.py +++ b/gql/client.py @@ -1,5 +1,4 @@ import asyncio -import warnings from typing import Any, AsyncGenerator, Dict, Generator, Optional, Union from graphql import ( @@ -45,7 +44,6 @@ def __init__( self, schema: Optional[Union[str, GraphQLSchema]] = None, introspection=None, - type_def: Optional[str] = None, transport: Optional[Union[Transport, AsyncTransport]] = None, fetch_schema_from_transport: bool = False, execute_timeout: Optional[Union[int, float]] = 10, @@ -67,19 +65,6 @@ def __init__( :param parse_results: Whether gql will try to parse the serialized output sent by the backend. Can be used to unserialize custom scalars or enums. """ - assert not ( - type_def and introspection - ), "Cannot provide introspection and type definition at the same time." - - if type_def: - assert ( - not schema - ), "Cannot provide type definition and schema at the same time." - warnings.warn( - "type_def is deprecated; use schema instead", - category=DeprecationWarning, - ) - schema = type_def if introspection: assert ( diff --git a/tests/test_async_client_validation.py b/tests/test_async_client_validation.py index 107bd6c2..b588e6ba 100644 --- a/tests/test_async_client_validation.py +++ b/tests/test_async_client_validation.py @@ -1,6 +1,5 @@ import asyncio import json -import warnings import graphql import pytest @@ -83,7 +82,6 @@ async def server_starwars(ws, path): [ {"schema": StarWarsSchema}, {"introspection": StarWarsIntrospection}, - {"type_def": StarWarsTypeDef}, {"schema": StarWarsTypeDef}, ], ) @@ -97,11 +95,7 @@ async def test_async_client_validation( sample_transport = WebsocketsTransport(url=url) - with warnings.catch_warnings(): - warnings.filterwarnings( - "ignore", message="type_def is deprecated; use schema instead" - ) - client = Client(transport=sample_transport, **client_params) + client = Client(transport=sample_transport, **client_params) async with client as session: @@ -135,7 +129,6 @@ async def test_async_client_validation( [ {"schema": StarWarsSchema}, {"introspection": StarWarsIntrospection}, - {"type_def": StarWarsTypeDef}, {"schema": StarWarsTypeDef}, ], ) @@ -149,11 +142,7 @@ async def test_async_client_validation_invalid_query( sample_transport = WebsocketsTransport(url=url) - with warnings.catch_warnings(): - warnings.filterwarnings( - "ignore", message="type_def is deprecated; use schema instead" - ) - client = Client(transport=sample_transport, **client_params) + client = Client(transport=sample_transport, **client_params) async with client as session: @@ -174,11 +163,7 @@ async def test_async_client_validation_invalid_query( @pytest.mark.parametrize("subscription_str", [starwars_invalid_subscription_str]) @pytest.mark.parametrize( "client_params", - [ - {"schema": StarWarsSchema, "introspection": StarWarsIntrospection}, - {"schema": StarWarsSchema, "type_def": StarWarsTypeDef}, - {"introspection": StarWarsIntrospection, "type_def": StarWarsTypeDef}, - ], + [{"schema": StarWarsSchema, "introspection": StarWarsIntrospection}], ) async def test_async_client_validation_different_schemas_parameters_forbidden( event_loop, server, subscription_str, client_params From ee67ade43b6297fb6e6a4e605e1c762bee1ed874 Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 15:10:37 +0100 Subject: [PATCH 05/11] Update mypy to 0.910 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 283f64a0..a44e4fc8 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ "check-manifest>=0.42,<1", "flake8==3.8.1", "isort==4.3.21", - "mypy==0.770", + "mypy==0.910", "sphinx>=3.0.0,<4", "sphinx_rtd_theme>=0.4,<1", "sphinx-argparse==0.2.5", From 7894104688aad72c6ef4ec1b00ee0155d60c78ea Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 15:12:48 +0100 Subject: [PATCH 06/11] Add library stubs for mypy --- setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.py b/setup.py index a44e4fc8..da8f336d 100644 --- a/setup.py +++ b/setup.py @@ -30,6 +30,9 @@ "sphinx>=3.0.0,<4", "sphinx_rtd_theme>=0.4,<1", "sphinx-argparse==0.2.5", + "types-aiofiles", + "types-mock", + "types-requests", ] + tests_requires install_aiohttp_requires = [ From f5f3c39922b25052a5da7b0487484d1f31319e54 Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 15:04:08 +0100 Subject: [PATCH 07/11] Ignore Python 3.10 get_event_loop warnings --- gql/client.py | 13 +++++++++++-- gql/transport/websockets.py | 7 ++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/gql/client.py b/gql/client.py index fc686c16..c5f1af39 100644 --- a/gql/client.py +++ b/gql/client.py @@ -1,4 +1,5 @@ import asyncio +import warnings from typing import Any, AsyncGenerator, Dict, Generator, Optional, Union from graphql import ( @@ -151,7 +152,11 @@ def execute(self, document: DocumentNode, *args, **kwargs) -> Dict: # Get the current asyncio event loop # Or create a new event loop if there isn't one (in a new Thread) try: - loop = asyncio.get_event_loop() + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", message="There is no current event loop" + ) + loop = asyncio.get_event_loop() except RuntimeError: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) @@ -194,7 +199,11 @@ def subscribe( # Get the current asyncio event loop # Or create a new event loop if there isn't one (in a new Thread) try: - loop = asyncio.get_event_loop() + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", message="There is no current event loop" + ) + loop = asyncio.get_event_loop() except RuntimeError: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) diff --git a/gql/transport/websockets.py b/gql/transport/websockets.py index 06552d2f..6d03f08e 100644 --- a/gql/transport/websockets.py +++ b/gql/transport/websockets.py @@ -1,6 +1,7 @@ import asyncio import json import logging +import warnings from contextlib import suppress from ssl import SSLContext from typing import Any, AsyncGenerator, Dict, Optional, Tuple, Union, cast @@ -165,7 +166,11 @@ def __init__( # We need to set an event loop here if there is none # Or else we will not be able to create an asyncio.Event() try: - self._loop = asyncio.get_event_loop() + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", message="There is no current event loop" + ) + self._loop = asyncio.get_event_loop() except RuntimeError: self._loop = asyncio.new_event_loop() asyncio.set_event_loop(self._loop) From edf5910d1e260500d003c1aee0007141c364dcbd Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 15:23:53 +0100 Subject: [PATCH 08/11] Filter Python 3.10 'There is no current event loop' warnings --- gql/client.py | 6 +++++- tests/test_graphqlws_subscription.py | 11 ++++++++--- tests/test_websocket_subscription.py | 11 ++++++++--- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/gql/client.py b/gql/client.py index c5f1af39..124cf34b 100644 --- a/gql/client.py +++ b/gql/client.py @@ -220,7 +220,11 @@ def subscribe( # Note: we need to create a task here in order to be able to close # the async generator properly on python 3.8 # See https://bugs.python.org/issue38559 - generator_task = asyncio.ensure_future(async_generator.__anext__()) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", message="There is no current event loop" + ) + generator_task = asyncio.ensure_future(async_generator.__anext__()) result = loop.run_until_complete(generator_task) yield result diff --git a/tests/test_graphqlws_subscription.py b/tests/test_graphqlws_subscription.py index 2c7cff23..3b7cab0a 100644 --- a/tests/test_graphqlws_subscription.py +++ b/tests/test_graphqlws_subscription.py @@ -1,4 +1,5 @@ import asyncio +import warnings import json import sys from typing import List @@ -742,9 +743,13 @@ def test_graphqlws_subscription_sync_graceful_shutdown( if count == 5: # Simulate a KeyboardInterrupt in the generator - asyncio.ensure_future( - client.session._generator.athrow(KeyboardInterrupt) - ) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", message="There is no current event loop" + ) + asyncio.ensure_future( + client.session._generator.athrow(KeyboardInterrupt) + ) count -= 1 diff --git a/tests/test_websocket_subscription.py b/tests/test_websocket_subscription.py index ff484157..0b206c2d 100644 --- a/tests/test_websocket_subscription.py +++ b/tests/test_websocket_subscription.py @@ -1,4 +1,5 @@ import asyncio +import warnings import json import sys from typing import List @@ -531,9 +532,13 @@ def test_websocket_subscription_sync_graceful_shutdown(server, subscription_str) if count == 5: # Simulate a KeyboardInterrupt in the generator - asyncio.ensure_future( - client.session._generator.athrow(KeyboardInterrupt) - ) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", message="There is no current event loop" + ) + asyncio.ensure_future( + client.session._generator.athrow(KeyboardInterrupt) + ) count -= 1 From 64ab3ae473b8170f755fce397026cb8ae2fcc1a9 Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 15:29:55 +0100 Subject: [PATCH 09/11] make check --- gql/client.py | 1 + tests/test_graphqlws_subscription.py | 2 +- tests/test_websocket_subscription.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gql/client.py b/gql/client.py index cd5fe955..124cf34b 100644 --- a/gql/client.py +++ b/gql/client.py @@ -1,4 +1,5 @@ import asyncio +import warnings from typing import Any, AsyncGenerator, Dict, Generator, Optional, Union from graphql import ( diff --git a/tests/test_graphqlws_subscription.py b/tests/test_graphqlws_subscription.py index 3b7cab0a..7826aca1 100644 --- a/tests/test_graphqlws_subscription.py +++ b/tests/test_graphqlws_subscription.py @@ -1,7 +1,7 @@ import asyncio -import warnings import json import sys +import warnings from typing import List import pytest diff --git a/tests/test_websocket_subscription.py b/tests/test_websocket_subscription.py index 0b206c2d..43795b14 100644 --- a/tests/test_websocket_subscription.py +++ b/tests/test_websocket_subscription.py @@ -1,7 +1,7 @@ import asyncio -import warnings import json import sys +import warnings from typing import List import pytest From 622a7559253da860e2f3bb4d5001a512f25c31e5 Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 15:46:05 +0100 Subject: [PATCH 10/11] Install different version of websockets depending on python version --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index da8f336d..c7e6dd7f 100644 --- a/setup.py +++ b/setup.py @@ -46,7 +46,8 @@ ] install_websockets_requires = [ - "websockets>=10,<11", + "websockets>=9,<10;python_version<='3.6'", + "websockets>=10,<11;python_version>'3.6'", ] install_all_requires = ( From 3511c5b66d32b1ab57baf000e94b4aa754f93547 Mon Sep 17 00:00:00 2001 From: Hanusz Leszek Date: Thu, 25 Nov 2021 16:05:02 +0100 Subject: [PATCH 11/11] Fix set logging to DEBUG for all tests --- tests/conftest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 519738cc..6fd9fc44 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -102,8 +102,10 @@ async def go(app, *, port=None, **kwargs): # type: ignore # Adding debug logs to websocket tests for name in [ "websockets.legacy.server", - "gql.transport.websockets", + "gql.transport.aiohttp", "gql.transport.phoenix_channel_websockets", + "gql.transport.requests", + "gql.transport.websockets", "gql.dsl", "gql.utilities.parse_result", ]: