tigrcorn-contract 0.3.16.dev5__tar.gz → 0.3.16.dev12__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.
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/PKG-INFO +74 -17
- tigrcorn_contract-0.3.16.dev12/README.md +101 -0
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/pyproject.toml +6 -4
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/src/tigrcorn_contract/__init__.py +40 -0
- tigrcorn_contract-0.3.16.dev12/src/tigrcorn_contract/classification.py +209 -0
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/src/tigrcorn_contract/events.py +215 -20
- tigrcorn_contract-0.3.16.dev12/src/tigrcorn_contract/metadata.py +347 -0
- tigrcorn_contract-0.3.16.dev12/src/tigrcorn_contract/projection.py +283 -0
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/src/tigrcorn_contract/scopes.py +8 -0
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/src/tigrcorn_contract.egg-info/PKG-INFO +74 -17
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/src/tigrcorn_contract.egg-info/SOURCES.txt +1 -0
- tigrcorn_contract-0.3.16.dev12/src/tigrcorn_contract.egg-info/requires.txt +3 -0
- tigrcorn_contract-0.3.16.dev5/README.md +0 -46
- tigrcorn_contract-0.3.16.dev5/src/tigrcorn_contract/classification.py +0 -104
- tigrcorn_contract-0.3.16.dev5/src/tigrcorn_contract/metadata.py +0 -206
- tigrcorn_contract-0.3.16.dev5/src/tigrcorn_contract.egg-info/requires.txt +0 -3
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/LICENSE +0 -0
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/setup.cfg +0 -0
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/src/tigrcorn_contract/compat.py +0 -0
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/src/tigrcorn_contract/py.typed +0 -0
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/src/tigrcorn_contract.egg-info/dependency_links.txt +0 -0
- {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/src/tigrcorn_contract.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tigrcorn-contract
|
|
3
|
-
Version: 0.3.16.
|
|
3
|
+
Version: 0.3.16.dev12
|
|
4
4
|
Summary: tigr-asgi-contract adapters and runtime-boundary classification for Tigrcorn ASGI3, WebSocket, and WebTransport surfaces.
|
|
5
5
|
Author-email: Jacob Stewart <jacob@swarmauri.com>
|
|
6
6
|
License: Apache License
|
|
@@ -175,40 +175,52 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
175
175
|
Classifier: Operating System :: OS Independent
|
|
176
176
|
Classifier: Programming Language :: Python :: 3
|
|
177
177
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
178
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
178
179
|
Classifier: Programming Language :: Python :: 3.11
|
|
179
180
|
Classifier: Programming Language :: Python :: 3.12
|
|
180
181
|
Classifier: Programming Language :: Python :: 3.13
|
|
182
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
181
183
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
182
184
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
183
185
|
Classifier: Typing :: Typed
|
|
184
|
-
Requires-Python:
|
|
186
|
+
Requires-Python: <3.15,>=3.10
|
|
185
187
|
Description-Content-Type: text/markdown
|
|
186
188
|
License-File: LICENSE
|
|
187
|
-
Requires-Dist: tigrcorn-core==0.3.16.
|
|
188
|
-
Requires-Dist: tigrcorn-asgi==0.3.16.
|
|
189
|
+
Requires-Dist: tigrcorn-core==0.3.16.dev12
|
|
190
|
+
Requires-Dist: tigrcorn-asgi==0.3.16.dev12
|
|
189
191
|
Requires-Dist: tigr-asgi-contract>=0.3.2
|
|
190
192
|
Dynamic: license-file
|
|
191
193
|
|
|
192
194
|
<div align="center">
|
|
193
195
|
<h1>tigrcorn-contract</h1>
|
|
196
|
+
<img
|
|
197
|
+
src="https://raw.githubusercontent.com/Tigrbl/tigrcorn/master/assets/tigrcorn_logo.png"
|
|
198
|
+
alt="Tigrcorn tiger-unicorn logo"
|
|
199
|
+
width="140"
|
|
200
|
+
/>
|
|
194
201
|
|
|
195
202
|
<p><strong>tigr-asgi-contract adapters and runtime-boundary classification for Tigrcorn ASGI3, WebSocket, and WebTransport surfaces.</strong></p>
|
|
196
203
|
|
|
197
204
|
<a href="https://pypi.org/project/tigrcorn-contract/"><img alt="PyPI version for tigrcorn-contract" src="https://img.shields.io/pypi/v/tigrcorn-contract?label=PyPI"></a>
|
|
198
205
|
<a href="https://pypi.org/project/tigrcorn-contract/"><img alt="tigrcorn-contract package on PyPI" src="https://img.shields.io/badge/package-PyPI-blue"></a>
|
|
206
|
+
<a href="https://pepy.tech/project/tigrcorn-contract"><img alt="Downloads for tigrcorn-contract" src="https://static.pepy.tech/badge/tigrcorn-contract"></a>
|
|
207
|
+
<a href="https://github.com/tigrbl/tigrcorn/blob/master/pkgs/tigrcorn-contract/README.md"><img alt="Hits for tigrcorn-contract README" src="https://hits.sh/github.com/tigrbl/tigrcorn/blob/master/pkgs/tigrcorn-contract/README.md.svg?label=hits"></a>
|
|
199
208
|
<a href="LICENSE"><img alt="Apache 2.0 license" src="https://img.shields.io/badge/license-Apache%202.0-525252"></a>
|
|
200
|
-
<a href="pyproject.toml"><img alt="Python 3.11 supported" src="https://img.shields.io/badge/python-3.11-3776ab"></a>
|
|
201
|
-
<a href="pyproject.toml"><img alt="Python 3.12 supported" src="https://img.shields.io/badge/python-3.12-3776ab"></a>
|
|
202
|
-
<a href="pyproject.toml"><img alt="Python 3.13 supported" src="https://img.shields.io/badge/python-3.13-3776ab"></a>
|
|
203
|
-
<a href="src/tigrcorn_contract/py.typed"><img alt="typed package" src="https://img.shields.io/badge/typed-py.typed-2f7ed8"></a>
|
|
209
|
+
<a href="pyproject.toml"><img alt="Python 3.10 | 3.11 | 3.12 | 3.13 | 3.14 supported" 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"></a>
|
|
204
210
|
<a href="https://pypi.org/project/tigrcorn-contract/"><img alt="contract role package" src="https://img.shields.io/badge/role-contract-0a7f5a"></a>
|
|
205
211
|
</div>
|
|
206
212
|
|
|
213
|
+
<p align="center"><a href="https://github.com/Tigrbl/tigrcorn/blob/master/.ssot/registry.json"><img alt="SSOT governed" src="https://img.shields.io/badge/SSOT-governed-2f6f4e.svg"></a> <a href="https://discord.gg/jzvrbEtTtt"><img alt="Discord" src="https://img.shields.io/badge/Discord-Join%20chat-5865F2?logo=discord&logoColor=white"></a></p>
|
|
214
|
+
|
|
207
215
|
## Install
|
|
208
216
|
|
|
209
|
-
|
|
217
|
+
```bash
|
|
218
|
+
uv add tigrcorn-contract
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
```bash
|
|
210
222
|
pip install tigrcorn-contract
|
|
211
|
-
|
|
223
|
+
```
|
|
212
224
|
|
|
213
225
|
Use the aggregate [tigrcorn](https://pypi.org/project/tigrcorn/) distribution when you want the full ASGI3 Python web server stack. Install <code>tigrcorn-contract</code> directly when you want only this package boundary and its declared dependencies.
|
|
214
226
|
|
|
@@ -216,22 +228,67 @@ Use the aggregate [tigrcorn](https://pypi.org/project/tigrcorn/) distribution wh
|
|
|
216
228
|
|
|
217
229
|
<code>tigrcorn-contract</code> owns native contract app markers, contract scope validation, contract event validation, and boundary classification. Its import package is <code>tigrcorn_contract</code>, and its declared package dependencies are: tigrcorn-core, tigrcorn-asgi, tigr-asgi-contract.
|
|
218
230
|
|
|
219
|
-
This package page is written for developers searching for Tigrcorn ASGI3 server components, Python web server packages, HTTP/3 and QUIC support, WebSocket and WebTransport
|
|
231
|
+
This package page is written for developers searching for Tigrcorn ASGI3 server components, Python web server packages, HTTP/3 and QUIC support, WebSocket and WebTransport-adjacent surfaces, and Apache 2.0 licensed infrastructure.
|
|
232
|
+
|
|
233
|
+
## Why Use This?
|
|
234
|
+
|
|
235
|
+
Use <code>tigrcorn-contract</code> when you want the contract layer as a direct install target instead of the full server bundle. It lets application, operator, or certification workflows depend on this boundary explicitly while keeping the broader Tigrcorn runtime assembled from smaller repo-owned package surfaces.
|
|
236
|
+
|
|
237
|
+
## FAQ
|
|
238
|
+
|
|
239
|
+
### What does this package export?
|
|
240
|
+
|
|
241
|
+
The package exports through the <code>tigrcorn_contract</code> namespace and keeps the root <code>tigrcorn</code> package as the compatibility umbrella.
|
|
242
|
+
|
|
243
|
+
### Which boundary does this package own?
|
|
244
|
+
|
|
245
|
+
It is the package boundary for native contract app markers, contract scope validation, contract event validation, and boundary classification in the Tigrcorn package graph.
|
|
246
|
+
|
|
247
|
+
### What does the contract layer validate?
|
|
248
|
+
|
|
249
|
+
It validates contract scopes, event ordering, endpoint metadata, runtime classification, and WebSocket or WebTransport boundary semantics against the tigr-asgi-contract surface.
|
|
250
|
+
|
|
251
|
+
## Features
|
|
252
|
+
|
|
253
|
+
- Owns native contract app markers, contract scope validation, contract event validation, and boundary classification inside the Tigrcorn split-package architecture.
|
|
254
|
+
- Publishes the <code>tigrcorn_contract</code> import surface for named public helpers and entrypoints.
|
|
255
|
+
- Declared runtime dependencies: tigrcorn-core, tigrcorn-asgi, tigr-asgi-contract.
|
|
256
|
+
- Optional dependency surface: none.
|
|
257
|
+
- Supports Python 3.10, 3.11, 3.12, 3.13, and 3.14.
|
|
220
258
|
|
|
221
259
|
## Use It When
|
|
222
260
|
|
|
223
|
-
Use <code>tigrcorn-contract</code> when you need
|
|
261
|
+
Use <code>tigrcorn-contract</code> when you need contract-level behavior without pulling the entire server stack into the import surface. It is part of Tigrcorn's split-package architecture, so it can be installed independently while remaining linked to the rest of the Tigrcorn package family on PyPI.
|
|
224
262
|
|
|
225
263
|
## Import Surface
|
|
226
264
|
|
|
227
|
-
|
|
228
|
-
import
|
|
265
|
+
```python
|
|
266
|
+
from tigrcorn_contract import contract_scope, validate_scope
|
|
229
267
|
|
|
230
|
-
|
|
231
|
-
|
|
268
|
+
scope = contract_scope("http", path="/")
|
|
269
|
+
print(validate_scope(scope))
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Namespace discovery starts with `import tigrcorn_contract`.
|
|
232
273
|
|
|
233
274
|
The package exposes its supported public surface through the <code>tigrcorn_contract</code> namespace. The root [tigrcorn](https://pypi.org/project/tigrcorn/) package keeps compatibility shims for users who install the full server distribution.
|
|
234
275
|
|
|
276
|
+
## Related Packages
|
|
277
|
+
|
|
278
|
+
- [tigrcorn-core](https://pypi.org/project/tigrcorn-core/)
|
|
279
|
+
- [tigrcorn-asgi](https://pypi.org/project/tigrcorn-asgi/)
|
|
280
|
+
- [tigrcorn](https://pypi.org/project/tigrcorn/)
|
|
281
|
+
|
|
235
282
|
## Package Graph
|
|
236
283
|
|
|
237
|
-
[tigrcorn](https://pypi.org/project/tigrcorn/) | [tigrcorn-
|
|
284
|
+
[tigrcorn-core](https://pypi.org/project/tigrcorn-core/) | [tigrcorn-config](https://pypi.org/project/tigrcorn-config/) | [tigrcorn-http](https://pypi.org/project/tigrcorn-http/) | [tigrcorn-asgi](https://pypi.org/project/tigrcorn-asgi/) | [tigrcorn-contract](https://pypi.org/project/tigrcorn-contract/) | [tigrcorn-transports](https://pypi.org/project/tigrcorn-transports/) | [tigrcorn-security](https://pypi.org/project/tigrcorn-security/) | [tigrcorn-protocols](https://pypi.org/project/tigrcorn-protocols/) | [tigrcorn-static](https://pypi.org/project/tigrcorn-static/) | [tigrcorn-observability](https://pypi.org/project/tigrcorn-observability/) | [tigrcorn-runtime](https://pypi.org/project/tigrcorn-runtime/) | [tigrcorn-compat](https://pypi.org/project/tigrcorn-compat/) | [tigrcorn-certification](https://pypi.org/project/tigrcorn-certification/)
|
|
285
|
+
|
|
286
|
+
## Best Practices
|
|
287
|
+
|
|
288
|
+
- Use this package when you need contract validation or classification rather than embedding that logic in protocol handlers.
|
|
289
|
+
- Keep new WebSocket, WebTransport, and endpoint-metadata semantics grounded in the contract surface here.
|
|
290
|
+
- Update runtime-boundary classification together with any new contract-facing feature rows.
|
|
291
|
+
|
|
292
|
+
## License
|
|
293
|
+
|
|
294
|
+
Apache-2.0
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>tigrcorn-contract</h1>
|
|
3
|
+
<img
|
|
4
|
+
src="https://raw.githubusercontent.com/Tigrbl/tigrcorn/master/assets/tigrcorn_logo.png"
|
|
5
|
+
alt="Tigrcorn tiger-unicorn logo"
|
|
6
|
+
width="140"
|
|
7
|
+
/>
|
|
8
|
+
|
|
9
|
+
<p><strong>tigr-asgi-contract adapters and runtime-boundary classification for Tigrcorn ASGI3, WebSocket, and WebTransport surfaces.</strong></p>
|
|
10
|
+
|
|
11
|
+
<a href="https://pypi.org/project/tigrcorn-contract/"><img alt="PyPI version for tigrcorn-contract" src="https://img.shields.io/pypi/v/tigrcorn-contract?label=PyPI"></a>
|
|
12
|
+
<a href="https://pypi.org/project/tigrcorn-contract/"><img alt="tigrcorn-contract package on PyPI" src="https://img.shields.io/badge/package-PyPI-blue"></a>
|
|
13
|
+
<a href="https://pepy.tech/project/tigrcorn-contract"><img alt="Downloads for tigrcorn-contract" src="https://static.pepy.tech/badge/tigrcorn-contract"></a>
|
|
14
|
+
<a href="https://github.com/tigrbl/tigrcorn/blob/master/pkgs/tigrcorn-contract/README.md"><img alt="Hits for tigrcorn-contract README" src="https://hits.sh/github.com/tigrbl/tigrcorn/blob/master/pkgs/tigrcorn-contract/README.md.svg?label=hits"></a>
|
|
15
|
+
<a href="LICENSE"><img alt="Apache 2.0 license" src="https://img.shields.io/badge/license-Apache%202.0-525252"></a>
|
|
16
|
+
<a href="pyproject.toml"><img alt="Python 3.10 | 3.11 | 3.12 | 3.13 | 3.14 supported" 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"></a>
|
|
17
|
+
<a href="https://pypi.org/project/tigrcorn-contract/"><img alt="contract role package" src="https://img.shields.io/badge/role-contract-0a7f5a"></a>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<p align="center"><a href="https://github.com/Tigrbl/tigrcorn/blob/master/.ssot/registry.json"><img alt="SSOT governed" src="https://img.shields.io/badge/SSOT-governed-2f6f4e.svg"></a> <a href="https://discord.gg/jzvrbEtTtt"><img alt="Discord" src="https://img.shields.io/badge/Discord-Join%20chat-5865F2?logo=discord&logoColor=white"></a></p>
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
uv add tigrcorn-contract
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install tigrcorn-contract
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Use the aggregate [tigrcorn](https://pypi.org/project/tigrcorn/) distribution when you want the full ASGI3 Python web server stack. Install <code>tigrcorn-contract</code> directly when you want only this package boundary and its declared dependencies.
|
|
33
|
+
|
|
34
|
+
## What It Owns
|
|
35
|
+
|
|
36
|
+
<code>tigrcorn-contract</code> owns native contract app markers, contract scope validation, contract event validation, and boundary classification. Its import package is <code>tigrcorn_contract</code>, and its declared package dependencies are: tigrcorn-core, tigrcorn-asgi, tigr-asgi-contract.
|
|
37
|
+
|
|
38
|
+
This package page is written for developers searching for Tigrcorn ASGI3 server components, Python web server packages, HTTP/3 and QUIC support, WebSocket and WebTransport-adjacent surfaces, and Apache 2.0 licensed infrastructure.
|
|
39
|
+
|
|
40
|
+
## Why Use This?
|
|
41
|
+
|
|
42
|
+
Use <code>tigrcorn-contract</code> when you want the contract layer as a direct install target instead of the full server bundle. It lets application, operator, or certification workflows depend on this boundary explicitly while keeping the broader Tigrcorn runtime assembled from smaller repo-owned package surfaces.
|
|
43
|
+
|
|
44
|
+
## FAQ
|
|
45
|
+
|
|
46
|
+
### What does this package export?
|
|
47
|
+
|
|
48
|
+
The package exports through the <code>tigrcorn_contract</code> namespace and keeps the root <code>tigrcorn</code> package as the compatibility umbrella.
|
|
49
|
+
|
|
50
|
+
### Which boundary does this package own?
|
|
51
|
+
|
|
52
|
+
It is the package boundary for native contract app markers, contract scope validation, contract event validation, and boundary classification in the Tigrcorn package graph.
|
|
53
|
+
|
|
54
|
+
### What does the contract layer validate?
|
|
55
|
+
|
|
56
|
+
It validates contract scopes, event ordering, endpoint metadata, runtime classification, and WebSocket or WebTransport boundary semantics against the tigr-asgi-contract surface.
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
- Owns native contract app markers, contract scope validation, contract event validation, and boundary classification inside the Tigrcorn split-package architecture.
|
|
61
|
+
- Publishes the <code>tigrcorn_contract</code> import surface for named public helpers and entrypoints.
|
|
62
|
+
- Declared runtime dependencies: tigrcorn-core, tigrcorn-asgi, tigr-asgi-contract.
|
|
63
|
+
- Optional dependency surface: none.
|
|
64
|
+
- Supports Python 3.10, 3.11, 3.12, 3.13, and 3.14.
|
|
65
|
+
|
|
66
|
+
## Use It When
|
|
67
|
+
|
|
68
|
+
Use <code>tigrcorn-contract</code> when you need contract-level behavior without pulling the entire server stack into the import surface. It is part of Tigrcorn's split-package architecture, so it can be installed independently while remaining linked to the rest of the Tigrcorn package family on PyPI.
|
|
69
|
+
|
|
70
|
+
## Import Surface
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from tigrcorn_contract import contract_scope, validate_scope
|
|
74
|
+
|
|
75
|
+
scope = contract_scope("http", path="/")
|
|
76
|
+
print(validate_scope(scope))
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Namespace discovery starts with `import tigrcorn_contract`.
|
|
80
|
+
|
|
81
|
+
The package exposes its supported public surface through the <code>tigrcorn_contract</code> namespace. The root [tigrcorn](https://pypi.org/project/tigrcorn/) package keeps compatibility shims for users who install the full server distribution.
|
|
82
|
+
|
|
83
|
+
## Related Packages
|
|
84
|
+
|
|
85
|
+
- [tigrcorn-core](https://pypi.org/project/tigrcorn-core/)
|
|
86
|
+
- [tigrcorn-asgi](https://pypi.org/project/tigrcorn-asgi/)
|
|
87
|
+
- [tigrcorn](https://pypi.org/project/tigrcorn/)
|
|
88
|
+
|
|
89
|
+
## Package Graph
|
|
90
|
+
|
|
91
|
+
[tigrcorn-core](https://pypi.org/project/tigrcorn-core/) | [tigrcorn-config](https://pypi.org/project/tigrcorn-config/) | [tigrcorn-http](https://pypi.org/project/tigrcorn-http/) | [tigrcorn-asgi](https://pypi.org/project/tigrcorn-asgi/) | [tigrcorn-contract](https://pypi.org/project/tigrcorn-contract/) | [tigrcorn-transports](https://pypi.org/project/tigrcorn-transports/) | [tigrcorn-security](https://pypi.org/project/tigrcorn-security/) | [tigrcorn-protocols](https://pypi.org/project/tigrcorn-protocols/) | [tigrcorn-static](https://pypi.org/project/tigrcorn-static/) | [tigrcorn-observability](https://pypi.org/project/tigrcorn-observability/) | [tigrcorn-runtime](https://pypi.org/project/tigrcorn-runtime/) | [tigrcorn-compat](https://pypi.org/project/tigrcorn-compat/) | [tigrcorn-certification](https://pypi.org/project/tigrcorn-certification/)
|
|
92
|
+
|
|
93
|
+
## Best Practices
|
|
94
|
+
|
|
95
|
+
- Use this package when you need contract validation or classification rather than embedding that logic in protocol handlers.
|
|
96
|
+
- Keep new WebSocket, WebTransport, and endpoint-metadata semantics grounded in the contract surface here.
|
|
97
|
+
- Update runtime-boundary classification together with any new contract-facing feature rows.
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
Apache-2.0
|
|
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tigrcorn-contract"
|
|
7
|
-
version = "0.3.16.
|
|
7
|
+
version = "0.3.16.dev12"
|
|
8
8
|
description = "tigr-asgi-contract adapters and runtime-boundary classification for Tigrcorn ASGI3, WebSocket, and WebTransport surfaces."
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.
|
|
10
|
+
requires-python = ">=3.10,<3.15"
|
|
11
11
|
license = {file = "LICENSE"}
|
|
12
12
|
authors = [{name = "Jacob Stewart", email = "jacob@swarmauri.com"}]
|
|
13
13
|
keywords = ["tigrcorn", "tigr-asgi-contract", "asgi-contract", "runtime-contract", "webtransport", "asgi3"]
|
|
@@ -19,16 +19,18 @@ classifiers = [
|
|
|
19
19
|
"Operating System :: OS Independent",
|
|
20
20
|
"Programming Language :: Python :: 3",
|
|
21
21
|
"Programming Language :: Python :: 3 :: Only",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
22
23
|
"Programming Language :: Python :: 3.11",
|
|
23
24
|
"Programming Language :: Python :: 3.12",
|
|
24
25
|
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Programming Language :: Python :: 3.14",
|
|
25
27
|
"Topic :: Internet :: WWW/HTTP",
|
|
26
28
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
29
|
"Typing :: Typed",
|
|
28
30
|
]
|
|
29
31
|
dependencies = [
|
|
30
|
-
"tigrcorn-core==0.3.16.
|
|
31
|
-
"tigrcorn-asgi==0.3.16.
|
|
32
|
+
"tigrcorn-core==0.3.16.dev12",
|
|
33
|
+
"tigrcorn-asgi==0.3.16.dev12",
|
|
32
34
|
"tigr-asgi-contract>=0.3.2",
|
|
33
35
|
]
|
|
34
36
|
|
{tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev12}/src/tigrcorn_contract/__init__.py
RENAMED
|
@@ -3,8 +3,13 @@ from __future__ import annotations
|
|
|
3
3
|
from .classification import (
|
|
4
4
|
BindingClassification,
|
|
5
5
|
FamilyCapability,
|
|
6
|
+
ProductSurfaceStatus,
|
|
6
7
|
classify_binding,
|
|
7
8
|
family_capability,
|
|
9
|
+
product_surface_excluded,
|
|
10
|
+
product_surface_status,
|
|
11
|
+
require_product_boundary_exclusion,
|
|
12
|
+
require_product_runtime_available,
|
|
8
13
|
runtime_interface_available,
|
|
9
14
|
validate_binding_legality,
|
|
10
15
|
)
|
|
@@ -26,6 +31,8 @@ from .compat import (
|
|
|
26
31
|
from .events import (
|
|
27
32
|
CompletionLevel,
|
|
28
33
|
CompletionStatus,
|
|
34
|
+
GenericDatagramRuntime,
|
|
35
|
+
GenericStreamRuntime,
|
|
29
36
|
datagram_receive,
|
|
30
37
|
datagram_send,
|
|
31
38
|
emit_complete,
|
|
@@ -43,7 +50,9 @@ from .events import (
|
|
|
43
50
|
map_contract_event,
|
|
44
51
|
stream_receive,
|
|
45
52
|
stream_send,
|
|
53
|
+
validate_datagram_event,
|
|
46
54
|
validate_event_order,
|
|
55
|
+
validate_stream_event,
|
|
47
56
|
websocket_accept,
|
|
48
57
|
websocket_close,
|
|
49
58
|
websocket_connect,
|
|
@@ -73,7 +82,19 @@ from .metadata import (
|
|
|
73
82
|
stream_identity,
|
|
74
83
|
transport_identity,
|
|
75
84
|
unit_identity,
|
|
85
|
+
validate_connection_identity,
|
|
76
86
|
validate_endpoint_metadata,
|
|
87
|
+
validate_security_metadata,
|
|
88
|
+
validate_stream_identity,
|
|
89
|
+
)
|
|
90
|
+
from .projection import (
|
|
91
|
+
EventProjection,
|
|
92
|
+
ScopeProjection,
|
|
93
|
+
project_event_classification,
|
|
94
|
+
project_receive_event,
|
|
95
|
+
project_scope_classification,
|
|
96
|
+
project_send_event,
|
|
97
|
+
validate_projected_event,
|
|
77
98
|
)
|
|
78
99
|
from .scopes import SUPPORTED_SCOPE_TYPES, contract_scope, validate_scope
|
|
79
100
|
|
|
@@ -84,10 +105,15 @@ __all__ = [
|
|
|
84
105
|
"ConnectionIdentity",
|
|
85
106
|
"EndpointMetadata",
|
|
86
107
|
"FamilyCapability",
|
|
108
|
+
"GenericDatagramRuntime",
|
|
109
|
+
"GenericStreamRuntime",
|
|
110
|
+
"ProductSurfaceStatus",
|
|
87
111
|
"CompatibilityParityRow",
|
|
88
112
|
"HTTPFeatureContractMap",
|
|
89
113
|
"SUPPORTED_SCOPE_TYPES",
|
|
90
114
|
"SecurityMetadata",
|
|
115
|
+
"EventProjection",
|
|
116
|
+
"ScopeProjection",
|
|
91
117
|
"StreamIdentity",
|
|
92
118
|
"UnitIdentity",
|
|
93
119
|
"alt_svc_contract_map",
|
|
@@ -120,7 +146,15 @@ __all__ = [
|
|
|
120
146
|
"map_contract_event",
|
|
121
147
|
"observability_contract_metadata",
|
|
122
148
|
"proxy_normalization_contract_map",
|
|
149
|
+
"product_surface_status",
|
|
150
|
+
"product_surface_excluded",
|
|
151
|
+
"project_event_classification",
|
|
152
|
+
"project_receive_event",
|
|
153
|
+
"project_scope_classification",
|
|
154
|
+
"project_send_event",
|
|
123
155
|
"require_lossless_metadata",
|
|
156
|
+
"require_product_boundary_exclusion",
|
|
157
|
+
"require_product_runtime_available",
|
|
124
158
|
"runtime_interface_available",
|
|
125
159
|
"security_metadata",
|
|
126
160
|
"static_delivery_contract_map",
|
|
@@ -131,9 +165,15 @@ __all__ = [
|
|
|
131
165
|
"trailers_contract_map",
|
|
132
166
|
"unit_identity",
|
|
133
167
|
"validate_binding_legality",
|
|
168
|
+
"validate_connection_identity",
|
|
169
|
+
"validate_datagram_event",
|
|
134
170
|
"validate_endpoint_metadata",
|
|
135
171
|
"validate_event_order",
|
|
172
|
+
"validate_projected_event",
|
|
173
|
+
"validate_security_metadata",
|
|
136
174
|
"validate_scope",
|
|
175
|
+
"validate_stream_event",
|
|
176
|
+
"validate_stream_identity",
|
|
137
177
|
"websocket_accept",
|
|
138
178
|
"websocket_close",
|
|
139
179
|
"websocket_connect",
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from tigrcorn_core.errors import ConfigError
|
|
7
|
+
|
|
8
|
+
BindingKind = Literal["http", "http.stream", "websocket", "lifespan", "webtransport", "stream", "datagram", "rest", "jsonrpc", "sse"]
|
|
9
|
+
ProductSurfaceKind = Literal[
|
|
10
|
+
"auto",
|
|
11
|
+
"tigr-asgi-contract",
|
|
12
|
+
"asgi3",
|
|
13
|
+
"asgi2",
|
|
14
|
+
"wsgi",
|
|
15
|
+
"rsgi",
|
|
16
|
+
"rest",
|
|
17
|
+
"jsonrpc",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
_SERVER_OWNED_RUNTIMES = {"http", "http.stream", "websocket", "lifespan", "webtransport", "stream", "datagram"}
|
|
21
|
+
_CLASSIFICATION_ONLY = {"rest", "jsonrpc", "sse"}
|
|
22
|
+
_SUPPORTED_APP_INTERFACES = {"auto", "tigr-asgi-contract", "asgi3"}
|
|
23
|
+
_UNSUPPORTED_COMPAT_INTERFACES = {"asgi2", "wsgi", "rsgi"}
|
|
24
|
+
_RUNTIME_EXCLUDED_CLASSIFICATIONS = {"rest", "jsonrpc"}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True, slots=True)
|
|
28
|
+
class BindingClassification:
|
|
29
|
+
kind: BindingKind
|
|
30
|
+
runtime_owned: bool
|
|
31
|
+
classification_only: bool
|
|
32
|
+
dispatch_runtime: str
|
|
33
|
+
scope_type: str
|
|
34
|
+
family: str
|
|
35
|
+
exchange: str
|
|
36
|
+
framing: str | None = None
|
|
37
|
+
allowed_framings: tuple[str, ...] = ()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(frozen=True, slots=True)
|
|
41
|
+
class FamilyCapability:
|
|
42
|
+
family: str
|
|
43
|
+
bindings: tuple[str, ...]
|
|
44
|
+
subevents: tuple[str, ...]
|
|
45
|
+
exchanges: tuple[str, ...]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True, slots=True)
|
|
49
|
+
class ProductSurfaceStatus:
|
|
50
|
+
kind: ProductSurfaceKind
|
|
51
|
+
runtime_available: bool
|
|
52
|
+
classification_only: bool
|
|
53
|
+
compatibility_exclusion: bool
|
|
54
|
+
reason: str
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
_FAMILY_CAPABILITIES = {
|
|
58
|
+
"request": FamilyCapability(
|
|
59
|
+
family="request",
|
|
60
|
+
bindings=("http", "http.stream", "rest", "jsonrpc"),
|
|
61
|
+
subevents=("request.open", "request.body_in", "request.chunk_in", "request.close", "request.disconnect"),
|
|
62
|
+
exchanges=("unary", "server_stream"),
|
|
63
|
+
),
|
|
64
|
+
"session": FamilyCapability(
|
|
65
|
+
family="session",
|
|
66
|
+
bindings=("websocket", "webtransport", "lifespan"),
|
|
67
|
+
subevents=("session.open", "session.accept", "session.ready", "session.heartbeat", "session.close", "session.disconnect"),
|
|
68
|
+
exchanges=("duplex",),
|
|
69
|
+
),
|
|
70
|
+
"message": FamilyCapability(
|
|
71
|
+
family="message",
|
|
72
|
+
bindings=("websocket",),
|
|
73
|
+
subevents=("message.in", "message.decode", "message.handle", "message.out", "message.ack", "message.nack"),
|
|
74
|
+
exchanges=("duplex",),
|
|
75
|
+
),
|
|
76
|
+
"stream": FamilyCapability(
|
|
77
|
+
family="stream",
|
|
78
|
+
bindings=("http.stream", "webtransport", "stream", "sse"),
|
|
79
|
+
subevents=("stream.open", "stream.chunk_in", "stream.chunk_out", "stream.flush", "stream.finalize", "stream.abort", "stream.close"),
|
|
80
|
+
exchanges=("server_stream", "duplex"),
|
|
81
|
+
),
|
|
82
|
+
"datagram": FamilyCapability(
|
|
83
|
+
family="datagram",
|
|
84
|
+
bindings=("webtransport", "datagram"),
|
|
85
|
+
subevents=("datagram.in", "datagram.handle", "datagram.out", "datagram.ack", "datagram.close"),
|
|
86
|
+
exchanges=("duplex",),
|
|
87
|
+
),
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
_BINDING_SHAPES: dict[str, tuple[str, str, str, str | None, tuple[str, ...]]] = {
|
|
91
|
+
"http": ("http", "request", "unary", None, ()),
|
|
92
|
+
"http.stream": ("http", "stream", "server_stream", None, ()),
|
|
93
|
+
"websocket": ("websocket", "message", "duplex", None, ()),
|
|
94
|
+
"lifespan": ("lifespan", "session", "duplex", None, ()),
|
|
95
|
+
"webtransport": ("webtransport", "session", "duplex", None, ()),
|
|
96
|
+
"stream": ("tigrcorn.stream", "stream", "duplex", None, ()),
|
|
97
|
+
"datagram": ("tigrcorn.datagram", "datagram", "duplex", None, ()),
|
|
98
|
+
"rest": ("http", "request", "unary", "json", ("json",)),
|
|
99
|
+
"jsonrpc": ("http", "request", "unary", "jsonrpc", ("jsonrpc",)),
|
|
100
|
+
"sse": ("http", "stream", "server_stream", "sse", ("sse",)),
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def classify_binding(kind: str) -> BindingClassification:
|
|
105
|
+
normalized = kind.strip().lower().replace("_", "-")
|
|
106
|
+
if normalized == "json-rpc":
|
|
107
|
+
normalized = "jsonrpc"
|
|
108
|
+
if normalized not in _SERVER_OWNED_RUNTIMES | _CLASSIFICATION_ONLY:
|
|
109
|
+
raise ConfigError(f"unsupported binding classification: {kind!r}")
|
|
110
|
+
scope_type, family, exchange, framing, allowed_framings = _BINDING_SHAPES[normalized]
|
|
111
|
+
return BindingClassification(
|
|
112
|
+
kind=normalized, # type: ignore[arg-type]
|
|
113
|
+
runtime_owned=normalized in _SERVER_OWNED_RUNTIMES,
|
|
114
|
+
classification_only=normalized in _CLASSIFICATION_ONLY,
|
|
115
|
+
dispatch_runtime="application" if normalized in _CLASSIFICATION_ONLY else "tigrcorn",
|
|
116
|
+
scope_type=scope_type,
|
|
117
|
+
family=family,
|
|
118
|
+
exchange=exchange,
|
|
119
|
+
framing=framing,
|
|
120
|
+
allowed_framings=allowed_framings,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def runtime_interface_available(interface: str) -> bool:
|
|
125
|
+
return product_surface_status(interface).runtime_available
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _normalize_product_surface(value: str) -> ProductSurfaceKind:
|
|
129
|
+
try:
|
|
130
|
+
normalized = value.strip().lower().replace("_", "-")
|
|
131
|
+
except AttributeError as exc:
|
|
132
|
+
raise ConfigError(f"unsupported product surface: {value!r}") from exc
|
|
133
|
+
if normalized == "json-rpc":
|
|
134
|
+
normalized = "jsonrpc"
|
|
135
|
+
if normalized not in _SUPPORTED_APP_INTERFACES | _UNSUPPORTED_COMPAT_INTERFACES | _RUNTIME_EXCLUDED_CLASSIFICATIONS:
|
|
136
|
+
raise ConfigError(f"unsupported product surface: {value!r}")
|
|
137
|
+
return normalized # type: ignore[return-value]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def product_surface_status(surface: str) -> ProductSurfaceStatus:
|
|
141
|
+
normalized = _normalize_product_surface(surface)
|
|
142
|
+
if normalized in _SUPPORTED_APP_INTERFACES:
|
|
143
|
+
return ProductSurfaceStatus(
|
|
144
|
+
kind=normalized,
|
|
145
|
+
runtime_available=True,
|
|
146
|
+
classification_only=False,
|
|
147
|
+
compatibility_exclusion=False,
|
|
148
|
+
reason="supported app interface",
|
|
149
|
+
)
|
|
150
|
+
if normalized in _RUNTIME_EXCLUDED_CLASSIFICATIONS:
|
|
151
|
+
return ProductSurfaceStatus(
|
|
152
|
+
kind=normalized,
|
|
153
|
+
runtime_available=False,
|
|
154
|
+
classification_only=True,
|
|
155
|
+
compatibility_exclusion=False,
|
|
156
|
+
reason="classification-only binding; runtime belongs to the application layer",
|
|
157
|
+
)
|
|
158
|
+
return ProductSurfaceStatus(
|
|
159
|
+
kind=normalized,
|
|
160
|
+
runtime_available=False,
|
|
161
|
+
classification_only=False,
|
|
162
|
+
compatibility_exclusion=True,
|
|
163
|
+
reason="unsupported compatibility interface",
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def require_product_runtime_available(surface: str) -> ProductSurfaceStatus:
|
|
168
|
+
status = product_surface_status(surface)
|
|
169
|
+
if not status.runtime_available:
|
|
170
|
+
raise ConfigError(f"unsupported runtime product surface: {surface!r} ({status.reason})")
|
|
171
|
+
return status
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def product_surface_excluded(surface: str) -> bool:
|
|
175
|
+
return not product_surface_status(surface).runtime_available
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def require_product_boundary_exclusion(surface: str) -> ProductSurfaceStatus:
|
|
179
|
+
status = product_surface_status(surface)
|
|
180
|
+
if status.runtime_available:
|
|
181
|
+
raise ConfigError(f"product surface is supported, not excluded: {surface!r}")
|
|
182
|
+
return status
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def family_capability(family: str) -> FamilyCapability:
|
|
186
|
+
normalized = family.strip().lower()
|
|
187
|
+
try:
|
|
188
|
+
return _FAMILY_CAPABILITIES[normalized]
|
|
189
|
+
except KeyError as exc:
|
|
190
|
+
raise ConfigError(f"unsupported contract family: {family!r}") from exc
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def validate_binding_legality(*, binding: str, family: str, subevent: str | None = None, exchange: str | None = None) -> None:
|
|
194
|
+
normalized_binding = binding.strip().lower().replace("_", "-")
|
|
195
|
+
if normalized_binding == "json-rpc":
|
|
196
|
+
normalized_binding = "jsonrpc"
|
|
197
|
+
classification = classify_binding(normalized_binding)
|
|
198
|
+
normalized_family = family.strip().lower()
|
|
199
|
+
if classification.classification_only and normalized_family != classification.family:
|
|
200
|
+
raise ConfigError(f"binding {binding!r} is illegal for family {family!r}")
|
|
201
|
+
capability = family_capability(family)
|
|
202
|
+
if normalized_binding not in capability.bindings:
|
|
203
|
+
raise ConfigError(f"binding {binding!r} is illegal for family {family!r}")
|
|
204
|
+
if subevent is not None and subevent not in capability.subevents and not subevent.endswith(".emit_complete"):
|
|
205
|
+
raise ConfigError(f"subevent {subevent!r} is illegal for family {family!r}")
|
|
206
|
+
if classification.classification_only and exchange is not None and exchange != classification.exchange:
|
|
207
|
+
raise ConfigError(f"exchange {exchange!r} is illegal for binding {binding!r}")
|
|
208
|
+
if exchange is not None and exchange not in capability.exchanges:
|
|
209
|
+
raise ConfigError(f"exchange {exchange!r} is illegal for family {family!r}")
|