photonhq-api 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.
photon_api/__init__.py ADDED
@@ -0,0 +1,18 @@
1
+ from .client import AsyncPhoton, Photon
2
+ from .errors import (
3
+ ApiError,
4
+ PhotonError,
5
+ ResponseValidationError,
6
+ TransportError,
7
+ )
8
+ from .transport import RawResponse
9
+
10
+ __all__ = [
11
+ "ApiError",
12
+ "AsyncPhoton",
13
+ "Photon",
14
+ "PhotonError",
15
+ "RawResponse",
16
+ "ResponseValidationError",
17
+ "TransportError",
18
+ ]
@@ -0,0 +1,62 @@
1
+ """Base classes and helpers of the generated models (tools/python-codegen).
2
+
3
+ The models carry the contract's types; values the contract restricts only by
4
+ validation keywords (patterns, lengths, bounds, sizes) are left to the service.
5
+ """
6
+
7
+ from typing import Annotated, Any, Generic, TypeVar
8
+
9
+ from pydantic import AfterValidator, ConfigDict, TypeAdapter
10
+ from pydantic import BaseModel as PydanticBaseModel
11
+ from pydantic import RootModel as PydanticRootModel
12
+
13
+ T = TypeVar("T")
14
+
15
+
16
+ class BaseModel(PydanticBaseModel):
17
+ # Members the SDK does not know are kept (a response may gain fields).
18
+ model_config = ConfigDict(extra="allow", defer_build=True)
19
+
20
+
21
+ class RootModel(PydanticRootModel[T], Generic[T]):
22
+ model_config = ConfigDict(defer_build=True)
23
+
24
+
25
+ def validate_all_of(data: Any, *constraints: type[PydanticBaseModel]) -> Any:
26
+ """Check the input of a union narrowed by object constraints against each constraint.
27
+
28
+ Generated (tools/python-codegen/intersections.py) as a `mode="before"`
29
+ validator: every constraint model validates the value as given, and the
30
+ root type validates the union; the value is valid only if all accept it.
31
+ A model instance is checked through its JSON form.
32
+ """
33
+ raw = (
34
+ data.model_dump(mode="json", by_alias=True) if isinstance(data, PydanticBaseModel) else data
35
+ )
36
+ for constraint in constraints:
37
+ constraint.model_validate(raw)
38
+ return data
39
+
40
+
41
+ class PrefixItems:
42
+ """`PrefixItems[T1, ..., Tn]`: a JSON Schema `prefixItems` array without `items`.
43
+
44
+ Item i, when present, validates as Ti; later items are unconstrained, and
45
+ the array may be shorter than n. Generated for arrays whose positional
46
+ items the model generator would otherwise drop
47
+ (tools/python-codegen/prefix_items.py). The value is a `list`.
48
+ """
49
+
50
+ def __class_getitem__(cls, params: Any) -> Any:
51
+ types = params if isinstance(params, tuple) else (params,)
52
+ adapters: list[TypeAdapter[Any]] = []
53
+
54
+ def validate(value: list[Any]) -> list[Any]:
55
+ if not adapters:
56
+ adapters.extend(TypeAdapter(item) for item in types)
57
+ return [
58
+ adapters[index].validate_python(item) if index < len(adapters) else item
59
+ for index, item in enumerate(value)
60
+ ]
61
+
62
+ return Annotated[list[Any], AfterValidator(validate)]
photon_api/client.py ADDED
@@ -0,0 +1,79 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ import httpx
6
+
7
+ from .config_generated import DEFAULT_BASE_URL
8
+ from .rpc_generated import AsyncRoot, SyncRoot
9
+ from .transport import (
10
+ DEFAULT_MAX_RETRY_AFTER,
11
+ AsyncHeaderProvider,
12
+ AsyncTransport,
13
+ SyncHeaderProvider,
14
+ SyncTransport,
15
+ )
16
+
17
+
18
+ class Photon(SyncRoot):
19
+ def __init__(
20
+ self,
21
+ *,
22
+ base_url: str = DEFAULT_BASE_URL,
23
+ headers: SyncHeaderProvider | None = None,
24
+ timeout: float = 30.0,
25
+ max_attempts: int = 3,
26
+ client: httpx.Client | None = None,
27
+ max_retry_after: float = DEFAULT_MAX_RETRY_AFTER,
28
+ ) -> None:
29
+ self._transport = SyncTransport(
30
+ base_url=base_url,
31
+ headers=headers,
32
+ timeout=timeout,
33
+ max_attempts=max_attempts,
34
+ client=client,
35
+ max_retry_after=max_retry_after,
36
+ )
37
+ super().__init__(self._transport)
38
+ self.raw = SyncRoot(self._transport, raw=True)
39
+
40
+ def close(self) -> None:
41
+ self._transport.close()
42
+
43
+ def __enter__(self) -> Photon:
44
+ return self
45
+
46
+ def __exit__(self, *_: Any) -> None:
47
+ self.close()
48
+
49
+
50
+ class AsyncPhoton(AsyncRoot):
51
+ def __init__(
52
+ self,
53
+ *,
54
+ base_url: str = DEFAULT_BASE_URL,
55
+ headers: AsyncHeaderProvider | None = None,
56
+ timeout: float = 30.0,
57
+ max_attempts: int = 3,
58
+ client: httpx.AsyncClient | None = None,
59
+ max_retry_after: float = DEFAULT_MAX_RETRY_AFTER,
60
+ ) -> None:
61
+ self._transport = AsyncTransport(
62
+ base_url=base_url,
63
+ headers=headers,
64
+ timeout=timeout,
65
+ max_attempts=max_attempts,
66
+ client=client,
67
+ max_retry_after=max_retry_after,
68
+ )
69
+ super().__init__(self._transport)
70
+ self.raw = AsyncRoot(self._transport, raw=True)
71
+
72
+ async def close(self) -> None:
73
+ await self._transport.close()
74
+
75
+ async def __aenter__(self) -> AsyncPhoton:
76
+ return self
77
+
78
+ async def __aexit__(self, *_: Any) -> None:
79
+ await self.close()
@@ -0,0 +1,2 @@
1
+ # Generated from config/sdk.json. Do not edit.
2
+ DEFAULT_BASE_URL = "https://api.photon.codes"
photon_api/errors.py ADDED
@@ -0,0 +1,62 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+
6
+ class PhotonError(Exception):
7
+ def __init__(
8
+ self,
9
+ message: str,
10
+ *,
11
+ operation_id: str | None = None,
12
+ request_id: str | None = None,
13
+ ) -> None:
14
+ super().__init__(message)
15
+ self.operation_id = operation_id
16
+ self.request_id = request_id
17
+
18
+
19
+ class ResponseValidationError(PhotonError):
20
+ def __init__(
21
+ self,
22
+ message: str,
23
+ *,
24
+ status: int,
25
+ raw_body: str,
26
+ operation_id: str,
27
+ request_id: str | None,
28
+ ) -> None:
29
+ super().__init__(
30
+ message,
31
+ operation_id=operation_id,
32
+ request_id=request_id,
33
+ )
34
+ self.status = status
35
+ self.raw_body = raw_body
36
+
37
+
38
+ class TransportError(PhotonError):
39
+ pass
40
+
41
+
42
+ class ApiError(PhotonError):
43
+ def __init__(
44
+ self,
45
+ message: str,
46
+ *,
47
+ status: int,
48
+ headers: dict[str, str],
49
+ body: Any,
50
+ raw_body: str,
51
+ operation_id: str,
52
+ request_id: str | None,
53
+ ) -> None:
54
+ super().__init__(
55
+ message,
56
+ operation_id=operation_id,
57
+ request_id=request_id,
58
+ )
59
+ self.status = status
60
+ self.headers = headers
61
+ self.body = body
62
+ self.raw_body = raw_body
@@ -0,0 +1 @@
1
+ from .models import *