Skip to content

Commit

Permalink
more strict ruff rules
Browse files Browse the repository at this point in the history
  • Loading branch information
Tishka17 committed Jul 27, 2024
1 parent 600fa86 commit 508ccf1
Show file tree
Hide file tree
Showing 15 changed files with 142 additions and 57 deletions.
42 changes: 42 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
line-length = 79
target-version="py38"
src = ["src"]

include = ["src/**.py", "tests/**.py"]
exclude = ["src/dishka/_adaptix/**"]

lint.select = [
"ALL"
]
lint.ignore = [
"ARG",
"ANN",
"D",
"EM101",
"EM102",
"PT001",
"PT023",
"SIM108",
"SIM114",
"TRY003",
"PLW2901",
"RET505",
"RET506",
"PLR0913",
"UP038",
"TCH001",
"FA100",
# tempraty disabled
"PGH005",
"PLR2004",
"N818", # compatibility issue
]

[lint.per-file-ignores]
"tests/**" = ["TID252", "PLR2004", "S101", "A002"]

[lint.isort]
no-lines-before = ["local-folder"]

[lint.flake8-tidy-imports]
ban-relative-imports = "parents"
2 changes: 1 addition & 1 deletion src/dataclass_rest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
]

from .http_request import File
from .rest import rest, get, put, post, patch, delete
from .rest import delete, get, patch, post, put, rest
3 changes: 2 additions & 1 deletion src/dataclass_rest/base_client.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from adaptix import Retort

from .client_protocol import (
ClientProtocol, FactoryProtocol,
ClientProtocol,
FactoryProtocol,
)


Expand Down
18 changes: 8 additions & 10 deletions src/dataclass_rest/boundmethod.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from abc import ABC, abstractmethod
from inspect import getcallargs
from logging import getLogger
from typing import Dict, Any, Callable, Optional, NoReturn, Type
from typing import Any, Callable, Dict, NoReturn, Optional, Type

from .client_protocol import ClientProtocol, ClientMethodProtocol
from .exceptions import MalformedResponse
from .http_request import HttpRequest, File
from .client_protocol import ClientMethodProtocol, ClientProtocol
from .exceptions import ClientLibraryError, MalformedResponse
from .http_request import File, HttpRequest
from .methodspec import MethodSpec

logger = getLogger(__name__)
Expand Down Expand Up @@ -74,7 +74,7 @@ def __call__(self, *args, **kwargs):
raise NotImplementedError

def _on_error_default(self, response: Any) -> Any:
raise RuntimeError # TODO exceptions
raise ClientLibraryError


class SyncMethod(BoundMethod):
Expand All @@ -90,8 +90,7 @@ def __call__(self, *args, **kwargs):
request = self._pre_process_request(request)
raw_response = self.client.do_request(request)
response = self._pre_process_response(raw_response)
response = self._post_process_response(response)
return response
return self._post_process_response(response)

def _pre_process_request(self, request: HttpRequest) -> HttpRequest:
return request
Expand Down Expand Up @@ -135,8 +134,7 @@ async def __call__(self, *args, **kwargs):
raw_response = await self.client.do_request(request)
response = await self._pre_process_response(raw_response)
await self._release_raw_response(raw_response)
response = await self._post_process_response(response)
return response
return await self._post_process_response(response)

async def _pre_process_request(self, request: HttpRequest) -> HttpRequest:
return request
Expand All @@ -162,7 +160,7 @@ async def _pre_process_response(self, response: Any) -> Any:
raise MalformedResponse from e

async def _on_error_default(self, response: Any) -> NoReturn:
raise RuntimeError # TODO exceptions
raise ClientLibraryError

@abstractmethod
async def _response_body(self, response: Any) -> Any:
Expand Down
12 changes: 10 additions & 2 deletions src/dataclass_rest/client_protocol.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
from typing import (
Protocol, Any, Optional, Callable, Type, runtime_checkable, TypeVar,
Any,
Callable,
Optional,
Protocol,
Type,
TypeVar,
runtime_checkable,
)

from .http_request import HttpRequest
Expand All @@ -18,7 +24,9 @@ class FactoryProtocol(Protocol):
def load(self, data: Any, class_: Type[TypeT]) -> TypeT:
raise NotImplementedError

