Skip to content

Commit 33ea2ab

Browse files
wiseaidevfselmokclowes
committed
➕ Add Python 3.10 support (ethereum#2175)
* ➕ Add Python 3.10 support to CI * Dropped support for all parities * Change docker image to use 3.10 * Update pytest-asyncio plugin * Mark async fixture as such, clean up pytest DeprecationWarnings Signed-off-by: Harmouch101 <[email protected]> Co-authored-by: Felipe Selmo <[email protected]> Co-authored-by: kclowes <[email protected]> Signed-off-by: Harmouch101 <[email protected]>
1 parent 26c6d8f commit 33ea2ab

File tree

14 files changed

+179
-47
lines changed

14 files changed

+179
-47
lines changed

.circleci/config.yml

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,75 @@ jobs:
421421
environment:
422422
TOXENV: py39-wheel-cli
423423

424+
#
425+
# Python 3.10
426+
#
427+
py310-core:
428+
<<: *common
429+
docker:
430+
- image: circleci/python:3.10
431+
environment:
432+
TOXENV: py310-core
433+
434+
py310-ens:
435+
<<: *common
436+
docker:
437+
- image: circleci/python:3.10
438+
environment:
439+
TOXENV: py310-ens
440+
441+
py310-ethpm:
442+
<<: *ethpm_steps
443+
docker:
444+
- image: circleci/python:3.10
445+
environment:
446+
TOXENV: py310-ethpm
447+
# Please don't use this key for any shenanigans
448+
WEB3_INFURA_PROJECT_ID: 7707850c2fb7465ebe6f150d67182e22
449+
450+
py310-integration-goethereum-ipc:
451+
<<: *geth_steps
452+
docker:
453+
- image: circleci/python:3.10
454+
environment:
455+
TOXENV: py310-integration-goethereum-ipc
456+
GETH_VERSION: v1.10.11
457+
458+
py310-integration-goethereum-http:
459+
<<: *geth_steps
460+
docker:
461+
- image: circleci/python:3.10
462+
environment:
463+
TOXENV: py310-integration-goethereum-http
464+
GETH_VERSION: v1.10.11
465+
466+
py310-integration-goethereum-ws:
467+
<<: *geth_steps
468+
docker:
469+
- image: circleci/python:3.10
470+
environment:
471+
TOXENV: py310-integration-goethereum-ws
472+
GETH_VERSION: v1.10.11
473+
474+
py310-integration-ethtester-pyevm:
475+
<<: *common
476+
docker:
477+
- image: circleci/python:3.10
478+
environment:
479+
TOXENV: py310-integration-ethtester
480+
ETHEREUM_TESTER_CHAIN_BACKEND: eth_tester.backends.PyEVMBackend
481+
482+
py310-wheel-cli:
483+
<<: *common
484+
docker:
485+
- image: circleci/python:3.10
486+
environment:
487+
TOXENV: py310-wheel-cli
488+
424489
benchmark:
425490
<<: *geth_steps
426491
docker:
427-
- image: circleci/python:3.9
492+
- image: circleci/python:3.10
428493
environment:
429494
TOXENV: benchmark
430495
GETH_VERSION: v1.10.13
@@ -437,6 +502,7 @@ workflows:
437502
- py37-core
438503
- py38-core
439504
- py39-core
505+
- py310-core
440506
- lint
441507
- docs
442508
- benchmark
@@ -462,3 +528,10 @@ workflows:
462528
- py39-integration-goethereum-ws
463529
- py39-integration-ethtester-pyevm
464530
- py39-wheel-cli
531+
- py310-ens
532+
- py310-ethpm
533+
- py310-integration-goethereum-ipc
534+
- py310-integration-goethereum-http
535+
- py310-integration-goethereum-ws
536+
- py310-integration-ethtester-pyevm
537+
- py310-wheel-cli

newsfragments/2175.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add support for Python 3.10

newsfragments/2344.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Adds a depreaction warning for the optional ``loop`` parameter of ``web3.providers.websocket``.

pytest.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
addopts= -v --showlocals --durations 10
33
python_paths= .
44
xfail_strict=true
5+
asyncio_mode=strict
56

67
[pytest-watch]
78
runner= pytest --failed-first --maxfail=1 --no-success-flaky-report

setup.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"contextlib2>=0.5.4",
2727
"py-geth>=3.6.0,<4",
2828
"py-solc>=0.4.0",
29-
"pytest>=4.4.0,<5.0.0",
29+
"pytest>=6.2.5,<7",
3030
"sphinx>=3.0,<4",
3131
"sphinx_rtd_theme>=0.1.9",
3232
"toposort>=1.4",
@@ -38,8 +38,8 @@
3838
"bumpversion",
3939
"flaky>=3.7.0,<4",
4040
"hypothesis>=3.31.2,<6",
41-
"pytest>=4.4.0,<5.0.0",
42-
"pytest-asyncio>=0.10.0,<0.11",
41+
"pytest>=6.2.5,<7",
42+
"pytest-asyncio>=0.18.1,<0.19",
4343
"pytest-mock>=1.10,<2",
4444
"pytest-pythonpath>=0.3",
4545
"pytest-watch>=4.2,<5",
@@ -92,7 +92,7 @@
9292
"typing-extensions>=3.7.4.1,<5;python_version<'3.8'",
9393
"websockets>=10.0.0,<11",
9494
],
95-
python_requires='>=3.7,<3.10',
95+
python_requires='>=3.7,<3.11',
9696
extras_require=extras_require,
9797
py_modules=['web3', 'ens', 'ethpm'],
9898
entry_points={"pytest11": ["pytest_ethereum = web3.tools.pytest_ethereum.plugins"]},
@@ -110,5 +110,6 @@
110110
'Programming Language :: Python :: 3.7',
111111
'Programming Language :: Python :: 3.8',
112112
'Programming Language :: Python :: 3.9',
113+
'Programming Language :: Python :: 3.10',
113114
],
114115
)

