volcano-sdk-python 0.10.3__py3-none-any.whl → 0.10.4__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.
volcano_sdk/_transport.py CHANGED
@@ -738,7 +738,7 @@ def _error_type(status: int) -> type[VolcanoError]:
738
738
  return VolcanoError
739
739
 
740
740
 
741
- def response_payload(response: TransportResponse, expected_status: int) -> Any:
741
+ def response_payload(response: TransportResponse, expected_status: int) -> object:
742
742
  status = int(response.status_code)
743
743
  if status != expected_status:
744
744
  payload: Mapping[str, object]
volcano_sdk/locks.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from collections.abc import Mapping
5
6
  from contextlib import contextmanager, suppress
6
7
  from datetime import datetime
7
8
  from typing import TYPE_CHECKING, Protocol, cast
@@ -22,6 +23,7 @@ _MIN_LOCK_TTL_SECONDS = 5
22
23
  _MAX_LOCK_TTL_SECONDS = 7_776_000
23
24
  _INVALID_LOCK_TTL = "ttl must be an integer between 5 seconds and 90 days"
24
25
  _MISSING_RENEWAL_FAILURE = "lock guard rejected renewal without a failure"
26
+ _INVALID_LOCK_RESPONSE = "Expected a complete lock response"
25
27
 
26
28
 
27
29
  class LocksContext(Protocol):
@@ -82,6 +84,26 @@ def _parse_datetime(value: object) -> datetime | None:
82
84
  return datetime.fromisoformat(str(value))
83
85
 
84
86
 
87
+ def _lock_values(payload: object) -> Mapping[object, object]:
88
+ if not isinstance(payload, Mapping):
89
+ raise TypeError(_INVALID_LOCK_RESPONSE)
90
+ return cast("Mapping[object, object]", payload)
91
+
92
+
93
+ def _fencing_token(value: object) -> int | None:
94
+ if value is None or type(value) is int:
95
+ return value
96
+ raise TypeError(_INVALID_LOCK_RESPONSE)
97
+
98
+
99
+ def _lease_fields(payload: Mapping[object, object]) -> tuple[datetime, int]:
100
+ expires_at = payload.get("expires_at")
101
+ fencing_token = payload.get("fencing_token")
102
+ if not isinstance(expires_at, str) or type(fencing_token) is not int:
103
+ raise TypeError(_INVALID_LOCK_RESPONSE)
104
+ return datetime.fromisoformat(expires_at), fencing_token
105
+
106
+
85
107
  def _validate_ttl(ttl: object) -> None:
86
108
  if (
87
109
  isinstance(ttl, bool)
@@ -125,11 +147,14 @@ class Locks:
125
147
  key=key,
126
148
  request_id=_request_uuid(request_id, "request_id"),
127
149
  )
128
- payload = response_payload(response, 200)
150
+ payload = _lock_values(response_payload(response, 200))
151
+ held = payload.get("held")
152
+ if not isinstance(held, bool):
153
+ raise TypeError(_INVALID_LOCK_RESPONSE)
129
154
  return LockState(
130
- held=payload["held"],
155
+ held=held,
131
156
  expires_at=_parse_datetime(payload.get("expires_at")),
132
- fencing_token=payload.get("fencing_token"),
157
+ fencing_token=_fencing_token(payload.get("fencing_token")),
133
158
  )
134
159
 
135
160
  def acquire(
@@ -173,17 +198,18 @@ class Locks:
173
198
  raise
174
199
  started_at = _lease_now()
175
200
  payload = self._acquire_payload(key, ttl, token, request_id, authorization)
201
+ expires_at, fencing_token = _lease_fields(payload)
176
202
  lease = LockLease(
177
203
  key=key,
178
204
  token=token,
179
- expires_at=_parse_datetime(payload.get("expires_at")),
180
- fencing_token=cast("int | None", payload.get("fencing_token")),
205
+ expires_at=expires_at,
206
+ fencing_token=fencing_token,
181
207
  )
182
208
  return lease, started_at
183
209
 
184
210
  def _acquire_payload(
185
211
  self, key: str, ttl: int, token: str, request_id: str, authorization: str
186
- ) -> dict[str, object]:
212
+ ) -> Mapping[object, object]:
187
213
  response = invoke(
188
214
  self._client._transport.acquire_project_lock,
189
215
  authorization=authorization,
@@ -192,7 +218,7 @@ class Locks:
192
218
  token=token,
193
219
  request_id=request_id,
194
220
  )
195
- return cast("dict[str, object]", response_payload(response, 201))
221
+ return _lock_values(response_payload(response, 201))
196
222
 
