Skip to content

Commit aa42aa4

Browse files
committed
linters
1 parent a94734d commit aa42aa4

File tree

7 files changed

+66
-55
lines changed

7 files changed

+66
-55
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from .web_service_mock import MockData, WebServiceMock
2-
from .fixtures import external_service_mock
2+
from .fixtures import external_service_mock, AddMockDataFunc
33

44
__all__ = [
55
"MockData",
66
"WebServiceMock",
77
"external_service_mock",
8+
"AddMockDataFunc",
89
]
Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,26 @@
1-
from typing import Callable
2-
3-
import pytest_asyncio
1+
from typing import Any, Awaitable, Callable, List, Tuple
42
from aiohttp import web
3+
from aiohttp.test_utils import TestServer
4+
import pytest_asyncio
55

66
from .web_service_mock import MockData, WebServiceMock
77

8+
AddMockDataFunc = Callable[[MockData], List[dict[str, Any]]]
89

9-
@pytest_asyncio.fixture
10-
async def external_service_mock(aiohttp_server):
11-
"""
12-
Mock server for an external service
1310

14-
Returns:
15-
function for adding an API to the server
16-
"""
11+
@pytest_asyncio.fixture
12+
async def external_service_mock(
13+
aiohttp_server: Callable[[web.Application], Awaitable[TestServer]],
14+
) -> Callable[[], Awaitable[Tuple[str, AddMockDataFunc]]]:
15+
"""Mock server for an external service."""
1716

18-
async def _create_mock() -> tuple[
19-
str, Callable[[MockData], list[dict[str, any]]]
20-
]:
17+
async def _create_mock() -> Tuple[str, AddMockDataFunc]:
2118
app = web.Application()
2219
web_service = WebServiceMock()
23-
# The route catches requests for any path with any method.
24-
# The web_service is responsible for actual routing, allowing new
25-
# APIs to be added at server runtime.
20+
2621
app.router.add_route("*", "/{tail:.+}", web_service.handle)
22+
2723
server = await aiohttp_server(app)
28-
return f"http://{server.host}:{server.port}", web_service.add_mock_data
24+
return str(server.make_url("")), web_service.add_mock_data
2925

3026
return _create_mock
Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
from copy import deepcopy
22
from dataclasses import dataclass
33
from inspect import isawaitable
4-
from typing import Awaitable, Callable
4+
from typing import Any, Awaitable, Callable
55

66
from aiohttp import web
77

88

9+
ResponseHandler = Callable[
10+
[web.Request], web.Response | Awaitable[web.Response]
11+
]
12+
13+
914
@dataclass
1015
class MockData:
1116
method: str # the method we replace
1217
path: str # the API path we are replacing
13-
response: (
14-
web.Response
15-
| Callable[[web.Request], web.Response | Awaitable[web.Response]]
16-
)
18+
response: web.Response | ResponseHandler
1719

1820

