ideal-postcodes 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,81 @@
1
+ """Public exceptions. Messages omit request URLs, credentials and response payloads."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, cast
6
+
7
+
8
+ class ClientError(Exception):
9
+ """Base for API responses, network failures and malformed responses."""
10
+
11
+
12
+ class TransportError(ClientError):
13
+ """The request failed before an HTTP response was available. Not retried."""
14
+
15
+
16
+ class ProtocolError(ClientError):
17
+ """The server returned an unexpected status, malformed envelope or invalid result.
18
+
19
+ result holds the unvalidated result when the envelope was valid but its fields were not, else None.
20
+ """
21
+
22
+ def __init__(self, message: str, result: object = None) -> None:
23
+ self.result = result
24
+ super().__init__(message)
25
+
26
+
27
+ class APIError(ClientError):
28
+ """An unsuccessful HTTP response, with API code and retry metadata."""
29
+
30
+ def __init__(self, status: int, body: dict[str, Any], retry_after: str | None = None) -> None:
31
+ code = body.get("code")
32
+ message = body.get("message")
33
+ self.status = status
34
+ self.code = code if isinstance(code, int) else 0
35
+ self.message = message if isinstance(message, str) else "API request failed"
36
+ self.body = body
37
+ self.retry_after = retry_after
38
+ summary = f"API request failed (HTTP {status}, code {self.code})"
39
+ super().__init__(f"{summary}: {message}" if isinstance(message, str) and message else summary)
40
+
41
+
42
+ class AuthenticationError(APIError):
43
+ """HTTP 401 or 403. Check credentials and permissions."""
44
+
45
+
46
+ class PaymentRequiredError(APIError):
47
+ """HTTP 402. Check the balance and account limits."""
48
+
49
+
50
+ class NotFoundError(APIError):
51
+ """HTTP 404. The requested resource was not found."""
52
+
53
+ @property
54
+ def suggestions(self) -> list[str]:
55
+ value = self.body.get("suggestions")
56
+ if not isinstance(value, list):
57
+ return []
58
+ return [item for item in cast("list[object]", value) if isinstance(item, str)]
59
+
60
+
61
+ class RateLimitError(APIError):
62
+ """HTTP 429 or API throttling code 5030. Retry-After is preserved verbatim."""
63
+
64
+
65
+ class ServerError(APIError):
66
+ """HTTP 5xx without a recognised throttling code."""
67
+
68
+
69
+ def error_for(status: int, body: dict[str, Any], retry_after: str | None) -> APIError:
70
+ if status == 429 or (status == 503 and body.get("code") == 5030):
71
+ cls = RateLimitError
72
+ elif status >= 500:
73
+ cls = ServerError
74
+ else:
75
+ cls = {
76
+ 401: AuthenticationError,
77
+ 403: AuthenticationError,
78
+ 402: PaymentRequiredError,
79
+ 404: NotFoundError,
80
+ }.get(status, APIError)
81
+ return cls(status, body, retry_after)
File without changes
@@ -0,0 +1,70 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: requests.json
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import NotRequired, TypedDict
7
+
8
+
9
+ class UpdateKeyDetailsDailyLimit(TypedDict):
10
+ limit: NotRequired[int | None]
11
+
12
+
13
+ class UpdateKeyDetailsMonthlyLimit(TypedDict):
14
+ limit: NotRequired[int | None]
15
+
16
+
17
+ class UpdateKeyDetailsIndividualLimit(TypedDict):
18
+ limit: NotRequired[int | None]
19
+
20
+
21
+ class UpdateKeyDetailsNotifications(TypedDict):
22
+ emails: NotRequired[list[str]]
23
+ enabled: NotRequired[bool]
24
+ balance_threshold: NotRequired[int | None]
25
+ no_balance: NotRequired[bool]
26
+ limit_reached: NotRequired[bool]
27
+
28
+
29
+ class UpdateKeyDetailsDatasets(TypedDict):
30
+ pafa: NotRequired[bool]
31
+ pafw: NotRequired[bool]
32
+ usps: NotRequired[bool]
33
+ hereap: NotRequired[bool]
34
+ herehk: NotRequired[bool]
35
+ herei: NotRequired[bool]
36
+ herem: NotRequired[bool]
37
+ heremea: NotRequired[bool]
38
+ heremeas: NotRequired[bool]
39
+ herena: NotRequired[bool]
40
+ hereo: NotRequired[bool]
41
+ heresa: NotRequired[bool]
42
+ heret: NotRequired[bool]
43
+ hereee: NotRequired[bool]
44
+ herewe: NotRequired[bool]
45
+ phone: NotRequired[bool]
46
+ email: NotRequired[bool]
47
+ gnaf: NotRequired[bool]
48
+ kadaster: NotRequired[bool]
49
+ kartverket: NotRequired[bool]
50
+ sdfi: NotRequired[bool]
51
+ cannar: NotRequired[bool]
52
+ fodbosa: NotRequired[bool]
53
+ mois: NotRequired[bool]
54
+ upujp: NotRequired[bool]
55
+ bev: NotRequired[bool]
56
+ ban: NotRequired[bool]
57
+ swt: NotRequired[bool]
58
+ ab: NotRequired[bool]
59
+ abp: NotRequired[bool]
60
+ nip: NotRequired[bool]
61
+ gbrcleanse: NotRequired[bool]
62
+ uspscleanse: NotRequired[bool]
63
+
64
+
65
+ class CreateLicenseeDaily(TypedDict):
66
+ limit: NotRequired[float | None]
67
+
68
+
69
+ class UpdateLicenseeDaily(TypedDict):
70
+ limit: NotRequired[float | None]