197
223
  def renew(
198
224
  self, key: str, lease: LockLease, *, ttl: int, request_id: str | None = None
@@ -216,12 +242,13 @@ class Locks:
216
242
  ttl=ttl,
217
243
  token=lease.token,
218
244
  )
219
- payload = response_payload(response, 200)
245
+ payload = _lock_values(response_payload(response, 200))
246
+ expires_at, fencing_token = _lease_fields(payload)
220
247
  return LockLease(
221
248
  key=key,
222
249
  token=lease.token,
223
- expires_at=_parse_datetime(payload.get("expires_at")),
224
- fencing_token=payload.get("fencing_token"),
250
+ expires_at=expires_at,
251
+ fencing_token=fencing_token,
225
252
  )
226
253
 
227
254
  def release(
volcano_sdk/realtime.py CHANGED
@@ -35,6 +35,7 @@ from ._transport import (
35
35
  invoke_async,
36
36
  response_payload,
37
37
  )
38
+ from .database import _database_rows
38
39
  from .models import JSONValue, _freeze_json
39
40
 
40
41
  if TYPE_CHECKING:
@@ -1391,8 +1392,7 @@ class Realtime:
1391
1392
  "limit": len(row_ids),
1392
1393
  },
1393
1394
  )
1394
- payload = response_payload(response, 200)
1395
- rows = list(payload["data"])
1395
+ rows = _database_rows(response_payload(response, 200))
1396
1396
  return tuple(
1397
1397
  next(
1398
1398
  (row for row in rows if row.get("id") == request.row_id),
volcano_sdk/storage.py CHANGED
@@ -50,6 +50,7 @@ _HTTP_PARTIAL_CONTENT = 206
50
50
  _UPLOAD_SPOOL_READ_SIZE = 1_048_576
51
51
  _UPLOAD_SOURCE_UNAVAILABLE = "Upload source is temporarily unavailable"
52
52
  _INVALID_SIMPLE_UPLOAD = "Upload data must be bytes or a readable binary stream"
53
+ _INVALID_UPLOAD_RESPONSE = "Expected a storage upload response object"
53
54
 
54
55
 
55
56
  def _optional_datetime(value: object) -> datetime | None:
@@ -498,7 +499,12 @@ class StorageBucket:
498
499
  binding=binding,
499
500
  )
500
501
  payload = response_payload(response, 201)
501
- return dict(payload)
502
+ if not isinstance(payload, Mapping):
503
+ raise TypeError(_INVALID_UPLOAD_RESPONSE)
504
+ values = cast("Mapping[object, object]", payload)
505
+ if not all(isinstance(key, str) for key in values):
506
+ raise TypeError(_INVALID_UPLOAD_RESPONSE)
507
+ return dict(cast("Mapping[str, Any]", values))
502
508
 
503
509
  def download(self, path: str, *, byte_range: str | None = None) -> bytes:
504
510
  """Download bytes from a path in this bucket.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: volcano-sdk-python
3
- Version: 0.10.3
3
+ Version: 0.10.4
4
4
  Summary: Official Python SDK for Volcano
5
5
  Project-URL: Homepage, https://volcano.dev
6
6
  Project-URL: Repository, https://github.com/Kong/volcano-sdk-python
@@ -8,7 +8,7 @@ volcano_sdk/_log_response.py,sha256=wZaugr0eD0ZLSa-M6TUEwdIDsI_wblyDXucYEwNK14c,
8
8
  volcano_sdk/_realtime_fetch_worker.py,sha256=f3mUPe5qZmGuhA9jfpqEUtpLZmvlJ1FhI1XkNz238FI,10406
9
9
  volcano_sdk/_session.py,sha256=w7B1rwbhH3yoE8kFA6gSpUpQb24rPwppotMu-IPHXdI,3025
10
10
  volcano_sdk/_session_operations.py,sha256=s_m-Gl-knjDrjUOFl6z2lJW4IGHAgCSCjRNA7LCB5j0,5727
11
- volcano_sdk/_transport.py,sha256=hPciv-WJ7A7Siu6SNU6Ix6x_avPGTucxj8rzJePj43w,61904
11
+ volcano_sdk/_transport.py,sha256=XcDk8NAEAHmtH3nmlMWIixcIiEFb-FP_n8VU44QcuXg,61907
12
12
  volcano_sdk/auth.py,sha256=OxK9s6XW9jNGA_cXos-cHEZYcmYsxrojruSyLS0mWVs,52237
13
13
  volcano_sdk/client.py,sha256=KH52e5WC4ii-hnipB9vNzSDEyfvvpOMBCdtwzRqNUOI,12701
14
14
  volcano_sdk/connection_string.py,sha256=p87P-fd9wVfia-LLRRsFTkW6tzx9FXn-GAy9OIOoDvE,2664
@@ -17,12 +17,12 @@ volcano_sdk/durable.py,sha256=YQa_5tT4kxkHTyP4nRMhjWyExnSICXD_RAipSQ1cax8,13422
17
17
  volcano_sdk/durable_authoring.py,sha256=L8qK694e0aPLnRLIDQm9dbYGy4M0NPf9wZYECkVrOfA,35842
18
18
  volcano_sdk/errors.py,sha256=ffs66FIN_jhyh5SMj7KdXb-zVV3DSgVK6xJEPNA5h9Y,1613
19
19
  volcano_sdk/functions.py,sha256=7loNEF1tkojAnp_C0rBWWcvO3l22Tx2JQn28l6PoV2Q,13264
20
- volcano_sdk/locks.py,sha256=ptZq7CvXtlK0VU42Qq6DcQQMMjMqQl1zw9cxqdALMfU,9922
20
+ volcano_sdk/locks.py,sha256=Ctr4OKAmJqCPD03lkPEjH7JzYfdpESHEYFOmTj0z1Ds,10894
21
21
  volcano_sdk/logs.py,sha256=l71mT5ejIq2_9O_aug5_pZuZPAYkdJQa03RhPvSDH9g,4075
22
22
  volcano_sdk/models.py,sha256=ZIo2YdZ-Ba7rCmHBo3eV9LGjpEftVTeVmrrfq-zGujs,11182
23
23
  volcano_sdk/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
24
- volcano_sdk/realtime.py,sha256=gYTqfrmR0owEVxUjUU2Su8k6u_wm1Pjyggo2jJXSR1g,64200
25
- volcano_sdk/storage.py,sha256=3US6vkhMC9jaTah6KcCatuAuLATjpPZfYHdF20t361U,27713
24
+ volcano_sdk/realtime.py,sha256=qulBz-rUm8SFId_jt40z7Q-wDtTb572gi1SKMDqbAto,64213
25
+ volcano_sdk/storage.py,sha256=kh5xN5Pu1gp3fOKyJlmrMGE9ZnN7U9jkLp_l2Ovj1_Y,28081
26
26
  volcano_sdk/_generated/__init__.py,sha256=ZlB8wMYdN6EjpUS5W_lX3jsxq9G1kOcmUr-j3Fccfn8,164
27
27
  volcano_sdk/_generated/client.py,sha256=GDzw6T2uRmPlUb1DImpBGxwy0dNbhmBknfvvIQW0GuU,12387
28
28
  volcano_sdk/_generated/errors.py,sha256=trp-p5qn1_JLRxGZhdHtICaNPaCrcDCe4TgIihBravk,546
@@ -810,7 +810,7 @@ volcano_sdk/_generated/models/usage_data_point.py,sha256=d4U08JbVTiIMM_l2BmRILL1
810
810
  volcano_sdk/_generated/models/variable.py,sha256=t8XaBfTwIH42L8RL4DFDtdqbhVfDEnRS5Axq2q6Tpvk,6405
811
811
  volcano_sdk/_generated/models/variable_deploy_source.py,sha256=G_aCiFHzQx8WhJFs0GvYZEFclfTrfkDvd3kT1e3vty8,463
812
812
  volcano_sdk/_generated/models/variable_status.py,sha256=THSsKBSiAYG4kAtBzGA4TZqxjgx8hdL0Q4qCdZfOj00,391
813
- volcano_sdk_python-0.10.3.dist-info/METADATA,sha256=hSD3rh78qfzXlJ1uF0_cOLwlp9q5IEHrXZA5vnwuCl4,45774
814
- volcano_sdk_python-0.10.3.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
815
- volcano_sdk_python-0.10.3.dist-info/licenses/LICENSE,sha256=AIHJy-5MFqM8fHfuGFTTb9a8rvJGypcVgN4aZ-7XTWw,11387
816
- volcano_sdk_python-0.10.3.dist-info/RECORD,,
813
+ volcano_sdk_python-0.10.4.dist-info/METADATA,sha256=HGwNfdnW1A-y9EZipIB3jxJbC8y9PDbHDjJBQY0O8-A,45774
814
+ volcano_sdk_python-0.10.4.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
815
+ volcano_sdk_python-0.10.4.dist-info/licenses/LICENSE,sha256=AIHJy-5MFqM8fHfuGFTTb9a8rvJGypcVgN4aZ-7XTWw,11387
816
+ volcano_sdk_python-0.10.4.dist-info/RECORD,,