Skip to content

Support python 3.10 #264

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"

Expand Down
19 changes: 16 additions & 3 deletions gql/client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
import warnings
from typing import Any, AsyncGenerator, Dict, Generator, Optional, Union

from graphql import (
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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

Expand Down
7 changes: 6 additions & 1 deletion gql/transport/websockets.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)
Expand Down
18 changes: 12 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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 = [
Expand All @@ -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 = (
Expand All @@ -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",
Expand Down
4 changes: 3 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
]:
Expand Down
11 changes: 8 additions & 3 deletions tests/test_graphqlws_subscription.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio
import json
import sys
import warnings
from typing import List

import pytest
Expand Down Expand Up @@ -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

Expand Down
11 changes: 8 additions & 3 deletions tests/test_websocket_subscription.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio
import json
import sys
import warnings
from typing import List

import pytest
Expand Down Expand Up @@ -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

Expand Down
5 changes: 3 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -12,6 +12,7 @@ python =
3.7: py37
3.8: py38
3.9: py39
3.10: py310
pypy3: pypy3

[testenv]
Expand All @@ -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]
Expand Down