Skip to content

Commit 162a39a

Browse files
committed
mypy fixes and compatibility with aiohttp>=3.8
1 parent 0069072 commit 162a39a

File tree

12 files changed

+98
-91
lines changed

12 files changed

+98
-91
lines changed

.github/workflows/tests.yml

+5-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
with:
3030
args: tox
3131

32-
build:
32+
tests:
3333
needs: lint
3434
runs-on: ubuntu-latest
3535

@@ -38,19 +38,20 @@ jobs:
3838

3939
matrix:
4040
toxenv:
41-
- py35
42-
- py36
4341
- py37
4442
- py38
4543
- py39
44+
- py310
4645

4746
steps:
4847
- uses: actions/checkout@v2
4948

5049
- name: tox ${{ matrix.toxenv }}
5150
uses: docker://snakepacker/python:all
5251
env:
53-
TOXENV: ${{ matrix.toxenv }}
5452
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
53+
FORCE_COLOR: yes
54+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55+
TOXENV: ${{ matrix.toxenv }}
5556
with:
5657
args: tox

pytest.ini

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
python_files = test_*
33
python_functions = test_*
44
python_classes = TestSuite*
5+
asyncio_mode=auto

setup.py

+13-17
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010
).load_module()
1111

1212

13+
TEST_REQUIRES = [
14+
"async-timeout~=4.0.2",
15+
"pytest~=7.1.2",
16+
"pytest-aiohttp~=1.0.4",
17+
"pytest-cov~=3.0.0",
18+
"coverage!=4.3",
19+
"coveralls~=3.3.1",
20+
]
21+
22+
1323
setup(
1424
name="wsrpc-aiohttp",
1525
version=module.__version__,
@@ -31,11 +41,10 @@
3141
"Operating System :: Microsoft",
3242
"Programming Language :: Python",
3343
"Programming Language :: Python :: 3",
34-
"Programming Language :: Python :: 3.5",
35-
"Programming Language :: Python :: 3.6",
3644
"Programming Language :: Python :: 3.7",
3745
"Programming Language :: Python :: 3.8",
3846
"Programming Language :: Python :: 3.9",
47+
"Programming Language :: Python :: 3.10",
3948
"Programming Language :: Python :: Implementation :: CPython",
4049
],
4150
long_description=open("README.md").read(),
@@ -46,24 +55,11 @@
4655
python_requires=">3.5.*, <4",
4756
extras_require={
4857
"ujson": ["ujson"],
49-
"testing": [
50-
"async-timeout",
51-
"pytest",
52-
"pytest-aiohttp",
53-
"pytest-cov",
54-
"coverage!=4.3",
55-
"coveralls",
56-
],
58+
"testing": TEST_REQUIRES,
5759
"develop": [
58-
"async-timeout",
59-
"coverage!=4.3",
60-
"coveralls",
61-
"pytest",
62-
"pytest-aiohttp",
63-
"pytest-cov",
6460
"Sphinx",
6561
"sphinxcontrib-plantuml",
6662
"tox>=2.4",
67-
],
63+
] + TEST_REQUIRES,
6864
},
6965
)

tests/conftest.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ def application(handler, socket_path):
2222

2323

2424
@pytest.fixture
25-
async def session(aiohttp_client, application, loop) -> ClientSession:
25+
async def session(aiohttp_client, application, event_loop) -> ClientSession:
2626
return await aiohttp_client(application)
2727

2828

2929
@pytest.fixture
30-
async def client(session: ClientSession, socket_path, loop) -> WSRPCClient:
31-
return WSRPCClient(socket_path, session=session, loop=loop)
30+
async def client(
31+
session: ClientSession, socket_path, event_loop
32+
) -> WSRPCClient:
33+
return WSRPCClient(socket_path, session=session, loop=event_loop)

tests/test_events.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ async def emitter(socket: WSRPCBase):
55
await socket.emit({"Hello": "world"})
66

77

8-
async def test_emitter(client: WSRPCClient, handler, loop):
8+
async def test_emitter(client: WSRPCClient, handler, event_loop):
99
handler.add_route("emitter", emitter)
1010

1111
async with client:
12-
future = loop.create_future()
12+
future = event_loop.create_future()
1313

1414
client.add_event_listener(future.set_result)
1515

tests/test_route.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -102,23 +102,21 @@ def foobar(self):
102102
assert "foobar" not in FooRoute.__no_proxy__
103103

