simple-module-hosting 0.0.14__tar.gz → 0.0.15__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.
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/PKG-INFO +3 -3
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/pyproject.toml +3 -3
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/_observability.py +12 -4
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/logging.py +3 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_logging.py +31 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/.gitignore +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/LICENSE +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/README.md +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/__init__.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/__main__.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/_error_handlers.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/_host_services.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/_hydrate_step.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/_inertia_setup.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/_inertia_shared.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/_phase_helpers.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/app_builder.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/bootstrap_settings.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/health.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/host_cli.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/host_settings.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/i18n_deps.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/i18n_manifest.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/i18n_middleware.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/inertia_deps.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/inertia_utils.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/manifest.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/middleware.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/migrations.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/permissions.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/py.typed +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/redirects.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/settings.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_app.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_check_migrations.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_health.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_host_cli.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_hosting_permissions.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_i18n_manifest.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_inertia_i18n_shared_props.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_lifespan_order.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_locale_middleware.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_manifest.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_middleware_order.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_redirects.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_session_cookie_security.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_settings_i18n.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_settings_secrets.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_strict_discovery_wiring.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_tenant_middleware.py +0 -0
- {simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_translator_dep.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simple_module_hosting
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.15
|
|
4
4
|
Summary: FastAPI + Inertia.js host runtime for simple_module — app_builder, middleware stack, CLI (sm / simple-module), scaffolding
|
|
5
5
|
Project-URL: Homepage, https://github.com/antosubash/simple_module_python
|
|
6
6
|
Project-URL: Repository, https://github.com/antosubash/simple_module_python
|
|
@@ -26,8 +26,8 @@ Requires-Dist: fastapi-inertia>=1.0
|
|
|
26
26
|
Requires-Dist: fastapi>=0.115
|
|
27
27
|
Requires-Dist: httpx>=0.27
|
|
28
28
|
Requires-Dist: jinja2>=3.1
|
|
29
|
-
Requires-Dist: simple-module-core==0.0.
|
|
30
|
-
Requires-Dist: simple-module-db==0.0.
|
|
29
|
+
Requires-Dist: simple-module-core==0.0.15
|
|
30
|
+
Requires-Dist: simple-module-db==0.0.15
|
|
31
31
|
Requires-Dist: starlette>=0.44
|
|
32
32
|
Requires-Dist: tomlkit>=0.13
|
|
33
33
|
Requires-Dist: uvicorn[standard]>=0.34
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "simple_module_hosting"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.15"
|
|
4
4
|
description = "FastAPI + Inertia.js host runtime for simple_module — app_builder, middleware stack, CLI (sm / simple-module), scaffolding"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -26,8 +26,8 @@ dependencies = [
|
|
|
26
26
|
"fastapi-inertia>=1.0",
|
|
27
27
|
"httpx>=0.27",
|
|
28
28
|
"jinja2>=3.1",
|
|
29
|
-
"simple_module_core==0.0.
|
|
30
|
-
"simple_module_db==0.0.
|
|
29
|
+
"simple_module_core==0.0.15",
|
|
30
|
+
"simple_module_db==0.0.15",
|
|
31
31
|
"starlette>=0.44",
|
|
32
32
|
"tomlkit>=0.13",
|
|
33
33
|
"uvicorn[standard]>=0.34",
|
|
@@ -26,10 +26,16 @@ _QUIET_PREFIXES = ("/health", "/static/")
|
|
|
26
26
|
class CorrelationIdMiddleware:
|
|
27
27
|
"""Generate or propagate a correlation ID for every request.
|
|
28
28
|
|
|
29
|
-
Reads the incoming ``X-Correlation-ID`` header (or generates a UUID4) and
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
Reads the incoming ``X-Correlation-ID`` header (or generates a UUID4) and:
|
|
30
|
+
|
|
31
|
+
* stores it in the ``simple_module_hosting.logging.correlation_id``
|
|
32
|
+
ContextVar so the stdlib logging filter (or a user-supplied structlog
|
|
33
|
+
processor — see ``docs/framework/middleware.md``) picks it up with no
|
|
34
|
+
per-handler plumbing;
|
|
35
|
+
* exposes it on ``request.state.correlation_id`` for handlers that
|
|
36
|
+
prefer the request object over the contextvar;
|
|
37
|
+
* echoes the value back as the ``X-Correlation-ID`` response header so
|
|
38
|
+
clients can cross-reference their request with server-side logs.
|
|
33
39
|
"""
|
|
34
40
|
|
|
35
41
|
HEADER = "X-Correlation-ID"
|
|
@@ -43,6 +49,8 @@ class CorrelationIdMiddleware:
|
|
|
43
49
|
return
|
|
44
50
|
|
|
45
51
|
cid = Headers(scope=scope).get(self.HEADER) or uuid.uuid4().hex
|
|
52
|
+
# Skip allocating a Request wrapper — downstream Request(scope).state reads this same dict.
|
|
53
|
+
scope.setdefault("state", {})["correlation_id"] = cid
|
|
46
54
|
|
|
47
55
|
async def send_with_header(message: Message) -> None:
|
|
48
56
|
if message["type"] == _MSG_RESPONSE_START:
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
7
8
|
|
|
8
9
|
import httpx
|
|
9
10
|
from simple_module_hosting.logging import (
|
|
@@ -12,6 +13,13 @@ from simple_module_hosting.logging import (
|
|
|
12
13
|
correlation_id,
|
|
13
14
|
setup_logging,
|
|
14
15
|
)
|
|
16
|
+
from simple_module_hosting.middleware import CorrelationIdMiddleware
|
|
17
|
+
from starlette.applications import Starlette
|
|
18
|
+
from starlette.responses import JSONResponse
|
|
19
|
+
from starlette.routing import Route
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from starlette.requests import Request
|
|
15
23
|
|
|
16
24
|
# ── JsonFormatter ──────────────────────────────────────────────────────
|
|
17
25
|
|
|
@@ -174,6 +182,29 @@ class TestCorrelationIdMiddleware:
|
|
|
174
182
|
r2 = await client.get("/health")
|
|
175
183
|
assert r1.headers["x-correlation-id"] != r2.headers["x-correlation-id"]
|
|
176
184
|
|
|
185
|
+
async def test_state_contextvar_and_header_agree(self):
|
|
186
|
+
# Background tasks read the ContextVar; handlers read request.state;
|
|
187
|
+
# clients read the response header — all three must agree per request.
|
|
188
|
+
async def echo(request: Request) -> JSONResponse:
|
|
189
|
+
return JSONResponse(
|
|
190
|
+
{
|
|
191
|
+
"state": request.state.correlation_id,
|
|
192
|
+
"contextvar": correlation_id.get(""),
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
app = Starlette(routes=[Route("/echo", echo)])
|
|
197
|
+
app.add_middleware(CorrelationIdMiddleware)
|
|
198
|
+
|
|
199
|
+
transport = httpx.ASGITransport(app=app)
|
|
200
|
+
async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as c:
|
|
201
|
+
resp = await c.get("/echo", headers={CorrelationIdMiddleware.HEADER: "trace-xyz"})
|
|
202
|
+
|
|
203
|
+
assert resp.headers[CorrelationIdMiddleware.HEADER] == "trace-xyz"
|
|
204
|
+
body = resp.json()
|
|
205
|
+
assert body["state"] == "trace-xyz"
|
|
206
|
+
assert body["contextvar"] == "trace-xyz"
|
|
207
|
+
|
|
177
208
|
|
|
178
209
|
# ── Request logging middleware (integration) ────────────────────────────
|
|
179
210
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/__init__.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/_hydrate_step.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/app_builder.py
RENAMED
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/health.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/host_cli.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/host_settings.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/i18n_deps.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/i18n_manifest.py
RENAMED
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/inertia_deps.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/inertia_utils.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/manifest.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/middleware.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/migrations.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/permissions.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/py.typed
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/redirects.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/simple_module_hosting/settings.py
RENAMED
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_check_migrations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_hosting_permissions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_locale_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_middleware_order.py
RENAMED
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_session_cookie_security.py
RENAMED
|
File without changes
|
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_settings_secrets.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_strict_discovery_wiring.py
RENAMED
|
File without changes
|
{simple_module_hosting-0.0.14 → simple_module_hosting-0.0.15}/tests/test_tenant_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|