unitysvc-core 0.2.20__tar.gz → 0.2.22__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.
- {unitysvc_core-0.2.20/src/unitysvc_core.egg-info → unitysvc_core-0.2.22}/PKG-INFO +2 -3
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/README.md +1 -1
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/pyproject.toml +1 -2
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/provider_data.py +10 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/provider_v1.json +8 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/utils.py +2 -3
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22/src/unitysvc_core.egg-info}/PKG-INFO +2 -3
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core.egg-info/requires.txt +0 -1
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_provider_account_rate_limits.py +22 -10
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/LICENSE +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/setup.cfg +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/__init__.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/__init__.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/base.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/documents.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/listing_data.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/listing_v1.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/offering_data.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/offering_v1.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/pricing.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/promotion_data.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/provider_v1.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/service.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/service_group_data.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/validators.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/py.typed +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/base.json +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/listing_v1.json +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/offering_v1.json +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/promotion_v1.json +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/service_group_v1.json +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/validator.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core.egg-info/SOURCES.txt +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core.egg-info/dependency_links.txt +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core.egg-info/top_level.txt +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_access_interface_routing.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_pricing.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_service_group.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_service_status.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_utils.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_validator.py +0 -0
- {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_validators.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unitysvc-core
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.22
|
|
4
4
|
Summary: Shared data models and validation helpers for UnitySVC packages
|
|
5
5
|
Author-email: Bo Peng <bo.peng@unitysvc.com>
|
|
6
6
|
Maintainer-email: Bo Peng <bo.peng@unitysvc.com>
|
|
@@ -18,7 +18,6 @@ Requires-Dist: pydantic>=2
|
|
|
18
18
|
Requires-Dist: email-validator
|
|
19
19
|
Requires-Dist: jsonschema
|
|
20
20
|
Requires-Dist: jinja2
|
|
21
|
-
Requires-Dist: json5
|
|
22
21
|
Requires-Dist: tomli-w
|
|
23
22
|
Requires-Dist: unitysvc-data>=0.1.9
|
|
24
23
|
Provides-Extra: test
|
|
@@ -95,7 +94,7 @@ pip install unitysvc-core
|
|
|
95
94
|
```
|
|
96
95
|
|
|
97
96
|
Dependencies: `pydantic`, `email-validator`, `jsonschema`, `jinja2`,
|
|
98
|
-
`
|
|
97
|
+
`tomli-w`. No `typer`, no `rich`, no `httpx`.
|
|
99
98
|
|
|
100
99
|
## Usage
|
|
101
100
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "unitysvc-core"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.22"
|
|
8
8
|
description = "Shared data models and validation helpers for UnitySVC packages"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Bo Peng", email = "bo.peng@unitysvc.com" }]
|
|
@@ -21,7 +21,6 @@ dependencies = [
|
|
|
21
21
|
"email-validator",
|
|
22
22
|
"jsonschema",
|
|
23
23
|
"jinja2",
|
|
24
|
-
"json5",
|
|
25
24
|
"tomli-w",
|
|
26
25
|
# Presets exposed under $<fn> sentinels that load_data_file expands
|
|
27
26
|
# transparently after parse + override-merge. The actual set of
|
|
@@ -36,6 +36,16 @@ class ProviderAccountRateLimit(BaseModel):
|
|
|
36
36
|
|
|
37
37
|
model_config = ConfigDict(extra="forbid")
|
|
38
38
|
|
|
39
|
+
name: str = Field(
|
|
40
|
+
min_length=1,
|
|
41
|
+
max_length=100,
|
|
42
|
+
description=(
|
|
43
|
+
"Seller-scoped rate-limit bucket name. Channels reference this "
|
|
44
|
+
"name via rate_limit_refs / ops_rate_limit_refs; all matching refs "
|
|
45
|
+
"for the same seller consume the same live gateway bucket."
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
|
|
39
49
|
limit: int = Field(gt=0, description="Maximum allowed — in flight for `concurrent`, per window otherwise")
|
|
40
50
|
|
|
41
51
|
unit: RateLimitUnitEnum = Field(description="What is being limited (requests, tokens, concurrent, …)")
|
|
@@ -179,6 +179,13 @@
|
|
|
179
179
|
"title": "Limit",
|
|
180
180
|
"type": "integer"
|
|
181
181
|
},
|
|
182
|
+
"name": {
|
|
183
|
+
"description": "Seller-scoped rate-limit bucket name. Channels reference this name via rate_limit_refs / ops_rate_limit_refs; all matching refs for the same seller consume the same live gateway bucket.",
|
|
184
|
+
"maxLength": 100,
|
|
185
|
+
"minLength": 1,
|
|
186
|
+
"title": "Name",
|
|
187
|
+
"type": "string"
|
|
188
|
+
},
|
|
182
189
|
"unit": {
|
|
183
190
|
"$ref": "#/$defs/RateLimitUnitEnum",
|
|
184
191
|
"description": "What is being limited (requests, tokens, concurrent, …)"
|
|
@@ -197,6 +204,7 @@
|
|
|
197
204
|
}
|
|
198
205
|
},
|
|
199
206
|
"required": [
|
|
207
|
+
"name",
|
|
200
208
|
"limit",
|
|
201
209
|
"unit"
|
|
202
210
|
],
|
|
@@ -19,7 +19,6 @@ from functools import lru_cache
|
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
from typing import Any
|
|
21
21
|
|
|
22
|
-
import json5
|
|
23
22
|
import tomli_w
|
|
24
23
|
|
|
25
24
|
# Presets discovered dynamically from unitysvc-data's registry. Any
|
|
@@ -297,7 +296,7 @@ def load_data_file(
|
|
|
297
296
|
preset_fns: Mapping[str, Callable[[Any], Any]] | None = DEFAULT_PRESET_FNS,
|
|
298
297
|
) -> tuple[dict[str, Any], str]:
|
|
299
298
|
"""
|
|
300
|
-
Load a data file (JSON
|
|
299
|
+
Load a data file (JSON or TOML) and return (data, format).
|
|
301
300
|
|
|
302
301
|
:func:`expand_presets` walks the result and replaces every
|
|
303
302
|
``$doc_preset`` / ``$file_preset`` sentinel with the matching preset
|
|
@@ -320,7 +319,7 @@ def load_data_file(
|
|
|
320
319
|
"""
|
|
321
320
|
if file_path.suffix == ".json":
|
|
322
321
|
with open(file_path, encoding="utf-8") as f:
|
|
323
|
-
data =
|
|
322
|
+
data = json.load(f)
|
|
324
323
|
file_format = "json"
|
|
325
324
|
elif file_path.suffix == ".toml":
|
|
326
325
|
with open(file_path, "rb") as f:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unitysvc-core
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.22
|
|
4
4
|
Summary: Shared data models and validation helpers for UnitySVC packages
|
|
5
5
|
Author-email: Bo Peng <bo.peng@unitysvc.com>
|
|
6
6
|
Maintainer-email: Bo Peng <bo.peng@unitysvc.com>
|
|
@@ -18,7 +18,6 @@ Requires-Dist: pydantic>=2
|
|
|
18
18
|
Requires-Dist: email-validator
|
|
19
19
|
Requires-Dist: jsonschema
|
|
20
20
|
Requires-Dist: jinja2
|
|
21
|
-
Requires-Dist: json5
|
|
22
21
|
Requires-Dist: tomli-w
|
|
23
22
|
Requires-Dist: unitysvc-data>=0.1.9
|
|
24
23
|
Provides-Extra: test
|
|
@@ -95,7 +94,7 @@ pip install unitysvc-core
|
|
|
95
94
|
```
|
|
96
95
|
|
|
97
96
|
Dependencies: `pydantic`, `email-validator`, `jsonschema`, `jinja2`,
|
|
98
|
-
`
|
|
97
|
+
`tomli-w`. No `typer`, no `rich`, no `httpx`.
|
|
99
98
|
|
|
100
99
|
## Usage
|
|
101
100
|
|
|
@@ -21,39 +21,46 @@ BASE = {
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def test_concurrency_needs_no_window() -> None:
|
|
24
|
-
limit = ProviderAccountRateLimit(limit=10, unit="concurrent")
|
|
24
|
+
limit = ProviderAccountRateLimit(name="fireworks_concurrency", limit=10, unit="concurrent")
|
|
25
|
+
assert limit.name == "fireworks_concurrency"
|
|
25
26
|
assert limit.window is None
|
|
26
27
|
|
|
27
28
|
|
|
29
|
+
def test_name_is_required() -> None:
|
|
30
|
+
with pytest.raises(ValidationError):
|
|
31
|
+
ProviderAccountRateLimit(limit=10, unit="concurrent")
|
|
32
|
+
|
|
33
|
+
|
|
28
34
|
def test_concurrency_rejects_a_window() -> None:
|
|
29
35
|
# A gauge has no window. Accepting one would let a seller author a limit
|
|
30
36
|
# the enforcement layer cannot honour as written.
|
|
31
37
|
with pytest.raises(ValidationError, match="takes no window"):
|
|
32
|
-
ProviderAccountRateLimit(limit=10, unit="concurrent", window="minute")
|
|
38
|
+
ProviderAccountRateLimit(name="fireworks_concurrency", limit=10, unit="concurrent", window="minute")
|
|
33
39
|
|
|
34
40
|
|
|
35
41
|
@pytest.mark.parametrize("unit", ["requests", "tokens", "input_tokens", "output_tokens", "bytes"])
|
|
36
42
|
def test_counted_units_require_a_window(unit: str) -> None:
|
|
37
43
|
with pytest.raises(ValidationError, match="counted over a window"):
|
|
38
|
-
ProviderAccountRateLimit(limit=100, unit=unit)
|
|
39
|
-
assert ProviderAccountRateLimit(limit=100, unit=unit, window="minute").window is not None
|
|
44
|
+
ProviderAccountRateLimit(name=f"fireworks_{unit}", limit=100, unit=unit)
|
|
45
|
+
assert ProviderAccountRateLimit(name=f"fireworks_{unit}", limit=100, unit=unit, window="minute").window is not None
|
|
40
46
|
|
|
41
47
|
|
|
42
48
|
def test_limit_must_be_positive() -> None:
|
|
43
49
|
with pytest.raises(ValidationError):
|
|
44
|
-
ProviderAccountRateLimit(limit=0, unit="concurrent")
|
|
50
|
+
ProviderAccountRateLimit(name="fireworks_concurrency", limit=0, unit="concurrent")
|
|
45
51
|
|
|
46
52
|
|
|
47
53
|
def test_unknown_field_is_rejected() -> None:
|
|
48
54
|
# extra="forbid": a typo'd key must not silently become a limit nobody enforces,
|
|
49
55
|
# which is the failure mode of the per-channel `rate_limits` this replaces.
|
|
50
56
|
with pytest.raises(ValidationError):
|
|
51
|
-
ProviderAccountRateLimit(limit=10, unit="concurrent", scope="account")
|
|
57
|
+
ProviderAccountRateLimit(name="fireworks_concurrency", limit=10, unit="concurrent", scope="account")
|
|
52
58
|
|
|
53
59
|
|
|
54
60
|
def test_provider_accepts_the_block() -> None:
|
|
55
|
-
provider = ProviderV1(**BASE, rate_limits=[{"limit": 10, "unit": "concurrent"}])
|
|
61
|
+
provider = ProviderV1(**BASE, rate_limits=[{"name": "fireworks_concurrency", "limit": 10, "unit": "concurrent"}])
|
|
56
62
|
assert provider.rate_limits is not None
|
|
63
|
+
assert provider.rate_limits[0].name == "fireworks_concurrency"
|
|
57
64
|
assert provider.rate_limits[0].limit == 10
|
|
58
65
|
|
|
59
66
|
|
|
@@ -67,9 +74,14 @@ def test_several_dimensions_coexist() -> None:
|
|
|
67
74
|
provider = ProviderV1(
|
|
68
75
|
**BASE,
|
|
69
76
|
rate_limits=[
|
|
70
|
-
{
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
{
|
|
78
|
+
"name": "fireworks_concurrency",
|
|
79
|
+
"limit": 10,
|
|
80
|
+
"unit": "concurrent",
|
|
81
|
+
"description": "engine capacity",
|
|
82
|
+
},
|
|
83
|
+
{"name": "fireworks_perminute", "limit": 600, "unit": "requests", "window": "minute"},
|
|
84
|
+
{"name": "fireworks_input_tokens", "limit": 60000, "unit": "input_tokens", "window": "minute"},
|
|
73
85
|
],
|
|
74
86
|
)
|
|
75
87
|
assert [rl.unit.value for rl in provider.rate_limits] == [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/service_group_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/service_group_v1.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|