104104

105-
def test_route__init__(loop):
105+
async def test_route__init__(event_loop):
106106
socket = Mock()
107-
socket._loop = object()
108-
109107
route = Route(socket)
110108

111109
assert route.socket is socket
112-
assert route.loop is socket._loop
110+
assert route.loop is event_loop
113111

114112
socket = object()
115113
route = Route(socket)
116114

117115
assert route.socket is socket
118-
assert route.loop is loop
116+
assert route.loop is event_loop
119117

120118

121-
def test_abc_inheritance(loop):
119+
def test_abc_inheritance(event_loop):
122120
class AbstractMixin(ABC):
123121
@abstractmethod
124122
def foo(self):

tests/test_rpc_route.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ async def test_call_when_params_none(
151151

152152

153153
async def test_broadcast(
154-
client: WSRPCClient, handler: WebSocketAsync, route: Route, loop
154+
client: WSRPCClient, handler: WebSocketAsync, route: Route, event_loop
155155
):
156156
async with client:
157-
future = loop.create_future()
157+
future = event_loop.create_future()
158158

159159
async def on_broadcast(_, result):
160160
nonlocal future
@@ -229,7 +229,7 @@ def get_data(self, _):
229229

230230
async def test_call_timeout(client: WSRPCClient, handler: WebSocketAsync):
231231
async def will_sleep_for(_, seconds):
232-
with timeout(0.5):
232+
async with timeout(0.5):
233233
await asyncio.sleep(seconds)
234234
return DATA_TO_RETURN
235235

tox.ini

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
[tox]
2-
envlist = lint,mypy,py3{5,6,7,8,9}
2+
envlist = lint,mypy,py3{7,8,9,10}
33

44
[testenv]
5-
passenv = COVERALLS_* AMQP_*
5+
passenv = COVERALLS_* AMQP_* GITHUB_* FORCE_COLOR
66

77
extras =
88
testing
99

1010
commands=
11-
py.test -vv -p no:asyncio \
11+
py.test -vv \
1212
--cov=wsrpc_aiohttp \
1313
--cov-report=term-missing \
1414
--doctest-modules \
@@ -21,7 +21,7 @@ deps =
2121
pylava
2222

2323
commands=
24-
pylava -o pylava.ini .
24+
pylava -o pylava.ini wsrpc_aiohttp tests
2525

2626
[testenv:mypy]
2727
usedevelop = true

wsrpc_aiohttp/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
team_email = "me@mosquito.su"
77

8-
version_info = (3, 1, 2)
8+
version_info = (3, 2, 1)
99

1010

1111
__author__ = ", ".join("{} <{}>".format(*info) for info in author_info)

wsrpc_aiohttp/websocket/abc.py

+49-39
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import asyncio
2-
from abc import (
3-
ABC, abstractmethod, abstractclassmethod, abstractproperty,
4-
abstractstaticmethod
5-
)
2+
from abc import ABC, abstractmethod
63
from enum import IntEnum
74
from typing import Any, Mapping, Coroutine, Union, Callable, Dict, Tuple
85

@@ -16,7 +13,8 @@ class AbstractWebSocket(ABC):
1613
def __init__(self, request: Request):
1714
raise NotImplementedError(request)
1815

19-
@abstractclassmethod
16+
@classmethod
17+
@abstractmethod
2018
def configure(cls, keepalive_timeout: int,
2119
client_timeout: int,
2220
max_concurrent_requests: int) -> None:
@@ -55,7 +53,8 @@ async def authorize(self) -> bool:
5553
async def __handle_request(self) -> WebSocketResponse:
5654
raise NotImplementedError
5755

58-
@abstractclassmethod
56+
@classmethod
57+
@abstractmethod
5958
def broadcast(
6059
cls, func, callback=None, return_exceptions=True,
6160
**kwargs: Mapping[str, Any]
@@ -115,7 +114,7 @@ def __getattr__(self, item: str):
115114
EventListenerType = Callable[[Dict[str, Any]], Any]
116115

117116

118-
class AbstactWSRPC(ABC):
117+
class WSRPCBase(ABC):
119118
@abstractmethod
120119
def __init__(self, loop: asyncio.AbstractEventLoop = None,
121120
timeout: Union[int, float] = None):
@@ -138,28 +137,31 @@ async def handle_message(self, message: WSMessage):
138137
async def _on_message(self, msg: WSMessage):
139138
raise NotImplementedError
140139

141-
@abstractclassmethod
140+
@classmethod
141+
@abstractmethod
142142
def get_routes(cls) -> Mapping[str, "RouteType"]:
143143
raise NotImplementedError
144144

145145
@classmethod
146-
def get_clients(cls) -> Dict[str, "AbstactWSRPC"]:
146+
def get_clients(cls) -> Dict[str, "AbstractWSRPC"]:
147147
raise NotImplementedError
148148

149-
@abstractproperty
149+
@property
150+
@abstractmethod
150151
def routes(self) -> Dict[str, "RouteType"]:
151152
raise NotImplementedError
152153

153154
@property
154-
def clients(self) -> Dict[str, "AbstactWSRPC"]:
155+
def clients(self) -> Dict[str, "AbstractWSRPC"]:
155156
""" Property which contains the socket clients """
156157
raise NotImplementedError
157158

158159
@abstractmethod
159160
def prepare_args(self, args) -> Tuple[Tuple[Any, ...], Dict[str, Any]]:
160161
raise NotImplementedError
161162

162-
@abstractstaticmethod
163+
@staticmethod
164+
@abstractmethod
163165
def is_route(func) -> bool:
164166
raise NotImplementedError
165167

@@ -217,30 +219,6 @@ async def make_something(self, foo, bar):
217219
async def emit(self, event: Any) -> None:
218220
pass
219221

220-
@abstractclassmethod
221-
def add_route(cls, route: str,
222-
handler: Union[AbstractRoute, Callable]) -> None:
223-
""" Expose local function through RPC
224-
225-
:param route: Name which function will be aliased for this function.
226-
Remote side should call function by this name.
227-
:param handler: Function or Route class (classes based on
228-
:class:`wsrpc_aiohttp.WebSocketRoute`).
229-
For route classes the public methods will
230-
be registered automatically.
231-
232-
.. note::
233-
234-
Route classes might be initialized only once for the each
235-
socket instance.
236-
237-
In case the method of class will be called first,
238-
:func:`wsrpc_aiohttp.WebSocketRoute.init` will be called
239-
without params before callable method.
240-
241-
"""
242-
raise NotImplementedError
243-
244222
@abstractmethod
245223
def add_event_listener(self, func: EventListenerType) -> None:
246224
raise NotImplementedError
@@ -255,7 +233,8 @@ def remove_route(cls, route: str, fail=True):
255233

256234
raise NotImplementedError
257235

258-
@abstractproperty
236+
@property
237+
@abstractmethod
259238
def proxy(self) -> Proxy:
260239
""" Special property which allow run the remote functions
261240
by `dot` notation
@@ -272,8 +251,39 @@ def proxy(self) -> Proxy:
272251

273252

274253
RouteType = Union[
275-
Callable[[AbstactWSRPC, Any], Any],
276-
Callable[[AbstactWSRPC, Any], Coroutine[Any, None, Any]],
254+
Callable[[WSRPCBase, Any], Any],
255+
Callable[[WSRPCBase, Any], Coroutine[Any, None, Any]],
277256
AbstractRoute
278257
]
258+
259+
260+
class AbstractWSRPC(WSRPCBase, ABC):
261+
@classmethod
262+
@abstractmethod
263+
def add_route(cls, route: str, handler: RouteType) -> None:
264+
""" Expose local function through RPC
265+
266+
:param route: Name which function will be aliased for this function.
267+
Remote side should call function by this name.
268+
:param handler: Function or Route class (classes based on
269+
:class:`wsrpc_aiohttp.WebSocketRoute`).
270+
For route classes the public methods will
271+
be registered automatically.
272+
273+
.. note::
274+
275+
Route classes might be initialized only once for each
276+
socket instance.
277+
278+
In case the method of class will be called first,
279+
:func:`wsrpc_aiohttp.WebSocketRoute.init` will be called
280+
without params before callable method.
281+
282+
"""
283+
raise NotImplementedError
284+
285+
286+
# backward compatibility for typo
287+
# noinspection SpellCheckingInspection
288+
AbstactWSRPC = AbstractWSRPC
279289
FrameMappingItemType = Mapping[IntEnum, Callable[[WSMessage], Any]]

0 commit comments

Comments
 (0)