stamm-sdk 0.1.2__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.
- stamm_sdk-0.1.2/.gitignore +10 -0
- stamm_sdk-0.1.2/.python-version +1 -0
- stamm_sdk-0.1.2/PKG-INFO +57 -0
- stamm_sdk-0.1.2/README.md +47 -0
- stamm_sdk-0.1.2/notebooks/stamm_sdk_colab_test.ipynb +106 -0
- stamm_sdk-0.1.2/pyproject.toml +20 -0
- stamm_sdk-0.1.2/src/stamm_package/__init__.py +2 -0
- stamm_sdk-0.1.2/src/stamm_sdk/__init__.py +5 -0
- stamm_sdk-0.1.2/src/stamm_sdk/client.py +42 -0
- stamm_sdk-0.1.2/src/stamm_sdk/core/__init__.py +4 -0
- stamm_sdk-0.1.2/src/stamm_sdk/core/config.py +39 -0
- stamm_sdk-0.1.2/src/stamm_sdk/core/session.py +121 -0
- stamm_sdk-0.1.2/src/stamm_sdk/learning/__init__.py +5 -0
- stamm_sdk-0.1.2/src/stamm_sdk/learning/centralized_trainer.py +19 -0
- stamm_sdk-0.1.2/src/stamm_sdk/learning/federated_aggregator.py +17 -0
- stamm_sdk-0.1.2/src/stamm_sdk/learning/federated_client.py +27 -0
- stamm_sdk-0.1.2/src/stamm_sdk/registry/__init__.py +5 -0
- stamm_sdk-0.1.2/src/stamm_sdk/registry/api_client.py +46 -0
- stamm_sdk-0.1.2/src/stamm_sdk/registry/artifact_bundle.py +33 -0
- stamm_sdk-0.1.2/src/stamm_sdk/registry/storage_manager.py +23 -0
- stamm_sdk-0.1.2/src/stamm_sdk/schemas/__init__.py +10 -0
- stamm_sdk-0.1.2/src/stamm_sdk/schemas/federation_schema.py +22 -0
- stamm_sdk-0.1.2/src/stamm_sdk/schemas/model_schema.py +25 -0
- stamm_sdk-0.1.2/src/stamm_sdk/tracking/__init__.py +3 -0
- stamm_sdk-0.1.2/src/stamm_sdk/tracking/experiment_logger.py +40 -0
- stamm_sdk-0.1.2/uv.lock +206 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12.0
|
stamm_sdk-0.1.2/PKG-INFO
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stamm-sdk
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Python client SDK for Stamm federated learning registry
|
|
5
|
+
Author-email: Santiago <sam2800ml@gmail.com>
|
|
6
|
+
Requires-Python: >=3.12.0
|
|
7
|
+
Requires-Dist: httpx>=0.28.1
|
|
8
|
+
Requires-Dist: pydantic>=2.11.5
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# Stamm SDK
|
|
12
|
+
|
|
13
|
+
Lightweight Python SDK to interact with the Stamm ML registry API (FastAPI backend), including auth and model inference/update endpoints.
|
|
14
|
+
|
|
15
|
+
## Install Dependencies
|
|
16
|
+
|
|
17
|
+
Use `uv` in this repository:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv sync
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from stamm_sdk import Client
|
|
27
|
+
|
|
28
|
+
sdk = Client(base_url="http://188.245.241.118:8080")
|
|
29
|
+
sdk.login(email="you@example.com", password="your-password")
|
|
30
|
+
|
|
31
|
+
projects = sdk.ml.list_projects()
|
|
32
|
+
print(projects)
|
|
33
|
+
|
|
34
|
+
prediction = sdk.ml.predict(
|
|
35
|
+
project_id="your-project-id",
|
|
36
|
+
model_id="your-model-id",
|
|
37
|
+
features={"temperature": 24.7, "ph": 6.8},
|
|
38
|
+
)
|
|
39
|
+
print(prediction)
|
|
40
|
+
|
|
41
|
+
sdk.logout()
|
|
42
|
+
sdk.close()
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Implemented Modules
|
|
46
|
+
|
|
47
|
+
- `stamm_sdk.core`: config and authenticated HTTP session
|
|
48
|
+
- `stamm_sdk.registry`: ML endpoint wrappers, artifact bundle, storage manager
|
|
49
|
+
- `stamm_sdk.schemas`: pydantic schemas for model/federation metadata
|
|
50
|
+
- `stamm_sdk.tracking`: local experiment logger with optional remote push
|
|
51
|
+
- `stamm_sdk.learning`: centralized/federated stubs for training orchestration
|
|
52
|
+
|
|
53
|
+
## Environment Variables
|
|
54
|
+
|
|
55
|
+
- `STAMM_API_BASE_URL`: default API base URL
|
|
56
|
+
- `STAMM_API_TIMEOUT`: request timeout in seconds
|
|
57
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Stamm SDK
|
|
2
|
+
|
|
3
|
+
Lightweight Python SDK to interact with the Stamm ML registry API (FastAPI backend), including auth and model inference/update endpoints.
|
|
4
|
+
|
|
5
|
+
## Install Dependencies
|
|
6
|
+
|
|
7
|
+
Use `uv` in this repository:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uv sync
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from stamm_sdk import Client
|
|
17
|
+
|
|
18
|
+
sdk = Client(base_url="http://188.245.241.118:8080")
|
|
19
|
+
sdk.login(email="you@example.com", password="your-password")
|
|
20
|
+
|
|
21
|
+
projects = sdk.ml.list_projects()
|
|
22
|
+
print(projects)
|
|
23
|
+
|
|
24
|
+
prediction = sdk.ml.predict(
|
|
25
|
+
project_id="your-project-id",
|
|
26
|
+
model_id="your-model-id",
|
|
27
|
+
features={"temperature": 24.7, "ph": 6.8},
|
|
28
|
+
)
|
|
29
|
+
print(prediction)
|
|
30
|
+
|
|
31
|
+
sdk.logout()
|
|
32
|
+
sdk.close()
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Implemented Modules
|
|
36
|
+
|
|
37
|
+
- `stamm_sdk.core`: config and authenticated HTTP session
|
|
38
|
+
- `stamm_sdk.registry`: ML endpoint wrappers, artifact bundle, storage manager
|
|
39
|
+
- `stamm_sdk.schemas`: pydantic schemas for model/federation metadata
|
|
40
|
+
- `stamm_sdk.tracking`: local experiment logger with optional remote push
|
|
41
|
+
- `stamm_sdk.learning`: centralized/federated stubs for training orchestration
|
|
42
|
+
|
|
43
|
+
## Environment Variables
|
|
44
|
+
|
|
45
|
+
- `STAMM_API_BASE_URL`: default API base URL
|
|
46
|
+
- `STAMM_API_TIMEOUT`: request timeout in seconds
|
|
47
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"id": "670b8e69",
|
|
6
|
+
"metadata": {},
|
|
7
|
+
"source": [
|
|
8
|
+
"# Stamm SDK - Colab Quick Test\n",
|
|
9
|
+
"Use this notebook to validate that your published package installs and can talk to the ML registry API."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"cell_type": "code",
|
|
14
|
+
"execution_count": null,
|
|
15
|
+
"id": "84e75cb6",
|
|
16
|
+
"metadata": {},
|
|
17
|
+
"outputs": [],
|
|
18
|
+
"source": [
|
|
19
|
+
"# Install from PyPI after publishing\n",
|
|
20
|
+
"!pip -q install --upgrade stamm-package"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"cell_type": "code",
|
|
25
|
+
"execution_count": null,
|
|
26
|
+
"id": "0cadfc39",
|
|
27
|
+
"metadata": {},
|
|
28
|
+
"outputs": [],
|
|
29
|
+
"source": [
|
|
30
|
+
"from stamm_sdk import Client\n",
|
|
31
|
+
"from getpass import getpass\n",
|
|
32
|
+
"\n",
|
|
33
|
+
"BASE_URL = \"http://188.245.241.118:8080\"\n",
|
|
34
|
+
"\n",
|
|
35
|
+
"email = input(\"Email: \")\n",
|
|
36
|
+
"password = getpass(\"Password (hidden): \")\n",
|
|
37
|
+
"\n",
|
|
38
|
+
"sdk = Client(base_url=BASE_URL)\n",
|
|
39
|
+
"login_response = sdk.login(email=email, password=password)\n",
|
|
40
|
+
"print(\"Logged in. Token keys:\", list(login_response.keys()))"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"cell_type": "code",
|
|
45
|
+
"execution_count": null,
|
|
46
|
+
"id": "1d41074f",
|
|
47
|
+
"metadata": {},
|
|
48
|
+
"outputs": [],
|
|
49
|
+
"source": [
|
|
50
|
+
"# List projects and pick one\n",
|
|
51
|
+
"projects = sdk.ml.list_projects()\n",
|
|
52
|
+
"projects"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"cell_type": "code",
|
|
57
|
+
"execution_count": null,
|
|
58
|
+
"id": "dfbec7b5",
|
|
59
|
+
"metadata": {},
|
|
60
|
+
"outputs": [],
|
|
61
|
+
"source": [
|
|
62
|
+
"# Set these values based on your registry\n",
|
|
63
|
+
"project_id = input(\"Project ID: \")\n",
|
|
64
|
+
"models = sdk.ml.list_models(project_id)\n",
|
|
65
|
+
"models"
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"cell_type": "code",
|
|
70
|
+
"execution_count": null,
|
|
71
|
+
"id": "72d4eaf8",
|
|
72
|
+
"metadata": {},
|
|
73
|
+
"outputs": [],
|
|
74
|
+
"source": [
|
|
75
|
+
"# Prediction test\n",
|
|
76
|
+
"model_id = input(\"Model ID: \")\n",
|
|
77
|
+
"features = {\n",
|
|
78
|
+
" \"temperature\": 24.7,\n",
|
|
79
|
+
" \"ph\": 6.8\n",
|
|
80
|
+
"}\n",
|
|
81
|
+
"prediction = sdk.ml.predict(project_id=project_id, model_id=model_id, features=features)\n",
|
|
82
|
+
"prediction"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"cell_type": "code",
|
|
87
|
+
"execution_count": null,
|
|
88
|
+
"id": "c9e7817e",
|
|
89
|
+
"metadata": {},
|
|
90
|
+
"outputs": [],
|
|
91
|
+
"source": [
|
|
92
|
+
"# Cleanup\n",
|
|
93
|
+
"sdk.logout()\n",
|
|
94
|
+
"sdk.close()\n",
|
|
95
|
+
"print(\"Done\")"
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
"metadata": {
|
|
100
|
+
"language_info": {
|
|
101
|
+
"name": "python"
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"nbformat": 4,
|
|
105
|
+
"nbformat_minor": 5
|
|
106
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "stamm-sdk"
|
|
3
|
+
version = "0.1.2"
|
|
4
|
+
description = "Python client SDK for Stamm federated learning registry"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Santiago", email = "sam2800ml@gmail.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.12.0"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"httpx>=0.28.1",
|
|
12
|
+
"pydantic>=2.11.5",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.scripts]
|
|
16
|
+
stamm-sdk = "stamm_sdk:main"
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["hatchling"]
|
|
20
|
+
build-backend = "hatchling.build"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""High-level SDK client used by downstream applications."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .core.config import Config
|
|
6
|
+
from .core.session import Session
|
|
7
|
+
from .registry.api_client import APIClient
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Client:
|
|
11
|
+
"""Main entry point for interacting with the Stamm ML registry API."""
|
|
12
|
+
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
base_url: str | None = None,
|
|
16
|
+
timeout: float | None = None,
|
|
17
|
+
) -> None:
|
|
18
|
+
self.config = Config.from_env(base_url=base_url, timeout=timeout)
|
|
19
|
+
self.session = Session(config=self.config)
|
|
20
|
+
self.ml = APIClient(session=self.session)
|
|
21
|
+
|
|
22
|
+
def register(self, email: str, password: str, full_name: str) -> dict:
|
|
23
|
+
return self.session.register(
|
|
24
|
+
email=email,
|
|
25
|
+
password=password,
|
|
26
|
+
full_name=full_name,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def login(self, email: str, password: str) -> dict:
|
|
30
|
+
return self.session.login(email=email, password=password)
|
|
31
|
+
|
|
32
|
+
def logout(self) -> dict:
|
|
33
|
+
return self.session.logout()
|
|
34
|
+
|
|
35
|
+
def close(self) -> None:
|
|
36
|
+
self.session.close()
|
|
37
|
+
|
|
38
|
+
def __enter__(self) -> "Client":
|
|
39
|
+
return self
|
|
40
|
+
|
|
41
|
+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
42
|
+
self.close()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Configuration management for the SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
import os
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
DEFAULT_BASE_URL = "http://188.245.241.118:8080"
|
|
10
|
+
DEFAULT_TIMEOUT = 30.0
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class Config:
|
|
15
|
+
base_url: str = DEFAULT_BASE_URL
|
|
16
|
+
timeout: float = DEFAULT_TIMEOUT
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def from_env(
|
|
20
|
+
cls,
|
|
21
|
+
base_url: str | None = None,
|
|
22
|
+
timeout: float | None = None,
|
|
23
|
+
) -> "Config":
|
|
24
|
+
resolved_base_url = (
|
|
25
|
+
base_url
|
|
26
|
+
or os.getenv("STAMM_API_BASE_URL")
|
|
27
|
+
or DEFAULT_BASE_URL
|
|
28
|
+
)
|
|
29
|
+
resolved_timeout = timeout
|
|
30
|
+
if resolved_timeout is None:
|
|
31
|
+
env_timeout = os.getenv("STAMM_API_TIMEOUT")
|
|
32
|
+
resolved_timeout = (
|
|
33
|
+
float(env_timeout) if env_timeout else DEFAULT_TIMEOUT
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
return cls(
|
|
37
|
+
base_url=resolved_base_url.rstrip("/"),
|
|
38
|
+
timeout=float(resolved_timeout),
|
|
39
|
+
)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""HTTP session with auth helpers for the Stamm API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
|
|
10
|
+
from .config import Config
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(slots=True)
|
|
14
|
+
class Tokens:
|
|
15
|
+
access_token: str
|
|
16
|
+
refresh_token: str
|
|
17
|
+
token_type: str = "bearer"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Session:
|
|
21
|
+
def __init__(self, config: Config) -> None:
|
|
22
|
+
self.config = config
|
|
23
|
+
self._client = httpx.Client(
|
|
24
|
+
base_url=config.base_url,
|
|
25
|
+
timeout=config.timeout,
|
|
26
|
+
)
|
|
27
|
+
self.tokens: Tokens | None = None
|
|
28
|
+
|
|
29
|
+
def close(self) -> None:
|
|
30
|
+
self._client.close()
|
|
31
|
+
|
|
32
|
+
def _auth_headers(self) -> dict[str, str]:
|
|
33
|
+
if not self.tokens:
|
|
34
|
+
return {}
|
|
35
|
+
return {"Authorization": f"Bearer {self.tokens.access_token}"}
|
|
36
|
+
|
|
37
|
+
def register(
|
|
38
|
+
self,
|
|
39
|
+
email: str,
|
|
40
|
+
password: str,
|
|
41
|
+
full_name: str,
|
|
42
|
+
) -> dict[str, Any]:
|
|
43
|
+
payload = {
|
|
44
|
+
"email": email,
|
|
45
|
+
"password": password,
|
|
46
|
+
"full_name": full_name,
|
|
47
|
+
}
|
|
48
|
+
response = self._client.post("/auth/register", json=payload)
|
|
49
|
+
response.raise_for_status()
|
|
50
|
+
return response.json()
|
|
51
|
+
|
|
52
|
+
def login(self, email: str, password: str) -> dict[str, Any]:
|
|
53
|
+
payload = {"email": email, "password": password}
|
|
54
|
+
response = self._client.post("/auth/login-json", json=payload)
|
|
55
|
+
response.raise_for_status()
|
|
56
|
+
data = response.json()
|
|
57
|
+
self.tokens = Tokens(**data)
|
|
58
|
+
return data
|
|
59
|
+
|
|
60
|
+
def refresh(self) -> dict[str, Any]:
|
|
61
|
+
if not self.tokens:
|
|
62
|
+
raise RuntimeError("Not authenticated. Call login first.")
|
|
63
|
+
|
|
64
|
+
response = self._client.post(
|
|
65
|
+
"/auth/refresh",
|
|
66
|
+
params={"refresh_token": self.tokens.refresh_token},
|
|
67
|
+
)
|
|
68
|
+
response.raise_for_status()
|
|
69
|
+
data = response.json()
|
|
70
|
+
|
|
71
|
+
access_token = data.get("access_token") or self.tokens.access_token
|
|
72
|
+
refresh_token = data.get("refresh_token") or self.tokens.refresh_token
|
|
73
|
+
token_type = data.get("token_type") or self.tokens.token_type
|
|
74
|
+
self.tokens = Tokens(
|
|
75
|
+
access_token=access_token,
|
|
76
|
+
refresh_token=refresh_token,
|
|
77
|
+
token_type=token_type,
|
|
78
|
+
)
|
|
79
|
+
return data
|
|
80
|
+
|
|
81
|
+
def me(self) -> dict[str, Any]:
|
|
82
|
+
response = self._client.get("/auth/me", headers=self._auth_headers())
|
|
83
|
+
response.raise_for_status()
|
|
84
|
+
return response.json()
|
|
85
|
+
|
|
86
|
+
def logout(self) -> dict[str, Any]:
|
|
87
|
+
if not self.tokens:
|
|
88
|
+
return {"detail": "No active session"}
|
|
89
|
+
|
|
90
|
+
response = self._client.post(
|
|
91
|
+
"/auth/logout",
|
|
92
|
+
params={"refresh_token": self.tokens.refresh_token},
|
|
93
|
+
headers=self._auth_headers(),
|
|
94
|
+
)
|
|
95
|
+
response.raise_for_status()
|
|
96
|
+
data = response.json()
|
|
97
|
+
self.tokens = None
|
|
98
|
+
return data
|
|
99
|
+
|
|
100
|
+
def request(
|
|
101
|
+
self,
|
|
102
|
+
method: str,
|
|
103
|
+
path: str,
|
|
104
|
+
*,
|
|
105
|
+
params: dict[str, Any] | None = None,
|
|
106
|
+
json: dict[str, Any] | None = None,
|
|
107
|
+
data: dict[str, Any] | None = None,
|
|
108
|
+
) -> dict[str, Any]:
|
|
109
|
+
response = self._client.request(
|
|
110
|
+
method,
|
|
111
|
+
path,
|
|
112
|
+
params=params,
|
|
113
|
+
json=json,
|
|
114
|
+
data=data,
|
|
115
|
+
headers=self._auth_headers(),
|
|
116
|
+
)
|
|
117
|
+
response.raise_for_status()
|
|
118
|
+
|
|
119
|
+
if response.content:
|
|
120
|
+
return response.json()
|
|
121
|
+
return {}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Stub implementation for centralized training workflows."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CentralizedTrainer:
|
|
9
|
+
def train(
|
|
10
|
+
self,
|
|
11
|
+
dataset: Any,
|
|
12
|
+
config: dict[str, Any] | None = None,
|
|
13
|
+
) -> dict[str, Any]:
|
|
14
|
+
return {
|
|
15
|
+
"status": "stub",
|
|
16
|
+
"message": "Implement centralized training logic",
|
|
17
|
+
"dataset_type": type(dataset).__name__,
|
|
18
|
+
"config": config or {},
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Stub implementation for federated aggregation logic."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class FederatedAggregator:
|
|
9
|
+
def aggregate(self, updates: list[dict[str, Any]]) -> dict[str, Any]:
|
|
10
|
+
return {
|
|
11
|
+
"status": "stub",
|
|
12
|
+
"message": (
|
|
13
|
+
"Implement server-side aggregation "
|
|
14
|
+
"(for example FedAvg)"
|
|
15
|
+
),
|
|
16
|
+
"num_updates": len(updates),
|
|
17
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Stub implementation for a federated learning client node."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class FederatedClient:
|
|
9
|
+
def fit(self, model_state: dict[str, Any], data: Any) -> dict[str, Any]:
|
|
10
|
+
return {
|
|
11
|
+
"status": "stub",
|
|
12
|
+
"message": "Implement local FL client training",
|
|
13
|
+
"model_state": model_state,
|
|
14
|
+
"data_type": type(data).__name__,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def evaluate(
|
|
18
|
+
self,
|
|
19
|
+
model_state: dict[str, Any],
|
|
20
|
+
data: Any,
|
|
21
|
+
) -> dict[str, Any]:
|
|
22
|
+
return {
|
|
23
|
+
"status": "stub",
|
|
24
|
+
"message": "Implement local FL client evaluation",
|
|
25
|
+
"model_state": model_state,
|
|
26
|
+
"data_type": type(data).__name__,
|
|
27
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Wrapper around ML registry endpoints."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from stamm_sdk.core.session import Session
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class APIClient:
|
|
11
|
+
def __init__(self, session: Session) -> None:
|
|
12
|
+
self.session = session
|
|
13
|
+
|
|
14
|
+
def list_projects(self) -> dict[str, Any]:
|
|
15
|
+
return self.session.request("GET", "/list_projects/")
|
|
16
|
+
|
|
17
|
+
def get_project_info(self, project_id: str) -> dict[str, Any]:
|
|
18
|
+
return self.session.request("GET", f"/{project_id}/project_info/")
|
|
19
|
+
|
|
20
|
+
def get_db_config(self, project_id: str) -> dict[str, Any]:
|
|
21
|
+
return self.session.request("GET", f"/{project_id}/db_config/")
|
|
22
|
+
|
|
23
|
+
def get_references(self, project_id: str) -> dict[str, Any]:
|
|
24
|
+
return self.session.request("GET", f"/{project_id}/references/")
|
|
25
|
+
|
|
26
|
+
def get_variables(self, project_id: str) -> dict[str, Any]:
|
|
27
|
+
return self.session.request("GET", f"/{project_id}/variables/")
|
|
28
|
+
|
|
29
|
+
def list_models(self, project_id: str) -> dict[str, Any]:
|
|
30
|
+
return self.session.request("GET", f"/{project_id}/list_models/")
|
|
31
|
+
|
|
32
|
+
def get_model_metadata(self, project_id: str, model_id: str) -> dict[str, Any]:
|
|
33
|
+
return self.session.request("GET", f"/{project_id}/metadata/{model_id}")
|
|
34
|
+
|
|
35
|
+
def list_models_full(self, project_id: str) -> dict[str, Any]:
|
|
36
|
+
return self.session.request("GET", f"/{project_id}/models_full/")
|
|
37
|
+
|
|
38
|
+
def update_model(self, project_id: str, model_id: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
39
|
+
return self.session.request("PUT", f"/{project_id}/update/{model_id}", json=payload)
|
|
40
|
+
|
|
41
|
+
def predict(self, project_id: str, model_id: str, features: dict[str, Any]) -> dict[str, Any]:
|
|
42
|
+
return self.session.request(
|
|
43
|
+
"POST",
|
|
44
|
+
f"/{project_id}/predict/{model_id}",
|
|
45
|
+
json={"req": features},
|
|
46
|
+
)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Artifact bundle definition used for model packaging."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(slots=True)
|
|
11
|
+
class ArtifactBundle:
|
|
12
|
+
name: str
|
|
13
|
+
version: str
|
|
14
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
15
|
+
files: list[Path] = field(default_factory=list)
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def from_directory(
|
|
19
|
+
cls,
|
|
20
|
+
path: str | Path,
|
|
21
|
+
*,
|
|
22
|
+
name: str,
|
|
23
|
+
version: str,
|
|
24
|
+
metadata: dict[str, Any] | None = None,
|
|
25
|
+
) -> "ArtifactBundle":
|
|
26
|
+
root = Path(path)
|
|
27
|
+
files = [p for p in root.rglob("*") if p.is_file()]
|
|
28
|
+
return cls(
|
|
29
|
+
name=name,
|
|
30
|
+
version=version,
|
|
31
|
+
metadata=metadata or {},
|
|
32
|
+
files=files,
|
|
33
|
+
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Simple local storage utilities for model artifacts and metadata."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class StorageManager:
|
|
11
|
+
def __init__(self, root_dir: str | Path = ".stamm") -> None:
|
|
12
|
+
self.root_dir = Path(root_dir)
|
|
13
|
+
self.root_dir.mkdir(parents=True, exist_ok=True)
|
|
14
|
+
|
|
15
|
+
def save_json(self, relative_path: str, payload: dict[str, Any]) -> Path:
|
|
16
|
+
target = self.root_dir / relative_path
|
|
17
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
18
|
+
target.write_text(json.dumps(payload, indent=2), encoding="utf-8")
|
|
19
|
+
return target
|
|
20
|
+
|
|
21
|
+
def load_json(self, relative_path: str) -> dict[str, Any]:
|
|
22
|
+
target = self.root_dir / relative_path
|
|
23
|
+
return json.loads(target.read_text(encoding="utf-8"))
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from .federation_schema import FederationParticipant, FederationSchema
|
|
2
|
+
from .model_schema import ModelSchema, PredictionRequest, PredictionResponse
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"FederationParticipant",
|
|
6
|
+
"FederationSchema",
|
|
7
|
+
"ModelSchema",
|
|
8
|
+
"PredictionRequest",
|
|
9
|
+
"PredictionResponse",
|
|
10
|
+
]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Typed schemas for federated learning metadata."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FederationParticipant(BaseModel):
|
|
11
|
+
node_id: str
|
|
12
|
+
role: str = "client"
|
|
13
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class FederationSchema(BaseModel):
|
|
17
|
+
model_config = ConfigDict(extra="allow")
|
|
18
|
+
|
|
19
|
+
federation_id: str
|
|
20
|
+
strategy: str = "fedavg"
|
|
21
|
+
round_number: int = 0
|
|
22
|
+
participants: list[FederationParticipant] = Field(default_factory=list)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Typed schemas for model operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ModelSchema(BaseModel):
|
|
11
|
+
model_config = ConfigDict(extra="allow")
|
|
12
|
+
|
|
13
|
+
id: str | None = None
|
|
14
|
+
name: str | None = None
|
|
15
|
+
version: str | None = None
|
|
16
|
+
status: str | None = None
|
|
17
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PredictionRequest(BaseModel):
|
|
21
|
+
req: dict[str, Any]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class PredictionResponse(BaseModel):
|
|
25
|
+
model_config = ConfigDict(extra="allow")
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Simple experiment logger for local and optional remote tracking."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from datetime import UTC, datetime
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from stamm_sdk.core.session import Session
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ExperimentLogger:
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
session: Session | None = None,
|
|
17
|
+
log_path: str | Path = ".stamm/experiments.jsonl",
|
|
18
|
+
) -> None:
|
|
19
|
+
self.session = session
|
|
20
|
+
self.log_path = Path(log_path)
|
|
21
|
+
self.log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
22
|
+
|
|
23
|
+
def log(self, event: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
24
|
+
record = {
|
|
25
|
+
"event": event,
|
|
26
|
+
"timestamp": datetime.now(UTC).isoformat(),
|
|
27
|
+
"payload": payload,
|
|
28
|
+
}
|
|
29
|
+
with self.log_path.open("a", encoding="utf-8") as handle:
|
|
30
|
+
handle.write(json.dumps(record) + "\n")
|
|
31
|
+
return record
|
|
32
|
+
|
|
33
|
+
def push_remote(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
34
|
+
if not self.session:
|
|
35
|
+
raise RuntimeError("ExperimentLogger.session is not configured")
|
|
36
|
+
return self.session.request(
|
|
37
|
+
"POST",
|
|
38
|
+
"/api/v1/experiments/",
|
|
39
|
+
json=payload,
|
|
40
|
+
)
|
stamm_sdk-0.1.2/uv.lock
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 2
|
|
3
|
+
requires-python = ">=3.12.0"
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "annotated-types"
|
|
7
|
+
version = "0.7.0"
|
|
8
|
+
source = { registry = "https://pypi.org/simple" }
|
|
9
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
|
|
10
|
+
wheels = [
|
|
11
|
+
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "anyio"
|
|
16
|
+
version = "4.13.0"
|
|
17
|
+
source = { registry = "https://pypi.org/simple" }
|
|
18
|
+
dependencies = [
|
|
19
|
+
{ name = "idna" },
|
|
20
|
+
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
|
21
|
+
]
|
|
22
|
+
sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" }
|
|
23
|
+
wheels = [
|
|
24
|
+
{ url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" },
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[[package]]
|
|
28
|
+
name = "certifi"
|
|
29
|
+
version = "2026.5.20"
|
|
30
|
+
source = { registry = "https://pypi.org/simple" }
|
|
31
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f3/ce/ee2ecad540810a79593028e88299baeae54d346cc7a0d94b6199988b89b1/certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d", size = 135422, upload-time = "2026-05-20T11:46:50.073Z" }
|
|
32
|
+
wheels = [
|
|
33
|
+
{ url = "https://files.pythonhosted.org/packages/59/8c/57e832b7af6d7c5abe66eb3fbe3a3a32f4d11ea23a1aa7131371035be991/certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897", size = 134134, upload-time = "2026-05-20T11:46:48.578Z" },
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[[package]]
|
|
37
|
+
name = "h11"
|
|
38
|
+
version = "0.16.0"
|
|
39
|
+
source = { registry = "https://pypi.org/simple" }
|
|
40
|
+
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
|
|
41
|
+
wheels = [
|
|
42
|
+
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[[package]]
|
|
46
|
+
name = "httpcore"
|
|
47
|
+
version = "1.0.9"
|
|
48
|
+
source = { registry = "https://pypi.org/simple" }
|
|
49
|
+
dependencies = [
|
|
50
|
+
{ name = "certifi" },
|
|
51
|
+
{ name = "h11" },
|
|
52
|
+
]
|
|
53
|
+
sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
|
|
54
|
+
wheels = [
|
|
55
|
+
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[[package]]
|
|
59
|
+
name = "httpx"
|
|
60
|
+
version = "0.28.1"
|
|
61
|
+
source = { registry = "https://pypi.org/simple" }
|
|
62
|
+
dependencies = [
|
|
63
|
+
{ name = "anyio" },
|
|
64
|
+
{ name = "certifi" },
|
|
65
|
+
{ name = "httpcore" },
|
|
66
|
+
{ name = "idna" },
|
|
67
|
+
]
|
|
68
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
|
|
69
|
+
wheels = [
|
|
70
|
+
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[[package]]
|
|
74
|
+
name = "idna"
|
|
75
|
+
version = "3.17"
|
|
76
|
+
source = { registry = "https://pypi.org/simple" }
|
|
77
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b9/28/99c51f664567218d824af024c0251650fb27e4ca066df188dab0769c5b91/idna-3.17.tar.gz", hash = "sha256:5eb0cb53bc467c12eadcf6de83163ad8527cec9416f44b9b61b19caedad2b87f", size = 196048, upload-time = "2026-05-28T14:32:38.55Z" }
|
|
78
|
+
wheels = [
|
|
79
|
+
{ url = "https://files.pythonhosted.org/packages/de/a7/f76514cc40ad6234098ecdebda08732d75964776c51a42845b7da10649e2/idna-3.17-py3-none-any.whl", hash = "sha256:466e48829084efe2548012b855df21540b96f2e20e51bd124c851536556a592c", size = 65316, upload-time = "2026-05-28T14:32:37.035Z" },
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
[[package]]
|
|
83
|
+
name = "pydantic"
|
|
84
|
+
version = "2.13.4"
|
|
85
|
+
source = { registry = "https://pypi.org/simple" }
|
|
86
|
+
dependencies = [
|
|
87
|
+
{ name = "annotated-types" },
|
|
88
|
+
{ name = "pydantic-core" },
|
|
89
|
+
{ name = "typing-extensions" },
|
|
90
|
+
{ name = "typing-inspection" },
|
|
91
|
+
]
|
|
92
|
+
sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" }
|
|
93
|
+
wheels = [
|
|
94
|
+
{ url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" },
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
[[package]]
|
|
98
|
+
name = "pydantic-core"
|
|
99
|
+
version = "2.46.4"
|
|
100
|
+
source = { registry = "https://pypi.org/simple" }
|
|
101
|
+
dependencies = [
|
|
102
|
+
{ name = "typing-extensions" },
|
|
103
|
+
]
|
|
104
|
+
sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" }
|
|
105
|
+
wheels = [
|
|
106
|
+
{ url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" },
|
|
107
|
+
{ url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" },
|
|
108
|
+
{ url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" },
|
|
109
|
+
{ url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" },
|
|
110
|
+
{ url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" },
|
|
111
|
+
{ url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" },
|
|
112
|
+
{ url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" },
|
|
113
|
+
{ url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" },
|
|
114
|
+
{ url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" },
|
|
115
|
+
{ url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" },
|
|
116
|
+
{ url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" },
|
|
117
|
+
{ url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" },
|
|
118
|
+
{ url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" },
|
|
119
|
+
{ url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" },
|
|
120
|
+
{ url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" },
|
|
121
|
+
{ url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" },
|
|
122
|
+
{ url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" },
|
|
123
|
+
{ url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" },
|
|
124
|
+
{ url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" },
|
|
125
|
+
{ url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" },
|
|
126
|
+
{ url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" },
|
|
127
|
+
{ url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" },
|
|
128
|
+
{ url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" },
|
|
129
|
+
{ url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" },
|
|
130
|
+
{ url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" },
|
|
131
|
+
{ url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" },
|
|
132
|
+
{ url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" },
|
|
133
|
+
{ url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" },
|
|
134
|
+
{ url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" },
|
|
135
|
+
{ url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" },
|
|
136
|
+
{ url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" },
|
|
137
|
+
{ url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" },
|
|
138
|
+
{ url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" },
|
|
139
|
+
{ url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" },
|
|
140
|
+
{ url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" },
|
|
141
|
+
{ url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" },
|
|
142
|
+
{ url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" },
|
|
143
|
+
{ url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" },
|
|
144
|
+
{ url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" },
|
|
145
|
+
{ url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" },
|
|
146
|
+
{ url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" },
|
|
147
|
+
{ url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" },
|
|
148
|
+
{ url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" },
|
|
149
|
+
{ url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" },
|
|
150
|
+
{ url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" },
|
|
151
|
+
{ url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" },
|
|
152
|
+
{ url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" },
|
|
153
|
+
{ url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" },
|
|
154
|
+
{ url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" },
|
|
155
|
+
{ url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" },
|
|
156
|
+
{ url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" },
|
|
157
|
+
{ url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" },
|
|
158
|
+
{ url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" },
|
|
159
|
+
{ url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" },
|
|
160
|
+
{ url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" },
|
|
161
|
+
{ url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" },
|
|
162
|
+
{ url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" },
|
|
163
|
+
{ url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" },
|
|
164
|
+
{ url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" },
|
|
165
|
+
{ url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" },
|
|
166
|
+
{ url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" },
|
|
167
|
+
{ url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" },
|
|
168
|
+
{ url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" },
|
|
169
|
+
{ url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" },
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
[[package]]
|
|
173
|
+
name = "stamm-package"
|
|
174
|
+
version = "0.1.1"
|
|
175
|
+
source = { editable = "." }
|
|
176
|
+
dependencies = [
|
|
177
|
+
{ name = "httpx" },
|
|
178
|
+
{ name = "pydantic" },
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
[package.metadata]
|
|
182
|
+
requires-dist = [
|
|
183
|
+
{ name = "httpx", specifier = ">=0.28.1" },
|
|
184
|
+
{ name = "pydantic", specifier = ">=2.11.5" },
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
[[package]]
|
|
188
|
+
name = "typing-extensions"
|
|
189
|
+
version = "4.15.0"
|
|
190
|
+
source = { registry = "https://pypi.org/simple" }
|
|
191
|
+
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
|
192
|
+
wheels = [
|
|
193
|
+
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
[[package]]
|
|
197
|
+
name = "typing-inspection"
|
|
198
|
+
version = "0.4.2"
|
|
199
|
+
source = { registry = "https://pypi.org/simple" }
|
|
200
|
+
dependencies = [
|
|
201
|
+
{ name = "typing-extensions" },
|
|
202
|
+
]
|
|
203
|
+
sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
|
|
204
|
+
wheels = [
|
|
205
|
+
{ url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
|
|
206
|
+
]
|