iii-sdk 0.21.0.dev1__tar.gz → 0.21.1.dev1__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.
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/PKG-INFO +2 -2
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/pyproject.toml +2 -2
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_register_function_args.py +41 -19
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/.gitignore +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/README.md +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/__init__.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/channel.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/channels.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/engine.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/errors.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/format_utils.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/helpers.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/iii.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/iii_constants.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/iii_types.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/internal.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/otel_worker_gauges.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/protocol.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/runtime.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/state.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/stream.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/trigger.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/triggers.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/types.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/utils.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/src/iii/worker_metrics.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/conftest.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_api_triggers.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_async_api.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_baggage_span_processor.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_bridge.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_channel_close_delay.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_channel_submodule.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_context_propagation.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_data_channels.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_engine_constants.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_errors.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_format_utils.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_healthcheck.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_helpers.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_hold_process.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_http_external_functions_integration.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_iii_registration_dedup.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_init_api.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_invocation_exception.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_invocation_metadata.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_logger_function_ids.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_logger_otel.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_middleware.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_payload.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_pubsub.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_queue_integration.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_rbac_workers.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_runtime_submodule.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_span_ops.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_state.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_stream_models.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_stream_types.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_streams.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_streams_runtime_annotations.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_sync_api.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_telemetry.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_telemetry_exporters.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_telemetry_types.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_trace_helpers.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_trigger_metadata.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_trigger_registration_error.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_trigger_submodule.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_trigger_type_lifecycle.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_utils.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_worker_metadata.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_worker_metrics.py +0 -0
- {iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iii-sdk
|
|
3
|
-
Version: 0.21.
|
|
3
|
+
Version: 0.21.1.dev1
|
|
4
4
|
Summary: III SDK for Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/iii-hq/iii
|
|
6
6
|
Project-URL: Repository, https://github.com/iii-hq/iii
|
|
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
16
|
Requires-Python: >=3.10
|
|
17
|
-
Requires-Dist: iii-helpers==0.21.
|
|
17
|
+
Requires-Dist: iii-helpers==0.21.1.dev1
|
|
18
18
|
Requires-Dist: opentelemetry-api>=1.25
|
|
19
19
|
Requires-Dist: pydantic>=2.0
|
|
20
20
|
Requires-Dist: websockets>=12.0
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "iii-sdk"
|
|
7
|
-
version = "0.21.
|
|
7
|
+
version = "0.21.1.dev1"
|
|
8
8
|
description = "III SDK for Python"
|
|
9
9
|
authors = [{ name = "III" }]
|
|
10
10
|
license = { text = "Apache-2.0" }
|
|
@@ -23,7 +23,7 @@ dependencies = [
|
|
|
23
23
|
"websockets>=12.0",
|
|
24
24
|
"pydantic>=2.0",
|
|
25
25
|
"opentelemetry-api>=1.25",
|
|
26
|
-
"iii-helpers==0.21.
|
|
26
|
+
"iii-helpers==0.21.1.dev1",
|
|
27
27
|
]
|
|
28
28
|
|
|
29
29
|
[project.urls]
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import time
|
|
5
|
+
from collections.abc import Callable
|
|
5
6
|
from types import SimpleNamespace
|
|
6
7
|
from typing import Any
|
|
7
8
|
|
|
@@ -17,6 +18,8 @@ from iii.iii_types import RegisterFunctionFormat
|
|
|
17
18
|
# FakeWs helpers
|
|
18
19
|
# ---------------------------------------------------------------------------
|
|
19
20
|
|
|
21
|
+
_CREATED_CLIENTS: list[III] = []
|
|
22
|
+
|
|
20
23
|
|
|
21
24
|
class FakeWebSocket:
|
|
22
25
|
def __init__(self) -> None:
|
|
@@ -51,10 +54,38 @@ def _patch_ws(monkeypatch: pytest.MonkeyPatch) -> FakeWebSocket:
|
|
|
51
54
|
|
|
52
55
|
def _make_client() -> III:
|
|
53
56
|
client = III("ws://fake", InitOptions())
|
|
54
|
-
|
|
57
|
+
_CREATED_CLIENTS.append(client)
|
|
58
|
+
_wait_for(lambda: client.get_connection_state() == "connected", "fake WebSocket client to connect")
|
|
55
59
|
return client
|
|
56
60
|
|
|
57
61
|
|
|
62
|
+
@pytest.fixture(autouse=True)
|
|
63
|
+
def _shutdown_created_clients() -> None:
|
|
64
|
+
yield
|
|
65
|
+
while _CREATED_CLIENTS:
|
|
66
|
+
client = _CREATED_CLIENTS.pop()
|
|
67
|
+
if client._thread.is_alive():
|
|
68
|
+
client.shutdown()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _wait_for(predicate: Callable[[], bool], what: str, timeout: float = 2.0) -> None:
|
|
72
|
+
deadline = time.monotonic() + timeout
|
|
73
|
+
while time.monotonic() < deadline:
|
|
74
|
+
if predicate():
|
|
75
|
+
return
|
|
76
|
+
time.sleep(0.005)
|
|
77
|
+
pytest.fail(f"timed out waiting for {what}")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _registration_messages(ws: FakeWebSocket, function_id: str) -> list[dict[str, Any]]:
|
|
81
|
+
return [m for m in ws.sent if m.get("type") == "registerfunction" and m.get("id") == function_id]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _wait_for_registration(ws: FakeWebSocket, function_id: str) -> list[dict[str, Any]]:
|
|
85
|
+
_wait_for(lambda: bool(_registration_messages(ws, function_id)), f"registration for {function_id}")
|
|
86
|
+
return _registration_messages(ws, function_id)
|
|
87
|
+
|
|
88
|
+
|
|
58
89
|
# ---------------------------------------------------------------------------
|
|
59
90
|
# Two-arg register_function tests
|
|
60
91
|
# ---------------------------------------------------------------------------
|
|
@@ -78,9 +109,8 @@ def test_register_function_str_with_request_format(monkeypatch: pytest.MonkeyPat
|
|
|
78
109
|
return data
|
|
79
110
|
|
|
80
111
|
client.register_function("demo.with_args", handler, request_format=req_fmt)
|
|
81
|
-
time.sleep(0.02)
|
|
82
112
|
|
|
83
|
-
reg_msgs =
|
|
113
|
+
reg_msgs = _wait_for_registration(ws, "demo.with_args")
|
|
84
114
|
assert len(reg_msgs) == 1
|
|
85
115
|
|
|
86
116
|
sent_req_fmt = reg_msgs[0].get("request_format")
|
|
@@ -127,9 +157,8 @@ def test_register_function_str_with_both_formats(monkeypatch: pytest.MonkeyPatch
|
|
|
127
157
|
response_format=res_fmt,
|
|
128
158
|
metadata={"version": "1"},
|
|
129
159
|
)
|
|
130
|
-
time.sleep(0.02)
|
|
131
160
|
|
|
132
|
-
reg_msgs =
|
|
161
|
+
reg_msgs = _wait_for_registration(ws, "demo.both_formats")
|
|
133
162
|
assert len(reg_msgs) == 1
|
|
134
163
|
assert reg_msgs[0].get("description") == "A search function"
|
|
135
164
|
assert reg_msgs[0].get("request_format") is not None
|
|
@@ -149,9 +178,8 @@ def test_register_function_str_minimal(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
|
149
178
|
return data
|
|
150
179
|
|
|
151
180
|
client.register_function("demo.minimal", handler)
|
|
152
|
-
time.sleep(0.02)
|
|
153
181
|
|
|
154
|
-
reg_msgs =
|
|
182
|
+
reg_msgs = _wait_for_registration(ws, "demo.minimal")
|
|
155
183
|
assert len(reg_msgs) == 1
|
|
156
184
|
assert "request_format" not in reg_msgs[0]
|
|
157
185
|
assert "response_format" not in reg_msgs[0]
|
|
@@ -179,9 +207,8 @@ def test_register_function_str_with_http_invocation_and_format(monkeypatch: pyte
|
|
|
179
207
|
HttpInvocationConfig(url="https://example.com/fn", method="POST"),
|
|
180
208
|
request_format=req_fmt,
|
|
181
209
|
)
|
|
182
|
-
time.sleep(0.02)
|
|
183
210
|
|
|
184
|
-
reg_msgs =
|
|
211
|
+
reg_msgs = _wait_for_registration(ws, "external::with_format")
|
|
185
212
|
assert len(reg_msgs) == 1
|
|
186
213
|
assert reg_msgs[0].get("invocation", {}).get("url") == "https://example.com/fn"
|
|
187
214
|
assert reg_msgs[0].get("request_format") is not None
|
|
@@ -230,9 +257,8 @@ def test_register_function_str_id_auto_extracts_formats(monkeypatch: pytest.Monk
|
|
|
230
257
|
return UserOutput(message=f"Hello {data.name}")
|
|
231
258
|
|
|
232
259
|
client.register_function("demo.auto", handler, description="Auto-extract demo")
|
|
233
|
-
time.sleep(0.02)
|
|
234
260
|
|
|
235
|
-
reg_msgs =
|
|
261
|
+
reg_msgs = _wait_for_registration(ws, "demo.auto")
|
|
236
262
|
assert len(reg_msgs) == 1
|
|
237
263
|
msg = reg_msgs[0]
|
|
238
264
|
|
|
@@ -282,9 +308,8 @@ def test_register_function_str_id_explicit_formats_override(monkeypatch: pytest.
|
|
|
282
308
|
request_format=explicit_req,
|
|
283
309
|
response_format=explicit_res,
|
|
284
310
|
)
|
|
285
|
-
time.sleep(0.02)
|
|
286
311
|
|
|
287
|
-
reg_msgs =
|
|
312
|
+
reg_msgs = _wait_for_registration(ws, "demo.explicit")
|
|
288
313
|
assert len(reg_msgs) == 1
|
|
289
314
|
msg = reg_msgs[0]
|
|
290
315
|
|
|
@@ -306,9 +331,8 @@ def test_register_function_str_id_no_annotations(monkeypatch: pytest.MonkeyPatch
|
|
|
306
331
|
return data
|
|
307
332
|
|
|
308
333
|
client.register_function("demo.no_hints", handler)
|
|
309
|
-
time.sleep(0.02)
|
|
310
334
|
|
|
311
|
-
reg_msgs =
|
|
335
|
+
reg_msgs = _wait_for_registration(ws, "demo.no_hints")
|
|
312
336
|
assert len(reg_msgs) == 1
|
|
313
337
|
assert "request_format" not in reg_msgs[0]
|
|
314
338
|
assert "response_format" not in reg_msgs[0]
|
|
@@ -325,9 +349,8 @@ def test_register_function_str_id_with_metadata(monkeypatch: pytest.MonkeyPatch)
|
|
|
325
349
|
return data
|
|
326
350
|
|
|
327
351
|
client.register_function("demo.meta", handler, metadata={"version": "2.0"})
|
|
328
|
-
time.sleep(0.02)
|
|
329
352
|
|
|
330
|
-
reg_msgs =
|
|
353
|
+
reg_msgs = _wait_for_registration(ws, "demo.meta")
|
|
331
354
|
assert len(reg_msgs) == 1
|
|
332
355
|
assert reg_msgs[0]["metadata"] == {"version": "2.0"}
|
|
333
356
|
|
|
@@ -352,9 +375,8 @@ def test_register_function_str_id_with_http_invocation(monkeypatch: pytest.Monke
|
|
|
352
375
|
HttpInvocationConfig(url="https://example.com/fn", method="POST"),
|
|
353
376
|
description="HTTP function",
|
|
354
377
|
)
|
|
355
|
-
time.sleep(0.02)
|
|
356
378
|
|
|
357
|
-
reg_msgs =
|
|
379
|
+
reg_msgs = _wait_for_registration(ws, "demo.http")
|
|
358
380
|
assert len(reg_msgs) == 1
|
|
359
381
|
assert reg_msgs[0]["invocation"]["url"] == "https://example.com/fn"
|
|
360
382
|
assert reg_msgs[0]["description"] == "HTTP function"
|
|
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
|
|
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
|
{iii_sdk-0.21.0.dev1 → iii_sdk-0.21.1.dev1}/tests/test_http_external_functions_integration.py
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
|
|
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
|