1921
class WebServiceMock:
@@ -24,9 +26,9 @@ class WebServiceMock:
2426
2. Add real APIs via add_mock_data
2527
"""
2628

27-
def __init__(self):
29+
def __init__(self) -> None:
2830
self._mock_data: list[MockData] = []
29-
self._call_info = {}
31+
self._call_info: dict[str, dict[str, list[dict[str, Any]]]] = {}
3032

3133
async def handle(self, request: web.Request) -> web.Response:
3234
"""
@@ -41,19 +43,18 @@ async def handle(self, request: web.Request) -> web.Response:
4143
await self._save_request(mock.method, mock.path, request)
4244
if isinstance(mock.response, web.Response):
4345
return deepcopy(mock.response)
44-
else:
45-
response = mock.response(request)
46-
if isawaitable(response):
47-
return await response
48-
else:
49-
return response
50-
51-
raise Exception(
46+
47+
response = mock.response(request)
48+
if isawaitable(response):
49+
return await response
50+
return response
51+
52+
raise LookupError(
5253
f"Mock with method={request.method} "
5354
f"and url={request.path} not found"
5455
)
5556

56-
def add_mock_data(self, mock_data: MockData) -> list[dict[str, any]]:
57+
def add_mock_data(self, mock_data: MockData) -> list[dict[str, Any]]:
5758
"""Saves a new mock and returns a reference to the call history"""
5859
self._mock_data.append(mock_data)
5960

@@ -66,11 +67,12 @@ def add_mock_data(self, mock_data: MockData) -> list[dict[str, any]]:
6667
async def _save_request(
6768
self, method: str, path: str, request: web.Request
6869
) -> None:
69-
data = {"headers": request.headers}
70+
data: dict[str, Any] = {"headers": request.headers}
71+
7072
if request.can_read_body:
7173
if request.content_type == "application/json":
7274
data["json"] = await request.json()
73-
if request.content_type == "text/plain":
75+
elif request.content_type == "text/plain":
7476
data["text"] = await request.text()
7577

7678
self._call_info[path][method].append(data)

mypy.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[mypy]
22
strict = true
33
pretty = true
4+
5+
[mypy-tests.*]
6+
disable_error_code = no-untyped-def

pyproject.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,3 @@ dev = [
1818
"ruff>=0.14.8",
1919
"wemake-python-styleguide>=1.4.0",
2020
]
21-
22-
[project.entry-points.pytest11]
23-
my_fixtures = "async_pytest_httpserver.fixtures"

setup.cfg

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
[flake8]
22
exclude = .venv
3-
;ignore=WPS476, WPS300, WPS410, WPS412, WPS501, WPS229, WPS202, WPS110, WPS473
4-
; WPS217, WPS430, WPS420
5-
;
6-
;per-file-ignores =
7-
; examples/*: WPS110, WPS432, WPS204, WPS114, WPS226, WPS201, WPS213
3+
ignore=WPS110, WPS430, WPS234, WPS300, WPS476, W503, WPS412, WPS410
4+
5+
per-file-ignores =
6+
tests/*: WPS226, WPS300

tests/conftest.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,56 @@
1-
from typing import Any, AsyncGenerator, Awaitable, Callable
1+
from typing import Any, AsyncGenerator, Awaitable, Callable, List
22

33
import pytest
44
import pytest_asyncio
55
from aiohttp import web, ClientSession
66

7-
from async_pytest_httpserver import MockData
7+
from async_pytest_httpserver import (
8+
MockData,
9+
AddMockDataFunc,
10+
)
811
from . import settings
912

1013

1114
@pytest_asyncio.fixture
1215
async def some_service_mock(
13-
external_service_mock,
14-
) -> AsyncGenerator[Callable[[MockData], list[dict[str, any]]]]:
16+
external_service_mock: Callable[
17+
[], Awaitable[tuple[str, AddMockDataFunc]]
18+
],
19+
) -> AsyncGenerator[AddMockDataFunc, None]:
1520
"""
1621
Example of how to use
1722
"""
1823
url, add_mock_data = await external_service_mock()
19-
# You have a URL for an external service specified somewhere.
20-
# We're replacing it with a new one as part of our testing.
2124
old_url = settings.EXTERNAL_SERVICE_URL
2225
settings.EXTERNAL_SERVICE_URL = url
23-
yield add_mock_data
24-
settings.EXTERNAL_SERVICE_URL = old_url
26+
try:
27+
yield add_mock_data
28+
finally:
29+
settings.EXTERNAL_SERVICE_URL = old_url
2530

2631

2732
@pytest.fixture
28-
def some_service_mock_api(some_service_mock):
33+
def some_service_mock_api(
34+
some_service_mock: AddMockDataFunc,
35+
) -> Callable[
36+
[
37+
web.Response
38+
| Callable[[web.Request], web.Response | Awaitable[web.Response]]
39+
],
40+
List[dict[str, Any]],
41+
]:
2942
"""An example of a fixture where a specific API is mocked"""
3043

3144
def _create_mock(
3245
response: web.Response
3346
| Callable[[web.Request], web.Response | Awaitable[web.Response]],
34-
) -> list[dict[str, Any]]:
47+
) -> List[dict[str, Any]]:
3548
return some_service_mock(MockData("POST", "/some_api", response))
3649

3750
return _create_mock
3851

3952

4053
@pytest_asyncio.fixture
41-
async def client() -> AsyncGenerator[ClientSession, Any]:
54+
async def client() -> AsyncGenerator[ClientSession, None]:
4255
async with ClientSession() as session:
4356
yield session

0 commit comments

Comments
 (0)