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.
Files changed (42) hide show
  1. {unitysvc_core-0.2.20/src/unitysvc_core.egg-info → unitysvc_core-0.2.22}/PKG-INFO +2 -3
  2. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/README.md +1 -1
  3. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/pyproject.toml +1 -2
  4. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/provider_data.py +10 -0
  5. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/provider_v1.json +8 -0
  6. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/utils.py +2 -3
  7. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22/src/unitysvc_core.egg-info}/PKG-INFO +2 -3
  8. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core.egg-info/requires.txt +0 -1
  9. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_provider_account_rate_limits.py +22 -10
  10. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/LICENSE +0 -0
  11. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/setup.cfg +0 -0
  12. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/__init__.py +0 -0
  13. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/__init__.py +0 -0
  14. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/base.py +0 -0
  15. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/documents.py +0 -0
  16. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/listing_data.py +0 -0
  17. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/listing_v1.py +0 -0
  18. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/offering_data.py +0 -0
  19. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/offering_v1.py +0 -0
  20. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/pricing.py +0 -0
  21. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/promotion_data.py +0 -0
  22. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/provider_v1.py +0 -0
  23. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/service.py +0 -0
  24. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/service_group_data.py +0 -0
  25. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/models/validators.py +0 -0
  26. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/py.typed +0 -0
  27. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/base.json +0 -0
  28. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/listing_v1.json +0 -0
  29. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/offering_v1.json +0 -0
  30. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/promotion_v1.json +0 -0
  31. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/schema/service_group_v1.json +0 -0
  32. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core/validator.py +0 -0
  33. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core.egg-info/SOURCES.txt +0 -0
  34. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core.egg-info/dependency_links.txt +0 -0
  35. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/src/unitysvc_core.egg-info/top_level.txt +0 -0
  36. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_access_interface_routing.py +0 -0
  37. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_pricing.py +0 -0
  38. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_service_group.py +0 -0
  39. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_service_status.py +0 -0
  40. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_utils.py +0 -0
  41. {unitysvc_core-0.2.20 → unitysvc_core-0.2.22}/tests/test_validator.py +0 -0
  42. {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.20
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
- `json5`, `tomli-w`. No `typer`, no `rich`, no `httpx`.
97
+ `tomli-w`. No `typer`, no `rich`, no `httpx`.
99
98
 
100
99
  ## Usage
101
100
 
@@ -59,7 +59,7 @@ pip install unitysvc-core
59
59
  ```
60
60
 
61
61
  Dependencies: `pydantic`, `email-validator`, `jsonschema`, `jinja2`,
62
- `json5`, `tomli-w`. No `typer`, no `rich`, no `httpx`.
62
+ `tomli-w`. No `typer`, no `rich`, no `httpx`.
63
63
 
64
64
  ## Usage
65
65
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "unitysvc-core"
7
- version = "0.2.20"
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/JSON5 or TOML) and return (data, format).
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 = json5.load(f)
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.20
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
- `json5`, `tomli-w`. No `typer`, no `rich`, no `httpx`.
97
+ `tomli-w`. No `typer`, no `rich`, no `httpx`.
99
98
 
100
99
  ## Usage
101
100
 
@@ -2,7 +2,6 @@ pydantic>=2
2
2
  email-validator
3
3
  jsonschema
4
4
  jinja2
5
- json5
6
5
  tomli-w
7
6
  unitysvc-data>=0.1.9
8
7
 
@@ -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
- {"limit": 10, "unit": "concurrent", "description": "engine capacity"},
71
- {"limit": 600, "unit": "requests", "window": "minute"},
72
- {"limit": 60000, "unit": "input_tokens", "window": "minute"},
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