Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions mpt_api_client/client.py

This file was deleted.

25 changes: 25 additions & 0 deletions mpt_api_client/http/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import httpx


class MPTClient(httpx.Client):
"""A client for interacting with SoftwareOne Marketplace Platform API."""

def __init__(
self,
*,
base_url: str,
api_token: str,
timeout: float = 5.0,
retries: int = 0,
):
self.api_token = api_token
base_headers = {
"User-Agent": "swo-marketplace-client/1.0",
"Authorization": f"Bearer {api_token}",
}
super().__init__(
base_url=base_url,
headers=base_headers,
timeout=timeout,
transport=httpx.HTTPTransport(retries=retries),
)
6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ classifiers = [
"Programming Language :: Python :: 3.12",
"Topic :: Utilities",
]
dependencies = []
dependencies = [
"httpx==0.28.*"
]

[dependency-groups]
dev = [
Expand All @@ -35,6 +37,7 @@ dev = [
"pytest-randomly==3.16.*",
"pytest-xdist==3.6.*",
"responses==0.25.*",
"respx==0.22.*",
"ruff==0.12.*",
"typing-extensions==4.13.*",
"wemake-python-styleguide==1.3.*",
Expand Down Expand Up @@ -164,6 +167,7 @@ pydocstyle.convention = "google"
[tool.ruff.lint.per-file-ignores]
"tests/*.py" = [
"D103", # missing docstring in public function
"PLR2004", # allow magic numbers in tests
"S101", # asserts
"S105", # hardcoded passwords
"S404", # subprocess calls are for tests
Expand Down
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ extend-exclude =

# We only run `wemake-python-styleguide` with `flake8`:
select = WPS, E999

per-file-ignores =
tests/*: WPS432
57 changes: 57 additions & 0 deletions tests/http/test_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import pytest
import respx
from httpx import ConnectTimeout, Response, codes

from mpt_api_client.http.client import MPTClient

API_TOKEN = "test-token"
API_URL = "https://api.example.com"


@pytest.fixture
def mpt_client():
return MPTClient(base_url=API_URL, api_token=API_TOKEN)


def test_mpt_client_initialization():
client = MPTClient(base_url=API_URL, api_token=API_TOKEN)

assert client.api_token == API_TOKEN
assert client.base_url == API_URL
assert client.headers["Authorization"] == "Bearer test-token"
assert client.headers["User-Agent"] == "swo-marketplace-client/1.0"


@respx.mock
def test_mock_call_success(mpt_client):
success_route = respx.get(f"{API_URL}/").mock(
return_value=Response(200, json={"message": "Hello, World!"})
)

success_response = mpt_client.get("/")

assert success_response.status_code == codes.OK
assert success_response.json() == {"message": "Hello, World!"}
assert success_route.called


@respx.mock
def test_mock_call_failure(mpt_client):
timeout_route = respx.get(f"{API_URL}/timeout").mock(side_effect=ConnectTimeout("Mock Timeout"))

with pytest.raises(ConnectTimeout):
mpt_client.get("/timeout")

assert timeout_route.called


@respx.mock
def test_mock_call_failure_with_retries(mpt_client):
not_found_route = respx.get(f"{API_URL}/not-found").mock(
side_effect=Response(codes.NOT_FOUND, json={"message": "Not Found"})
)

not_found_response = mpt_client.get("/not-found")

assert not_found_response.status_code == codes.NOT_FOUND
assert not_found_route.called
9 changes: 0 additions & 9 deletions tests/test_client.py

This file was deleted.

78 changes: 78 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.