bronto-sdk 0.2.1__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.
- bronto_sdk/__init__.py +57 -0
- bronto_sdk/_async_client.py +245 -0
- bronto_sdk/_auth.py +40 -0
- bronto_sdk/_client.py +234 -0
- bronto_sdk/_client_config.py +170 -0
- bronto_sdk/_errors.py +335 -0
- bronto_sdk/_regions.py +73 -0
- bronto_sdk/_request_options.py +216 -0
- bronto_sdk/_transport.py +110 -0
- bronto_sdk/_version.py +8 -0
- bronto_sdk/domain/__init__.py +39 -0
- bronto_sdk/domain/datasets.py +26 -0
- bronto_sdk/domain/query.py +104 -0
- bronto_sdk/domain/time_range.py +310 -0
- bronto_sdk/mcp/__init__.py +77 -0
- bronto_sdk/models/__init__.py +71 -0
- bronto_sdk/models/_common.py +49 -0
- bronto_sdk/models/_dataset.py +50 -0
- bronto_sdk/models/_error.py +22 -0
- bronto_sdk/models/_metric.py +21 -0
- bronto_sdk/models/_monitor.py +258 -0
- bronto_sdk/models/_search.py +344 -0
- bronto_sdk/py.typed +0 -0
- bronto_sdk/resources/__init__.py +28 -0
- bronto_sdk/resources/_datasets.py +133 -0
- bronto_sdk/resources/_metrics.py +99 -0
- bronto_sdk/resources/_monitors.py +240 -0
- bronto_sdk/resources/_search.py +107 -0
- bronto_sdk-0.2.1.dist-info/METADATA +382 -0
- bronto_sdk-0.2.1.dist-info/RECORD +32 -0
- bronto_sdk-0.2.1.dist-info/WHEEL +4 -0
- bronto_sdk-0.2.1.dist-info/licenses/LICENSE +21 -0
bronto_sdk/__init__.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Python SDK for the Bronto observability platform.
|
|
2
|
+
|
|
3
|
+
Importing this package has no side effects: it configures no logging, reads no
|
|
4
|
+
environment variables, opens no connections, and holds no global mutable state.
|
|
5
|
+
A client instance is the only entry point.
|
|
6
|
+
|
|
7
|
+
Only the names re-exported here (and the documented `domain`, `models`,
|
|
8
|
+
`resources` and `mcp` subpackages) are public API; everything in a module
|
|
9
|
+
prefixed with `_` is an implementation detail and may change without a major
|
|
10
|
+
version bump.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from ._async_client import AsyncBrontoClient
|
|
14
|
+
from ._client import BrontoClient
|
|
15
|
+
from ._errors import (
|
|
16
|
+
BrontoAPIError,
|
|
17
|
+
BrontoAuthenticationError,
|
|
18
|
+
BrontoBadRequestError,
|
|
19
|
+
BrontoConfigError,
|
|
20
|
+
BrontoConnectionError,
|
|
21
|
+
BrontoError,
|
|
22
|
+
BrontoNotFoundError,
|
|
23
|
+
BrontoPermissionError,
|
|
24
|
+
BrontoRateLimitError,
|
|
25
|
+
BrontoServerError,
|
|
26
|
+
)
|
|
27
|
+
from ._regions import (
|
|
28
|
+
KNOWN_REGIONS,
|
|
29
|
+
ingest_base_url,
|
|
30
|
+
mcp_url,
|
|
31
|
+
rest_base_url,
|
|
32
|
+
validate_region,
|
|
33
|
+
)
|
|
34
|
+
from ._request_options import RequestOptions
|
|
35
|
+
from ._version import VERSION
|
|
36
|
+
|
|
37
|
+
__all__ = [
|
|
38
|
+
"KNOWN_REGIONS",
|
|
39
|
+
"VERSION",
|
|
40
|
+
"AsyncBrontoClient",
|
|
41
|
+
"BrontoAPIError",
|
|
42
|
+
"BrontoAuthenticationError",
|
|
43
|
+
"BrontoBadRequestError",
|
|
44
|
+
"BrontoClient",
|
|
45
|
+
"BrontoConfigError",
|
|
46
|
+
"BrontoConnectionError",
|
|
47
|
+
"BrontoError",
|
|
48
|
+
"BrontoNotFoundError",
|
|
49
|
+
"BrontoPermissionError",
|
|
50
|
+
"BrontoRateLimitError",
|
|
51
|
+
"BrontoServerError",
|
|
52
|
+
"RequestOptions",
|
|
53
|
+
"ingest_base_url",
|
|
54
|
+
"mcp_url",
|
|
55
|
+
"rest_base_url",
|
|
56
|
+
"validate_region",
|
|
57
|
+
]
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""The asynchronous Bronto client — a thin I/O shell over ``httpx.AsyncClient``.
|
|
2
|
+
|
|
3
|
+
A mirror of :class:`bronto_sdk._client.BrontoClient`: identical surface and
|
|
4
|
+
identical request-shaping, differing only in awaiting the HTTP call and
|
|
5
|
+
in the ``max_concurrency`` semaphore that caps concurrent requests to the
|
|
6
|
+
Bronto API gateway.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
from functools import cached_property
|
|
13
|
+
from types import TracebackType
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
import httpx
|
|
17
|
+
|
|
18
|
+
from ._client_config import (
|
|
19
|
+
client_default_options,
|
|
20
|
+
prepare_request,
|
|
21
|
+
read_env_config,
|
|
22
|
+
resolve_base_url,
|
|
23
|
+
wrap_transport_error,
|
|
24
|
+
)
|
|
25
|
+
from ._request_options import RequestOptions, client_credential
|
|
26
|
+
from ._transport import parse_response
|
|
27
|
+
from .resources._datasets import AsyncDatasetsResource
|
|
28
|
+
from .resources._metrics import AsyncMetricsResource
|
|
29
|
+
from .resources._monitors import AsyncMonitorsResource
|
|
30
|
+
from .resources._search import AsyncSearchResource
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AsyncBrontoClient:
|
|
34
|
+
"""An asynchronous client for the Bronto REST API.
|
|
35
|
+
|
|
36
|
+
The client is either *client-bound* (constructed with ``api_key`` or
|
|
37
|
+
``bearer_token``; every call uses it) or *credential-less* (constructed with
|
|
38
|
+
neither; every call must supply a credential via ``options``). The mode is
|
|
39
|
+
fixed at construction — see the two-mode rule in
|
|
40
|
+
:mod:`bronto_sdk._request_options`.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
api_key: str | None = None,
|
|
46
|
+
region: str | None = None,
|
|
47
|
+
*,
|
|
48
|
+
bearer_token: str | None = None,
|
|
49
|
+
timeout: float = 30.0,
|
|
50
|
+
base_url: str | None = None,
|
|
51
|
+
http_client: httpx.AsyncClient | None = None,
|
|
52
|
+
max_concurrency: int = 20,
|
|
53
|
+
) -> None:
|
|
54
|
+
"""Construct a client.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
api_key: A Bronto API key to bind to every call. Omit for a
|
|
58
|
+
credential-less client.
|
|
59
|
+
region: The region slug (e.g. ``"eu"``); resolved to the REST base
|
|
60
|
+
URL. Ignored when ``base_url`` is given.
|
|
61
|
+
bearer_token: A JWT bearer token to bind to every call. Wins over
|
|
62
|
+
``api_key``. Omit for a credential-less client.
|
|
63
|
+
timeout: The default per-request timeout in seconds.
|
|
64
|
+
base_url: An explicit base URL that overrides ``region`` — for
|
|
65
|
+
testing or a non-standard deployment. Trusted and used verbatim.
|
|
66
|
+
http_client: An existing ``httpx.AsyncClient`` to reuse. When given,
|
|
67
|
+
the SDK will not close it.
|
|
68
|
+
max_concurrency: The maximum number of in-flight requests.
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
BrontoConfigError: When neither ``region`` nor ``base_url`` resolves
|
|
72
|
+
an endpoint, or the region slug is invalid.
|
|
73
|
+
ValueError: When ``max_concurrency`` is less than 1.
|
|
74
|
+
"""
|
|
75
|
+
if max_concurrency < 1:
|
|
76
|
+
raise ValueError("max_concurrency must be a positive integer")
|
|
77
|
+
self._base_url = resolve_base_url(region=region, base_url=base_url)
|
|
78
|
+
self._bound = client_credential(api_key=api_key, bearer_token=bearer_token)
|
|
79
|
+
self._defaults = client_default_options(timeout=timeout)
|
|
80
|
+
self._http = http_client or httpx.AsyncClient()
|
|
81
|
+
self._owns_http_client = http_client is None
|
|
82
|
+
self._semaphore = asyncio.Semaphore(max_concurrency)
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def from_env(cls) -> AsyncBrontoClient:
|
|
86
|
+
"""Build a client from ``BRONTO_API_KEY`` and ``BRONTO_REGION``.
|
|
87
|
+
|
|
88
|
+
``BRONTO_BASE_URL`` is honoured when set and wins over ``BRONTO_REGION``.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
A client-bound :class:`AsyncBrontoClient`.
|
|
92
|
+
|
|
93
|
+
Raises:
|
|
94
|
+
BrontoConfigError: Naming the first missing environment variable.
|
|
95
|
+
"""
|
|
96
|
+
env = read_env_config()
|
|
97
|
+
return cls(api_key=env.api_key, region=env.region, base_url=env.base_url)
|
|
98
|
+
|
|
99
|
+
@cached_property
|
|
100
|
+
def search(self) -> AsyncSearchResource:
|
|
101
|
+
"""The typed ``POST /search`` surface."""
|
|
102
|
+
return AsyncSearchResource(self)
|
|
103
|
+
|
|
104
|
+
@cached_property
|
|
105
|
+
def monitors(self) -> AsyncMonitorsResource:
|
|
106
|
+
"""The typed monitor surface."""
|
|
107
|
+
return AsyncMonitorsResource(self)
|
|
108
|
+
|
|
109
|
+
@cached_property
|
|
110
|
+
def datasets(self) -> AsyncDatasetsResource:
|
|
111
|
+
"""The typed dataset surface."""
|
|
112
|
+
return AsyncDatasetsResource(self)
|
|
113
|
+
|
|
114
|
+
@cached_property
|
|
115
|
+
def metrics(self) -> AsyncMetricsResource:
|
|
116
|
+
"""The typed metric-definition surface."""
|
|
117
|
+
return AsyncMetricsResource(self)
|
|
118
|
+
|
|
119
|
+
async def get(
|
|
120
|
+
self,
|
|
121
|
+
path: str,
|
|
122
|
+
*,
|
|
123
|
+
params: dict[str, Any] | None = None,
|
|
124
|
+
options: RequestOptions | None = None,
|
|
125
|
+
) -> dict[str, object]:
|
|
126
|
+
"""Send a ``GET`` request and return the parsed JSON object.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
path: The request path, absolute-style (``"/search"``) or bare
|
|
130
|
+
(``"monitors/m-1"``).
|
|
131
|
+
params: Optional query-string parameters.
|
|
132
|
+
options: Optional per-request overrides.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
The decoded JSON response object.
|
|
136
|
+
|
|
137
|
+
Raises:
|
|
138
|
+
BrontoAPIError: On any non-2xx response.
|
|
139
|
+
BrontoConnectionError: On a transport-level failure.
|
|
140
|
+
BrontoConfigError: On a credential resolution error.
|
|
141
|
+
"""
|
|
142
|
+
return await self._request(
|
|
143
|
+
"GET", path, params=params, json_body=None, options=options
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
async def post(
|
|
147
|
+
self,
|
|
148
|
+
path: str,
|
|
149
|
+
*,
|
|
150
|
+
json: dict[str, Any] | None = None,
|
|
151
|
+
params: dict[str, Any] | None = None,
|
|
152
|
+
options: RequestOptions | None = None,
|
|
153
|
+
) -> dict[str, object]:
|
|
154
|
+
"""Send a ``POST`` request and return the parsed JSON object.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
path: The request path, absolute-style or bare.
|
|
158
|
+
json: Optional JSON request body.
|
|
159
|
+
params: Optional query-string parameters.
|
|
160
|
+
options: Optional per-request overrides.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
The decoded JSON response object.
|
|
164
|
+
|
|
165
|
+
Raises:
|
|
166
|
+
BrontoAPIError: On any non-2xx response.
|
|
167
|
+
BrontoConnectionError: On a transport-level failure.
|
|
168
|
+
BrontoConfigError: On a credential resolution error.
|
|
169
|
+
"""
|
|
170
|
+
return await self._request(
|
|
171
|
+
"POST", path, params=params, json_body=json, options=options
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
async def _request(
|
|
175
|
+
self,
|
|
176
|
+
method: str,
|
|
177
|
+
path: str,
|
|
178
|
+
*,
|
|
179
|
+
params: dict[str, Any] | None,
|
|
180
|
+
json_body: dict[str, Any] | None,
|
|
181
|
+
options: RequestOptions | None,
|
|
182
|
+
) -> dict[str, object]:
|
|
183
|
+
"""Perform the shared per-call flow around a single ``httpx`` request.
|
|
184
|
+
|
|
185
|
+
The concurrency semaphore is held only for the duration of the network
|
|
186
|
+
call, so credential resolution and option merging never occupy a slot.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
method: The HTTP method.
|
|
190
|
+
path: The request path.
|
|
191
|
+
params: Optional query-string parameters.
|
|
192
|
+
json_body: Optional JSON request body.
|
|
193
|
+
options: Optional per-request overrides.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
The decoded JSON response object.
|
|
197
|
+
|
|
198
|
+
Raises:
|
|
199
|
+
BrontoAPIError: On any non-2xx response.
|
|
200
|
+
BrontoConnectionError: On a transport-level failure.
|
|
201
|
+
BrontoConfigError: On a credential resolution error.
|
|
202
|
+
"""
|
|
203
|
+
prepared = prepare_request(
|
|
204
|
+
bound=self._bound,
|
|
205
|
+
defaults=self._defaults,
|
|
206
|
+
base_url=self._base_url,
|
|
207
|
+
path=path,
|
|
208
|
+
options=options,
|
|
209
|
+
)
|
|
210
|
+
timeout = (
|
|
211
|
+
prepared.timeout
|
|
212
|
+
if prepared.timeout is not None
|
|
213
|
+
else httpx.USE_CLIENT_DEFAULT
|
|
214
|
+
)
|
|
215
|
+
try:
|
|
216
|
+
async with self._semaphore:
|
|
217
|
+
response = await self._http.request(
|
|
218
|
+
method,
|
|
219
|
+
prepared.url,
|
|
220
|
+
params=params,
|
|
221
|
+
json=json_body,
|
|
222
|
+
headers=prepared.headers,
|
|
223
|
+
timeout=timeout,
|
|
224
|
+
)
|
|
225
|
+
except httpx.HTTPError as exc:
|
|
226
|
+
raise wrap_transport_error(exc) from exc
|
|
227
|
+
return parse_response(response.status_code, response.headers, response.text)
|
|
228
|
+
|
|
229
|
+
async def aclose(self) -> None:
|
|
230
|
+
"""Close the underlying HTTP client, unless it was caller-supplied."""
|
|
231
|
+
if self._owns_http_client:
|
|
232
|
+
await self._http.aclose()
|
|
233
|
+
|
|
234
|
+
async def __aenter__(self) -> AsyncBrontoClient:
|
|
235
|
+
"""Enter the async context manager, returning the client."""
|
|
236
|
+
return self
|
|
237
|
+
|
|
238
|
+
async def __aexit__(
|
|
239
|
+
self,
|
|
240
|
+
exc_type: type[BaseException] | None,
|
|
241
|
+
exc: BaseException | None,
|
|
242
|
+
tb: TracebackType | None,
|
|
243
|
+
) -> None:
|
|
244
|
+
"""Close the client on async context-manager exit."""
|
|
245
|
+
await self.aclose()
|
bronto_sdk/_auth.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Authentication and identity header construction.
|
|
2
|
+
|
|
3
|
+
Bronto accepts two schemes: a JWT bearer token (``Authorization``) and an API
|
|
4
|
+
key (``X-BRONTO-API-KEY``).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Literal
|
|
10
|
+
|
|
11
|
+
from ._version import VERSION
|
|
12
|
+
|
|
13
|
+
_API_KEY_HEADER = "X-BRONTO-API-KEY"
|
|
14
|
+
_BEARER_HEADER = "Authorization"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def credential_header(
|
|
18
|
+
scheme: Literal["bearer", "api_key"], value: str
|
|
19
|
+
) -> dict[str, str]:
|
|
20
|
+
"""Build the auth header for an already-resolved single credential.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
scheme: ``"bearer"`` or ``"api_key"``.
|
|
24
|
+
value: The credential string for that scheme.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
A single-entry dict with the matching authentication header.
|
|
28
|
+
"""
|
|
29
|
+
if scheme == "bearer":
|
|
30
|
+
return {_BEARER_HEADER: value}
|
|
31
|
+
return {_API_KEY_HEADER: value}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def user_agent() -> str:
|
|
35
|
+
"""Return the SDK's ``User-Agent`` value.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
``bronto-sdk-python/<version>``.
|
|
39
|
+
"""
|
|
40
|
+
return f"bronto-sdk-python/{VERSION}"
|
bronto_sdk/_client.py
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""The synchronous Bronto client — a thin I/O shell over ``httpx.Client``.
|
|
2
|
+
|
|
3
|
+
Every request-shaping decision lives in the pure helpers of
|
|
4
|
+
:mod:`bronto_sdk._client_config` and :mod:`bronto_sdk._transport`; this module
|
|
5
|
+
only performs the actual HTTP call, so it stays a mirror of
|
|
6
|
+
:class:`bronto_sdk._async_client.AsyncBrontoClient`.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from functools import cached_property
|
|
12
|
+
from types import TracebackType
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
import httpx
|
|
16
|
+
|
|
17
|
+
from ._client_config import (
|
|
18
|
+
client_default_options,
|
|
19
|
+
prepare_request,
|
|
20
|
+
read_env_config,
|
|
21
|
+
resolve_base_url,
|
|
22
|
+
wrap_transport_error,
|
|
23
|
+
)
|
|
24
|
+
from ._request_options import RequestOptions, client_credential
|
|
25
|
+
from ._transport import parse_response
|
|
26
|
+
from .resources._datasets import DatasetsResource
|
|
27
|
+
from .resources._metrics import MetricsResource
|
|
28
|
+
from .resources._monitors import MonitorsResource
|
|
29
|
+
from .resources._search import SearchResource
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class BrontoClient:
|
|
33
|
+
"""A synchronous client for the Bronto REST API.
|
|
34
|
+
|
|
35
|
+
The client is either *client-bound* (constructed with ``api_key`` or
|
|
36
|
+
``bearer_token``; every call uses it) or *credential-less* (constructed with
|
|
37
|
+
neither; every call must supply a credential via ``options``). The mode is
|
|
38
|
+
fixed at construction — see the two-mode rule in
|
|
39
|
+
:mod:`bronto_sdk._request_options`.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
api_key: str | None = None,
|
|
45
|
+
region: str | None = None,
|
|
46
|
+
*,
|
|
47
|
+
bearer_token: str | None = None,
|
|
48
|
+
timeout: float = 30.0,
|
|
49
|
+
base_url: str | None = None,
|
|
50
|
+
http_client: httpx.Client | None = None,
|
|
51
|
+
) -> None:
|
|
52
|
+
"""Construct a client.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
api_key: A Bronto API key to bind to every call. Omit for a
|
|
56
|
+
credential-less client.
|
|
57
|
+
region: The region slug (e.g. ``"eu"``); resolved to the REST base
|
|
58
|
+
URL. Ignored when ``base_url`` is given.
|
|
59
|
+
bearer_token: A JWT bearer token to bind to every call. Wins over
|
|
60
|
+
``api_key``. Omit for a credential-less client.
|
|
61
|
+
timeout: The default per-request timeout in seconds.
|
|
62
|
+
base_url: An explicit base URL that overrides ``region`` — for
|
|
63
|
+
testing or a non-standard deployment. Trusted and used verbatim.
|
|
64
|
+
http_client: An existing ``httpx.Client`` to reuse. When given, the
|
|
65
|
+
SDK will not close it.
|
|
66
|
+
|
|
67
|
+
Raises:
|
|
68
|
+
BrontoConfigError: When neither ``region`` nor ``base_url`` resolves
|
|
69
|
+
an endpoint, or the region slug is invalid.
|
|
70
|
+
"""
|
|
71
|
+
self._base_url = resolve_base_url(region=region, base_url=base_url)
|
|
72
|
+
self._bound = client_credential(api_key=api_key, bearer_token=bearer_token)
|
|
73
|
+
self._defaults = client_default_options(timeout=timeout)
|
|
74
|
+
self._http = http_client or httpx.Client()
|
|
75
|
+
self._owns_http_client = http_client is None
|
|
76
|
+
|
|
77
|
+
@classmethod
|
|
78
|
+
def from_env(cls) -> BrontoClient:
|
|
79
|
+
"""Build a client from ``BRONTO_API_KEY`` and ``BRONTO_REGION``.
|
|
80
|
+
|
|
81
|
+
``BRONTO_BASE_URL`` is honoured when set and wins over ``BRONTO_REGION``.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
A client-bound :class:`BrontoClient`.
|
|
85
|
+
|
|
86
|
+
Raises:
|
|
87
|
+
BrontoConfigError: Naming the first missing environment variable.
|
|
88
|
+
"""
|
|
89
|
+
env = read_env_config()
|
|
90
|
+
return cls(api_key=env.api_key, region=env.region, base_url=env.base_url)
|
|
91
|
+
|
|
92
|
+
@cached_property
|
|
93
|
+
def search(self) -> SearchResource:
|
|
94
|
+
"""The typed ``POST /search`` surface."""
|
|
95
|
+
return SearchResource(self)
|
|
96
|
+
|
|
97
|
+
@cached_property
|
|
98
|
+
def monitors(self) -> MonitorsResource:
|
|
99
|
+
"""The typed monitor surface."""
|
|
100
|
+
return MonitorsResource(self)
|
|
101
|
+
|
|
102
|
+
@cached_property
|
|
103
|
+
def datasets(self) -> DatasetsResource:
|
|
104
|
+
"""The typed dataset surface."""
|
|
105
|
+
return DatasetsResource(self)
|
|
106
|
+
|
|
107
|
+
@cached_property
|
|
108
|
+
def metrics(self) -> MetricsResource:
|
|
109
|
+
"""The typed metric-definition surface."""
|
|
110
|
+
return MetricsResource(self)
|
|
111
|
+
|
|
112
|
+
def get(
|
|
113
|
+
self,
|
|
114
|
+
path: str,
|
|
115
|
+
*,
|
|
116
|
+
params: dict[str, Any] | None = None,
|
|
117
|
+
options: RequestOptions | None = None,
|
|
118
|
+
) -> dict[str, object]:
|
|
119
|
+
"""Send a ``GET`` request and return the parsed JSON object.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
path: The request path, absolute-style (``"/search"``) or bare
|
|
123
|
+
(``"monitors/m-1"``).
|
|
124
|
+
params: Optional query-string parameters.
|
|
125
|
+
options: Optional per-request overrides.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
The decoded JSON response object.
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
BrontoAPIError: On any non-2xx response.
|
|
132
|
+
BrontoConnectionError: On a transport-level failure.
|
|
133
|
+
BrontoConfigError: On a credential resolution error.
|
|
134
|
+
"""
|
|
135
|
+
return self._request(
|
|
136
|
+
"GET", path, params=params, json_body=None, options=options
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
def post(
|
|
140
|
+
self,
|
|
141
|
+
path: str,
|
|
142
|
+
*,
|
|
143
|
+
json: dict[str, Any] | None = None,
|
|
144
|
+
params: dict[str, Any] | None = None,
|
|
145
|
+
options: RequestOptions | None = None,
|
|
146
|
+
) -> dict[str, object]:
|
|
147
|
+
"""Send a ``POST`` request and return the parsed JSON object.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
path: The request path, absolute-style or bare.
|
|
151
|
+
json: Optional JSON request body.
|
|
152
|
+
params: Optional query-string parameters.
|
|
153
|
+
options: Optional per-request overrides.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
The decoded JSON response object.
|
|
157
|
+
|
|
158
|
+
Raises:
|
|
159
|
+
BrontoAPIError: On any non-2xx response.
|
|
160
|
+
BrontoConnectionError: On a transport-level failure.
|
|
161
|
+
BrontoConfigError: On a credential resolution error.
|
|
162
|
+
"""
|
|
163
|
+
return self._request(
|
|
164
|
+
"POST", path, params=params, json_body=json, options=options
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
def _request(
|
|
168
|
+
self,
|
|
169
|
+
method: str,
|
|
170
|
+
path: str,
|
|
171
|
+
*,
|
|
172
|
+
params: dict[str, Any] | None,
|
|
173
|
+
json_body: dict[str, Any] | None,
|
|
174
|
+
options: RequestOptions | None,
|
|
175
|
+
) -> dict[str, object]:
|
|
176
|
+
"""Perform the shared per-call flow around a single ``httpx`` request.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
method: The HTTP method.
|
|
180
|
+
path: The request path.
|
|
181
|
+
params: Optional query-string parameters.
|
|
182
|
+
json_body: Optional JSON request body.
|
|
183
|
+
options: Optional per-request overrides.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
The decoded JSON response object.
|
|
187
|
+
|
|
188
|
+
Raises:
|
|
189
|
+
BrontoAPIError: On any non-2xx response.
|
|
190
|
+
BrontoConnectionError: On a transport-level failure.
|
|
191
|
+
BrontoConfigError: On a credential resolution error.
|
|
192
|
+
"""
|
|
193
|
+
prepared = prepare_request(
|
|
194
|
+
bound=self._bound,
|
|
195
|
+
defaults=self._defaults,
|
|
196
|
+
base_url=self._base_url,
|
|
197
|
+
path=path,
|
|
198
|
+
options=options,
|
|
199
|
+
)
|
|
200
|
+
timeout = (
|
|
201
|
+
prepared.timeout
|
|
202
|
+
if prepared.timeout is not None
|
|
203
|
+
else httpx.USE_CLIENT_DEFAULT
|
|
204
|
+
)
|
|
205
|
+
try:
|
|
206
|
+
response = self._http.request(
|
|
207
|
+
method,
|
|
208
|
+
prepared.url,
|
|
209
|
+
params=params,
|
|
210
|
+
json=json_body,
|
|
211
|
+
headers=prepared.headers,
|
|
212
|
+
timeout=timeout,
|
|
213
|
+
)
|
|
214
|
+
except httpx.HTTPError as exc:
|
|
215
|
+
raise wrap_transport_error(exc) from exc
|
|
216
|
+
return parse_response(response.status_code, response.headers, response.text)
|
|
217
|
+
|
|
218
|
+
def close(self) -> None:
|
|
219
|
+
"""Close the underlying HTTP client, unless it was caller-supplied."""
|
|
220
|
+
if self._owns_http_client:
|
|
221
|
+
self._http.close()
|
|
222
|
+
|
|
223
|
+
def __enter__(self) -> BrontoClient:
|
|
224
|
+
"""Enter the context manager, returning the client."""
|
|
225
|
+
return self
|
|
226
|
+
|
|
227
|
+
def __exit__(
|
|
228
|
+
self,
|
|
229
|
+
exc_type: type[BaseException] | None,
|
|
230
|
+
exc: BaseException | None,
|
|
231
|
+
tb: TracebackType | None,
|
|
232
|
+
) -> None:
|
|
233
|
+
"""Close the client on context-manager exit."""
|
|
234
|
+
self.close()
|