ebarimt-pos-sdk 0.0.1b2__tar.gz → 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/PKG-INFO +1 -1
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/pyproject.toml +10 -18
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/__init__.py +14 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/errors.py +46 -8
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/bank_accounts/bank_accounts.py +7 -7
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/info/info.py +7 -7
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/receipt/receipt.py +17 -25
- ebarimt_pos_sdk-0.1.0/src/ebarimt_pos_sdk/resources/resource.py +91 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/send_data/send_data.py +5 -6
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/settings.py +1 -0
- ebarimt_pos_sdk-0.0.1b2/src/ebarimt_pos_sdk/resources/resource.py +0 -66
- ebarimt_pos_sdk-0.0.1b2/src/ebarimt_pos_sdk/resources/third_party/third_party.py +0 -0
- ebarimt_pos_sdk-0.0.1b2/src/ebarimt_pos_sdk/utils.py +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/README.md +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/client.py +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/py.typed +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/__init__.py +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/bank_accounts/schema.py +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/info/schema.py +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/receipt/__init__.py +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/receipt/schema.py +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/transport/__init__.py +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/transport/async_transport.py +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/transport/http.py +0 -0
- {ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/transport/sync_transport.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ebarimt-pos-sdk"
|
|
3
|
-
version = "0.0
|
|
3
|
+
version = "0.1.0"
|
|
4
4
|
description = "Python SDK for Ebarimt POS API 3.0"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -11,12 +11,12 @@ dependencies = ["httpx>=0.27.0", "pydantic>=2.7.0"]
|
|
|
11
11
|
|
|
12
12
|
[dependency-groups]
|
|
13
13
|
dev = [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
"pytest>=9.0.2",
|
|
15
|
+
"pytest-asyncio>=1.3.0",
|
|
16
|
+
"respx>=0.22.0",
|
|
17
|
+
"ruff>=0.5.0",
|
|
18
|
+
"mypy>=1.10.0",
|
|
19
|
+
"pytest-cov>=7.0.0",
|
|
20
20
|
]
|
|
21
21
|
|
|
22
22
|
[build-system]
|
|
@@ -26,22 +26,14 @@ build-backend = "uv_build"
|
|
|
26
26
|
[tool.pytest.ini_options]
|
|
27
27
|
asyncio_mode = "auto"
|
|
28
28
|
testpaths = ["tests"]
|
|
29
|
+
markers = ["integration: tests that require a real PosAPI server"]
|
|
29
30
|
|
|
30
31
|
[tool.ruff]
|
|
31
32
|
line-length = 100
|
|
32
33
|
target-version = "py310"
|
|
34
|
+
exclude = ["tests"]
|
|
35
|
+
src = ["src"]
|
|
33
36
|
|
|
34
37
|
[tool.ruff.lint]
|
|
35
38
|
select = ["E", "F", "I", "B", "UP"]
|
|
36
39
|
ignore = ["E501"]
|
|
37
|
-
|
|
38
|
-
[tool.mypy]
|
|
39
|
-
python_version = "3.10"
|
|
40
|
-
warn_return_any = true
|
|
41
|
-
warn_unused_ignores = true
|
|
42
|
-
no_implicit_optional = true
|
|
43
|
-
disallow_untyped_defs = true
|
|
44
|
-
check_untyped_defs = true
|
|
45
|
-
mypy_path = ["src"]
|
|
46
|
-
files = ["src"]
|
|
47
|
-
exclude = '^tests/'
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
from .client import PosApiClient
|
|
2
|
+
from .errors import (
|
|
3
|
+
PosApiBusinessError,
|
|
4
|
+
PosApiDecodeError,
|
|
5
|
+
PosApiError,
|
|
6
|
+
PosApiHttpError,
|
|
7
|
+
PosApiTransportError,
|
|
8
|
+
PosApiValidationError,
|
|
9
|
+
)
|
|
2
10
|
from .resources.receipt import (
|
|
3
11
|
BarCodeType,
|
|
4
12
|
CreateReceiptRequest,
|
|
@@ -38,4 +46,10 @@ __all__ = [
|
|
|
38
46
|
"ReceiptItemResponse",
|
|
39
47
|
"ReceiptType",
|
|
40
48
|
"TaxType",
|
|
49
|
+
"PosApiBusinessError",
|
|
50
|
+
"PosApiDecodeError",
|
|
51
|
+
"PosApiError",
|
|
52
|
+
"PosApiHttpError",
|
|
53
|
+
"PosApiTransportError",
|
|
54
|
+
"PosApiValidationError",
|
|
41
55
|
]
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
5
7
|
import httpx
|
|
8
|
+
from pydantic import ValidationError
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
class PosApiError(Exception):
|
|
@@ -14,10 +17,16 @@ class PosApiError(Exception):
|
|
|
14
17
|
*,
|
|
15
18
|
request: httpx.Request | None = None,
|
|
16
19
|
response: httpx.Response | None = None,
|
|
20
|
+
cause: Exception | None = None,
|
|
17
21
|
) -> None:
|
|
18
22
|
super().__init__(message)
|
|
23
|
+
self.message = message
|
|
19
24
|
self.request = request
|
|
20
25
|
self.response = response
|
|
26
|
+
self.cause = cause
|
|
27
|
+
|
|
28
|
+
def __str__(self) -> str:
|
|
29
|
+
return self.message
|
|
21
30
|
|
|
22
31
|
|
|
23
32
|
class PosApiTransportError(PosApiError):
|
|
@@ -31,18 +40,47 @@ class PosApiDecodeError(PosApiError):
|
|
|
31
40
|
class PosApiValidationError(PosApiError):
|
|
32
41
|
"""Pydantic validation errors (request or response)."""
|
|
33
42
|
|
|
34
|
-
|
|
35
|
-
class PosApiHttpError(PosApiError):
|
|
36
|
-
"""Non-2xx response from server."""
|
|
37
|
-
|
|
38
43
|
def __init__(
|
|
39
44
|
self,
|
|
40
|
-
message: str,
|
|
41
45
|
*,
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
stage: Literal["request", "response"],
|
|
47
|
+
model: type | str,
|
|
48
|
+
validation_error: ValidationError,
|
|
49
|
+
request: httpx.Request | None = None,
|
|
50
|
+
response: httpx.Response | None = None,
|
|
44
51
|
) -> None:
|
|
45
|
-
|
|
52
|
+
self.stage = stage
|
|
53
|
+
self.model = model if isinstance(model, str) else model.__name__
|
|
54
|
+
self.validation_error = validation_error
|
|
55
|
+
|
|
56
|
+
message = f"Validation failed during {stage} for model '{self.model}'"
|
|
57
|
+
|
|
58
|
+
super().__init__(
|
|
59
|
+
message,
|
|
60
|
+
request=request,
|
|
61
|
+
response=response,
|
|
62
|
+
cause=validation_error,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def errors(self) -> list:
|
|
67
|
+
"""Return Pydantic-style validation errors."""
|
|
68
|
+
return self.validation_error.errors()
|
|
69
|
+
|
|
70
|
+
def __str__(self) -> str:
|
|
71
|
+
lines = [self.message]
|
|
72
|
+
|
|
73
|
+
for err in self.errors:
|
|
74
|
+
loc = ".".join(str(x) for x in err.get("loc", []))
|
|
75
|
+
msg = err.get("msg", "")
|
|
76
|
+
typ = err.get("type", "")
|
|
77
|
+
lines.append(f" - {loc}: {msg} ({typ})")
|
|
78
|
+
|
|
79
|
+
return "\n".join(lines)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class PosApiHttpError(PosApiError):
|
|
83
|
+
"""Non-2xx response from server."""
|
|
46
84
|
|
|
47
85
|
|
|
48
86
|
class PosApiBusinessError(PosApiError):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import httpx
|
|
2
2
|
|
|
3
|
-
from ..resource import BaseResource, HeaderTypes
|
|
3
|
+
from ..resource import BaseResource, HeaderTypes
|
|
4
4
|
from .schema import BankAccount
|
|
5
5
|
|
|
6
6
|
|
|
@@ -19,14 +19,14 @@ class BankAccountsResource(BaseResource):
|
|
|
19
19
|
"GET",
|
|
20
20
|
self._path,
|
|
21
21
|
params=httpx.QueryParams({"tin": tin}),
|
|
22
|
-
headers=_build_headers(self._headers, headers),
|
|
22
|
+
headers=self._build_headers(self._headers, headers),
|
|
23
23
|
)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
response = self._ensure_http_success(result.response)
|
|
26
26
|
|
|
27
27
|
output: list[BankAccount] = []
|
|
28
28
|
|
|
29
|
-
for data in
|
|
29
|
+
for data in self._decode_json(response):
|
|
30
30
|
output.append(BankAccount.model_validate(data))
|
|
31
31
|
|
|
32
32
|
return output
|
|
@@ -41,14 +41,14 @@ class BankAccountsResource(BaseResource):
|
|
|
41
41
|
"GET",
|
|
42
42
|
self._path,
|
|
43
43
|
params=httpx.QueryParams({"tin": tin}),
|
|
44
|
-
headers=_build_headers(self._headers, headers),
|
|
44
|
+
headers=self._build_headers(self._headers, headers),
|
|
45
45
|
)
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
response = self._ensure_http_success(result.response)
|
|
48
48
|
|
|
49
49
|
output: list[BankAccount] = []
|
|
50
50
|
|
|
51
|
-
for data in
|
|
51
|
+
for data in self._decode_json(response):
|
|
52
52
|
output.append(BankAccount.model_validate(data))
|
|
53
53
|
|
|
54
54
|
return output
|
{ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/info/info.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from ..resource import BaseResource, HeaderTypes
|
|
1
|
+
from ..resource import BaseResource, HeaderTypes
|
|
2
2
|
from .schema import ReadInfoResponse
|
|
3
3
|
|
|
4
4
|
|
|
@@ -11,20 +11,20 @@ class InfoResource(BaseResource):
|
|
|
11
11
|
result = self._sync.send(
|
|
12
12
|
"GET",
|
|
13
13
|
self._path,
|
|
14
|
-
headers=_build_headers(self._headers, headers),
|
|
14
|
+
headers=self._build_headers(self._headers, headers),
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
-
_ensure_http_success(result.response)
|
|
17
|
+
self._ensure_http_success(result.response)
|
|
18
18
|
|
|
19
|
-
return ReadInfoResponse.model_validate(result.response
|
|
19
|
+
return ReadInfoResponse.model_validate(self._decode_json(result.response))
|
|
20
20
|
|
|
21
21
|
async def aread(self, *, headers: HeaderTypes | None = None) -> ReadInfoResponse:
|
|
22
22
|
result = await self._async.send(
|
|
23
23
|
"GET",
|
|
24
24
|
self._path,
|
|
25
|
-
headers=_build_headers(self._headers, headers),
|
|
25
|
+
headers=self._build_headers(self._headers, headers),
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
-
_ensure_http_success(result.response)
|
|
28
|
+
self._ensure_http_success(result.response)
|
|
29
29
|
|
|
30
|
-
return ReadInfoResponse.model_validate(result.response
|
|
30
|
+
return ReadInfoResponse.model_validate(self._decode_json(result.response))
|
{ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/receipt/receipt.py
RENAMED
|
@@ -2,13 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
|
-
from ..resource import
|
|
6
|
-
BaseResource,
|
|
7
|
-
HeaderTypes,
|
|
8
|
-
_build_headers,
|
|
9
|
-
_ensure_http_success,
|
|
10
|
-
_validate_payload,
|
|
11
|
-
)
|
|
5
|
+
from ..resource import BaseResource, HeaderTypes
|
|
12
6
|
from .schema import (
|
|
13
7
|
CreateReceiptRequest,
|
|
14
8
|
CreateReceiptResponse,
|
|
@@ -16,8 +10,6 @@ from .schema import (
|
|
|
16
10
|
DeleteReceiptResponse,
|
|
17
11
|
)
|
|
18
12
|
|
|
19
|
-
_DEFAULT_HEADERS = {"Accept": "application/json"}
|
|
20
|
-
|
|
21
13
|
|
|
22
14
|
class ReceiptResource(BaseResource):
|
|
23
15
|
@property
|
|
@@ -30,18 +22,18 @@ class ReceiptResource(BaseResource):
|
|
|
30
22
|
*,
|
|
31
23
|
headers: HeaderTypes | None = None,
|
|
32
24
|
) -> CreateReceiptResponse:
|
|
33
|
-
payload = _validate_payload(model=CreateReceiptRequest, payload=payload)
|
|
25
|
+
payload = self._validate_payload(model=CreateReceiptRequest, payload=payload)
|
|
34
26
|
|
|
35
27
|
result = self._sync.send(
|
|
36
28
|
"POST",
|
|
37
29
|
self._path,
|
|
38
|
-
headers=_build_headers(self._headers, headers),
|
|
30
|
+
headers=self._build_headers(self._headers, headers),
|
|
39
31
|
payload=payload.model_dump(mode="json", by_alias=True, exclude_none=True),
|
|
40
32
|
)
|
|
41
33
|
|
|
42
|
-
_ensure_http_success(result.response)
|
|
34
|
+
self._ensure_http_success(result.response)
|
|
43
35
|
|
|
44
|
-
return CreateReceiptResponse.model_validate(result.response
|
|
36
|
+
return CreateReceiptResponse.model_validate(self._decode_json(result.response))
|
|
45
37
|
|
|
46
38
|
async def acreate(
|
|
47
39
|
self,
|
|
@@ -49,47 +41,47 @@ class ReceiptResource(BaseResource):
|
|
|
49
41
|
*,
|
|
50
42
|
headers: HeaderTypes | None = None,
|
|
51
43
|
) -> CreateReceiptResponse:
|
|
52
|
-
payload = _validate_payload(model=CreateReceiptRequest, payload=payload)
|
|
44
|
+
payload = self._validate_payload(model=CreateReceiptRequest, payload=payload)
|
|
53
45
|
|
|
54
46
|
result = await self._async.send(
|
|
55
47
|
"POST",
|
|
56
48
|
self._path,
|
|
57
|
-
headers=_build_headers(self._headers, headers),
|
|
49
|
+
headers=self._build_headers(self._headers, headers),
|
|
58
50
|
payload=payload.model_dump(mode="json", by_alias=True, exclude_none=True),
|
|
59
51
|
)
|
|
60
52
|
|
|
61
|
-
_ensure_http_success(result.response)
|
|
53
|
+
self._ensure_http_success(result.response)
|
|
62
54
|
|
|
63
|
-
return CreateReceiptResponse.model_validate(result.response
|
|
55
|
+
return CreateReceiptResponse.model_validate(self._decode_json(result.response))
|
|
64
56
|
|
|
65
57
|
def delete(
|
|
66
58
|
self, payload: DeleteReceiptRequest | dict[str, Any], *, headers: HeaderTypes | None = None
|
|
67
59
|
) -> DeleteReceiptResponse:
|
|
68
|
-
payload = _validate_payload(model=DeleteReceiptRequest, payload=payload)
|
|
60
|
+
payload = self._validate_payload(model=DeleteReceiptRequest, payload=payload)
|
|
69
61
|
|
|
70
62
|
result = self._sync.send(
|
|
71
63
|
"POST",
|
|
72
64
|
self._path,
|
|
73
|
-
headers=_build_headers(self._headers, headers),
|
|
65
|
+
headers=self._build_headers(self._headers, headers),
|
|
74
66
|
payload=payload.model_dump(mode="json", by_alias=True, exclude_none=True),
|
|
75
67
|
)
|
|
76
68
|
|
|
77
|
-
_ensure_http_success(result.response)
|
|
69
|
+
self._ensure_http_success(result.response)
|
|
78
70
|
|
|
79
|
-
return DeleteReceiptResponse.model_validate(result.response
|
|
71
|
+
return DeleteReceiptResponse.model_validate(self._decode_json(result.response))
|
|
80
72
|
|
|
81
73
|
async def adelete(
|
|
82
74
|
self, payload: DeleteReceiptRequest | dict[str, Any], *, headers: HeaderTypes | None = None
|
|
83
75
|
) -> DeleteReceiptResponse:
|
|
84
|
-
payload = _validate_payload(model=DeleteReceiptRequest, payload=payload)
|
|
76
|
+
payload = self._validate_payload(model=DeleteReceiptRequest, payload=payload)
|
|
85
77
|
|
|
86
78
|
result = await self._async.send(
|
|
87
79
|
"POST",
|
|
88
80
|
self._path,
|
|
89
|
-
headers=_build_headers(self._headers, headers),
|
|
81
|
+
headers=self._build_headers(self._headers, headers),
|
|
90
82
|
payload=payload.model_dump(mode="json", by_alias=True, exclude_none=True),
|
|
91
83
|
)
|
|
92
84
|
|
|
93
|
-
_ensure_http_success(result.response)
|
|
85
|
+
self._ensure_http_success(result.response)
|
|
94
86
|
|
|
95
|
-
return DeleteReceiptResponse.model_validate(result.response
|
|
87
|
+
return DeleteReceiptResponse.model_validate(self._decode_json(result.response))
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# src/ebarimt_pos_sdk/resources/receipt.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from abc import abstractmethod
|
|
5
|
+
from typing import Any, TypeVar
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
from pydantic import BaseModel, ValidationError
|
|
9
|
+
|
|
10
|
+
from ..errors import PosApiDecodeError, PosApiHttpError, PosApiValidationError
|
|
11
|
+
from ..transport import AsyncTransport, HeaderTypes, SyncTransport
|
|
12
|
+
|
|
13
|
+
T = TypeVar("T", bound=BaseModel)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BaseResource:
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
*,
|
|
20
|
+
sync: SyncTransport,
|
|
21
|
+
async_: AsyncTransport,
|
|
22
|
+
headers: HeaderTypes | None = None,
|
|
23
|
+
) -> None:
|
|
24
|
+
self._sync = sync
|
|
25
|
+
self._async = async_
|
|
26
|
+
self._headers = headers
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def _path(self) -> str: ...
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def _decode_json(response: httpx.Response) -> Any:
|
|
34
|
+
try:
|
|
35
|
+
return response.json()
|
|
36
|
+
except Exception as exc:
|
|
37
|
+
raise PosApiDecodeError(
|
|
38
|
+
"Failed to decode JSON response",
|
|
39
|
+
response=response,
|
|
40
|
+
) from exc
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def _ensure_http_success(response: httpx.Response) -> httpx.Response:
|
|
44
|
+
try:
|
|
45
|
+
return response.raise_for_status()
|
|
46
|
+
except httpx.HTTPStatusError as exc:
|
|
47
|
+
raise PosApiHttpError(
|
|
48
|
+
f"HTTP {exc.response.status_code}",
|
|
49
|
+
request=exc.request,
|
|
50
|
+
response=exc.response,
|
|
51
|
+
) from exc
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def _validate_payload(model: type[T], payload: T | dict[str, Any]) -> T:
|
|
55
|
+
if isinstance(payload, model):
|
|
56
|
+
return payload
|
|
57
|
+
try:
|
|
58
|
+
return model.model_validate(payload)
|
|
59
|
+
except ValidationError as exc:
|
|
60
|
+
raise PosApiValidationError(
|
|
61
|
+
stage="request",
|
|
62
|
+
model=model,
|
|
63
|
+
validation_error=exc,
|
|
64
|
+
) from exc
|
|
65
|
+
|
|
66
|
+
@staticmethod
|
|
67
|
+
def _validate_response(model: type[T], response: Any) -> T:
|
|
68
|
+
try:
|
|
69
|
+
return model.model_validate(response)
|
|
70
|
+
except ValidationError as exc:
|
|
71
|
+
raise PosApiValidationError(
|
|
72
|
+
stage="response",
|
|
73
|
+
model=model,
|
|
74
|
+
validation_error=exc,
|
|
75
|
+
) from exc
|
|
76
|
+
|
|
77
|
+
@staticmethod
|
|
78
|
+
def _build_headers(*headers: HeaderTypes | None) -> httpx.Headers:
|
|
79
|
+
"""Merges headers and returns one header.
|
|
80
|
+
|
|
81
|
+
Note:
|
|
82
|
+
Highest priority header should be the last.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
httpx.Headers: Merged header.
|
|
86
|
+
"""
|
|
87
|
+
out = httpx.Headers()
|
|
88
|
+
for header in headers:
|
|
89
|
+
if header is not None:
|
|
90
|
+
out.update(header)
|
|
91
|
+
return out
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
from ..resource import BaseResource, HeaderTypes, _build_headers, _ensure_http_success
|
|
1
|
+
from ..resource import BaseResource, HeaderTypes
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
class SendDataResource(BaseResource):
|
|
@@ -11,10 +10,10 @@ class SendDataResource(BaseResource):
|
|
|
11
10
|
result = self._sync.send(
|
|
12
11
|
"GET",
|
|
13
12
|
self._path,
|
|
14
|
-
headers=_build_headers(self._headers, headers),
|
|
13
|
+
headers=self._build_headers(self._headers, headers),
|
|
15
14
|
)
|
|
16
15
|
|
|
17
|
-
_ensure_http_success(result.response)
|
|
16
|
+
self._ensure_http_success(result.response)
|
|
18
17
|
|
|
19
18
|
return None
|
|
20
19
|
|
|
@@ -22,9 +21,9 @@ class SendDataResource(BaseResource):
|
|
|
22
21
|
result = await self._async.send(
|
|
23
22
|
"GET",
|
|
24
23
|
self._path,
|
|
25
|
-
headers=_build_headers(self._headers, headers),
|
|
24
|
+
headers=self._build_headers(self._headers, headers),
|
|
26
25
|
)
|
|
27
26
|
|
|
28
|
-
_ensure_http_success(result.response)
|
|
27
|
+
self._ensure_http_success(result.response)
|
|
29
28
|
|
|
30
29
|
return None
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
# src/ebarimt_pos_sdk/resources/receipt.py
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
|
|
4
|
-
from abc import abstractmethod
|
|
5
|
-
from typing import Any, TypeVar
|
|
6
|
-
|
|
7
|
-
import httpx
|
|
8
|
-
from pydantic import BaseModel
|
|
9
|
-
|
|
10
|
-
from ..errors import PosApiHttpError
|
|
11
|
-
from ..transport import AsyncTransport, HeaderTypes, SyncTransport
|
|
12
|
-
|
|
13
|
-
T = TypeVar("T", bound=BaseModel)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class BaseResource:
|
|
17
|
-
def __init__(
|
|
18
|
-
self,
|
|
19
|
-
*,
|
|
20
|
-
sync: SyncTransport,
|
|
21
|
-
async_: AsyncTransport,
|
|
22
|
-
headers: HeaderTypes | None = None,
|
|
23
|
-
) -> None:
|
|
24
|
-
self._sync = sync
|
|
25
|
-
self._async = async_
|
|
26
|
-
self._headers = headers
|
|
27
|
-
|
|
28
|
-
@property
|
|
29
|
-
@abstractmethod
|
|
30
|
-
def _path(self) -> str: ...
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def _ensure_http_success(response: httpx.Response) -> httpx.Response:
|
|
34
|
-
try:
|
|
35
|
-
response.raise_for_status()
|
|
36
|
-
except httpx.HTTPStatusError as exc:
|
|
37
|
-
raise PosApiHttpError(
|
|
38
|
-
f"HTTP {exc.response.status_code}",
|
|
39
|
-
request=exc.request,
|
|
40
|
-
response=exc.response,
|
|
41
|
-
) from exc
|
|
42
|
-
return response
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def _validate_payload(model: type[T], payload: T | dict[str, Any]) -> T:
|
|
46
|
-
if isinstance(payload, model):
|
|
47
|
-
return payload
|
|
48
|
-
return model.model_validate(payload)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def _build_headers(*headers: HeaderTypes | None) -> httpx.Headers:
|
|
52
|
-
"""Merges headers and returns one header.
|
|
53
|
-
|
|
54
|
-
Note:
|
|
55
|
-
Highest priority header should be the last.
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
httpx.Headers: Merged header.
|
|
59
|
-
"""
|
|
60
|
-
out = httpx.Headers()
|
|
61
|
-
for header in headers:
|
|
62
|
-
out.update(header)
|
|
63
|
-
return out
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
__all__ = ["_ensure_http_success", "_validate_payload", "_build_headers"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/info/schema.py
RENAMED
|
File without changes
|
{ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/receipt/__init__.py
RENAMED
|
File without changes
|
{ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/resources/receipt/schema.py
RENAMED
|
File without changes
|
|
File without changes
|
{ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/transport/async_transport.py
RENAMED
|
File without changes
|
|
File without changes
|
{ebarimt_pos_sdk-0.0.1b2 → ebarimt_pos_sdk-0.1.0}/src/ebarimt_pos_sdk/transport/sync_transport.py
RENAMED
|
File without changes
|