tests/core/providers/test_websocket_provider.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
ValidationError,
1616
)
1717
from web3.providers.websocket import (
18+
PersistentWebSocket,
1819
WebsocketProvider,
1920
)
2021

@@ -28,7 +29,7 @@
2829
)
2930

3031

31-
@pytest.yield_fixture
32+
@pytest.fixture
3233
def start_websocket_server(open_port):
3334
event_loop = asyncio.new_event_loop()
3435

@@ -39,7 +40,7 @@ async def empty_server(websocket, path):
3940
await websocket.send(data)
4041

4142
asyncio.set_event_loop(event_loop)
42-
server = websockets.serve(empty_server, '127.0.0.1', open_port)
43+
server = websockets.serve(empty_server, "127.0.0.1", open_port)
4344
event_loop.run_until_complete(server)
4445
event_loop.run_forever()
4546

@@ -51,11 +52,11 @@ async def empty_server(websocket, path):
5152
event_loop.call_soon_threadsafe(event_loop.stop)
5253

5354

54-
@pytest.fixture()
55+
@pytest.fixture
5556
def w3(open_port, start_websocket_server):
5657
# need new event loop as the one used by server is already running
5758
event_loop = asyncio.new_event_loop()
58-
endpoint_uri = 'ws://127.0.0.1:{}'.format(open_port)
59+
endpoint_uri = "ws://127.0.0.1:{}".format(open_port)
5960
event_loop.run_until_complete(wait_for_ws(endpoint_uri))
6061
provider = WebsocketProvider(endpoint_uri, websocket_timeout=0.01)
6162
return Web3(provider)
@@ -67,7 +68,28 @@ def test_websocket_provider_timeout(w3):
6768

6869

6970
def test_restricted_websocket_kwargs():
70-
invalid_kwargs = {'uri': 'ws://127.0.0.1:8546'}
71-
re_exc_message = r'.*found: {0}*'.format(set(invalid_kwargs.keys()))
71+
invalid_kwargs = {"uri": "ws://127.0.0.1:8546"}
72+
re_exc_message = r".*found: {0}*".format(set(invalid_kwargs.keys()))
7273
with pytest.raises(ValidationError, match=re_exc_message):
7374
WebsocketProvider(websocket_kwargs=invalid_kwargs)
75+
76+
77+
def test_event_loop_argument_deprecated():
78+
event_loop = asyncio.new_event_loop()
79+
endpoint_uri = "ws://127.0.0.1:8546"
80+
websocket_kwargs = {}
81+
match = (
82+
"The loop parameter is deprecated and was removed from websocket "
83+
"provider as of web3 v5. Consider instantiating this class without passing this argument instead."
84+
)
85+
with pytest.warns(
86+
expected_warning=DeprecationWarning,
87+
match=match,
88+
):
89+
WebsocketProvider(endpoint_uri, websocket_timeout=0.01, loop=event_loop)
90+
with pytest.warns(
91+
expected_warning=DeprecationWarning,
92+
match=match,
93+
):
94+
PersistentWebSocket(endpoint_uri, websocket_kwargs, loop=event_loop)
95+
event_loop.close()

tests/integration/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def revert_contract_factory(web3):
3737
return contract_factory
3838

3939

40-
@pytest.yield_fixture(scope="module")
40+
@pytest.fixture(scope="module")
4141
def event_loop(request):
4242
loop = asyncio.get_event_loop_policy().new_event_loop()
4343
yield loop

tests/integration/go_ethereum/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def unlockable_account_dual_type(unlockable_account, address_conversion_func):
181181
return address_conversion_func(unlockable_account)
182182

183183

184-
@pytest.yield_fixture
184+
@pytest.fixture
185185
def unlocked_account_dual_type(web3, unlockable_account_dual_type, unlockable_account_pw):
186186
web3.geth.personal.unlock_account(unlockable_account_dual_type, unlockable_account_pw)
187187
yield unlockable_account_dual_type

tests/integration/go_ethereum/test_goethereum_http.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import pytest
22

3+
import pytest_asyncio
4+
35
from tests.utils import (
46
get_open_port,
57
)
@@ -94,7 +96,7 @@ def web3(geth_process, endpoint_uri):
9496
return _web3
9597

9698

97-
@pytest.fixture(scope="module")
99+
@pytest_asyncio.fixture(scope="module")
98100
async def async_w3(geth_process, endpoint_uri):
99101
await wait_for_aiohttp(endpoint_uri)
100102
_web3 = Web3(

tests/utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
import asyncio
22
import socket
33
import time
4+
import warnings
45

56
import websockets
67

78

89
def get_open_port():
910
sock = socket.socket()
10-
sock.bind(('127.0.0.1', 0))
11+
sock.bind(("127.0.0.1", 0))
1112
port = sock.getsockname()[1]
1213
sock.close()
1314
return str(port)
1415

1516

1617
async def wait_for_ws(endpoint_uri, timeout=10):
1718
start = time.time()
18-
while time.time() < start + timeout:
19+
stop = start + timeout
20+
while time.time() < stop:
1921
try:
2022
async with websockets.connect(uri=endpoint_uri):
2123
pass

0 commit comments

Comments
 (0)