tigrbl-runtime 0.4.2.dev3__tar.gz → 0.4.3__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.
- tigrbl_runtime-0.4.3/NOTICE +7 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/PKG-INFO +121 -28
- tigrbl_runtime-0.4.3/README.md +166 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/pyproject.toml +1 -1
- tigrbl_runtime-0.4.3/tigrbl_runtime/__init__.py +25 -0
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/webhooks.py → tigrbl_runtime-0.4.3/tigrbl_runtime/callbacks.py +12 -12
- tigrbl_runtime-0.4.3/tigrbl_runtime/channel/_asgi_completion.py +33 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/channel/_asgi_context.py +96 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/channel/_asgi_jsonrpc.py +38 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/channel/_asgi_receive.py +63 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/channel/_asgi_scope.py +75 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/channel/_asgi_send.py +242 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/channel/_asgi_webtransport.py +335 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/channel/asgi.py +77 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/executors/__init__.py +2 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/executors/_invoke_support.py +193 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/executors/ctx/__init__.py +15 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/executors/ctx/context.py +392 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/executors/ctx/hot.py +35 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/executors/ctx/hot_namespaces.py +421 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/executors/ctx/hot_state.py +226 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/executors/invoke.py +70 -174
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/executors/kernel_executor.py +1 -1
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/executors/packed.py +154 -603
- tigrbl_runtime-0.4.3/tigrbl_runtime/executors/types.py +39 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/handle.py +19 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/runtime/__init__.py +0 -7
- tigrbl_runtime-0.4.3/tigrbl_runtime/runtime/exceptions.py +8 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/runtime/runtime.py +155 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/runtime/system.py +2 -2
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/rust/__init__.py +5 -12
- tigrbl_runtime-0.4.3/tigrbl_runtime/rust/_fallback.py +73 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/rust/_load_rust.py +3 -9
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/rust/backend.py +25 -1
- tigrbl_runtime-0.4.3/tigrbl_runtime/rust/callbacks.py +43 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/rust/codec.py +27 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/rust/compile.py +15 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/rust/errors.py +27 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/rust/request.py +8 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/rust/response.py +8 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/rust/runtime.py +62 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/rust/trace.py +29 -0
- tigrbl_runtime-0.4.3/tigrbl_runtime/semantics.py +319 -0
- tigrbl_runtime-0.4.2.dev3/README.md +0 -74
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/__init__.py +0 -52
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/callbacks.py +0 -15
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/channel/asgi.py +0 -865
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/channel/state.py +0 -11
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/executors/helpers.py +0 -3
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/executors/loop_regions.py +0 -46
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/executors/types.py +0 -975
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/handle.py +0 -11
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/__init__.py +0 -19
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/_iterators.py +0 -3
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/anchors.py +0 -38
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/app_frame_codec.py +0 -111
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/completion_fence.py +0 -41
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/dispatch_atoms.py +0 -46
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/framing_atoms.py +0 -50
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/http_stream.py +0 -3
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/http_unary.py +0 -8
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/lifespan_chain.py +0 -3
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/loop_modes.py +0 -24
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/scope_schemas.py +0 -63
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/sse.py +0 -3
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/static_files.py +0 -3
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/subevent_handlers.py +0 -3
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/transport_atoms.py +0 -3
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/websocket.py +0 -3
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/webtransport.py +0 -9
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/protocol/webtransport_session.py +0 -129
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/events.py +0 -97
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/exceptions.py +0 -18
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/executor/__init__.py +0 -6
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/executor/invoke.py +0 -72
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/kernel.py +0 -35
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/labels.py +0 -3
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/runtime.py +0 -229
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/status/__init__.py +0 -1
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/status/converters.py +0 -1
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/status/exceptions.py +0 -1
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/status/mappings.py +0 -1
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/runtime/status/utils.py +0 -1
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/rust/_fallback.py +0 -320
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/rust/_parity_contract.py +0 -161
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/rust/callbacks.py +0 -60
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/rust/codec.py +0 -14
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/rust/compile.py +0 -35
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/rust/errors.py +0 -2
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/rust/parity.py +0 -72
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/rust/runtime.py +0 -127
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/rust/trace.py +0 -64
- tigrbl_runtime-0.4.2.dev3/tigrbl_runtime/transactions.py +0 -3
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/LICENSE +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/channel/__init__.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/channel/capabilities.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/channel/websocket.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/config/__init__.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/config/constants.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/executors/base.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/executors/numba_packed.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/executors/phase.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/runtime/_typing_aliases.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/runtime/base.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/runtime/channel.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/runtime/hook_types.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/runtime/response.py +0 -0
- {tigrbl_runtime-0.4.2.dev3 → tigrbl_runtime-0.4.3}/tigrbl_runtime/rust/availability.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tigrbl-runtime
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Runtime pipeline helpers and execution bridge surfaces for Tigrbl ASGI applications, transports, and operation dispatch.
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -204,6 +204,7 @@ License: Apache License
|
|
|
204
204
|
See the License for the specific language governing permissions and
|
|
205
205
|
limitations under the License.
|
|
206
206
|
License-File: LICENSE
|
|
207
|
+
License-File: NOTICE
|
|
207
208
|
Keywords: tigrbl,asgi,api,json-rpc,rest,sqlalchemy,pydantic,runtime,pipeline,bridge,openapi,openrpc,schema-first
|
|
208
209
|
Author: Jacob Stewart
|
|
209
210
|
Author-email: jacob@swarmauri.com
|
|
@@ -243,12 +244,45 @@ Description-Content-Type: text/markdown
|
|
|
243
244
|
<p><strong>Runtime pipeline helpers and execution bridge surfaces for Tigrbl ASGI applications, transports, and operation dispatch.</strong></p>
|
|
244
245
|
<a href="https://pypi.org/project/tigrbl-runtime/"><img src="https://img.shields.io/pypi/v/tigrbl-runtime?label=PyPI" alt="PyPI version for tigrbl-runtime"/></a>
|
|
245
246
|
<a href="https://pypi.org/project/tigrbl-runtime/"><img src="https://static.pepy.tech/badge/tigrbl-runtime" alt="Downloads for tigrbl-runtime"/></a>
|
|
247
|
+
<a href="https://discord.gg/K4YTAPapjR"><img src="https://img.shields.io/badge/Discord-Join%20chat-5865F2?logo=discord&logoColor=white" alt="Discord community for tigrbl-runtime"/></a>
|
|
246
248
|
<a href="https://github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_runtime/README.md"><img src="https://hits.sh/github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_runtime/README.md.svg?label=hits" alt="Repository hits for tigrbl-runtime README"/></a>
|
|
247
249
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-525252" alt="Apache 2.0 license"/></a>
|
|
248
|
-
<a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.10%
|
|
250
|
+
<a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-3776ab" alt="Python versions 3.10 | 3.11 | 3.12 | 3.13 | 3.14 for tigrbl-runtime"/></a>
|
|
249
251
|
<a href="https://github.com/tigrbl/tigrbl/blob/master/docs/README.md"><img src="https://img.shields.io/badge/workspace-core-1f6feb" alt="Workspace group for tigrbl-runtime"/></a>
|
|
250
252
|
</div>
|
|
251
253
|
|
|
254
|
+
## What is tigrbl-runtime?
|
|
255
|
+
|
|
256
|
+
Runtime pipeline helpers and execution bridge surfaces for Tigrbl ASGI applications, transports, and operation dispatch.
|
|
257
|
+
|
|
258
|
+
## Why use tigrbl-runtime?
|
|
259
|
+
|
|
260
|
+
Use it when you need this foundational Tigrbl layer directly as a small, focused dependency.
|
|
261
|
+
|
|
262
|
+
## When should I install tigrbl-runtime?
|
|
263
|
+
|
|
264
|
+
Install it for extension packages, package-local tests, or internals that need this boundary without the whole facade.
|
|
265
|
+
|
|
266
|
+
## Who is tigrbl-runtime for?
|
|
267
|
+
|
|
268
|
+
Framework maintainers, extension authors, and advanced users composing Tigrbl from split packages.
|
|
269
|
+
|
|
270
|
+
## Where does tigrbl-runtime fit?
|
|
271
|
+
|
|
272
|
+
`tigrbl-runtime` lives at `pkgs/core/tigrbl_runtime` and serves a focused layer in the split Tigrbl framework.
|
|
273
|
+
|
|
274
|
+
## How does tigrbl-runtime work?
|
|
275
|
+
|
|
276
|
+
It owns a narrow layer in the split workspace and is consumed by higher-level packages through explicit dependencies.
|
|
277
|
+
|
|
278
|
+
## Certification Status
|
|
279
|
+
|
|
280
|
+
- Package status: governed package in the `tigrbl/tigrbl` workspace.
|
|
281
|
+
- Governance source: [SSOT registry](https://github.com/tigrbl/tigrbl/blob/master/.ssot/registry.json).
|
|
282
|
+
- Release evidence: [publish workflow](https://github.com/tigrbl/tigrbl/actions/workflows/publish.yml) validates package builds, tests, GitHub release assets, and PyPI publication for managed packages.
|
|
283
|
+
- Local certification guard: `pkgs/core/tigrbl_tests/tests/unit/test_package_badges_and_notices.py` verifies every package README keeps the Discord badge, Apache 2.0 badge, explicit Python-version badge, `LICENSE`, and `NOTICE`.
|
|
284
|
+
- Scope note: this README documents the package boundary. Runtime feature support remains governed by `.ssot/` entities and the conformance docs linked below.
|
|
285
|
+
|
|
252
286
|
## Install
|
|
253
287
|
|
|
254
288
|
```bash
|
|
@@ -259,56 +293,115 @@ uv add tigrbl-runtime
|
|
|
259
293
|
pip install tigrbl-runtime
|
|
260
294
|
```
|
|
261
295
|
|
|
296
|
+
## Surface Coverage
|
|
297
|
+
|
|
298
|
+
| Surface | Value |
|
|
299
|
+
|---|---|
|
|
300
|
+
| PyPI package | [`tigrbl-runtime`](https://pypi.org/project/tigrbl-runtime/) |
|
|
301
|
+
| Repository path | [`pkgs/core/tigrbl_runtime`](https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_runtime) |
|
|
302
|
+
| Python import root | `tigrbl_runtime` |
|
|
303
|
+
| Console scripts | none declared |
|
|
304
|
+
| Entry points | none declared |
|
|
305
|
+
| Optional extras | none declared |
|
|
306
|
+
| Legal files | `LICENSE`, `NOTICE` |
|
|
307
|
+
| Supported Python | `3.10 | 3.11 | 3.12 | 3.13 | 3.14` |
|
|
308
|
+
|
|
262
309
|
## What It Owns
|
|
263
310
|
|
|
264
|
-
`tigrbl-runtime` owns the
|
|
265
|
-
Rust crates and optional Python extension bindings have moved to the private `tigrbl/tigrbl_rs` repository.
|
|
311
|
+
`tigrbl-runtime` owns the `foundational framework package` boundary. It should be installed when you need this package's focused responsibility without assuming every other Tigrbl workspace package is present.
|
|
266
312
|
|
|
267
|
-
|
|
313
|
+
Implementation orientation:
|
|
314
|
+
- `tigrbl_runtime`: callbacks, channel/, config/, executors/, handle, protocol/, runtime/, transactions, webhooks
|
|
315
|
+
- `tigrbl_runtime/rust/`: deprecated compatibility shims only; Rust execution is unavailable.
|
|
268
316
|
|
|
269
|
-
|
|
317
|
+
Runtime authoring BCP:
|
|
318
|
+
- Do use this package for runtime-owned routing, request execution, transport-unit execution, framing atoms, transport channels, transaction helpers, and kernel integration.
|
|
319
|
+
- Do keep handler invocation, transaction progression, error handling, and transport emission aligned with compiled plans.
|
|
320
|
+
- Do not make application route handlers, FastAPI/Starlette objects, direct SQLAlchemy session calls, or ad-hoc engine construction the runtime contract.
|
|
321
|
+
- Do not bypass kernel plans or lifecycle phases when adding REST, JSON-RPC, stream, SSE, WebSocket, or WebTransport behavior.
|
|
322
|
+
- Avoid hiding behavior in transport wrappers that diagnostics and compiled plans cannot inspect.
|
|
270
323
|
|
|
271
|
-
## Public Surface
|
|
324
|
+
## Public API and Import Surface
|
|
272
325
|
|
|
273
|
-
-
|
|
326
|
+
- Import roots: `tigrbl_runtime`.
|
|
327
|
+
- Public symbols: `Runtime`, `RuntimeBase`.
|
|
328
|
+
- Rust-named symbols live only under `tigrbl_runtime.rust` as deprecated compatibility shims and must not be used for execution.
|
|
329
|
+
- Workspace dependencies: [`tigrbl-typing`](https://pypi.org/project/tigrbl-typing/), [`tigrbl-kernel`](https://pypi.org/project/tigrbl-kernel/), [`tigrbl-atoms`](https://pypi.org/project/tigrbl-atoms/), [`tigrbl-base`](https://pypi.org/project/tigrbl-base/), [`tigrbl-core`](https://pypi.org/project/tigrbl-core/).
|
|
330
|
+
- External runtime dependencies: `numba>=0.61.2`.
|
|
274
331
|
|
|
275
|
-
##
|
|
332
|
+
## Usage Examples
|
|
276
333
|
|
|
277
|
-
|
|
278
|
-
- Package class: `core framework package`.
|
|
279
|
-
- Python requirement: `>=3.10,<3.15`.
|
|
334
|
+
### Verify the installed package
|
|
280
335
|
|
|
281
|
-
|
|
336
|
+
```bash
|
|
337
|
+
python -m pip show tigrbl-runtime
|
|
338
|
+
python - <<'PY'
|
|
339
|
+
from importlib.metadata import version
|
|
340
|
+
print(version("tigrbl-runtime"))
|
|
341
|
+
PY
|
|
342
|
+
```
|
|
282
343
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
344
|
+
### Import the package boundary
|
|
345
|
+
|
|
346
|
+
```python
|
|
347
|
+
import importlib
|
|
348
|
+
|
|
349
|
+
module = importlib.import_module("tigrbl_runtime")
|
|
350
|
+
print(module.__name__)
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Import a public symbol
|
|
354
|
+
|
|
355
|
+
```python
|
|
356
|
+
from tigrbl_runtime import Runtime
|
|
357
|
+
|
|
358
|
+
print(Runtime)
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Use with the facade when building applications
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
uv add tigrbl tigrbl-runtime
|
|
365
|
+
python - <<'PY'
|
|
366
|
+
import tigrbl
|
|
367
|
+
print(tigrbl.__name__)
|
|
368
|
+
PY
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## How To Choose This Package
|
|
372
|
+
|
|
373
|
+
Choose `tigrbl-runtime` when the quick-answer table matches your use case. Choose [`tigrbl`](https://pypi.org/project/tigrbl/) instead when you want the full public facade. Choose a lower-level package such as [`tigrbl-core`](https://pypi.org/project/tigrbl-core/), [`tigrbl-base`](https://pypi.org/project/tigrbl-base/), or [`tigrbl-runtime`](https://pypi.org/project/tigrbl-runtime/) when you are building framework extensions or testing a specific internal boundary.
|
|
286
374
|
|
|
287
375
|
## Related Packages
|
|
288
376
|
|
|
289
|
-
- [`tigrbl`](https://pypi.org/project/tigrbl/)
|
|
290
377
|
- [`tigrbl-typing`](https://pypi.org/project/tigrbl-typing/)
|
|
291
378
|
- [`tigrbl-kernel`](https://pypi.org/project/tigrbl-kernel/)
|
|
292
379
|
- [`tigrbl-atoms`](https://pypi.org/project/tigrbl-atoms/)
|
|
293
380
|
- [`tigrbl-base`](https://pypi.org/project/tigrbl-base/)
|
|
294
381
|
- [`tigrbl-core`](https://pypi.org/project/tigrbl-core/)
|
|
382
|
+
- [`tigrbl`](https://pypi.org/project/tigrbl/)
|
|
383
|
+
|
|
384
|
+
## Documentation Links
|
|
385
|
+
|
|
386
|
+
- [Workspace docs](https://github.com/tigrbl/tigrbl/blob/master/docs/README.md)
|
|
387
|
+
- [Package catalog](https://github.com/tigrbl/tigrbl/blob/master/docs/developer/PACKAGE_CATALOG.md)
|
|
388
|
+
- [Package layout](https://github.com/tigrbl/tigrbl/blob/master/docs/developer/PACKAGE_LAYOUT.md)
|
|
389
|
+
- [Current target](https://github.com/tigrbl/tigrbl/blob/master/docs/conformance/CURRENT_TARGET.md)
|
|
390
|
+
- [Current state](https://github.com/tigrbl/tigrbl/blob/master/docs/conformance/CURRENT_STATE.md)
|
|
391
|
+
- [SSOT registry](https://github.com/tigrbl/tigrbl/blob/master/.ssot/registry.json)
|
|
392
|
+
- [Release workflow](https://github.com/tigrbl/tigrbl/actions/workflows/publish.yml)
|
|
295
393
|
|
|
296
|
-
##
|
|
394
|
+
## Support
|
|
297
395
|
|
|
298
|
-
-
|
|
299
|
-
-
|
|
300
|
-
-
|
|
301
|
-
- `docs/conformance/NEXT_STEPS.md`
|
|
302
|
-
- `docs/governance/DOC_POINTERS.md`
|
|
303
|
-
- `docs/developer/PACKAGE_CATALOG.md`
|
|
304
|
-
- `docs/developer/PACKAGE_LAYOUT.md`
|
|
396
|
+
- Community: [Discord](https://discord.gg/K4YTAPapjR).
|
|
397
|
+
- Issues: [GitHub Issues](https://github.com/tigrbl/tigrbl/issues).
|
|
398
|
+
- Repository: [pkgs/core/tigrbl_runtime](https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_runtime).
|
|
305
399
|
|
|
306
400
|
## Package-local Boundary
|
|
307
401
|
|
|
308
|
-
This
|
|
309
|
-
Use this page for package installation and boundary orientation. Repository governance, conformance state, target status, and release evidence remain governed from `docs/` and `.ssot/`.
|
|
402
|
+
This README is the package-local distribution entry point for `tigrbl-runtime`. It answers install, usage, API, ownership, and certification-orientation questions for this package. Broader architectural decisions, release status, and cross-package proof chains remain in the repository-level docs and SSOT registry.
|
|
310
403
|
|
|
311
404
|
## License
|
|
312
405
|
|
|
313
|
-
Licensed under the Apache License, Version 2.0. See `LICENSE` and the official [Apache 2.0 license text](https://www.apache.org/licenses/LICENSE-2.0).
|
|
406
|
+
Licensed under the Apache License, Version 2.0. See `LICENSE`, `NOTICE`, and the official [Apache 2.0 license text](https://www.apache.org/licenses/LICENSE-2.0).
|
|
314
407
|
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>tigrbl-runtime</h1>
|
|
3
|
+
<img src="https://raw.githubusercontent.com/swarmauri/swarmauri-sdk/master/assets/tigrbl_full_logo.png" alt="Tigrbl logo" width="140"/>
|
|
4
|
+
<p><strong>Runtime pipeline helpers and execution bridge surfaces for Tigrbl ASGI applications, transports, and operation dispatch.</strong></p>
|
|
5
|
+
<a href="https://pypi.org/project/tigrbl-runtime/"><img src="https://img.shields.io/pypi/v/tigrbl-runtime?label=PyPI" alt="PyPI version for tigrbl-runtime"/></a>
|
|
6
|
+
<a href="https://pypi.org/project/tigrbl-runtime/"><img src="https://static.pepy.tech/badge/tigrbl-runtime" alt="Downloads for tigrbl-runtime"/></a>
|
|
7
|
+
<a href="https://discord.gg/K4YTAPapjR"><img src="https://img.shields.io/badge/Discord-Join%20chat-5865F2?logo=discord&logoColor=white" alt="Discord community for tigrbl-runtime"/></a>
|
|
8
|
+
<a href="https://github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_runtime/README.md"><img src="https://hits.sh/github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_runtime/README.md.svg?label=hits" alt="Repository hits for tigrbl-runtime README"/></a>
|
|
9
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-525252" alt="Apache 2.0 license"/></a>
|
|
10
|
+
<a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-3776ab" alt="Python versions 3.10 | 3.11 | 3.12 | 3.13 | 3.14 for tigrbl-runtime"/></a>
|
|
11
|
+
<a href="https://github.com/tigrbl/tigrbl/blob/master/docs/README.md"><img src="https://img.shields.io/badge/workspace-core-1f6feb" alt="Workspace group for tigrbl-runtime"/></a>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
## What is tigrbl-runtime?
|
|
15
|
+
|
|
16
|
+
Runtime pipeline helpers and execution bridge surfaces for Tigrbl ASGI applications, transports, and operation dispatch.
|
|
17
|
+
|
|
18
|
+
## Why use tigrbl-runtime?
|
|
19
|
+
|
|
20
|
+
Use it when you need this foundational Tigrbl layer directly as a small, focused dependency.
|
|
21
|
+
|
|
22
|
+
## When should I install tigrbl-runtime?
|
|
23
|
+
|
|
24
|
+
Install it for extension packages, package-local tests, or internals that need this boundary without the whole facade.
|
|
25
|
+
|
|
26
|
+
## Who is tigrbl-runtime for?
|
|
27
|
+
|
|
28
|
+
Framework maintainers, extension authors, and advanced users composing Tigrbl from split packages.
|
|
29
|
+
|
|
30
|
+
## Where does tigrbl-runtime fit?
|
|
31
|
+
|
|
32
|
+
`tigrbl-runtime` lives at `pkgs/core/tigrbl_runtime` and serves a focused layer in the split Tigrbl framework.
|
|
33
|
+
|
|
34
|
+
## How does tigrbl-runtime work?
|
|
35
|
+
|
|
36
|
+
It owns a narrow layer in the split workspace and is consumed by higher-level packages through explicit dependencies.
|
|
37
|
+
|
|
38
|
+
## Certification Status
|
|
39
|
+
|
|
40
|
+
- Package status: governed package in the `tigrbl/tigrbl` workspace.
|
|
41
|
+
- Governance source: [SSOT registry](https://github.com/tigrbl/tigrbl/blob/master/.ssot/registry.json).
|
|
42
|
+
- Release evidence: [publish workflow](https://github.com/tigrbl/tigrbl/actions/workflows/publish.yml) validates package builds, tests, GitHub release assets, and PyPI publication for managed packages.
|
|
43
|
+
- Local certification guard: `pkgs/core/tigrbl_tests/tests/unit/test_package_badges_and_notices.py` verifies every package README keeps the Discord badge, Apache 2.0 badge, explicit Python-version badge, `LICENSE`, and `NOTICE`.
|
|
44
|
+
- Scope note: this README documents the package boundary. Runtime feature support remains governed by `.ssot/` entities and the conformance docs linked below.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
uv add tigrbl-runtime
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install tigrbl-runtime
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Surface Coverage
|
|
57
|
+
|
|
58
|
+
| Surface | Value |
|
|
59
|
+
|---|---|
|
|
60
|
+
| PyPI package | [`tigrbl-runtime`](https://pypi.org/project/tigrbl-runtime/) |
|
|
61
|
+
| Repository path | [`pkgs/core/tigrbl_runtime`](https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_runtime) |
|
|
62
|
+
| Python import root | `tigrbl_runtime` |
|
|
63
|
+
| Console scripts | none declared |
|
|
64
|
+
| Entry points | none declared |
|
|
65
|
+
| Optional extras | none declared |
|
|
66
|
+
| Legal files | `LICENSE`, `NOTICE` |
|
|
67
|
+
| Supported Python | `3.10 | 3.11 | 3.12 | 3.13 | 3.14` |
|
|
68
|
+
|
|
69
|
+
## What It Owns
|
|
70
|
+
|
|
71
|
+
`tigrbl-runtime` owns the `foundational framework package` boundary. It should be installed when you need this package's focused responsibility without assuming every other Tigrbl workspace package is present.
|
|
72
|
+
|
|
73
|
+
Implementation orientation:
|
|
74
|
+
- `tigrbl_runtime`: callbacks, channel/, config/, executors/, handle, protocol/, runtime/, transactions, webhooks
|
|
75
|
+
- `tigrbl_runtime/rust/`: deprecated compatibility shims only; Rust execution is unavailable.
|
|
76
|
+
|
|
77
|
+
Runtime authoring BCP:
|
|
78
|
+
- Do use this package for runtime-owned routing, request execution, transport-unit execution, framing atoms, transport channels, transaction helpers, and kernel integration.
|
|
79
|
+
- Do keep handler invocation, transaction progression, error handling, and transport emission aligned with compiled plans.
|
|
80
|
+
- Do not make application route handlers, FastAPI/Starlette objects, direct SQLAlchemy session calls, or ad-hoc engine construction the runtime contract.
|
|
81
|
+
- Do not bypass kernel plans or lifecycle phases when adding REST, JSON-RPC, stream, SSE, WebSocket, or WebTransport behavior.
|
|
82
|
+
- Avoid hiding behavior in transport wrappers that diagnostics and compiled plans cannot inspect.
|
|
83
|
+
|
|
84
|
+
## Public API and Import Surface
|
|
85
|
+
|
|
86
|
+
- Import roots: `tigrbl_runtime`.
|
|
87
|
+
- Public symbols: `Runtime`, `RuntimeBase`.
|
|
88
|
+
- Rust-named symbols live only under `tigrbl_runtime.rust` as deprecated compatibility shims and must not be used for execution.
|
|
89
|
+
- Workspace dependencies: [`tigrbl-typing`](https://pypi.org/project/tigrbl-typing/), [`tigrbl-kernel`](https://pypi.org/project/tigrbl-kernel/), [`tigrbl-atoms`](https://pypi.org/project/tigrbl-atoms/), [`tigrbl-base`](https://pypi.org/project/tigrbl-base/), [`tigrbl-core`](https://pypi.org/project/tigrbl-core/).
|
|
90
|
+
- External runtime dependencies: `numba>=0.61.2`.
|
|
91
|
+
|
|
92
|
+
## Usage Examples
|
|
93
|
+
|
|
94
|
+
### Verify the installed package
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
python -m pip show tigrbl-runtime
|
|
98
|
+
python - <<'PY'
|
|
99
|
+
from importlib.metadata import version
|
|
100
|
+
print(version("tigrbl-runtime"))
|
|
101
|
+
PY
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Import the package boundary
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
import importlib
|
|
108
|
+
|
|
109
|
+
module = importlib.import_module("tigrbl_runtime")
|
|
110
|
+
print(module.__name__)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Import a public symbol
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from tigrbl_runtime import Runtime
|
|
117
|
+
|
|
118
|
+
print(Runtime)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Use with the facade when building applications
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
uv add tigrbl tigrbl-runtime
|
|
125
|
+
python - <<'PY'
|
|
126
|
+
import tigrbl
|
|
127
|
+
print(tigrbl.__name__)
|
|
128
|
+
PY
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## How To Choose This Package
|
|
132
|
+
|
|
133
|
+
Choose `tigrbl-runtime` when the quick-answer table matches your use case. Choose [`tigrbl`](https://pypi.org/project/tigrbl/) instead when you want the full public facade. Choose a lower-level package such as [`tigrbl-core`](https://pypi.org/project/tigrbl-core/), [`tigrbl-base`](https://pypi.org/project/tigrbl-base/), or [`tigrbl-runtime`](https://pypi.org/project/tigrbl-runtime/) when you are building framework extensions or testing a specific internal boundary.
|
|
134
|
+
|
|
135
|
+
## Related Packages
|
|
136
|
+
|
|
137
|
+
- [`tigrbl-typing`](https://pypi.org/project/tigrbl-typing/)
|
|
138
|
+
- [`tigrbl-kernel`](https://pypi.org/project/tigrbl-kernel/)
|
|
139
|
+
- [`tigrbl-atoms`](https://pypi.org/project/tigrbl-atoms/)
|
|
140
|
+
- [`tigrbl-base`](https://pypi.org/project/tigrbl-base/)
|
|
141
|
+
- [`tigrbl-core`](https://pypi.org/project/tigrbl-core/)
|
|
142
|
+
- [`tigrbl`](https://pypi.org/project/tigrbl/)
|
|
143
|
+
|
|
144
|
+
## Documentation Links
|
|
145
|
+
|
|
146
|
+
- [Workspace docs](https://github.com/tigrbl/tigrbl/blob/master/docs/README.md)
|
|
147
|
+
- [Package catalog](https://github.com/tigrbl/tigrbl/blob/master/docs/developer/PACKAGE_CATALOG.md)
|
|
148
|
+
- [Package layout](https://github.com/tigrbl/tigrbl/blob/master/docs/developer/PACKAGE_LAYOUT.md)
|
|
149
|
+
- [Current target](https://github.com/tigrbl/tigrbl/blob/master/docs/conformance/CURRENT_TARGET.md)
|
|
150
|
+
- [Current state](https://github.com/tigrbl/tigrbl/blob/master/docs/conformance/CURRENT_STATE.md)
|
|
151
|
+
- [SSOT registry](https://github.com/tigrbl/tigrbl/blob/master/.ssot/registry.json)
|
|
152
|
+
- [Release workflow](https://github.com/tigrbl/tigrbl/actions/workflows/publish.yml)
|
|
153
|
+
|
|
154
|
+
## Support
|
|
155
|
+
|
|
156
|
+
- Community: [Discord](https://discord.gg/K4YTAPapjR).
|
|
157
|
+
- Issues: [GitHub Issues](https://github.com/tigrbl/tigrbl/issues).
|
|
158
|
+
- Repository: [pkgs/core/tigrbl_runtime](https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_runtime).
|
|
159
|
+
|
|
160
|
+
## Package-local Boundary
|
|
161
|
+
|
|
162
|
+
This README is the package-local distribution entry point for `tigrbl-runtime`. It answers install, usage, API, ownership, and certification-orientation questions for this package. Broader architectural decisions, release status, and cross-package proof chains remain in the repository-level docs and SSOT registry.
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
Licensed under the Apache License, Version 2.0. See `LICENSE`, `NOTICE`, and the official [Apache 2.0 license text](https://www.apache.org/licenses/LICENSE-2.0).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tigrbl-runtime"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.3"
|
|
4
4
|
description = "Runtime pipeline helpers and execution bridge surfaces for Tigrbl ASGI applications, transports, and operation dispatch."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { file = "LICENSE" }
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Public exports for ``tigrbl_runtime`` with lazy loading."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from importlib import import_module
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
_LAZY_EXPORTS = {
|
|
9
|
+
"Runtime": "runtime",
|
|
10
|
+
"RuntimeBase": "runtime",
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
*_LAZY_EXPORTS,
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def __getattr__(name: str) -> Any:
|
|
19
|
+
module_name = _LAZY_EXPORTS.get(name)
|
|
20
|
+
if module_name is None:
|
|
21
|
+
raise AttributeError(name)
|
|
22
|
+
module = import_module(f"{__name__}.{module_name}")
|
|
23
|
+
value = getattr(module, name)
|
|
24
|
+
globals()[name] = value
|
|
25
|
+
return value
|
|
@@ -7,7 +7,7 @@ from collections.abc import Callable, Mapping
|
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def
|
|
10
|
+
def compile_callback_delivery_plan(
|
|
11
11
|
*,
|
|
12
12
|
event: str,
|
|
13
13
|
endpoint: str,
|
|
@@ -19,11 +19,11 @@ def compile_webhook_delivery_plan(
|
|
|
19
19
|
"endpoint": endpoint,
|
|
20
20
|
"signing": {"algorithm": "hmac-sha256", "secret_ref": signing_secret_ref},
|
|
21
21
|
"retry": dict(retry or {"max_attempts": 1}),
|
|
22
|
-
"completion_subevent": "
|
|
22
|
+
"completion_subevent": "callback.delivery.emit_complete",
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
def
|
|
26
|
+
def build_callback_payload(
|
|
27
27
|
*, event: str, data: Mapping[str, Any], idempotency_key: str
|
|
28
28
|
) -> dict[str, object]:
|
|
29
29
|
return {
|
|
@@ -33,13 +33,13 @@ def build_webhook_payload(
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
def
|
|
36
|
+
def sign_callback_payload(payload: Mapping[str, Any], *, secret: str) -> dict[str, object]:
|
|
37
37
|
canonical = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
|
38
38
|
digest = hmac.new(secret.encode("utf-8"), canonical, hashlib.sha256).hexdigest()
|
|
39
39
|
return {"payload": dict(payload), "signature": f"sha256={digest}"}
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
def
|
|
42
|
+
def deliver_callback(
|
|
43
43
|
payload: Mapping[str, Any],
|
|
44
44
|
*,
|
|
45
45
|
send: Callable[[Mapping[str, Any]], Mapping[str, Any]],
|
|
@@ -54,7 +54,7 @@ def deliver_webhook(
|
|
|
54
54
|
for attempt in range(1, max_attempts + 1):
|
|
55
55
|
attempts = attempt
|
|
56
56
|
if trace and attempt == 1:
|
|
57
|
-
trace("
|
|
57
|
+
trace("callback.delivery.emit")
|
|
58
58
|
try:
|
|
59
59
|
response = send(payload)
|
|
60
60
|
except Exception as exc:
|
|
@@ -65,7 +65,7 @@ def deliver_webhook(
|
|
|
65
65
|
"attempts": attempts,
|
|
66
66
|
"completed": False,
|
|
67
67
|
"error_ctx": {
|
|
68
|
-
"subevent": "
|
|
68
|
+
"subevent": "callback.delivery.emit",
|
|
69
69
|
"message": str(exc),
|
|
70
70
|
},
|
|
71
71
|
}
|
|
@@ -73,7 +73,7 @@ def deliver_webhook(
|
|
|
73
73
|
status_code = int(response.get("status_code", 0))
|
|
74
74
|
if 200 <= status_code < 300:
|
|
75
75
|
if trace:
|
|
76
|
-
trace("
|
|
76
|
+
trace("callback.delivery.emit_complete")
|
|
77
77
|
return {
|
|
78
78
|
"status": "delivered",
|
|
79
79
|
"attempts": attempts,
|
|
@@ -109,8 +109,8 @@ def _is_transient(status_code: int) -> bool:
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
__all__ = [
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
112
|
+
"build_callback_payload",
|
|
113
|
+
"compile_callback_delivery_plan",
|
|
114
|
+
"deliver_callback",
|
|
115
|
+
"sign_callback_payload",
|
|
116
116
|
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from tigrbl_atoms.atoms.transport.asgi_channel import (
|
|
6
|
+
complete_channel_state as _complete_channel_state,
|
|
7
|
+
)
|
|
8
|
+
from tigrbl_typing.channel import OpChannel
|
|
9
|
+
|
|
10
|
+
from ._asgi_scope import build_asgi_channel
|
|
11
|
+
from ._asgi_send import send_transport_via_channel
|
|
12
|
+
from .websocket import RuntimeWebSocket
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def channel_senders():
|
|
16
|
+
from tigrbl_atoms.atoms.egress.asgi_send import _send_json
|
|
17
|
+
|
|
18
|
+
return _send_json, send_transport_via_channel
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def complete_channel(env: Any, ctx: Any) -> None:
|
|
22
|
+
channel = ctx.get("channel")
|
|
23
|
+
if channel is None:
|
|
24
|
+
channel = build_asgi_channel(env)
|
|
25
|
+
ctx["channel"] = channel
|
|
26
|
+
if isinstance(getattr(channel, "state", None), dict):
|
|
27
|
+
_complete_channel_state(channel.state)
|
|
28
|
+
ctx["transport_completed"] = True
|
|
29
|
+
ctx["current_phase"] = "POST_EMIT"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def websocket_adapter(channel: OpChannel) -> RuntimeWebSocket:
|
|
33
|
+
return RuntimeWebSocket(channel)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any, Mapping
|
|
5
|
+
|
|
6
|
+
from tigrbl_kernel.channel_taxonomy import normalize_exchange
|
|
7
|
+
from tigrbl_typing.channel import OpChannel
|
|
8
|
+
|
|
9
|
+
from ._asgi_jsonrpc import _resolve_jsonrpc_endpoint
|
|
10
|
+
from ._asgi_receive import _receive_session_message
|
|
11
|
+
from ._asgi_scope import _scheme, build_asgi_channel
|
|
12
|
+
from ._asgi_webtransport import (
|
|
13
|
+
_receive_webtransport_session_messages,
|
|
14
|
+
_webtransport_scope_state,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async def prepare_channel_context(env: Any, ctx: Any) -> OpChannel:
|
|
19
|
+
temp = ctx.get("temp")
|
|
20
|
+
if not isinstance(temp, dict):
|
|
21
|
+
ctx["temp"] = {}
|
|
22
|
+
temp = ctx["temp"]
|
|
23
|
+
|
|
24
|
+
route = temp.setdefault("route", {})
|
|
25
|
+
exchange = str(
|
|
26
|
+
route.get("exchange")
|
|
27
|
+
or getattr(ctx, "tigrbl_exchange", None)
|
|
28
|
+
or "request_response"
|
|
29
|
+
)
|
|
30
|
+
exchange = normalize_exchange(exchange)
|
|
31
|
+
protocol = str(route.get("protocol") or _scheme(getattr(env, "scope", {}) or {}))
|
|
32
|
+
framing = route.get("framing")
|
|
33
|
+
channel = build_asgi_channel(
|
|
34
|
+
env,
|
|
35
|
+
exchange=exchange,
|
|
36
|
+
protocol=protocol or None,
|
|
37
|
+
framing=str(framing) if isinstance(framing, str) else None,
|
|
38
|
+
)
|
|
39
|
+
ctx["channel"] = channel
|
|
40
|
+
ctx["path"] = channel.path
|
|
41
|
+
ctx["method"] = channel.method or channel.protocol.upper()
|
|
42
|
+
|
|
43
|
+
dispatch = temp.setdefault("dispatch", {})
|
|
44
|
+
if isinstance(dispatch, dict):
|
|
45
|
+
dispatch.setdefault("channel_protocol", channel.protocol)
|
|
46
|
+
dispatch.setdefault("channel_selector", channel.selector)
|
|
47
|
+
dispatch.setdefault("path_params", dict(channel.path_params))
|
|
48
|
+
endpoint = _resolve_jsonrpc_endpoint(ctx, channel)
|
|
49
|
+
if endpoint:
|
|
50
|
+
dispatch.setdefault("endpoint", endpoint)
|
|
51
|
+
|
|
52
|
+
scope = getattr(env, "scope", {}) or {}
|
|
53
|
+
scope_type = str(scope.get("type") or "http")
|
|
54
|
+
if scope_type == "webtransport":
|
|
55
|
+
await _receive_webtransport_session_messages(env, channel, ctx)
|
|
56
|
+
wt_state = _webtransport_scope_state(env)
|
|
57
|
+
trace = wt_state.get("trace")
|
|
58
|
+
if isinstance(trace, list):
|
|
59
|
+
ctx["webtransport_trace"] = trace
|
|
60
|
+
channel.state["webtransport_trace"] = trace
|
|
61
|
+
hook_trace = wt_state.get("hook_trace")
|
|
62
|
+
if isinstance(hook_trace, list):
|
|
63
|
+
ctx["webtransport_hook_trace"] = hook_trace
|
|
64
|
+
channel.state["webtransport_hook_trace"] = hook_trace
|
|
65
|
+
route.setdefault("protocol", dispatch.get("binding_protocol"))
|
|
66
|
+
route.setdefault("selector", channel.path)
|
|
67
|
+
route.setdefault("path_params", dict(channel.path_params))
|
|
68
|
+
route.setdefault("endpoint", dispatch.get("endpoint"))
|
|
69
|
+
elif scope_type == "websocket":
|
|
70
|
+
await _receive_session_message(
|
|
71
|
+
env,
|
|
72
|
+
channel,
|
|
73
|
+
ctx,
|
|
74
|
+
connect_type="websocket.connect",
|
|
75
|
+
receive_type="websocket.receive",
|
|
76
|
+
disconnect_type="websocket.disconnect",
|
|
77
|
+
eager_payload_after_connect=False,
|
|
78
|
+
)
|
|
79
|
+
message = ctx.get("channel_message")
|
|
80
|
+
if isinstance(message, Mapping) and message.get("text") is not None:
|
|
81
|
+
try:
|
|
82
|
+
parsed = json.loads(str(message.get("text")))
|
|
83
|
+
except Exception:
|
|
84
|
+
parsed = None
|
|
85
|
+
if isinstance(parsed, Mapping) and parsed.get("jsonrpc") == "2.0":
|
|
86
|
+
dispatch["binding_protocol"] = (
|
|
87
|
+
"wss.jsonrpc" if channel.protocol == "wss" else "ws.jsonrpc"
|
|
88
|
+
)
|
|
89
|
+
dispatch["rpc"] = dict(parsed)
|
|
90
|
+
dispatch["rpc_method"] = parsed.get("method")
|
|
91
|
+
route.setdefault("protocol", dispatch.get("binding_protocol"))
|
|
92
|
+
route.setdefault("selector", channel.path)
|
|
93
|
+
route.setdefault("path_params", dict(channel.path_params))
|
|
94
|
+
route.setdefault("endpoint", dispatch.get("endpoint"))
|
|
95
|
+
|
|
96
|
+
return channel
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Mapping
|
|
4
|
+
|
|
5
|
+
from tigrbl_core.config.constants import __JSONRPC_DEFAULT_ENDPOINT_MAPPINGS__
|
|
6
|
+
from tigrbl_typing.channel import OpChannel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _normalize_path(path: str) -> str:
|
|
10
|
+
return path.rstrip("/") or "/"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _resolve_jsonrpc_endpoint(ctx: Any, channel: OpChannel) -> str | None:
|
|
14
|
+
if channel.kind != "http" or str(channel.method or "").upper() != "POST":
|
|
15
|
+
return None
|
|
16
|
+
|
|
17
|
+
path = _normalize_path(channel.path)
|
|
18
|
+
route = {}
|
|
19
|
+
temp = ctx.get("temp")
|
|
20
|
+
if isinstance(temp, dict):
|
|
21
|
+
route = temp.setdefault("route", {})
|
|
22
|
+
if isinstance(route, Mapping):
|
|
23
|
+
endpoint = route.get("endpoint")
|
|
24
|
+
if isinstance(endpoint, str) and endpoint:
|
|
25
|
+
return endpoint
|
|
26
|
+
|
|
27
|
+
for owner_key in ("router", "app"):
|
|
28
|
+
owner = ctx.get(owner_key)
|
|
29
|
+
mounts = getattr(owner, "_jsonrpc_endpoint_mounts", None)
|
|
30
|
+
if isinstance(mounts, Mapping):
|
|
31
|
+
endpoint = mounts.get(path) or mounts.get(channel.path)
|
|
32
|
+
if isinstance(endpoint, str) and endpoint:
|
|
33
|
+
return endpoint
|
|
34
|
+
|
|
35
|
+
for endpoint, mapped_path in __JSONRPC_DEFAULT_ENDPOINT_MAPPINGS__.items():
|
|
36
|
+
if path == _normalize_path(mapped_path):
|
|
37
|
+
return endpoint
|
|
38
|
+
return None
|