Skip to content

Commit 4d76872

Browse files
authored
#MPT-12324 HTTP layer with Httpx (#3)
2 parents a614f0f + 2771382 commit 4d76872

File tree

7 files changed

+168
-13
lines changed

7 files changed

+168
-13
lines changed

mpt_api_client/client.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

mpt_api_client/http/client.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import httpx
2+
3+
4+
class MPTClient(httpx.Client):
5+
"""A client for interacting with SoftwareOne Marketplace Platform API."""
6+
7+
def __init__(
8+
self,
9+
*,
10+
base_url: str,
11+
api_token: str,
12+
timeout: float = 5.0,
13+
retries: int = 0,
14+
):
15+
self.api_token = api_token
16+
base_headers = {
17+
"User-Agent": "swo-marketplace-client/1.0",
18+
"Authorization": f"Bearer {api_token}",
19+
}
20+
super().__init__(
21+
base_url=base_url,
22+
headers=base_headers,
23+
timeout=timeout,
24+
transport=httpx.HTTPTransport(retries=retries),
25+
)

pyproject.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ classifiers = [
1919
"Programming Language :: Python :: 3.12",
2020
"Topic :: Utilities",
2121
]
22-
dependencies = []
22+
dependencies = [
23+
"httpx==0.28.*"
24+
]
2325

2426
[dependency-groups]
2527
dev = [
@@ -35,6 +37,7 @@ dev = [
3537
"pytest-randomly==3.16.*",
3638
"pytest-xdist==3.6.*",
3739
"responses==0.25.*",
40+
"respx==0.22.*",
3841
"ruff==0.12.*",
3942
"typing-extensions==4.13.*",
4043
"wemake-python-styleguide==1.3.*",
@@ -164,6 +167,7 @@ pydocstyle.convention = "google"
164167
[tool.ruff.lint.per-file-ignores]
165168
"tests/*.py" = [
166169
"D103", # missing docstring in public function
170+
"PLR2004", # allow magic numbers in tests
167171
"S101", # asserts
168172
"S105", # hardcoded passwords
169173
"S404", # subprocess calls are for tests

setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ extend-exclude =
2424

2525
# We only run `wemake-python-styleguide` with `flake8`:
2626
select = WPS, E999
27+
28+
per-file-ignores =
29+
tests/*: WPS432

tests/http/test_client.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import pytest
2+
import respx
3+
from httpx import ConnectTimeout, Response, codes
4+
5+
from mpt_api_client.http.client import MPTClient
6+
7+
API_TOKEN = "test-token"
8+
API_URL = "https://api.example.com"
9+
10+
11+
@pytest.fixture
12+
def mpt_client():
13+
return MPTClient(base_url=API_URL, api_token=API_TOKEN)
14+
15+
16+
def test_mpt_client_initialization():
17+
client = MPTClient(base_url=API_URL, api_token=API_TOKEN)
18+
19+
assert client.api_token == API_TOKEN
20+
assert client.base_url == API_URL
21+
assert client.headers["Authorization"] == "Bearer test-token"
22+
assert client.headers["User-Agent"] == "swo-marketplace-client/1.0"
23+
24+
25+
@respx.mock
26+
def test_mock_call_success(mpt_client):
27+
success_route = respx.get(f"{API_URL}/").mock(
28+
return_value=Response(200, json={"message": "Hello, World!"})
29+
)
30+
31+
success_response = mpt_client.get("/")
32+
33+
assert success_response.status_code == codes.OK
34+
assert success_response.json() == {"message": "Hello, World!"}
35+
assert success_route.called
36+
37+
38+
@respx.mock
39+
def test_mock_call_failure(mpt_client):
40+
timeout_route = respx.get(f"{API_URL}/timeout").mock(side_effect=ConnectTimeout("Mock Timeout"))
41+
42+
with pytest.raises(ConnectTimeout):
43+
mpt_client.get("/timeout")
44+
45+
assert timeout_route.called
46+
47+
48+
@respx.mock
49+
def test_mock_call_failure_with_retries(mpt_client):
50+
not_found_route = respx.get(f"{API_URL}/not-found").mock(
51+
side_effect=Response(codes.NOT_FOUND, json={"message": "Not Found"})
52+
)
53+
54+
not_found_response = mpt_client.get("/not-found")
55+
56+
assert not_found_response.status_code == codes.NOT_FOUND
57+
assert not_found_route.called

tests/test_client.py

Lines changed: 0 additions & 9 deletions
This file was deleted.

uv.lock

Lines changed: 78 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)