def dump(self, data: TypeT, class_: Type[TypeT] = None) -> Any:
def dump(
self, data: TypeT, class_: Optional[Type[TypeT]] = None,
) -> Any:
raise NotImplementedError


Expand Down
19 changes: 13 additions & 6 deletions src/dataclass_rest/http/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@

from aiohttp import FormData
from aiohttp.client import (
ClientResponse, ClientSession, ClientError as AioHttpClientError,
ClientError as AioHttpClientError,
)
from aiohttp.client import (
ClientResponse,
ClientSession,
)

from ..base_client import BaseClient
from ..boundmethod import AsyncMethod
from ..exceptions import (
ClientError, ClientLibraryError, ServerError, MalformedResponse,
from dataclass_rest.base_client import BaseClient
from dataclass_rest.boundmethod import AsyncMethod
from dataclass_rest.exceptions import (
ClientError,
ClientLibraryError,
MalformedResponse,
ServerError,
)
from ..http_request import HttpRequest
from dataclass_rest.http_request import HttpRequest


class AiohttpMethod(AsyncMethod):
Expand Down
15 changes: 9 additions & 6 deletions src/dataclass_rest/http/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
from json import JSONDecodeError
from typing import Any, Optional, Tuple

from requests import Session, Response, RequestException
from requests import RequestException, Response, Session

from ..base_client import BaseClient
from ..boundmethod import SyncMethod
from ..exceptions import (
ClientLibraryError, ClientError, ServerError, MalformedResponse,
from dataclass_rest.base_client import BaseClient
from dataclass_rest.boundmethod import SyncMethod
from dataclass_rest.exceptions import (
ClientError,
ClientLibraryError,
MalformedResponse,
ServerError,
)
from ..http_request import HttpRequest, File
from dataclass_rest.http_request import File, HttpRequest


class RequestsMethod(SyncMethod):
Expand Down
2 changes: 1 addition & 1 deletion src/dataclass_rest/http_request.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import dataclass
from typing import Any, Dict, Union, IO, Optional
from typing import IO, Any, Dict, Optional, Union


@dataclass
Expand Down
2 changes: 1 addition & 1 deletion src/dataclass_rest/method.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def __set_name__(self, owner, name):
f"No type for bound method is specified. "
f"Provide either `{owner.__name__}.method_class` attribute or "
f"`method_class=` argument for decorator "
f"on your `{name}` method"
f"on your `{name}` method",
)

def __get__(
Expand Down
3 changes: 2 additions & 1 deletion src/dataclass_rest/methodspec.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from typing import Any, Dict, Type, Callable, List
from typing import Any, Callable, Dict, List, Type


class MethodSpec:
def __init__(
self,
func: Callable,
*,
url_template: str,
http_method: str,
response_type: Type,
Expand Down
5 changes: 3 additions & 2 deletions src/dataclass_rest/parse_func.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import string
from inspect import getfullargspec, FullArgSpec, isclass
from typing import Callable, List, Sequence, Any, Type, TypedDict, Dict
from inspect import FullArgSpec, getfullargspec, isclass
from typing import Any, Callable, Dict, List, Sequence, Type, TypedDict

from .http_request import File
from .methodspec import MethodSpec
Expand Down Expand Up @@ -53,6 +53,7 @@ def get_file_params(spec):

def parse_func(
func: Callable,
*,
method: str,
url_template: str,
additional_params: Dict[str, Any],
Expand Down
5 changes: 4 additions & 1 deletion tests/requests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@

from dataclass_rest.http import requests


@pytest.fixture
def session():
return requests.Session()


@pytest.fixture
def mocker(session):
with requests_mock.Mocker(session=session, case_sensitive=True) as session_mock:
with requests_mock.Mocker(
session=session, case_sensitive=True,
) as session_mock:
yield session_mock
11 changes: 7 additions & 4 deletions tests/requests/test_factory.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dataclasses import dataclass
from enum import Enum

from adaptix import Retort, NameStyle, name_mapping
from adaptix import NameStyle, Retort, name_mapping

from dataclass_rest import patch
from dataclass_rest.http.requests import RequestsClient
Expand Down Expand Up @@ -43,7 +43,7 @@ def _init_response_body_factory(self) -> Retort:

@patch("/post/")
def post_x(self, long_param: str, body: RequestBody) -> ResponseBody:
raise NotImplementedError()
raise NotImplementedError

mocker.patch(
url="http://example.com/post/?LONG.PARAM=hello",
Expand All @@ -52,8 +52,11 @@ def post_x(self, long_param: str, body: RequestBody) -> ResponseBody:
)
client = Api(base_url="http://example.com", session=session)
result = client.post_x(
long_param="hello", body=RequestBody(int_param=42, selection=Selection.ONE),
long_param="hello",
body=RequestBody(int_param=42, selection=Selection.ONE),
)
assert result == ResponseBody(int_param=1, selection=Selection.TWO)
assert mocker.called_once
assert mocker.request_history[0].json() == {"intParam": 42, "selection": "ONE"}

resp = mocker.request_history[0].json()
assert resp == {"intParam": 42, "selection": "ONE"}
53 changes: 34 additions & 19 deletions tests/requests/test_params.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
from dataclasses import dataclass
from typing import Optional
from typing import List, Optional

import requests
import requests_mock

from dataclass_rest import get, post
from dataclass_rest.http.requests import RequestsClient


def test_methods(session, mocker):
def test_methods(session: requests.Session, mocker: requests_mock.Mocker):
class Api(RequestsClient):
@get("/get")
def get_x(self) -> list[int]:
raise NotImplementedError()
def get_x(self) -> List[int]:
raise NotImplementedError

@post("/post")
def post_x(self) -> list[int]:
raise NotImplementedError()
def post_x(self) -> List[int]:
raise NotImplementedError

mocker.get("http://example.com/get", text="[1,2]", complete_qs=True)
mocker.post("http://example.com/post", text="[1,2,3]", complete_qs=True)
Expand All @@ -22,11 +25,11 @@ def post_x(self) -> list[int]:
assert client.post_x() == [1, 2, 3]


def test_path_params(session, mocker):
def test_path_params(session: requests.Session, mocker: requests_mock.Mocker):
class Api(RequestsClient):
@post("/post/{id}")
def post_x(self, id) -> list[int]:
raise NotImplementedError()
def post_x(self, id) -> List[int]:
raise NotImplementedError

mocker.post("http://example.com/post/1", text="[1]", complete_qs=True)
mocker.post("http://example.com/post/2", text="[1,2]", complete_qs=True)
Expand All @@ -35,15 +38,24 @@ def post_x(self, id) -> list[int]:
assert client.post_x(2) == [1, 2]


def test_query_params(session, mocker):
def test_query_params(session: requests.Session, mocker: requests_mock.Mocker):
class Api(RequestsClient):
@post("/post/{id}")
def post_x(self, id: str, param: Optional[int]) -> list[int]:
raise NotImplementedError()

mocker.post("http://example.com/post/x?", text="[0]", complete_qs=True)
mocker.post("http://example.com/post/x?param=1", text="[1]", complete_qs=True)
mocker.post("http://example.com/post/x?param=2", text="[1,2]", complete_qs=True)
def post_x(self, id: str, param: Optional[int]) -> List[int]:
raise NotImplementedError

mocker.post(
url="http://example.com/post/x?",
text="[0]", complete_qs=True,
)
mocker.post(
url="http://example.com/post/x?param=1",
text="[1]", complete_qs=True,
)
mocker.post(
url="http://example.com/post/x?param=2",
text="[1,2]", complete_qs=True,
)
client = Api(base_url="http://example.com", session=session)
assert client.post_x("x", None) == [0]
assert client.post_x("x", 1) == [1]
Expand All @@ -56,13 +68,16 @@ class RequestBody:
y: str


def test_body(session, mocker):
def test_body(session: requests.Session, mocker: requests_mock.Mocker):
class Api(RequestsClient):
@post("/post/")
def post_x(self, body: RequestBody) -> None:
raise NotImplementedError()
raise NotImplementedError

mocker.post("http://example.com/post/", text="null", complete_qs=True)
mocker.post(
url="http://example.com/post/",
text="null", complete_qs=True,
)
client = Api(base_url="http://example.com", session=session)
assert client.post_x(RequestBody(x=1, y="test")) is None
assert mocker.called_once
Expand Down
Loading

0 comments on commit 508ccf1

Please sign in to comment.