runapi-core 0.9.0__tar.gz → 0.9.1__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.
- {runapi_core-0.9.0 → runapi_core-0.9.1}/PKG-INFO +2 -2
- {runapi_core-0.9.0 → runapi_core-0.9.1}/pyproject.toml +1 -1
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/contract_gen.py +6 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/resource.py +15 -5
- runapi_core-0.9.1/src/runapi/core/version.py +1 -0
- runapi_core-0.9.1/tests/test_contract_rule_messages.py +28 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_resource.py +1 -1
- runapi_core-0.9.0/src/runapi/core/version.py +0 -1
- {runapi_core-0.9.0 → runapi_core-0.9.1}/README.md +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/__init__.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/account.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/auth.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/config.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/constants.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/errors.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/files.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/http_client.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/models.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/multipart.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/options.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/polling.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/pricing.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/provider_client.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/py.typed +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/response.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/src/runapi/core/uploads.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_account.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_auth.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_config.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_errors.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_files.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_http_client.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_models.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_polling.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_pricing.py +0 -0
- {runapi_core-0.9.0 → runapi_core-0.9.1}/tests/test_uploads.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: runapi-core
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: RunAPI core SDK for JavaScript, Python, Ruby, Go, Java, and PHP
|
|
5
5
|
Project-URL: Homepage, https://runapi.ai/models
|
|
6
6
|
Project-URL: Documentation, https://runapi.ai/docs/resources/sdks
|
|
7
7
|
Project-URL: Source, https://github.com/runapi-ai/core-sdk
|
|
8
8
|
Project-URL: Issues, https://github.com/runapi-ai/core-sdk/issues
|
|
9
9
|
Project-URL: Changelog, https://github.com/runapi-ai/core-sdk/blob/main/CHANGELOG.md
|
|
10
|
-
Project-URL: Release Notes, https://github.com/runapi-ai/core-sdk/releases/tag/python%2Fv0.9.
|
|
10
|
+
Project-URL: Release Notes, https://github.com/runapi-ai/core-sdk/releases/tag/python%2Fv0.9.1
|
|
11
11
|
Author-email: RunAPI <contact@runapi.ai>
|
|
12
12
|
License-Expression: Apache-2.0
|
|
13
13
|
Keywords: api,core,golang,gradle,java,maven,pypi,python,ruby,runapi,runapi-ai,sdk,typescript
|
|
@@ -19,7 +19,7 @@ Documentation = "https://runapi.ai/docs/resources/sdks"
|
|
|
19
19
|
Source = "https://github.com/runapi-ai/core-sdk"
|
|
20
20
|
Issues = "https://github.com/runapi-ai/core-sdk/issues"
|
|
21
21
|
Changelog = "https://github.com/runapi-ai/core-sdk/blob/main/CHANGELOG.md"
|
|
22
|
-
"Release Notes" = "https://github.com/runapi-ai/core-sdk/releases/tag/python%2Fv0.9.
|
|
22
|
+
"Release Notes" = "https://github.com/runapi-ai/core-sdk/releases/tag/python%2Fv0.9.1"
|
|
23
23
|
|
|
24
24
|
[tool.hatch.version]
|
|
25
25
|
path = "src/runapi/core/version.py"
|
|
@@ -2459,6 +2459,9 @@ CONTRACT = {
|
|
|
2459
2459
|
}
|
|
2460
2460
|
},
|
|
2461
2461
|
"wan-2.5-image-to-video": {
|
|
2462
|
+
"duration_seconds": {
|
|
2463
|
+
"enum": [5, 10]
|
|
2464
|
+
},
|
|
2462
2465
|
"output_resolution": {
|
|
2463
2466
|
"enum": ["720p", "1080p"]
|
|
2464
2467
|
}
|
|
@@ -2523,6 +2526,9 @@ CONTRACT = {
|
|
|
2523
2526
|
}
|
|
2524
2527
|
},
|
|
2525
2528
|
"wan-2.5-text-to-video": {
|
|
2529
|
+
"duration_seconds": {
|
|
2530
|
+
"enum": [5, 10]
|
|
2531
|
+
},
|
|
2526
2532
|
"output_resolution": {
|
|
2527
2533
|
"enum": ["720p", "1080p"]
|
|
2528
2534
|
}
|
|
@@ -227,7 +227,7 @@ class Resource:
|
|
|
227
227
|
|
|
228
228
|
enum = rules.get("enum")
|
|
229
229
|
if enum is not None and not self._enum_allowed(enum, value):
|
|
230
|
-
raise ValidationError(f"{field} must be one of: {', '.join(
|
|
230
|
+
raise ValidationError(f"{field} must be one of: {', '.join(self._message_value(option) for option in enum)}")
|
|
231
231
|
|
|
232
232
|
if rules.get("type") == "integer":
|
|
233
233
|
self._validate_integer(field, value, rules)
|
|
@@ -318,8 +318,9 @@ class Resource:
|
|
|
318
318
|
):
|
|
319
319
|
return
|
|
320
320
|
|
|
321
|
+
# Sorted so the message matches every other SDK; Go maps have no declaration order.
|
|
321
322
|
context = " and ".join(
|
|
322
|
-
self._rule_condition_label(key,
|
|
323
|
+
self._rule_condition_label(key, conditions[key]) for key in sorted(conditions)
|
|
323
324
|
)
|
|
324
325
|
qualifier = f" when {context}" if context else ""
|
|
325
326
|
|
|
@@ -335,12 +336,14 @@ class Resource:
|
|
|
335
336
|
if self._field_present(params, field):
|
|
336
337
|
raise ValidationError(f"{field} is not allowed{qualifier}")
|
|
337
338
|
|
|
338
|
-
|
|
339
|
+
narrowed = rule.get("enum") or {}
|
|
340
|
+
for field in sorted(narrowed):
|
|
341
|
+
allowed = narrowed[field]
|
|
339
342
|
if not self._field_present(params, field):
|
|
340
343
|
continue
|
|
341
344
|
if any(str(candidate) == str(params[field]) for candidate in allowed):
|
|
342
345
|
continue
|
|
343
|
-
joined = ", ".join(
|
|
346
|
+
joined = ", ".join(self._message_value(candidate) for candidate in allowed)
|
|
344
347
|
raise ValidationError(f"{field} must be one of: {joined}{qualifier}")
|
|
345
348
|
|
|
346
349
|
def _rule_condition_met(self, params: Dict[str, Any], field: str, condition: Any) -> bool:
|
|
@@ -360,7 +363,14 @@ class Resource:
|
|
|
360
363
|
def _rule_condition_label(self, field: str, condition: Any) -> str:
|
|
361
364
|
if self._is_presence_condition(condition):
|
|
362
365
|
return f"{field} is present" if condition["present"] is True else f"{field} is absent"
|
|
363
|
-
return f"{field} is {condition}"
|
|
366
|
+
return f"{field} is {self._message_value(condition)}"
|
|
367
|
+
|
|
368
|
+
@staticmethod
|
|
369
|
+
def _message_value(value: Any) -> str:
|
|
370
|
+
"""Render booleans as JSON does (``false``) to match the other SDKs."""
|
|
371
|
+
if isinstance(value, bool):
|
|
372
|
+
return "true" if value else "false"
|
|
373
|
+
return str(value)
|
|
364
374
|
|
|
365
375
|
@classmethod
|
|
366
376
|
def _field_present(cls, params: Dict[str, Any], field: str) -> bool:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.9.1"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Rule messages must match every other SDK (sdk/contract_rule_messages.json)."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from runapi.core import Resource
|
|
9
|
+
from runapi.core.errors import ValidationError
|
|
10
|
+
|
|
11
|
+
SDK_ROOT = Path(__file__).resolve().parents[4]
|
|
12
|
+
FIXTURE = SDK_ROOT / "contract_rule_messages.json"
|
|
13
|
+
CONTRACT = SDK_ROOT / "contract.json"
|
|
14
|
+
|
|
15
|
+
# The shared fixture lives in the SDK monorepo; the public package repo does not ship it.
|
|
16
|
+
pytestmark = pytest.mark.skipif(not FIXTURE.exists(), reason="shared SDK fixture not available")
|
|
17
|
+
|
|
18
|
+
CASES = json.loads(FIXTURE.read_text())["cases"] if FIXTURE.exists() else []
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.parametrize("case", CASES, ids=[case["name"] for case in CASES])
|
|
22
|
+
def test_rule_message_matches_shared_fixture(case):
|
|
23
|
+
schema = json.loads(CONTRACT.read_text())["actions"][case["action"]]
|
|
24
|
+
|
|
25
|
+
with pytest.raises(ValidationError) as error:
|
|
26
|
+
Resource(object())._validate_contract(schema, dict(case["params"]))
|
|
27
|
+
|
|
28
|
+
assert str(error.value) == case["message"]
|
|
@@ -151,7 +151,7 @@ def test_validate_boolean_enum_requires_boolean_value():
|
|
|
151
151
|
|
|
152
152
|
resource._validate_contract(schema, {"model": "m", "flag": True})
|
|
153
153
|
resource._validate_contract(schema, {"model": "m", "flag": False})
|
|
154
|
-
with pytest.raises(ValidationError, match="^flag must be one of:
|
|
154
|
+
with pytest.raises(ValidationError, match="^flag must be one of: true, false$"):
|
|
155
155
|
resource._validate_contract(schema, {"model": "m", "flag": "true"})
|
|
156
156
|
|
|
157
157
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.9.0"
|
|
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
|
|
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
|