iii-sdk 0.19.2.dev1__tar.gz → 0.19.3.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.19.2.dev1 → iii_sdk-0.19.3.dev1}/PKG-INFO +2 -2
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/pyproject.toml +2 -2
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_api_triggers.py +58 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/.gitignore +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/README.md +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/__init__.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/channels.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/errors.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/format_utils.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/helpers.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/iii.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/iii_constants.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/iii_types.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/otel_worker_gauges.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/state.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/stream.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/triggers.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/types.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/utils.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/src/iii/worker_metrics.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/conftest.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_async_api.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_baggage_span_processor.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_bridge.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_channel_close_delay.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_context_propagation.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_data_channels.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_errors.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_format_utils.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_healthcheck.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_helpers.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_hold_process.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_http_external_functions_integration.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_iii_registration_dedup.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_init_api.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_invocation_exception.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_logger_function_ids.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_logger_otel.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_middleware.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_payload.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_pubsub.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_queue_integration.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_rbac_workers.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_register_function_args.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_span_ops.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_state.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_stream_models.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_streams.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_streams_runtime_annotations.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_sync_api.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_telemetry.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_telemetry_exporters.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_telemetry_types.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_trace_helpers.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_trigger_metadata.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_trigger_registration_error.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_trigger_type_lifecycle.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_utils.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_worker_metadata.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/tests/test_worker_metrics.py +0 -0
- {iii_sdk-0.19.2.dev1 → iii_sdk-0.19.3.dev1}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iii-sdk
|
|
3
|
-
Version: 0.19.
|
|
3
|
+
Version: 0.19.3.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-observability==0.19.
|
|
17
|
+
Requires-Dist: iii-observability==0.19.3.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.19.
|
|
7
|
+
version = "0.19.3.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-observability==0.19.
|
|
26
|
+
"iii-observability==0.19.3.dev1",
|
|
27
27
|
]
|
|
28
28
|
|
|
29
29
|
[project.urls]
|
|
@@ -136,6 +136,64 @@ async def test_raw_json_request_body(engine_http_url, iii_client: III):
|
|
|
136
136
|
trigger.unregister()
|
|
137
137
|
|
|
138
138
|
|
|
139
|
+
@pytest.mark.asyncio
|
|
140
|
+
async def test_conflicting_route_structure_is_rejected(engine_http_url, iii_client: III, caplog):
|
|
141
|
+
"""Two routes with identical structure but swapped path-param names must not
|
|
142
|
+
crash the engine: the first keeps serving and the second is rejected with a
|
|
143
|
+
logged registration error."""
|
|
144
|
+
caplog.set_level("ERROR", logger="iii")
|
|
145
|
+
|
|
146
|
+
def handler(input_data):
|
|
147
|
+
return {"status_code": 200, "body": {"ok": True}}
|
|
148
|
+
|
|
149
|
+
# First route registers normally.
|
|
150
|
+
fn_a = iii_client.register_function("test.api.conflict.a.py", handler)
|
|
151
|
+
trig_a = iii_client.register_trigger(
|
|
152
|
+
{
|
|
153
|
+
"type": "http",
|
|
154
|
+
"function_id": "test.api.conflict.a.py",
|
|
155
|
+
"config": {
|
|
156
|
+
"api_path": "test/py/conflict/:listId/:userId",
|
|
157
|
+
"http_method": "GET",
|
|
158
|
+
},
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# Second route has the same axum shape with swapped param names -> conflict.
|
|
163
|
+
fn_b = iii_client.register_function("test.api.conflict.b.py", handler)
|
|
164
|
+
trig_b = iii_client.register_trigger(
|
|
165
|
+
{
|
|
166
|
+
"type": "http",
|
|
167
|
+
"function_id": "test.api.conflict.b.py",
|
|
168
|
+
"config": {
|
|
169
|
+
"api_path": "test/py/conflict/:userId/:listId",
|
|
170
|
+
"http_method": "GET",
|
|
171
|
+
},
|
|
172
|
+
}
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# Give the engine time to process both registrations and reply.
|
|
176
|
+
time.sleep(0.5)
|
|
177
|
+
|
|
178
|
+
# Engine stayed alive and the first route still serves — no panic.
|
|
179
|
+
async with aiohttp.ClientSession() as session:
|
|
180
|
+
async with session.get(f"{engine_http_url}/test/py/conflict/list1/user1") as resp:
|
|
181
|
+
assert resp.status == 200
|
|
182
|
+
data = await resp.json()
|
|
183
|
+
assert data["ok"] is True
|
|
184
|
+
|
|
185
|
+
# The conflicting registration was surfaced as an error. The engine rejects
|
|
186
|
+
# whichever route it processes second (wire order is not guaranteed), so assert on
|
|
187
|
+
# the conflict message rather than a specific route or the random trigger id.
|
|
188
|
+
messages = [record.getMessage() for record in caplog.records]
|
|
189
|
+
assert any("conflicts with already-registered route" in m for m in messages), messages
|
|
190
|
+
|
|
191
|
+
fn_a.unregister()
|
|
192
|
+
trig_a.unregister()
|
|
193
|
+
fn_b.unregister()
|
|
194
|
+
trig_b.unregister()
|
|
195
|
+
|
|
196
|
+
|
|
139
197
|
@pytest.mark.asyncio
|
|
140
198
|
async def test_path_parameters(engine_http_url, iii_client: III):
|
|
141
199
|
"""Verify path parameters are extracted correctly."""
|
|
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.19.2.dev1 → iii_sdk-0.19.3.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
|