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" diff --git a/gql/client.py b/gql/client.py index fc686c16..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 ( @@ -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) @@ -211,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/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) diff --git a/setup.py b/setup.py index 94f3a9ee..c7e6dd7f 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", @@ -26,10 +26,13 @@ "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", + "types-aiofiles", + "types-mock", + "types-requests", ] + tests_requires install_aiohttp_requires = [ @@ -43,7 +46,8 @@ ] install_websockets_requires = [ - "websockets>=9,<10", + "websockets>=9,<10;python_version<='3.6'", + "websockets>=10,<11;python_version>'3.6'", ] install_all_requires = ( @@ -67,14 +71,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/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", ]: diff --git a/tests/test_graphqlws_subscription.py b/tests/test_graphqlws_subscription.py index 2c7cff23..7826aca1 100644 --- a/tests/test_graphqlws_subscription.py +++ b/tests/test_graphqlws_subscription.py @@ -1,6 +1,7 @@ import asyncio import json import sys +import warnings from typing import List import pytest @@ -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..43795b14 100644 --- a/tests/test_websocket_subscription.py +++ b/tests/test_websocket_subscription.py @@ -1,6 +1,7 @@ import asyncio import json import sys +import warnings from typing import List import pytest @@ -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 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]