clone-sdk 0.2.0__tar.gz → 0.3.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.
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/PKG-INFO +24 -6
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/README.md +20 -5
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/pyproject.toml +4 -1
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/src/clone_sdk/__init__.py +5 -1
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/src/clone_sdk/client.py +53 -6
- clone_sdk-0.3.0/src/clone_sdk/media.py +202 -0
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/src/clone_sdk/models.py +8 -0
- clone_sdk-0.3.0/tests/test_media.py +71 -0
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/uv.lock +201 -1
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/.gitignore +0 -0
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/LICENSE +0 -0
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/src/clone_sdk/py.typed +0 -0
- {clone_sdk-0.2.0 → clone_sdk-0.3.0}/tests/test_client.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clone-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Server-side Python client for Clone prompt predictions.
|
|
5
5
|
Project-URL: Homepage, https://clone.is/clone-sdk
|
|
6
6
|
Project-URL: Repository, https://github.com/cloneisyou/clone-sdk
|
|
@@ -13,6 +13,9 @@ Classifier: Typing :: Typed
|
|
|
13
13
|
Requires-Python: >=3.11
|
|
14
14
|
Requires-Dist: httpx<1,>=0.28.1
|
|
15
15
|
Requires-Dist: pydantic<3,>=2.7
|
|
16
|
+
Provides-Extra: media
|
|
17
|
+
Requires-Dist: av<18,>=16; extra == 'media'
|
|
18
|
+
Requires-Dist: numpy<3,>=1.26; extra == 'media'
|
|
16
19
|
Description-Content-Type: text/markdown
|
|
17
20
|
|
|
18
21
|
# Clone Python SDK
|
|
@@ -21,11 +24,21 @@ Server-side synchronous and asynchronous clients for Clone predictions, usage,
|
|
|
21
24
|
observation events, cancellation and optional user-approved Clone connections.
|
|
22
25
|
Composer UI stays in the JavaScript SDK. This client never submits a user message.
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
For selected local artifacts, `image_artifact(path, id="draft", revision="1")` prepares a bounded JPEG/PNG.
|
|
28
|
+
The media additions below are unreleased and require the corresponding SDK build and matching API deployment.
|
|
29
|
+
Install the `media` extra from the matching SDK build and call
|
|
30
|
+
`video_artifact(path, id="draft", revision="1")` to prepare the original video/audio and four preview frames, or `audio_artifact(...)` for a selected audio file.
|
|
31
|
+
Pass the returned dictionary as the prediction request's `artifact`.
|
|
32
|
+
Preparation is local; the subsequent explicit prediction uploads selected pixels and original media.
|
|
33
|
+
Both clients reject a media result unless its receipts match the supplied pixels and timestamps.
|
|
34
|
+
This requires matching API deployment and image/audiovisual provider configuration.
|
|
35
|
+
The separate reviewer returns `artifact_review` with findings, time intervals and coverage before prompt prediction. The server uses OpenAI only, with timestamped video frames (up to 48 uniform frames plus detected changes and an end frame), bounded 5fps reinspection, and actual normalized WAV audio (up to 240 seconds per original). Partial extraction cannot produce approval. Actual player playback and every-frame understanding remain separate evidence. Add `artifact["criteria"]` entries with explicit IDs and text; preferences remain optional taste guidance. See [context mappings](../docs/context-mapping.md).
|
|
36
|
+
|
|
37
|
+
Python 3.11+. Install `clone-sdk` from [PyPI](https://pypi.org/project/clone-sdk/);
|
|
38
|
+
import `clone_sdk`.
|
|
26
39
|
|
|
27
40
|
```sh
|
|
28
|
-
pip install
|
|
41
|
+
python -m pip install clone-sdk==0.3.0
|
|
29
42
|
```
|
|
30
43
|
|
|
31
44
|
```python
|
|
@@ -50,7 +63,7 @@ with CloneClient(os.environ["CLONE_APP_KEY"]) as client:
|
|
|
50
63
|
|
|
51
64
|
For FastAPI or other async servers, use `async with AsyncCloneClient(...)` and
|
|
52
65
|
`await client.predict(...)`. Reuse a client for the application's lifetime and
|
|
53
|
-
close it during shutdown.
|
|
66
|
+
close it during shutdown. Media predictions automatically use a 180-second budget. For ordinary requests the async client enforces a total 15-second deadline,
|
|
54
67
|
including body reads. The sync client uses 15-second per-I/O timeouts and checks
|
|
55
68
|
the elapsed budget between response chunks. Both bound concurrency to 16 by
|
|
56
69
|
default, reject saturation without queuing, limit response bodies to 1 MiB, and
|
|
@@ -89,7 +102,12 @@ client.cancel(subject, "prediction-001")
|
|
|
89
102
|
```
|
|
90
103
|
|
|
91
104
|
Only report `submitted` after your host accepts the send. Reuse an event ID on
|
|
92
|
-
delivery retries.
|
|
105
|
+
delivery retries. Behavior receipts and outcomes contain no prompt text and do
|
|
106
|
+
not change billing. Explicit evaluations can supply a reason; guidance and edited
|
|
107
|
+
successful submissions require `content_opt_in=True` before sending text. Feedback
|
|
108
|
+
memory is encrypted, app/user scoped, and expires after 30 days. Call
|
|
109
|
+
`client.clear_feedback(subject)` to clear it. See
|
|
110
|
+
[feedback](https://clone.is/docs/api-reference#observation-events) for event fields and clearing semantics.
|
|
93
111
|
Read the [public API](https://clone.is/docs/api-reference),
|
|
94
112
|
[billing](https://clone.is/docs/billing) and
|
|
95
113
|
[reliability](https://clone.is/docs/reliability) contracts before production use.
|
|
@@ -4,11 +4,21 @@ Server-side synchronous and asynchronous clients for Clone predictions, usage,
|
|
|
4
4
|
observation events, cancellation and optional user-approved Clone connections.
|
|
5
5
|
Composer UI stays in the JavaScript SDK. This client never submits a user message.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
For selected local artifacts, `image_artifact(path, id="draft", revision="1")` prepares a bounded JPEG/PNG.
|
|
8
|
+
The media additions below are unreleased and require the corresponding SDK build and matching API deployment.
|
|
9
|
+
Install the `media` extra from the matching SDK build and call
|
|
10
|
+
`video_artifact(path, id="draft", revision="1")` to prepare the original video/audio and four preview frames, or `audio_artifact(...)` for a selected audio file.
|
|
11
|
+
Pass the returned dictionary as the prediction request's `artifact`.
|
|
12
|
+
Preparation is local; the subsequent explicit prediction uploads selected pixels and original media.
|
|
13
|
+
Both clients reject a media result unless its receipts match the supplied pixels and timestamps.
|
|
14
|
+
This requires matching API deployment and image/audiovisual provider configuration.
|
|
15
|
+
The separate reviewer returns `artifact_review` with findings, time intervals and coverage before prompt prediction. The server uses OpenAI only, with timestamped video frames (up to 48 uniform frames plus detected changes and an end frame), bounded 5fps reinspection, and actual normalized WAV audio (up to 240 seconds per original). Partial extraction cannot produce approval. Actual player playback and every-frame understanding remain separate evidence. Add `artifact["criteria"]` entries with explicit IDs and text; preferences remain optional taste guidance. See [context mappings](../docs/context-mapping.md).
|
|
16
|
+
|
|
17
|
+
Python 3.11+. Install `clone-sdk` from [PyPI](https://pypi.org/project/clone-sdk/);
|
|
18
|
+
import `clone_sdk`.
|
|
9
19
|
|
|
10
20
|
```sh
|
|
11
|
-
pip install
|
|
21
|
+
python -m pip install clone-sdk==0.3.0
|
|
12
22
|
```
|
|
13
23
|
|
|
14
24
|
```python
|
|
@@ -33,7 +43,7 @@ with CloneClient(os.environ["CLONE_APP_KEY"]) as client:
|
|
|
33
43
|
|
|
34
44
|
For FastAPI or other async servers, use `async with AsyncCloneClient(...)` and
|
|
35
45
|
`await client.predict(...)`. Reuse a client for the application's lifetime and
|
|
36
|
-
close it during shutdown.
|
|
46
|
+
close it during shutdown. Media predictions automatically use a 180-second budget. For ordinary requests the async client enforces a total 15-second deadline,
|
|
37
47
|
including body reads. The sync client uses 15-second per-I/O timeouts and checks
|
|
38
48
|
the elapsed budget between response chunks. Both bound concurrency to 16 by
|
|
39
49
|
default, reject saturation without queuing, limit response bodies to 1 MiB, and
|
|
@@ -72,7 +82,12 @@ client.cancel(subject, "prediction-001")
|
|
|
72
82
|
```
|
|
73
83
|
|
|
74
84
|
Only report `submitted` after your host accepts the send. Reuse an event ID on
|
|
75
|
-
delivery retries.
|
|
85
|
+
delivery retries. Behavior receipts and outcomes contain no prompt text and do
|
|
86
|
+
not change billing. Explicit evaluations can supply a reason; guidance and edited
|
|
87
|
+
successful submissions require `content_opt_in=True` before sending text. Feedback
|
|
88
|
+
memory is encrypted, app/user scoped, and expires after 30 days. Call
|
|
89
|
+
`client.clear_feedback(subject)` to clear it. See
|
|
90
|
+
[feedback](https://clone.is/docs/api-reference#observation-events) for event fields and clearing semantics.
|
|
76
91
|
Read the [public API](https://clone.is/docs/api-reference),
|
|
77
92
|
[billing](https://clone.is/docs/billing) and
|
|
78
93
|
[reliability](https://clone.is/docs/reliability) contracts before production use.
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "clone-sdk"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "Server-side Python client for Clone prompt predictions."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -13,6 +13,9 @@ license-files = ["LICENSE"]
|
|
|
13
13
|
dependencies = ["httpx>=0.28.1,<1", "pydantic>=2.7,<3"]
|
|
14
14
|
classifiers = ["Programming Language :: Python :: 3", "Typing :: Typed"]
|
|
15
15
|
|
|
16
|
+
[project.optional-dependencies]
|
|
17
|
+
media = ["av>=16,<18", "numpy>=1.26,<3"]
|
|
18
|
+
|
|
16
19
|
[project.urls]
|
|
17
20
|
Homepage = "https://clone.is/clone-sdk"
|
|
18
21
|
Repository = "https://github.com/cloneisyou/clone-sdk"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from .client import AsyncCloneClient, CloneClient, CloneError, ConnectionFlow
|
|
2
|
+
from .media import audio_artifact, image_artifact, video_artifact
|
|
2
3
|
from .models import (
|
|
3
4
|
CancelResult,
|
|
4
5
|
Connection,
|
|
@@ -12,6 +13,9 @@ from .models import (
|
|
|
12
13
|
|
|
13
14
|
__all__ = [
|
|
14
15
|
"AsyncCloneClient",
|
|
16
|
+
"image_artifact",
|
|
17
|
+
"video_artifact",
|
|
18
|
+
"audio_artifact",
|
|
15
19
|
"CloneClient",
|
|
16
20
|
"CloneError",
|
|
17
21
|
"ConnectionFlow",
|
|
@@ -24,4 +28,4 @@ __all__ = [
|
|
|
24
28
|
"RevokeResult",
|
|
25
29
|
"Usage",
|
|
26
30
|
]
|
|
27
|
-
__version__ = "0.
|
|
31
|
+
__version__ = "0.3.0"
|
|
@@ -95,6 +95,27 @@ def _identity(result: Prediction, request: Mapping[str, Any]) -> Prediction:
|
|
|
95
95
|
)
|
|
96
96
|
if expected != actual:
|
|
97
97
|
raise CloneError("response_identity_mismatch", 502)
|
|
98
|
+
artifact = request.get("artifact") or {}
|
|
99
|
+
images = artifact.get("images") or []
|
|
100
|
+
media = artifact.get("media") or []
|
|
101
|
+
if images or media:
|
|
102
|
+
expected_media = [
|
|
103
|
+
(
|
|
104
|
+
image["ref"],
|
|
105
|
+
hashlib.sha256(base64.b64decode(image["data"], validate=True)).hexdigest(),
|
|
106
|
+
image.get("timestamp_seconds"),
|
|
107
|
+
)
|
|
108
|
+
for image in [*images, *media]
|
|
109
|
+
]
|
|
110
|
+
actual_media = [(item.ref, item.sha256, item.timestamp_seconds) for item in result.media_review]
|
|
111
|
+
if expected_media != actual_media:
|
|
112
|
+
raise CloneError("media_review_not_acknowledged", 502)
|
|
113
|
+
if media:
|
|
114
|
+
sources = (result.artifact_review or {}).get("sources") or []
|
|
115
|
+
if [
|
|
116
|
+
(item.get("ref"), item.get("sha256"), item.get("timestamp_seconds")) for item in sources
|
|
117
|
+
] != expected_media:
|
|
118
|
+
raise CloneError("native_media_review_missing", 502)
|
|
98
119
|
if result.status == "abstained" and (result.completion or result.usage.prediction_units):
|
|
99
120
|
raise CloneError("invalid_response", 502)
|
|
100
121
|
return result
|
|
@@ -168,20 +189,24 @@ class CloneClient(_Options):
|
|
|
168
189
|
limits=httpx.Limits(max_connections=self.limit, max_keepalive_connections=self.limit),
|
|
169
190
|
)
|
|
170
191
|
|
|
171
|
-
def _call(
|
|
192
|
+
def _call(
|
|
193
|
+
self, path: str, model: type[T], body: dict | None = None, *, timeout: float | None = None
|
|
194
|
+
) -> T:
|
|
172
195
|
if not self._slots.acquire(blocking=False):
|
|
173
196
|
raise CloneError("client_capacity_exceeded", 503)
|
|
174
197
|
try:
|
|
175
198
|
start = time.monotonic()
|
|
199
|
+
timeout = self.timeout if timeout is None else timeout
|
|
176
200
|
with self._client.stream(
|
|
177
201
|
"GET" if body is None else "POST",
|
|
178
202
|
self.base_url + "/v1" + path,
|
|
179
203
|
headers=self.headers,
|
|
180
204
|
json=body,
|
|
205
|
+
timeout=timeout,
|
|
181
206
|
) as response:
|
|
182
207
|
data = bytearray()
|
|
183
208
|
for chunk in response.iter_bytes():
|
|
184
|
-
if time.monotonic() - start >
|
|
209
|
+
if time.monotonic() - start > timeout:
|
|
185
210
|
raise CloneError("request_timeout", 504)
|
|
186
211
|
data.extend(chunk)
|
|
187
212
|
if len(data) > MAX_RESPONSE_BYTES:
|
|
@@ -195,7 +220,17 @@ class CloneClient(_Options):
|
|
|
195
220
|
self._slots.release()
|
|
196
221
|
|
|
197
222
|
def predict(self, user_id: str, request: Mapping[str, Any]) -> Prediction:
|
|
198
|
-
return _identity(
|
|
223
|
+
return _identity(
|
|
224
|
+
self._call(
|
|
225
|
+
"/predictions",
|
|
226
|
+
Prediction,
|
|
227
|
+
{**request, "user_id": user_id},
|
|
228
|
+
timeout=180
|
|
229
|
+
if any((request.get("artifact") or {}).get(key) for key in ("media", "images"))
|
|
230
|
+
else None,
|
|
231
|
+
),
|
|
232
|
+
request,
|
|
233
|
+
)
|
|
199
234
|
|
|
200
235
|
def record_event(self, user_id: str, event: Mapping[str, Any]) -> EventResult:
|
|
201
236
|
return self._call("/prediction-events", EventResult, {**event, "user_id": user_id})
|
|
@@ -256,17 +291,21 @@ class AsyncCloneClient(_Options):
|
|
|
256
291
|
limits=httpx.Limits(max_connections=self.limit, max_keepalive_connections=self.limit),
|
|
257
292
|
)
|
|
258
293
|
|
|
259
|
-
async def _call(
|
|
294
|
+
async def _call(
|
|
295
|
+
self, path: str, model: type[T], body: dict | None = None, *, timeout: float | None = None
|
|
296
|
+
) -> T:
|
|
260
297
|
if self._in_flight >= self.limit:
|
|
261
298
|
raise CloneError("client_capacity_exceeded", 503)
|
|
262
299
|
self._in_flight += 1
|
|
263
300
|
try:
|
|
264
|
-
|
|
301
|
+
timeout = self.timeout if timeout is None else timeout
|
|
302
|
+
async with asyncio.timeout(timeout):
|
|
265
303
|
async with self._client.stream(
|
|
266
304
|
"GET" if body is None else "POST",
|
|
267
305
|
self.base_url + "/v1" + path,
|
|
268
306
|
headers=self.headers,
|
|
269
307
|
json=body,
|
|
308
|
+
timeout=timeout,
|
|
270
309
|
) as response:
|
|
271
310
|
data = bytearray()
|
|
272
311
|
async for chunk in response.aiter_bytes():
|
|
@@ -283,7 +322,15 @@ class AsyncCloneClient(_Options):
|
|
|
283
322
|
|
|
284
323
|
async def predict(self, user_id: str, request: Mapping[str, Any]) -> Prediction:
|
|
285
324
|
return _identity(
|
|
286
|
-
await self._call(
|
|
325
|
+
await self._call(
|
|
326
|
+
"/predictions",
|
|
327
|
+
Prediction,
|
|
328
|
+
{**request, "user_id": user_id},
|
|
329
|
+
timeout=180
|
|
330
|
+
if any((request.get("artifact") or {}).get(key) for key in ("media", "images"))
|
|
331
|
+
else None,
|
|
332
|
+
),
|
|
333
|
+
request,
|
|
287
334
|
)
|
|
288
335
|
|
|
289
336
|
async def record_event(self, user_id: str, event: Mapping[str, Any]) -> EventResult:
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""Local artifact preparation. A later explicit prediction uploads selected pixels and original media."""
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
import hashlib
|
|
5
|
+
import io
|
|
6
|
+
import math
|
|
7
|
+
import time
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def image_artifact(path: str | Path, *, id: str, revision: str, summary: str = "") -> dict:
|
|
12
|
+
source = Path(path)
|
|
13
|
+
if not 0 < source.stat().st_size <= 480_000:
|
|
14
|
+
raise ValueError("Image must be a JPEG or PNG of at most 480000 bytes")
|
|
15
|
+
raw = source.read_bytes()
|
|
16
|
+
mime = "image/png" if raw.startswith(b"\x89PNG\r\n\x1a\n") else "image/jpeg"
|
|
17
|
+
if len(raw) > 480_000 or not (raw.startswith(b"\x89PNG\r\n\x1a\n") or raw.startswith(b"\xff\xd8\xff")):
|
|
18
|
+
raise ValueError("Image must be a JPEG or PNG of at most 480000 bytes")
|
|
19
|
+
return {
|
|
20
|
+
"kind": "image",
|
|
21
|
+
"id": id,
|
|
22
|
+
"revision": revision,
|
|
23
|
+
"summary": summary,
|
|
24
|
+
"images": [{"ref": id, "mime_type": mime, "data": base64.b64encode(raw).decode("ascii")}],
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def video_artifact(path: str | Path, *, id: str, revision: str, summary: str = "") -> dict:
|
|
29
|
+
"""Prepare the original video/audio and preview frames; a later predict uploads the whole source."""
|
|
30
|
+
try:
|
|
31
|
+
import av
|
|
32
|
+
except ImportError:
|
|
33
|
+
raise RuntimeError("Install clone-sdk[media] to prepare local video artifacts") from None
|
|
34
|
+
source = Path(path)
|
|
35
|
+
if not 0 < source.stat().st_size <= 100 * 1024 * 1024:
|
|
36
|
+
raise ValueError("Video must be at most 100 MiB")
|
|
37
|
+
raw = source.read_bytes()
|
|
38
|
+
if len(raw) > 100 * 1024 * 1024:
|
|
39
|
+
raise ValueError("Video must be at most 100 MiB")
|
|
40
|
+
deadline = time.monotonic() + 8
|
|
41
|
+
images = []
|
|
42
|
+
with av.open(io.BytesIO(raw)) as container:
|
|
43
|
+
stream = next(iter(container.streams.video), None)
|
|
44
|
+
if stream is None or not 0 < stream.width * stream.height <= 25_000_000:
|
|
45
|
+
raise ValueError("No supported video stream")
|
|
46
|
+
start = float((stream.start_time or 0) * stream.time_base)
|
|
47
|
+
duration = (
|
|
48
|
+
float(stream.duration * stream.time_base)
|
|
49
|
+
if stream.duration
|
|
50
|
+
else (float(container.duration / av.time_base) if container.duration else 0)
|
|
51
|
+
)
|
|
52
|
+
source_duration = max(
|
|
53
|
+
duration, float(container.duration / av.time_base) if container.duration else duration
|
|
54
|
+
)
|
|
55
|
+
if not math.isfinite(source_duration) or not 0 < source_duration <= 3600:
|
|
56
|
+
raise ValueError("Video requires a known duration of at most one hour")
|
|
57
|
+
for target in [0, duration / 3, duration * 2 / 3, max(0, duration - 0.1)]:
|
|
58
|
+
container.seek(int((target + start) / float(stream.time_base)), stream=stream, backward=True)
|
|
59
|
+
frame = None
|
|
60
|
+
for index, candidate in enumerate(container.decode(stream)):
|
|
61
|
+
if index >= 180 or time.monotonic() > deadline:
|
|
62
|
+
raise ValueError("Video decoding exceeded its bounded budget")
|
|
63
|
+
if candidate.time is not None:
|
|
64
|
+
frame = candidate
|
|
65
|
+
if candidate.time is not None and candidate.time - start >= target - 0.0001:
|
|
66
|
+
break
|
|
67
|
+
if frame is None:
|
|
68
|
+
raise ValueError("Video frame could not be decoded")
|
|
69
|
+
timestamp = round(float(frame.time) - start, 3)
|
|
70
|
+
if images and timestamp <= images[-1]["timestamp_seconds"]:
|
|
71
|
+
continue
|
|
72
|
+
rotation = int(getattr(frame, "rotation", 0))
|
|
73
|
+
if rotation:
|
|
74
|
+
if rotation % 90:
|
|
75
|
+
raise ValueError("Unsupported video display matrix")
|
|
76
|
+
import numpy as np
|
|
77
|
+
|
|
78
|
+
frame = av.VideoFrame.from_ndarray(
|
|
79
|
+
np.rot90(frame.to_ndarray(format="rgb24"), rotation // 90).copy(), format="rgb24"
|
|
80
|
+
)
|
|
81
|
+
scale = min(1, 1600 / max(frame.width, frame.height))
|
|
82
|
+
width = max(2, int(frame.width * scale) // 2 * 2)
|
|
83
|
+
height = max(2, int(frame.height * scale) // 2 * 2)
|
|
84
|
+
destination = io.BytesIO()
|
|
85
|
+
with av.open(destination, mode="w", format="mjpeg") as output:
|
|
86
|
+
encoder = output.add_stream("mjpeg", rate=1)
|
|
87
|
+
encoder.width, encoder.height, encoder.pix_fmt = width, height, "yuvj420p"
|
|
88
|
+
for packet in encoder.encode(frame.reformat(width=width, height=height, format="yuvj420p")):
|
|
89
|
+
output.mux(packet)
|
|
90
|
+
for packet in encoder.encode():
|
|
91
|
+
output.mux(packet)
|
|
92
|
+
encoded = destination.getvalue()
|
|
93
|
+
if not encoded or len(encoded) > 480_000:
|
|
94
|
+
raise ValueError("Encoded video frame exceeds the image budget")
|
|
95
|
+
images.append(
|
|
96
|
+
{
|
|
97
|
+
"ref": f"{id}#t={timestamp}",
|
|
98
|
+
"mime_type": "image/jpeg",
|
|
99
|
+
"data": base64.b64encode(encoded).decode("ascii"),
|
|
100
|
+
"timestamp_seconds": timestamp,
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
diagnostics = _scan_source(raw)
|
|
104
|
+
mime = {".mov": "video/quicktime", ".webm": "video/webm", ".mkv": "video/x-matroska"}.get(
|
|
105
|
+
source.suffix.lower(), "video/mp4"
|
|
106
|
+
)
|
|
107
|
+
return {
|
|
108
|
+
"kind": "video",
|
|
109
|
+
"id": id,
|
|
110
|
+
"revision": revision,
|
|
111
|
+
"summary": summary,
|
|
112
|
+
"duration_seconds": source_duration,
|
|
113
|
+
"images": images,
|
|
114
|
+
"media": [
|
|
115
|
+
{
|
|
116
|
+
"ref": id,
|
|
117
|
+
"mime_type": mime,
|
|
118
|
+
"data": base64.b64encode(raw).decode("ascii"),
|
|
119
|
+
"sha256": hashlib.sha256(raw).hexdigest(),
|
|
120
|
+
"duration_seconds": source_duration,
|
|
121
|
+
"diagnostics": diagnostics,
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _scan_source(raw: bytes) -> dict:
|
|
128
|
+
import av
|
|
129
|
+
|
|
130
|
+
started = time.monotonic()
|
|
131
|
+
video_frames = audio_frames = 0
|
|
132
|
+
complete = True
|
|
133
|
+
with av.open(io.BytesIO(raw)) as container:
|
|
134
|
+
has_audio = bool(container.streams.audio)
|
|
135
|
+
try:
|
|
136
|
+
for packet in container.demux():
|
|
137
|
+
for frame in packet.decode():
|
|
138
|
+
if time.monotonic() - started > 25:
|
|
139
|
+
complete = False
|
|
140
|
+
break
|
|
141
|
+
if isinstance(frame, av.VideoFrame):
|
|
142
|
+
video_frames += 1
|
|
143
|
+
elif isinstance(frame, av.AudioFrame):
|
|
144
|
+
audio_frames += 1
|
|
145
|
+
if not complete:
|
|
146
|
+
break
|
|
147
|
+
except av.FFmpegError:
|
|
148
|
+
complete = False
|
|
149
|
+
return {
|
|
150
|
+
"full_decode": complete,
|
|
151
|
+
"decoded_video_frames": video_frames,
|
|
152
|
+
"decoded_audio_frames": audio_frames,
|
|
153
|
+
"audio_track_present": has_audio,
|
|
154
|
+
"player_verified": False,
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def audio_artifact(path: str | Path, *, id: str, revision: str, summary: str = "") -> dict:
|
|
159
|
+
"""Prepare a hash-bound original audio source without sending it."""
|
|
160
|
+
try:
|
|
161
|
+
import av
|
|
162
|
+
except ImportError:
|
|
163
|
+
raise RuntimeError("Install clone-sdk[media] to prepare local audio artifacts") from None
|
|
164
|
+
|
|
165
|
+
source = Path(path)
|
|
166
|
+
if not 0 < source.stat().st_size <= 100 * 1024 * 1024:
|
|
167
|
+
raise ValueError("Audio must be at most 100 MiB")
|
|
168
|
+
raw = source.read_bytes()
|
|
169
|
+
if len(raw) > 100 * 1024 * 1024:
|
|
170
|
+
raise ValueError("Audio must be at most 100 MiB")
|
|
171
|
+
with av.open(io.BytesIO(raw)) as container:
|
|
172
|
+
stream = next(iter(container.streams.audio), None)
|
|
173
|
+
if stream is None:
|
|
174
|
+
raise ValueError("Audio stream is missing")
|
|
175
|
+
duration = (
|
|
176
|
+
float(stream.duration * stream.time_base)
|
|
177
|
+
if stream.duration
|
|
178
|
+
else float((container.duration or 0) / av.time_base)
|
|
179
|
+
)
|
|
180
|
+
if not math.isfinite(duration) or not 0 < duration <= 3600:
|
|
181
|
+
raise ValueError("Audio duration must be within one hour")
|
|
182
|
+
mime = {".wav": "audio/wav", ".mp3": "audio/mpeg", ".m4a": "audio/mp4", ".webm": "audio/webm"}.get(
|
|
183
|
+
source.suffix.lower()
|
|
184
|
+
)
|
|
185
|
+
if mime is None:
|
|
186
|
+
raise ValueError("Supported audio containers: wav, mp3, m4a, webm")
|
|
187
|
+
return {
|
|
188
|
+
"kind": "other",
|
|
189
|
+
"id": id,
|
|
190
|
+
"revision": revision,
|
|
191
|
+
"summary": summary,
|
|
192
|
+
"media": [
|
|
193
|
+
{
|
|
194
|
+
"ref": id,
|
|
195
|
+
"mime_type": mime,
|
|
196
|
+
"data": base64.b64encode(raw).decode("ascii"),
|
|
197
|
+
"sha256": hashlib.sha256(raw).hexdigest(),
|
|
198
|
+
"duration_seconds": duration,
|
|
199
|
+
"diagnostics": _scan_source(raw),
|
|
200
|
+
}
|
|
201
|
+
],
|
|
202
|
+
}
|
|
@@ -13,6 +13,12 @@ class PredictionUsage(ResponseModel):
|
|
|
13
13
|
prediction_units: int = Field(ge=0, le=1)
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
class MediaReceipt(ResponseModel):
|
|
17
|
+
ref: str
|
|
18
|
+
sha256: str
|
|
19
|
+
timestamp_seconds: float | None = None
|
|
20
|
+
|
|
21
|
+
|
|
16
22
|
class Prediction(ResponseModel):
|
|
17
23
|
request_id: str
|
|
18
24
|
prediction_id: str
|
|
@@ -28,6 +34,8 @@ class Prediction(ResponseModel):
|
|
|
28
34
|
context_truncated: bool
|
|
29
35
|
usage: PredictionUsage
|
|
30
36
|
feedback_revision: str = ""
|
|
37
|
+
media_review: list[MediaReceipt] = Field(default_factory=list)
|
|
38
|
+
artifact_review: dict | None = None
|
|
31
39
|
|
|
32
40
|
|
|
33
41
|
class Usage(ResponseModel):
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import hashlib
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from clone_sdk import CloneError, audio_artifact, image_artifact, video_artifact
|
|
7
|
+
from clone_sdk.client import _identity
|
|
8
|
+
from clone_sdk.models import Prediction
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_image_preparation_and_missing_or_changed_receipts_fail_closed(tmp_path):
|
|
12
|
+
pixels = b"\x89PNG\r\n\x1a\nfixture"
|
|
13
|
+
path = tmp_path / "draft.png"
|
|
14
|
+
path.write_bytes(pixels)
|
|
15
|
+
artifact = image_artifact(path, id="draft", revision="1")
|
|
16
|
+
assert base64.b64decode(artifact["images"][0]["data"]) == pixels
|
|
17
|
+
request = {"request_id": "r", "session_id": "s", "context_revision": "1", "draft": {"revision": 1},
|
|
18
|
+
"artifact": artifact}
|
|
19
|
+
body = {"request_id": "r", "prediction_id": "p", "session_id": "s", "connection_id": None,
|
|
20
|
+
"draft_revision": 1, "context_revision": "1", "profile_revision": "", "grant_revision": 0,
|
|
21
|
+
"status": "suggested", "completion": "Fix the draft.", "expires_at": 123,
|
|
22
|
+
"context_truncated": False, "usage": {"prediction_units": 1}}
|
|
23
|
+
with pytest.raises(CloneError, match="media_review_not_acknowledged"):
|
|
24
|
+
_identity(Prediction.model_validate(body), request)
|
|
25
|
+
body["media_review"] = [{"ref": "draft", "sha256": hashlib.sha256(pixels).hexdigest()}]
|
|
26
|
+
assert _identity(Prediction.model_validate(body), request).media_review
|
|
27
|
+
body["media_review"][0]["sha256"] = "changed"
|
|
28
|
+
with pytest.raises(CloneError, match="media_review_not_acknowledged"):
|
|
29
|
+
_identity(Prediction.model_validate(body), request)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_video_preparation_samples_actual_opening_and_ending_pixels(tmp_path):
|
|
33
|
+
av = pytest.importorskip("av")
|
|
34
|
+
np = pytest.importorskip("numpy")
|
|
35
|
+
path = tmp_path / "draft.mp4"
|
|
36
|
+
with av.open(str(path), mode="w") as output:
|
|
37
|
+
stream = output.add_stream("mpeg4", rate=10)
|
|
38
|
+
stream.width, stream.height, stream.pix_fmt = 160, 90, "yuv420p"
|
|
39
|
+
for index in range(40):
|
|
40
|
+
pixels = np.zeros((90, 160, 3), dtype=np.uint8)
|
|
41
|
+
pixels[:, :, 0 if index < 20 else 2] = 255
|
|
42
|
+
frame = av.VideoFrame.from_ndarray(pixels, format="rgb24")
|
|
43
|
+
for packet in stream.encode(frame):
|
|
44
|
+
output.mux(packet)
|
|
45
|
+
for packet in stream.encode():
|
|
46
|
+
output.mux(packet)
|
|
47
|
+
artifact = video_artifact(path, id="draft", revision="1")
|
|
48
|
+
assert artifact["duration_seconds"] == 4
|
|
49
|
+
assert len(artifact["images"]) == 4
|
|
50
|
+
assert artifact["images"][0]["timestamp_seconds"] == 0
|
|
51
|
+
assert artifact["images"][-1]["timestamp_seconds"] >= 3.8
|
|
52
|
+
assert artifact["images"][0]["data"] != artifact["images"][-1]["data"]
|
|
53
|
+
assert base64.b64decode(artifact["media"][0]["data"]) == path.read_bytes()
|
|
54
|
+
assert artifact["media"][0]["sha256"] == hashlib.sha256(path.read_bytes()).hexdigest()
|
|
55
|
+
assert artifact["media"][0]["diagnostics"]["decoded_video_frames"] == 40
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_audio_preparation_preserves_original_source_and_duration(tmp_path):
|
|
59
|
+
import wave
|
|
60
|
+
path = tmp_path / "tone.wav"
|
|
61
|
+
with wave.open(str(path), "wb") as output:
|
|
62
|
+
output.setnchannels(1)
|
|
63
|
+
output.setsampwidth(2)
|
|
64
|
+
output.setframerate(16000)
|
|
65
|
+
output.writeframes(b"\x00\x00" * 16000)
|
|
66
|
+
artifact = audio_artifact(path, id="audio", revision="1")
|
|
67
|
+
media = artifact["media"][0]
|
|
68
|
+
assert media["mime_type"] == "audio/wav" and media["duration_seconds"] == 1
|
|
69
|
+
assert base64.b64decode(media["data"]) == path.read_bytes()
|
|
70
|
+
assert media["sha256"] == hashlib.sha256(path.read_bytes()).hexdigest()
|
|
71
|
+
assert media["diagnostics"]["decoded_audio_frames"] > 0
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
version = 1
|
|
2
2
|
revision = 3
|
|
3
3
|
requires-python = ">=3.11"
|
|
4
|
+
resolution-markers = [
|
|
5
|
+
"python_full_version >= '3.12'",
|
|
6
|
+
"python_full_version < '3.12'",
|
|
7
|
+
]
|
|
4
8
|
|
|
5
9
|
[[package]]
|
|
6
10
|
name = "annotated-types"
|
|
@@ -24,6 +28,34 @@ wheels = [
|
|
|
24
28
|
{ url = "https://files.pythonhosted.org/packages/12/b8/4bd346e22b28902df4d651910f5242c28d84e4a5c2435ca5c3f797ed7e2e/anyio-4.15.1-py3-none-any.whl", hash = "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101", size = 132079, upload-time = "2026-09-05T10:42:37.923Z" },
|
|
25
29
|
]
|
|
26
30
|
|
|
31
|
+
[[package]]
|
|
32
|
+
name = "av"
|
|
33
|
+
version = "17.1.0"
|
|
34
|
+
source = { registry = "https://pypi.org/simple" }
|
|
35
|
+
sdist = { url = "https://files.pythonhosted.org/packages/5e/e3/477fa20578c284abeda08d91b63ee9abaebc93445d8feeb989d3d444bae1/av-17.1.0.tar.gz", hash = "sha256:7f1e71ff621b66253333926f948e00faae11d855b2442133c65128bca64cdeb3", size = 4288546, upload-time = "2026-06-07T05:52:55.999Z" }
|
|
36
|
+
wheels = [
|
|
37
|
+
{ url = "https://files.pythonhosted.org/packages/ec/87/8036b5c781bc3639ea04ef42d4e26da253bd4bd4311d8705b6a1c8824047/av-17.1.0-cp311-abi3-macosx_11_0_x86_64.whl", hash = "sha256:ad7b4aa011093324b7118245f50ac6db244cfe9900d4072508a5245a2b0d3f41", size = 22460847, upload-time = "2026-06-07T05:52:04.261Z" },
|
|
38
|
+
{ url = "https://files.pythonhosted.org/packages/6d/af/dfdf6fc7b17814b50d0aa9e7a7e37b87be91be3890f44b0d525433cd1fd1/av-17.1.0-cp311-abi3-macosx_14_0_arm64.whl", hash = "sha256:43ebbe977f19a7f2d2bd1a4e119675a0b15e05852cf7309846b6ab922ba7ffe9", size = 18159115, upload-time = "2026-06-07T05:52:06.64Z" },
|
|
39
|
+
{ url = "https://files.pythonhosted.org/packages/ad/13/64f6c466471cea225b8b2f4cdc51a571f8a286984b55a08d169b932fda5d/av-17.1.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6a20658ec7d96a70e14b1196eff00b7cdd8831ac3b99868e16b8ba8b24090847", size = 33224427, upload-time = "2026-06-07T05:52:09.165Z" },
|
|
40
|
+
{ url = "https://files.pythonhosted.org/packages/77/43/96b35170bf2e64e00a41748c6400ff73232dc0fc62ded283679fb07c7fe0/av-17.1.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f9a65d1f48b818323fb411e80358f89d77dec340b01d27c6b2dfbb9cbf4b779f", size = 35370183, upload-time = "2026-06-07T05:52:11.959Z" },
|
|
41
|
+
{ url = "https://files.pythonhosted.org/packages/2e/b3/8e8b4b6498731bfbd88e8399a756543f8088f1bd33d08eab678b5aebe728/av-17.1.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:58f7593726437cda5bd19793027e027768450b5c4a594777bf487798a33db702", size = 24459265, upload-time = "2026-06-07T05:52:14.66Z" },
|
|
42
|
+
{ url = "https://files.pythonhosted.org/packages/14/ac/ceb84b7553db21f1143d817245c560d9267168e1e58b1a8eeae2b62c4d04/av-17.1.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:bbab058bd965309f39962e53caac8126987c68c0be094fc4f9427e5615b0218f", size = 34283709, upload-time = "2026-06-07T05:52:17.389Z" },
|
|
43
|
+
{ url = "https://files.pythonhosted.org/packages/59/f9/4115fd84148c9a1cf365096694be6ac882fd3cd3cdb7a2f35e71fecf1631/av-17.1.0-cp311-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:9514cfda85180554c430695282faf4be3ffdf95775d8519733821244eecb58e0", size = 25397573, upload-time = "2026-06-07T05:52:20.012Z" },
|
|
44
|
+
{ url = "https://files.pythonhosted.org/packages/e2/ac/92e52d5ed0e0b84d9d93e52b4338c2713d8a44082b8696e6516fdae7c4e4/av-17.1.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e1c90f85cd7431ede95b11e8e711571a896ebea433f298849c2c0f1594c8d86e", size = 36451495, upload-time = "2026-06-07T05:52:22.581Z" },
|
|
45
|
+
{ url = "https://files.pythonhosted.org/packages/6b/f2/53a7cd34adb6a971d7e6d99663e74db286966c9db8afdca17472fdf0f98e/av-17.1.0-cp311-abi3-win_amd64.whl", hash = "sha256:5df5c1172ef1cf65a1529d612f7da7798ce2cf82c1ff7212466b538a6cc7214c", size = 28036393, upload-time = "2026-06-07T05:52:25.657Z" },
|
|
46
|
+
{ url = "https://files.pythonhosted.org/packages/66/47/cd9ae0edf2206351c1251bb94b5ec58728e42c5f6ee16c03c412f3a1bb3e/av-17.1.0-cp311-abi3-win_arm64.whl", hash = "sha256:ee98534242a74da847af78624779ac5a3177dc7c69f956a4da9e6f0fdb37d7f6", size = 21174601, upload-time = "2026-06-07T05:52:28.077Z" },
|
|
47
|
+
{ url = "https://files.pythonhosted.org/packages/36/90/b5668cddb3c401fcf22553bc495d5b0c6d8a01d118624b26f0db1d0b8653/av-17.1.0-cp314-cp314t-macosx_11_0_x86_64.whl", hash = "sha256:5327807c1219293803ef0c5d1578ff3ae1cf638c09e5998962026e1a554ec240", size = 22699499, upload-time = "2026-06-07T05:52:30.335Z" },
|
|
48
|
+
{ url = "https://files.pythonhosted.org/packages/e0/7e/7be6bfddb823d045ff9fd5d4deb922ee3847605e162c3882e6c45b4c35ff/av-17.1.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:6c9b71fe5c0c5a8d303b1588d4d8ce9397d6b023f467cfef95000ba1f75507fa", size = 18366696, upload-time = "2026-06-07T05:52:32.645Z" },
|
|
49
|
+
{ url = "https://files.pythonhosted.org/packages/a2/23/391dcfa75c1ae1977efca44b753a11b929399b558826670c16a8808dd0e3/av-17.1.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:f997e3351bdf51127c07a74e21741a2996e9230cbeb2d81c14acde761b116c9c", size = 36582649, upload-time = "2026-06-07T05:52:35.218Z" },
|
|
50
|
+
{ url = "https://files.pythonhosted.org/packages/fb/32/7312854868b318b9d1b1dcbd1bddb460aaaeac7d57f816e11efec3bef5b1/av-17.1.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:efe9b1397300b67b644ad220c89df4892a76f2debe70f16bae1749fa20526e63", size = 38479390, upload-time = "2026-06-07T05:52:37.968Z" },
|
|
51
|
+
{ url = "https://files.pythonhosted.org/packages/2a/72/af47f59b4458e81ca7d89f477698dbfb3d5a0cd8ae6c1e4441d01074af8a/av-17.1.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:fa64e1f1500d01c4a98e7a41dc1a9a35fb4dfe71f5de0389264ec1192200c76a", size = 27127432, upload-time = "2026-06-07T05:52:40.371Z" },
|
|
52
|
+
{ url = "https://files.pythonhosted.org/packages/88/85/c2e6861baf0f8c7d21c4ce811d4d424fedac915e3910d3570ce4377717dc/av-17.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ffbd78d73d2c9bf31e9a007c992faec3991428b2941a3b085b84fb82e8c32d19", size = 37406592, upload-time = "2026-06-07T05:52:43.215Z" },
|
|
53
|
+
{ url = "https://files.pythonhosted.org/packages/ba/40/3cc13125aea976101c0858af99ac47257c0654411aa199b5d8e81eea7002/av-17.1.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:bff8896454b38fcb785a70e5ae0485d7021cb776303a5849393128a30b8f850b", size = 28336228, upload-time = "2026-06-07T05:52:46.134Z" },
|
|
54
|
+
{ url = "https://files.pythonhosted.org/packages/a2/38/c7d9c3e746209a1a695c13e3aa7d817229e84a85d0a84271f313d1befdd3/av-17.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1284addf3c0dd939887a9722dc30df2241a97471ad52c3c507e31583ae22ff02", size = 39490680, upload-time = "2026-06-07T05:52:48.887Z" },
|
|
55
|
+
{ url = "https://files.pythonhosted.org/packages/a1/25/9d42da561b7b8f7dabdfaebba07b52977bee58c5c7e4285ac991abcfaa72/av-17.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:ec630be6321b04e317862f6082e84812bbd801e55a3c2298312e3fc8a0a4af4f", size = 28355673, upload-time = "2026-06-07T05:52:51.614Z" },
|
|
56
|
+
{ url = "https://files.pythonhosted.org/packages/a8/41/562a61d5a61fba3ffb273a115e249f1d8471b9515c59fcc38b4b9deda238/av-17.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:b41647e42884bf543b8e8d0a1dabd4d1b006c99183eb1a2d7afc5b01f73eeff4", size = 21324700, upload-time = "2026-06-07T05:52:53.972Z" },
|
|
57
|
+
]
|
|
58
|
+
|
|
27
59
|
[[package]]
|
|
28
60
|
name = "backports-tarfile"
|
|
29
61
|
version = "1.2.0"
|
|
@@ -254,13 +286,20 @@ wheels = [
|
|
|
254
286
|
|
|
255
287
|
[[package]]
|
|
256
288
|
name = "clone-sdk"
|
|
257
|
-
version = "0.
|
|
289
|
+
version = "0.3.0"
|
|
258
290
|
source = { editable = "." }
|
|
259
291
|
dependencies = [
|
|
260
292
|
{ name = "httpx" },
|
|
261
293
|
{ name = "pydantic" },
|
|
262
294
|
]
|
|
263
295
|
|
|
296
|
+
[package.optional-dependencies]
|
|
297
|
+
media = [
|
|
298
|
+
{ name = "av" },
|
|
299
|
+
{ name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" },
|
|
300
|
+
{ name = "numpy", version = "2.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" },
|
|
301
|
+
]
|
|
302
|
+
|
|
264
303
|
[package.dev-dependencies]
|
|
265
304
|
dev = [
|
|
266
305
|
{ name = "build" },
|
|
@@ -272,9 +311,12 @@ dev = [
|
|
|
272
311
|
|
|
273
312
|
[package.metadata]
|
|
274
313
|
requires-dist = [
|
|
314
|
+
{ name = "av", marker = "extra == 'media'", specifier = ">=16,<18" },
|
|
275
315
|
{ name = "httpx", specifier = ">=0.28.1,<1" },
|
|
316
|
+
{ name = "numpy", marker = "extra == 'media'", specifier = ">=1.26,<3" },
|
|
276
317
|
{ name = "pydantic", specifier = ">=2.7,<3" },
|
|
277
318
|
]
|
|
319
|
+
provides-extras = ["media"]
|
|
278
320
|
|
|
279
321
|
[package.metadata.requires-dev]
|
|
280
322
|
dev = [
|
|
@@ -560,6 +602,164 @@ wheels = [
|
|
|
560
602
|
{ url = "https://files.pythonhosted.org/packages/f9/70/e140dffff6e808dc6343598df76e7e2407fd0f581de3524c75fba2e0cf24/nh3-0.3.7-cp38-abi3-win_arm64.whl", hash = "sha256:f04b7d333b27f13ca439da3cf1c75c2fba34f104969f6ce4ac8e7079699c2f4a", size = 621867, upload-time = "2026-08-23T14:26:29.547Z" },
|
|
561
603
|
]
|
|
562
604
|
|
|
605
|
+
[[package]]
|
|
606
|
+
name = "numpy"
|
|
607
|
+
version = "2.4.6"
|
|
608
|
+
source = { registry = "https://pypi.org/simple" }
|
|
609
|
+
resolution-markers = [
|
|
610
|
+
"python_full_version < '3.12'",
|
|
611
|
+
]
|
|
612
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d0/ad/fed0499ce6a338d2a03ebae59cd15093910c8875328855781952abf6c2fe/numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda", size = 20735807, upload-time = "2026-05-18T23:37:14.07Z" }
|
|
613
|
+
wheels = [
|
|
614
|
+
{ url = "https://files.pythonhosted.org/packages/b3/49/ec46835a70be8fa6446c495126ac84fdb28cb2558e1620ffb87a10c8b64c/numpy-2.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4", size = 16969194, upload-time = "2026-05-18T23:33:13.503Z" },
|
|
615
|
+
{ url = "https://files.pythonhosted.org/packages/0e/0d/f5957185c0ee2f3e12f78715aa9e3b353fd83633316c8532b38faa37e3f6/numpy-2.4.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d", size = 14964111, upload-time = "2026-05-18T23:33:17.795Z" },
|
|
616
|
+
{ url = "https://files.pythonhosted.org/packages/ad/40/40a40ee0ddf7ceb782c49af278894b686e586d65d8c1889c8b5da01a3d7d/numpy-2.4.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8", size = 5469159, upload-time = "2026-05-18T23:33:20.654Z" },
|
|
617
|
+
{ url = "https://files.pythonhosted.org/packages/63/13/f9a8046535cb21deae82f8d03de9617e08882d274fad2539630761888228/numpy-2.4.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538", size = 6798936, upload-time = "2026-05-18T23:33:22.987Z" },
|
|
618
|
+
{ url = "https://files.pythonhosted.org/packages/33/a8/6fa8c1a345a8c85dbb21932c447bee07c30a2c2a3f31e369c0a84b300147/numpy-2.4.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47", size = 15966692, upload-time = "2026-05-18T23:33:26.62Z" },
|
|
619
|
+
{ url = "https://files.pythonhosted.org/packages/02/03/74fe2a4cb3817d94d86402f2506554130a2f01414e299b5a843e5a8a957f/numpy-2.4.6-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93", size = 16918164, upload-time = "2026-05-18T23:33:29.955Z" },
|
|
620
|
+
{ url = "https://files.pythonhosted.org/packages/c5/80/3615be3313f7e7696609bc194b9f0101da809df79e859bdb84e0cd043f46/numpy-2.4.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8", size = 17322877, upload-time = "2026-05-18T23:33:34.724Z" },
|
|
621
|
+
{ url = "https://files.pythonhosted.org/packages/ca/ac/a691e0fe2675e370d0e08ff905adc49a1c8830e8cae03efe4477e92cd55d/numpy-2.4.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6", size = 18651487, upload-time = "2026-05-18T23:33:38.217Z" },
|
|
622
|
+
{ url = "https://files.pythonhosted.org/packages/15/a7/9bc1cd626d7bf6869bfedf27b91b6ab5dd607758bf8e959d6fa80c6a59cb/numpy-2.4.6-cp311-cp311-win32.whl", hash = "sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8", size = 6233945, upload-time = "2026-05-18T23:33:41.331Z" },
|
|
623
|
+
{ url = "https://files.pythonhosted.org/packages/c5/31/7fc6239c12bce7e931463251cca4426c465e1876ba3cc785402ef4dd8f4e/numpy-2.4.6-cp311-cp311-win_amd64.whl", hash = "sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147", size = 12608406, upload-time = "2026-05-18T23:33:44.131Z" },
|
|
624
|
+
{ url = "https://files.pythonhosted.org/packages/27/83/140f85a466595a16382996a1bf06b2b54bcd597488921b0c9daaeeda72af/numpy-2.4.6-cp311-cp311-win_arm64.whl", hash = "sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577", size = 10479528, upload-time = "2026-05-18T23:33:50.725Z" },
|
|
625
|
+
{ url = "https://files.pythonhosted.org/packages/95/2a/3d7b5ac8aac24feaf9ad7ed58f45b0bbc06d37e4338ae84c9f2298b570f9/numpy-2.4.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1", size = 16689119, upload-time = "2026-05-18T23:33:54.065Z" },
|
|
626
|
+
{ url = "https://files.pythonhosted.org/packages/ea/12/92c4c131527599e8288d6918e888d88726f84d805d784b771f32408aeaef/numpy-2.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb", size = 14699246, upload-time = "2026-05-18T23:33:57.621Z" },
|
|
627
|
+
{ url = "https://files.pythonhosted.org/packages/ad/fe/c0a6b7b2ca128a8fb228575147073b660656734b8ebe4d76c8fd748dcc79/numpy-2.4.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41", size = 5204410, upload-time = "2026-05-18T23:34:00.302Z" },
|
|
628
|
+
{ url = "https://files.pythonhosted.org/packages/f3/d4/9770d14ba719432bb90a421bfd443872ed0f70f7264b64bec12ea363d5fd/numpy-2.4.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698", size = 6551240, upload-time = "2026-05-18T23:34:02.852Z" },
|
|
629
|
+
{ url = "https://files.pythonhosted.org/packages/c9/c6/50a46a6205feba2343f1d6d17438107c5dc491ed1c736e6ea68689fd906b/numpy-2.4.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f", size = 15671012, upload-time = "2026-05-18T23:34:05.485Z" },
|
|
630
|
+
{ url = "https://files.pythonhosted.org/packages/99/60/14115e6364fa676c5397c2ad3004e527e9aa487abf5d0706ec81bbd08529/numpy-2.4.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853", size = 16645538, upload-time = "2026-05-18T23:34:09.265Z" },
|
|
631
|
+
{ url = "https://files.pythonhosted.org/packages/ae/c5/693cbe59e57db94d2231fa519ca3978dc9e19da5a8f088588f5c6e947ff2/numpy-2.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a", size = 17020706, upload-time = "2026-05-18T23:34:13.053Z" },
|
|
632
|
+
{ url = "https://files.pythonhosted.org/packages/ef/fc/85b7c4eff9b4966ade25c2273cf7e7012e92366c032058653934b37de044/numpy-2.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2", size = 18368541, upload-time = "2026-05-18T23:34:17.024Z" },
|
|
633
|
+
{ url = "https://files.pythonhosted.org/packages/f6/81/e1b27545deedce7f4a0b348618c6b62d74e36a4dc9ccd42f3eb2f85eee32/numpy-2.4.6-cp312-cp312-win32.whl", hash = "sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45", size = 5962825, upload-time = "2026-05-18T23:34:20.3Z" },
|
|
634
|
+
{ url = "https://files.pythonhosted.org/packages/ab/ca/feab00bd44aa5fe1ad2c18f08b4d3bb92e26484b0b1d1443897809ed528c/numpy-2.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751", size = 12321687, upload-time = "2026-05-18T23:34:23.095Z" },
|
|
635
|
+
{ url = "https://files.pythonhosted.org/packages/63/cf/5a6d34850a39d1093558564f77ee8e8e0bee5061151b8f05a55711001ec7/numpy-2.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8", size = 10221482, upload-time = "2026-05-18T23:34:25.876Z" },
|
|
636
|
+
{ url = "https://files.pythonhosted.org/packages/fb/82/bdab26d7438c6791ca31b7c024ca37c1eab8b726ba236129005cd4a06e45/numpy-2.4.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0", size = 16684648, upload-time = "2026-05-18T23:34:29.41Z" },
|
|
637
|
+
{ url = "https://files.pythonhosted.org/packages/1b/30/a80189bcc7f5e4258b3fbc3968d909d1756f54d023299ecc39ad6fdb9ef8/numpy-2.4.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb", size = 14693902, upload-time = "2026-05-18T23:34:33.013Z" },
|
|
638
|
+
{ url = "https://files.pythonhosted.org/packages/97/12/70b5d0d7c15e1ebb8a6a84a8caa1d19e181d84fb58bb6d70aca29099dec1/numpy-2.4.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f", size = 5198992, upload-time = "2026-05-18T23:34:36.132Z" },
|
|
639
|
+
{ url = "https://files.pythonhosted.org/packages/ba/8c/ebd2a8f8a83541f8d38cc5667e8c2b69cecfd30da6e45693e8158857d44b/numpy-2.4.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3", size = 6546944, upload-time = "2026-05-18T23:34:38.484Z" },
|
|
640
|
+
{ url = "https://files.pythonhosted.org/packages/bb/c5/7b863a97a91671a0338f4253bd3b5a3d3852f0692dae91711c9f4a10e787/numpy-2.4.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b", size = 15669392, upload-time = "2026-05-18T23:34:41.257Z" },
|
|
641
|
+
{ url = "https://files.pythonhosted.org/packages/a5/9d/3584b9984ca4c047aea75214ce1a4c4c73d849bd71b604264b7f5653f8a8/numpy-2.4.6-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089", size = 16633220, upload-time = "2026-05-18T23:34:45.075Z" },
|
|
642
|
+
{ url = "https://files.pythonhosted.org/packages/05/ae/7c67fba23bd98caec7c99261f3a16072ade14813486b0282cb29846de832/numpy-2.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a", size = 17020800, upload-time = "2026-05-18T23:34:49.065Z" },
|
|
643
|
+
{ url = "https://files.pythonhosted.org/packages/d9/5d/3b6725cb31d983c5e66916f5d36f6d7e5521129e4c4404d64f918292a5b6/numpy-2.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605", size = 18357600, upload-time = "2026-05-18T23:34:52.709Z" },
|
|
644
|
+
{ url = "https://files.pythonhosted.org/packages/f7/da/2ccc6c2fe8898dee01d90c75c5f5f914a23daf99e3e0f59516a08760c8b5/numpy-2.4.6-cp313-cp313-win32.whl", hash = "sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91", size = 5961134, upload-time = "2026-05-18T23:34:55.618Z" },
|
|
645
|
+
{ url = "https://files.pythonhosted.org/packages/b5/cd/9cc4dc876fb065d5c220aae4d5e14826b2715331bb7618ce1fb07a679d99/numpy-2.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359", size = 12318598, upload-time = "2026-05-18T23:34:58.928Z" },
|
|
646
|
+
{ url = "https://files.pythonhosted.org/packages/39/1e/c0bcba1f8694116485fe28fd1be698c278fcda4141c5b0e53a2aed8b12a8/numpy-2.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778", size = 10222272, upload-time = "2026-05-18T23:35:02.167Z" },
|
|
647
|
+
{ url = "https://files.pythonhosted.org/packages/63/6d/cc5619247c8f4204e507f5883528372e4ac4bb189e579fb859a12e480b1f/numpy-2.4.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1", size = 14821197, upload-time = "2026-05-18T23:35:05.468Z" },
|
|
648
|
+
{ url = "https://files.pythonhosted.org/packages/00/58/f1c39161c87d9e9bed660f1ed4bafc0e403d5ec9650b6dd77aead07d489b/numpy-2.4.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe", size = 5326287, upload-time = "2026-05-18T23:35:08.693Z" },
|
|
649
|
+
{ url = "https://files.pythonhosted.org/packages/af/57/3917ab0fd97f271a8694513581b8a36c655f111c446852c302f04ccdb6fc/numpy-2.4.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997", size = 6646763, upload-time = "2026-05-18T23:35:11.459Z" },
|
|
650
|
+
{ url = "https://files.pythonhosted.org/packages/eb/0f/037e64c494b67581ae18193d770adef354c41f3f2c8ebf865602d949bf8f/numpy-2.4.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20", size = 15728070, upload-time = "2026-05-18T23:35:14.79Z" },
|
|
651
|
+
{ url = "https://files.pythonhosted.org/packages/21/a6/5d2bae9c9542eb4df16dc9c46dc79c186e9bad53805dfa5399a6023c6db0/numpy-2.4.6-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d", size = 16681752, upload-time = "2026-05-18T23:35:18.836Z" },
|
|
652
|
+
{ url = "https://files.pythonhosted.org/packages/92/14/23d1dfb410ae362cd59ce53e936b1513d545eb40db3949ced632e19a459e/numpy-2.4.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67", size = 17086024, upload-time = "2026-05-18T23:35:22.52Z" },
|
|
653
|
+
{ url = "https://files.pythonhosted.org/packages/4b/6e/23595a2c642cdf3bc567877064bdd7f91c8b0038a4453cf2daf7248eafe9/numpy-2.4.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd", size = 18403398, upload-time = "2026-05-18T23:35:26.398Z" },
|
|
654
|
+
{ url = "https://files.pythonhosted.org/packages/8a/90/0ac3bc947217e66dec77e7cbc6a1979d1af70b6461b82f620d3bccd5e4c8/numpy-2.4.6-cp313-cp313t-win32.whl", hash = "sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab", size = 6084971, upload-time = "2026-05-18T23:35:29.387Z" },
|
|
655
|
+
{ url = "https://files.pythonhosted.org/packages/77/71/5673e351671a1d2bd6063b91b44f70c0affea7d1516fa7a6572941ba4aa1/numpy-2.4.6-cp313-cp313t-win_amd64.whl", hash = "sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75", size = 12458532, upload-time = "2026-05-18T23:35:32.175Z" },
|
|
656
|
+
{ url = "https://files.pythonhosted.org/packages/3f/88/19d3503c5046e688f049274b27a3ef3d771152fa80d3ba3d01a3dff61abe/numpy-2.4.6-cp313-cp313t-win_arm64.whl", hash = "sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd", size = 10291881, upload-time = "2026-05-18T23:35:35.465Z" },
|
|
657
|
+
{ url = "https://files.pythonhosted.org/packages/f8/91/3ab2044d05fd16d343c5ac2e69b127f1b2854040dd20b193257c78028bd3/numpy-2.4.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079", size = 16683458, upload-time = "2026-05-18T23:35:38.353Z" },
|
|
658
|
+
{ url = "https://files.pythonhosted.org/packages/8e/62/764ce66fa4147ae6d73071a3abf804ffe606f174618697c571acdf26a7c9/numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7", size = 14704559, upload-time = "2026-05-18T23:35:42.14Z" },
|
|
659
|
+
{ url = "https://files.pythonhosted.org/packages/60/61/23f27c172f022e04025b7dc2367f4d63c1a398120607ec896228649a6f48/numpy-2.4.6-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5", size = 5209716, upload-time = "2026-05-18T23:35:45.377Z" },
|
|
660
|
+
{ url = "https://files.pythonhosted.org/packages/03/71/21cf70dc6ea3e3acb95fc53a265b2fc248b981f0194ceb5b475271b8809d/numpy-2.4.6-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096", size = 6543947, upload-time = "2026-05-18T23:35:47.926Z" },
|
|
661
|
+
{ url = "https://files.pythonhosted.org/packages/d5/91/64288395ee1799bd2e0b04a305dce9666da90c961e1f3fe982a05ee1c036/numpy-2.4.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b", size = 15685197, upload-time = "2026-05-18T23:35:50.863Z" },
|
|
662
|
+
{ url = "https://files.pythonhosted.org/packages/f3/eb/ebffaa97dc55502df69584a8f0dcf07f69a3e0b3e2323670a2722db9aa39/numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8", size = 16638245, upload-time = "2026-05-18T23:35:54.752Z" },
|
|
663
|
+
{ url = "https://files.pythonhosted.org/packages/b8/0b/54f9da33128d7e350fab89c7455902eeae70349ee52bddb448dc4a576f45/numpy-2.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402", size = 17036587, upload-time = "2026-05-18T23:35:58.355Z" },
|
|
664
|
+
{ url = "https://files.pythonhosted.org/packages/b6/f0/fdebc1052db1cc37c64beb22072d67cd6d1c71adca1299f53dec2b5e20d3/numpy-2.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb", size = 18363226, upload-time = "2026-05-18T23:36:02.845Z" },
|
|
665
|
+
{ url = "https://files.pythonhosted.org/packages/aa/b4/298628d98c72b57e57f7165ae6a481a1deaf6f3c28262a6e4c739c275930/numpy-2.4.6-cp314-cp314-win32.whl", hash = "sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1", size = 6010196, upload-time = "2026-05-18T23:36:05.92Z" },
|
|
666
|
+
{ url = "https://files.pythonhosted.org/packages/df/ac/46de6dda46478f7942f839e094970be2d4a861e005c4b3bf07c92e291a09/numpy-2.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261", size = 12450334, upload-time = "2026-05-18T23:36:09.107Z" },
|
|
667
|
+
{ url = "https://files.pythonhosted.org/packages/78/92/b8b798ac784102c0da830d2257d59358e3d3d90d1e2b3f2575dad976c5cf/numpy-2.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6", size = 10495678, upload-time = "2026-05-18T23:36:12.766Z" },
|
|
668
|
+
{ url = "https://files.pythonhosted.org/packages/30/34/ec28d1aa8115971537c01469ab2011ee96827930f0a124de1000cc2a7ed7/numpy-2.4.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a", size = 14823672, upload-time = "2026-05-18T23:36:16.473Z" },
|
|
669
|
+
{ url = "https://files.pythonhosted.org/packages/16/bd/f6d1fede4e54e8042a7ff97bb495510f3c220f94bcd9e8b228e87c92cc0d/numpy-2.4.6-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e", size = 5328731, upload-time = "2026-05-18T23:36:19.767Z" },
|
|
670
|
+
{ url = "https://files.pythonhosted.org/packages/f4/f0/e105b9e2fd728a9910103884decd6951d9dd73896b914a98d9a231de02ee/numpy-2.4.6-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e", size = 6649805, upload-time = "2026-05-18T23:36:22.266Z" },
|
|
671
|
+
{ url = "https://files.pythonhosted.org/packages/82/dd/1206a7ca6ab15e3f02069707ca96222e202af681bb73756da7527f3cb837/numpy-2.4.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43", size = 15730496, upload-time = "2026-05-18T23:36:25.713Z" },
|
|
672
|
+
{ url = "https://files.pythonhosted.org/packages/51/e7/38d3ea825dcab85a591734decb2f6c67caa7c8367d374df1a1c3842f9b07/numpy-2.4.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e", size = 16679616, upload-time = "2026-05-18T23:36:29.652Z" },
|
|
673
|
+
{ url = "https://files.pythonhosted.org/packages/93/b7/caabfdf53edf663e0b4eb74d7d405d83baef09eb5e83bcd32d601d72b93e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895", size = 17085145, upload-time = "2026-05-18T23:36:33.449Z" },
|
|
674
|
+
{ url = "https://files.pythonhosted.org/packages/f9/45/68d7c33a6bcf3e5aa3bdbd57a367e6f615286dfd6482f97e8ffeb734306e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4", size = 18403813, upload-time = "2026-05-18T23:36:37.369Z" },
|
|
675
|
+
{ url = "https://files.pythonhosted.org/packages/9c/50/0753655aa844c99cd9e018aacf76f130f1bd81d881bb74bc0aef5d73a8ba/numpy-2.4.6-cp314-cp314t-win32.whl", hash = "sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063", size = 6156982, upload-time = "2026-05-18T23:36:40.817Z" },
|
|
676
|
+
{ url = "https://files.pythonhosted.org/packages/b2/d4/7c67becf668f973cb490cec3e98dfd799d866f9c989a54d355672cfa0db6/numpy-2.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627", size = 12638908, upload-time = "2026-05-18T23:36:43.996Z" },
|
|
677
|
+
{ url = "https://files.pythonhosted.org/packages/43/bb/e1c71a4295b1b1d1393d50dbb4f2a36283c6859d9d3892e84f00ec5a91d5/numpy-2.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66", size = 10565867, upload-time = "2026-05-18T23:36:47.114Z" },
|
|
678
|
+
{ url = "https://files.pythonhosted.org/packages/de/12/b422cc84439adc0d00de605bf4a308890ae5c26f2c71fbd73e5d08fbb0dd/numpy-2.4.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662", size = 16847511, upload-time = "2026-05-18T23:36:50.673Z" },
|
|
679
|
+
{ url = "https://files.pythonhosted.org/packages/44/53/f481bef68011740f8849418d82db07230e825013f31f4eef5ba5b805316a/numpy-2.4.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7", size = 14889064, upload-time = "2026-05-18T23:36:53.879Z" },
|
|
680
|
+
{ url = "https://files.pythonhosted.org/packages/7f/57/42ed575c10ced8af951d426bc4e1f8aff16fd851db33f067036215a7f860/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f", size = 5394157, upload-time = "2026-05-18T23:36:57.194Z" },
|
|
681
|
+
{ url = "https://files.pythonhosted.org/packages/6a/ef/f66cc724fcc36c1e364c67f51ae9146090b8b584f27d58b97fdae3edd737/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c", size = 6708728, upload-time = "2026-05-18T23:36:59.575Z" },
|
|
682
|
+
{ url = "https://files.pythonhosted.org/packages/1a/9c/c531f2293b91265d8b48e9b329f54fdd7ffae73cb4134ea10cca4237e9cc/numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0", size = 15798374, upload-time = "2026-05-18T23:37:02.674Z" },
|
|
683
|
+
{ url = "https://files.pythonhosted.org/packages/1a/b0/413077f6b1153ed3cba361401c6783bbad6114804a000cc22eb71c13e190/numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02", size = 16747286, upload-time = "2026-05-18T23:37:06.327Z" },
|
|
684
|
+
{ url = "https://files.pythonhosted.org/packages/15/ce/e5ec180bc41812edcd8daeb8639d205622c0e8c02259d8ab25a0201b3c2a/numpy-2.4.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73", size = 12504263, upload-time = "2026-05-18T23:37:09.715Z" },
|
|
685
|
+
]
|
|
686
|
+
|
|
687
|
+
[[package]]
|
|
688
|
+
name = "numpy"
|
|
689
|
+
version = "2.5.3"
|
|
690
|
+
source = { registry = "https://pypi.org/simple" }
|
|
691
|
+
resolution-markers = [
|
|
692
|
+
"python_full_version >= '3.12'",
|
|
693
|
+
]
|
|
694
|
+
sdist = { url = "https://files.pythonhosted.org/packages/13/01/11703282db468b85f6f7b8c7f22d058de5970d5c7e60a3a8aaa313c3de36/numpy-2.5.3.tar.gz", hash = "sha256:df2d5874ff183595a4ba404edd04f6bd9b5505c1d7708573f6a6c17489a67563", size = 20791231, upload-time = "2026-09-06T16:27:47.073Z" }
|
|
695
|
+
wheels = [
|
|
696
|
+
{ url = "https://files.pythonhosted.org/packages/d6/50/8fdbb16af64895706a45f06a4068e29db732ec180f3c1375f14123359138/numpy-2.5.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cb189f09db39283b26bfd061ec16189e14f71c6755207f72a0f7540867afe5b9", size = 16994982, upload-time = "2026-09-06T16:24:29.244Z" },
|
|
697
|
+
{ url = "https://files.pythonhosted.org/packages/60/39/789131c1188c078dcb3a1692e72e1e050c68b88ffe72c9ccaac9bcd7a9cd/numpy-2.5.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f59a878c33d6b88122d80d239bb3b845d58708750b0cb06a09aebb9b18ec696c", size = 12009327, upload-time = "2026-09-06T16:24:32.491Z" },
|
|
698
|
+
{ url = "https://files.pythonhosted.org/packages/9c/59/a312e95696e5f601914dd8b6dd844692ba61670807417e24b68e337b5c70/numpy-2.5.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:a72f874bc9e10e4b8f80426fb49716d5141f64442a0c8418065093ec8017fbb0", size = 5445405, upload-time = "2026-09-06T16:24:35.071Z" },
|
|
699
|
+
{ url = "https://files.pythonhosted.org/packages/30/d0/5623a1707ed4fe16e3909fe3cf5ee3da004ae677ad23d83bbf3adf1a6faf/numpy-2.5.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:fc36dc566135b5eceec4cf89758fcb719266a019ef07dae1754ae7c9f617ef3e", size = 6783213, upload-time = "2026-09-06T16:24:37.253Z" },
|
|
700
|
+
{ url = "https://files.pythonhosted.org/packages/f1/32/84146fc020ad3c25f805f70ab60da46fe3c540a21369754a7e4369754b6f/numpy-2.5.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:76c2c1e6bfa5c84adc6434dfbf013aa92096a7985221762c8f11fedfd20fff58", size = 15687872, upload-time = "2026-09-06T16:24:39.751Z" },
|
|
701
|
+
{ url = "https://files.pythonhosted.org/packages/65/af/aa78d1a88805456e212b65461354cd943197fb9acecc4c90fd12295123a3/numpy-2.5.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7e18c623bb5c95acb3b3328861272816ba199fb531921c5d6d0b675f1fde9e3", size = 16717410, upload-time = "2026-09-06T16:24:42.745Z" },
|
|
702
|
+
{ url = "https://files.pythonhosted.org/packages/3b/24/faa79d865e69a97ba17473b23a1b74094b2259c03e820c70297293b9ea49/numpy-2.5.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4f8929ee6c96bfbd7b4ed2032e0c03af86fe1826740ab61ddabf9072d06e57ff", size = 17040975, upload-time = "2026-09-06T16:24:45.961Z" },
|
|
703
|
+
{ url = "https://files.pythonhosted.org/packages/62/4a/8877e629445a7176297dffcaf9c485faa96a95d81728a62521ad55bd4c0f/numpy-2.5.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b5d93cf48f687479941d12b69c873ad2cc76bbd487f0091c2200636497f34034", size = 18476479, upload-time = "2026-09-06T16:24:49.35Z" },
|
|
704
|
+
{ url = "https://files.pythonhosted.org/packages/c8/db/35e1c2d38b04cbd5b731f9d71495e055e813197669d22b612f11748d2ff9/numpy-2.5.3-cp312-cp312-win32.whl", hash = "sha256:bf63afbe037eb5d2fe87fbcc7778e61da53ebaf21d938a4515aa73b62532a5d4", size = 6133378, upload-time = "2026-09-06T16:24:51.915Z" },
|
|
705
|
+
{ url = "https://files.pythonhosted.org/packages/3c/a1/accf6d4f0c80c5d9ba9735d6b1550e444180599f34dec69ca01360f717ad/numpy-2.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:0a59a421a32580a009e8a1751345bf829631b990dc1794b80514ab722b435def", size = 12567828, upload-time = "2026-09-06T16:24:54.255Z" },
|
|
706
|
+
{ url = "https://files.pythonhosted.org/packages/22/43/1764aff32e4652526ae2f71fa8b3efd8d25c8a3d6926914454e47138ed1e/numpy-2.5.3-cp312-cp312-win_arm64.whl", hash = "sha256:ccb32e0525d29e8b0572eb84c9a57af0e7a4e615726927506f55063c62414034", size = 10485432, upload-time = "2026-09-06T16:24:57.278Z" },
|
|
707
|
+
{ url = "https://files.pythonhosted.org/packages/79/e5/8fb89cd46d14e35699d13bf943a5f5f441ecee8667120a1f6105ab89e349/numpy-2.5.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:66a78fe4556c60aceda5916f9eacd638b18e9e681016ec302dcb4682d6d4d034", size = 16991061, upload-time = "2026-09-06T16:25:00.411Z" },
|
|
708
|
+
{ url = "https://files.pythonhosted.org/packages/2f/06/9dc9e48b5e5e941c8b10350c5ff2d721da42a20517d911d15544246775ff/numpy-2.5.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92f30e89b8ee0ecf363033576c422b2f58fed6a80bed0aa48dff6d14c654663e", size = 12003676, upload-time = "2026-09-06T16:25:03.475Z" },
|
|
709
|
+
{ url = "https://files.pythonhosted.org/packages/ab/2a/98282aa5b8f58b1157d440bb6282eed47e3632a5de53a714fbab17e659fe/numpy-2.5.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f9a2353b37a1a9e78fd82b27ad7e2a32a2d036604d18f02b05e3136c62ca3b09", size = 5439695, upload-time = "2026-09-06T16:25:05.978Z" },
|
|
710
|
+
{ url = "https://files.pythonhosted.org/packages/a1/f9/b6533d777be9d6ffd29dc1be0867e563e6e8cc9a220ff1b716adc317f060/numpy-2.5.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:ccbc4665079665c3cf3bab4db9f6b095370cd6437d66be549b6c2a1fd19e1958", size = 6779395, upload-time = "2026-09-06T16:25:08.599Z" },
|
|
711
|
+
{ url = "https://files.pythonhosted.org/packages/73/85/735720d04ec197c5dcfacdfc9922667c7f1f5f496a279b7ba4d7c74c4cc7/numpy-2.5.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c76d5dde9f445058f83d0c02af00557a4db91de9a9a57c0df87d1535001d654b", size = 15681750, upload-time = "2026-09-06T16:25:11.173Z" },
|
|
712
|
+
{ url = "https://files.pythonhosted.org/packages/3a/1b/3b16a9bc514a440a7a0883684111dcb1ef1aee960af2ca95da8fc775f124/numpy-2.5.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5fa86b80fd24bcd1aff83ad23be44ea323de3f787be8f8b15d4a65621e25321", size = 16708577, upload-time = "2026-09-06T16:25:14.171Z" },
|
|
713
|
+
{ url = "https://files.pythonhosted.org/packages/69/c4/386f397831b07328b639c96c5b62719346cf4baf07c68d927239752b1534/numpy-2.5.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd4cb9ad3c7889b9b3fe0a9a9fb5d2ed26f9879bff2608d9f01aed147a20d231", size = 17042047, upload-time = "2026-09-06T16:25:17.582Z" },
|
|
714
|
+
{ url = "https://files.pythonhosted.org/packages/5f/3e/a700ecbf36e85ae8328fd3b0e12eeddc22ed6358a64cb2bd913e0d195d65/numpy-2.5.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1302b90c0e52281681b2975adfe8a860cb7b12216a27b4b0b4207c44bf7bccf0", size = 18465724, upload-time = "2026-09-06T16:25:20.949Z" },
|
|
715
|
+
{ url = "https://files.pythonhosted.org/packages/41/ee/38e785e88a4045f6ad1d1f2808dcdfafdca48c760260c0587bf171e29fc9/numpy-2.5.3-cp313-cp313-win32.whl", hash = "sha256:1c80eabb4035ecf4ca9cd49cde8a9fdd69a729e63e6474887d1523ade7aa277f", size = 6129003, upload-time = "2026-09-06T16:25:23.664Z" },
|
|
716
|
+
{ url = "https://files.pythonhosted.org/packages/f3/ec/100f2b1794ede74a9b3d7ec6b9736927f56713414c1dfe19ab6c383494bf/numpy-2.5.3-cp313-cp313-win_amd64.whl", hash = "sha256:71cad2b2a7451ab79d8f5e71b453485b6775963d5cf794179144a7463fe6e8ec", size = 12560965, upload-time = "2026-09-06T16:25:26.602Z" },
|
|
717
|
+
{ url = "https://files.pythonhosted.org/packages/80/b1/7dc825ca94c12acebbce4c37caa5e198695eb31424bc579679f32b1bb49d/numpy-2.5.3-cp313-cp313-win_arm64.whl", hash = "sha256:8e4dd766076855b5ff7ea52fa5f07ce26286726e0f8bff446b7739d02e6ea204", size = 10482343, upload-time = "2026-09-06T16:25:29.772Z" },
|
|
718
|
+
{ url = "https://files.pythonhosted.org/packages/70/78/cf416f15dc29375a229d9dfebf8db6e313f291580b39fa1a568b6052bb07/numpy-2.5.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:350ba9783ce969cf9f7ce6e6a9a58e1a6e2a19ca025b7ee448c4db727706212a", size = 16998686, upload-time = "2026-09-06T16:25:33.171Z" },
|
|
719
|
+
{ url = "https://files.pythonhosted.org/packages/9e/59/abcc2d8def4fd60eec7d87f92d27c13448ffd9ab14339bcc63a0d7a2fdea/numpy-2.5.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:012e66aca395d795496446e52aeeb5866312a5d4d3f27da270e5a0b43f70dc5c", size = 12013862, upload-time = "2026-09-06T16:25:36.748Z" },
|
|
720
|
+
{ url = "https://files.pythonhosted.org/packages/94/75/4640d2d6e4b64a049e48425a82728a41ef4adb61332d2cba68055774878b/numpy-2.5.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:adc1ada2662f8a5f960b8a10d9986897e7499ef07e06d4cfe7197f8cce923c07", size = 5449793, upload-time = "2026-09-06T16:25:39.476Z" },
|
|
721
|
+
{ url = "https://files.pythonhosted.org/packages/96/cd/625b57ae33d4ca560f32cc0b47b4a5922146d9beb998ddf773900d440a73/numpy-2.5.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:54a115e5a73b8fc44f0cebef486365a1894b5c9760685d4558b72b7c3eb846e0", size = 6785176, upload-time = "2026-09-06T16:25:42.069Z" },
|
|
722
|
+
{ url = "https://files.pythonhosted.org/packages/9c/72/12918652e7912ef9751e8694c88820fcd1908e0618cb23f5f3caa6004b7b/numpy-2.5.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be5a8381859b6da607c84f4f7d6847725f1cf1853ef8a2c9e115b7d58bef47dc", size = 15703377, upload-time = "2026-09-06T16:25:45.135Z" },
|
|
723
|
+
{ url = "https://files.pythonhosted.org/packages/45/8f/9beacf79ca7c650688ad0baa80931adb988fe6e6e5d5903c23cc3dbd70eb/numpy-2.5.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b0521d0f4aebb6e06189451025fa17a913287b13c03d5fe05c017333b654ea5b", size = 16711928, upload-time = "2026-09-06T16:25:48.461Z" },
|
|
724
|
+
{ url = "https://files.pythonhosted.org/packages/09/8d/41d0a56e1ac4c87495c897a211b1368691b7237aadabec8b3b8f3a74d48f/numpy-2.5.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9deb49575e5b0b94ed72c8a64ec4d033381adc27e9060ae842971f697ba96104", size = 17059507, upload-time = "2026-09-06T16:25:51.873Z" },
|
|
725
|
+
{ url = "https://files.pythonhosted.org/packages/08/1e/0dfbc5cc251d54e2af790f254d24ec38637fa97ec7d5d11de7ffed787098/numpy-2.5.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b00eefbcf0f292945c4b4dec2ae845389ef5bcdcd596e6e4328051db5b5ba694", size = 18471002, upload-time = "2026-09-06T16:25:55.233Z" },
|
|
726
|
+
{ url = "https://files.pythonhosted.org/packages/b5/2c/dfa40f6991f8185c8c30ffd023dfcbb11888e823cfab9557b920f3bb7bed/numpy-2.5.3-cp314-cp314-win32.whl", hash = "sha256:c2381f82999704f818e2c987a865050e285ec3621262c66d40f5a96c8f899f8e", size = 6180485, upload-time = "2026-09-06T16:25:58.157Z" },
|
|
727
|
+
{ url = "https://files.pythonhosted.org/packages/a4/73/d2c08231e4fde7e415501fd02c715d96e98599b2d8384445933944152984/numpy-2.5.3-cp314-cp314-win_amd64.whl", hash = "sha256:2c25dfa72943e4336ddb6b0ee4277b47a0c85bede0807530ec68103bf58e2c10", size = 12698179, upload-time = "2026-09-06T16:26:00.789Z" },
|
|
728
|
+
{ url = "https://files.pythonhosted.org/packages/5c/e9/dcdcc9b95cf5f49815055573aee1b11cfbf5299f38a180e437ded050810f/numpy-2.5.3-cp314-cp314-win_arm64.whl", hash = "sha256:15aa985ac73a8db02db7663381aa109510449d3819d37206caed27b33a65a8a6", size = 10769383, upload-time = "2026-09-06T16:26:04.011Z" },
|
|
729
|
+
{ url = "https://files.pythonhosted.org/packages/49/c4/af8bc08a7ef4e1529a7c0cf24969accce316b783999802089a581ec99272/numpy-2.5.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ac7bb1c52d445bd4f8f7f97fefe6abc3a084dc4d63df50d79b17fa2b78e89297", size = 12132668, upload-time = "2026-09-06T16:26:07.138Z" },
|
|
730
|
+
{ url = "https://files.pythonhosted.org/packages/c5/ae/0f15eb56d4ec5e13c1f7ff04ff407f997d1acbadb45d3e1f2e2645a8f43c/numpy-2.5.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:e6ab667ba76450084eb64013762c438ea76d9d29cc676dcd6c2e9892ba37f841", size = 5568580, upload-time = "2026-09-06T16:26:09.828Z" },
|
|
731
|
+
{ url = "https://files.pythonhosted.org/packages/23/fb/c72a8f25d4b6e96c354e7ab45ace3b27dc11e5d6a13b6c7d0cd6b08bf112/numpy-2.5.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:f7fabeb6cea87d65f3b926de33d03fb016cfdc29314c90974383b5582ae72891", size = 6882634, upload-time = "2026-09-06T16:26:12.524Z" },
|
|
732
|
+
{ url = "https://files.pythonhosted.org/packages/07/a9/968c90ed2ab15060c338e8137f1215b5a60756ae07328e0a60d1c6734df4/numpy-2.5.3-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1fb6f8fb9ff0b3a69f52c66ce397b0246583e9f28616231b0e32ca49259a5fa6", size = 15748923, upload-time = "2026-09-06T16:26:15.092Z" },
|
|
733
|
+
{ url = "https://files.pythonhosted.org/packages/59/08/9df04103947b95e3b6b1f2ed1a70521f325647a31b82da6a2aae3a485508/numpy-2.5.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93e1f5447e2b1e479d7bd74701e84746b86450cff1fc368b132d195e2b8f8211", size = 16746748, upload-time = "2026-09-06T16:26:18.43Z" },
|
|
734
|
+
{ url = "https://files.pythonhosted.org/packages/41/a0/14c8d5fe5b53a334aabb653deb391c0fef49558f491880ea300ed6785224/numpy-2.5.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c00abe94c1a69d75d827dcf1c025b25c8a45d230b3bcd77a9020883a1b047653", size = 17111561, upload-time = "2026-09-06T16:26:22.113Z" },
|
|
735
|
+
{ url = "https://files.pythonhosted.org/packages/c4/a6/d7e96e42f01522e154c32489640f16dfc4f6181d165d05fc3bec8c2c4999/numpy-2.5.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:536f963710a4e63934d80ac0dc4f478804a83e9a84b6828018f25d09953ada33", size = 18513945, upload-time = "2026-09-06T16:26:25.401Z" },
|
|
736
|
+
{ url = "https://files.pythonhosted.org/packages/25/39/3453afb7119d0449ef11c886874120ff180e2c337760e0e2d88f70f1a945/numpy-2.5.3-cp314-cp314t-win32.whl", hash = "sha256:4c8a6d2ebce6305fd82fbefca827775437147052a976ee7c94b36a0c1b52ac6c", size = 6335421, upload-time = "2026-09-06T16:26:28.175Z" },
|
|
737
|
+
{ url = "https://files.pythonhosted.org/packages/99/01/22815d2b19a1a746b1d45205cffebb3fe511a18acb75fba6c88491fc9894/numpy-2.5.3-cp314-cp314t-win_amd64.whl", hash = "sha256:9a37475425b431b4d060f23b4f52cd2f3aef6bc7c654bd760adf0040eec9d435", size = 12896420, upload-time = "2026-09-06T16:26:31.265Z" },
|
|
738
|
+
{ url = "https://files.pythonhosted.org/packages/fa/ee/a7cbba67eeaff038dc29ca8b98a88396c8b0cc9c89d4924f4a27a5c9150b/numpy-2.5.3-cp314-cp314t-win_arm64.whl", hash = "sha256:2d8240cb4c16fd831074aa2b2cf9fc54664d826341d61c372245b96a74a49a9a", size = 10857177, upload-time = "2026-09-06T16:26:34.167Z" },
|
|
739
|
+
{ url = "https://files.pythonhosted.org/packages/45/56/78194492883ff5eec90423fe56a3a44b154da047d88a6307f629713c584f/numpy-2.5.3-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:a6391fafaba97500887132cd582abc6e19452b1ac775a47caa7b24490e152058", size = 16996531, upload-time = "2026-09-06T16:26:37.287Z" },
|
|
740
|
+
{ url = "https://files.pythonhosted.org/packages/11/39/dd55c0af90bbab564b09ae3b0aa60ec5c02b900fa4f1ba23440525c8b32d/numpy-2.5.3-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:09d5a423c71ad5feb5625844ad58050e35df43871004b52ac9c0ad44a56775be", size = 12012569, upload-time = "2026-09-06T16:26:40.707Z" },
|
|
741
|
+
{ url = "https://files.pythonhosted.org/packages/b6/51/04f67d32e4862b281b1cb84ceeaed3421189a84fb6fb51a391cd6d5009f7/numpy-2.5.3-cp315-cp315-macosx_14_0_arm64.whl", hash = "sha256:f9579f383d1bf9df80081e72760e84960a7fd4f88cf0c9e535a8597c9bb646f5", size = 5448498, upload-time = "2026-09-06T16:26:43.435Z" },
|
|
742
|
+
{ url = "https://files.pythonhosted.org/packages/a3/c9/25b4dc0dd1344ec26c7319e84fd4e9809d2b5628f4e12decd618036e5178/numpy-2.5.3-cp315-cp315-macosx_14_0_x86_64.whl", hash = "sha256:86bff898a431c0fb71f7610b75726e75a54d47b37edc9d537f48de63bb3c0b90", size = 6783026, upload-time = "2026-09-06T16:26:46.374Z" },
|
|
743
|
+
{ url = "https://files.pythonhosted.org/packages/fc/c7/29285be1e5232a6e7ee3268a33c85843f5a8ee93350c6465cddd66ebbf76/numpy-2.5.3-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f3ed25271581281f2fccb1adcedfcde4c07362eec69189b50baf6f90e3ae159", size = 15697322, upload-time = "2026-09-06T16:26:49.415Z" },
|
|
744
|
+
{ url = "https://files.pythonhosted.org/packages/55/49/bbad5335fb4996a16881f853ff3e0ba582f01720e55c89b1c06b8fc42a90/numpy-2.5.3-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ffdc76bfcae6b255dff75202c5e7feaf95b40246bc0a17944facc1fecf9f79ab", size = 16708995, upload-time = "2026-09-06T16:26:53.127Z" },
|
|
745
|
+
{ url = "https://files.pythonhosted.org/packages/ef/e9/1df35483760b04a65ea44669f89dc64f30e5aca098b48ceb8b1310b0e0fe/numpy-2.5.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:116f96cadd935c6122e9228d676fe7ede19e741f5c8bb1c3cddbe0c51ccebea2", size = 17052508, upload-time = "2026-09-06T16:26:56.464Z" },
|
|
746
|
+
{ url = "https://files.pythonhosted.org/packages/b8/99/66e54da8265cc8be8a7382bf96edce17aaa2837d6f484432025932a3caa5/numpy-2.5.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:09ffa5d903faeaa5c4dd05009cf81c8bab9f2cb37c548b8d39b65b4cfa7c97f7", size = 18468224, upload-time = "2026-09-06T16:26:59.966Z" },
|
|
747
|
+
{ url = "https://files.pythonhosted.org/packages/01/bc/b5e90a91c115168d793dfd2ad9c69c438c2fe7a13a437e770bc5b078e732/numpy-2.5.3-cp315-cp315-win32.whl", hash = "sha256:e01c918ac3d48e18a927cf7b14a26a3e29ff2bdf2eacb976da0aecd6a43ed034", size = 6179919, upload-time = "2026-09-06T16:27:03.166Z" },
|
|
748
|
+
{ url = "https://files.pythonhosted.org/packages/37/ea/780748fd3985109075514ef8fc64cd25f943e40dde13a6d59141eb268fc8/numpy-2.5.3-cp315-cp315-win_amd64.whl", hash = "sha256:e931e4f499e0dc7ef29d269a8e5b35dd722e5d14be07df6240166ea7c6532fae", size = 12697656, upload-time = "2026-09-06T16:27:06.153Z" },
|
|
749
|
+
{ url = "https://files.pythonhosted.org/packages/b3/16/407be69a2a87c8cab64d95975a8977a426a29e138f07e276ec258f0fe4e5/numpy-2.5.3-cp315-cp315-win_arm64.whl", hash = "sha256:26e15e4aecd8617dfbaecb37d223e365d7b39411fba20454be2670a96aa74cb5", size = 10767601, upload-time = "2026-09-06T16:27:09.297Z" },
|
|
750
|
+
{ url = "https://files.pythonhosted.org/packages/44/bf/a97ffb01e41d50a32a9177aef942a4d0e389a3daf451d04e5f38ef6afb87/numpy-2.5.3-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:6cef4bb1706dfec49243c05d921eefb4e190d41e2528b30d8035ea1f36b4c24a", size = 17090092, upload-time = "2026-09-06T16:27:12.907Z" },
|
|
751
|
+
{ url = "https://files.pythonhosted.org/packages/d1/24/136c02f2c2af9a067a84d0c3aa10c99012c0476fa5066732fa4a4202557d/numpy-2.5.3-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:d1c89973648c85069c5046ad460f7b8a00218b29a2e42359ac8cc63e9ab94832", size = 12129429, upload-time = "2026-09-06T16:27:16.089Z" },
|
|
752
|
+
{ url = "https://files.pythonhosted.org/packages/fe/6c/b47582d6597789bf946d5efbeb6b9e56fd8bcbd5efc6fbf51dbe1ea31eb3/numpy-2.5.3-cp315-cp315t-macosx_14_0_arm64.whl", hash = "sha256:214045a5bf00113a146ab9ee9730c44501af6723cdf1f6830932f7b5ef2e7af0", size = 5565452, upload-time = "2026-09-06T16:27:19.868Z" },
|
|
753
|
+
{ url = "https://files.pythonhosted.org/packages/be/b4/ef3cc6da73774202d4deae16bb321fd8298a4e0561e3539f8c4be237d916/numpy-2.5.3-cp315-cp315t-macosx_14_0_x86_64.whl", hash = "sha256:8617bbfae4486cf99c9f899966699428d19da931d06ca94ad3da986c76e15997", size = 6876736, upload-time = "2026-09-06T16:27:22.232Z" },
|
|
754
|
+
{ url = "https://files.pythonhosted.org/packages/9e/24/e3813329498596cb842703dcacac1741612ed9fb9c4e6a3e0c7e2ebbc597/numpy-2.5.3-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:595d020938c84e320bcf40ad71089e108eac0d377cd018e14a8c094f39e98d85", size = 15745777, upload-time = "2026-09-06T16:27:25.181Z" },
|
|
755
|
+
{ url = "https://files.pythonhosted.org/packages/4a/9e/4e7a07fd0776dc2210cdacf2010be8665194d094defc10c419d7dea794cc/numpy-2.5.3-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f24021b9f22bc6301c37b196974a92c1c18dccedb6fef3dd252e95f2d6adbe4", size = 16746949, upload-time = "2026-09-06T16:27:28.576Z" },
|
|
756
|
+
{ url = "https://files.pythonhosted.org/packages/91/db/01674c0e20335057813a00c2ebd546ed25bff9ed7914f9bced00f8c55d94/numpy-2.5.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:71b39d9f935b6ec0f8753e3e2afb51e3efba6f2e05b68b32a40754d24bcd4a3c", size = 17108994, upload-time = "2026-09-06T16:27:31.946Z" },
|
|
757
|
+
{ url = "https://files.pythonhosted.org/packages/45/7a/584c5e71f8d378e57cac0b033891ed65c683ef90573ba4854e8c28203db0/numpy-2.5.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:6b05c171afb3aa07adbd20abc00aea86fe375beb0fdb9ef780ec5b7f63bab1c0", size = 18512266, upload-time = "2026-09-06T16:27:35.196Z" },
|
|
758
|
+
{ url = "https://files.pythonhosted.org/packages/a1/d2/4e1014173aa3c55e6a756e0e567290743a6ab33a288460374d7ef6bcd239/numpy-2.5.3-cp315-cp315t-win32.whl", hash = "sha256:f54660b0eb6b0b9f36e7fe1cdfdff472028dd0d14acd9b9b65098efbad059469", size = 6330292, upload-time = "2026-09-06T16:27:38.149Z" },
|
|
759
|
+
{ url = "https://files.pythonhosted.org/packages/6c/b0/ff5658a58199b7bcaad87bf260eef6713d9d42cca4e028f935b4fc5fbac6/numpy-2.5.3-cp315-cp315t-win_amd64.whl", hash = "sha256:1aad64d99730d013cfc6debafed22783b4fc5a7f4b8bc744d2d8cf7dcc880551", size = 12884918, upload-time = "2026-09-06T16:27:40.965Z" },
|
|
760
|
+
{ url = "https://files.pythonhosted.org/packages/fb/0b/b12a2df5d1b774bd9007a6fdff9381145b6223d37f11afc9c37ab0efd9a1/numpy-2.5.3-cp315-cp315t-win_arm64.whl", hash = "sha256:befa1ae5bd6030b3f512b43ff3fa5290bbed6b84411a44244b14adf835f5b89d", size = 10850807, upload-time = "2026-09-06T16:27:43.868Z" },
|
|
761
|
+
]
|
|
762
|
+
|
|
563
763
|
[[package]]
|
|
564
764
|
name = "packaging"
|
|
565
765
|
version = "26.3"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|