xtr-http-kernel 4.0.4__tar.gz → 4.1.0__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.
Files changed (99) hide show
  1. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/PKG-INFO +28 -31
  2. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/README.md +26 -22
  3. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/pyproject.toml +3 -11
  4. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/pyproject.toml.orig +3 -15
  5. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/.agents/skills/xtr-http-kernel/SKILL.md +8 -8
  6. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/.agents/skills/xtr-http-kernel/references/rate-limits.md +2 -2
  7. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bundle/http_kernel_bundle.py +4 -3
  8. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event_listener/__init__.py +2 -2
  9. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event_listener/log_unit_listener.py +2 -2
  10. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event_listener/request_id_listener.py +4 -4
  11. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/rate_limiter/__init__.py +2 -2
  12. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/LICENSE +0 -0
  13. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/.agents/skills/xtr-http-kernel/references/configure.md +0 -0
  14. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/.agents/skills/xtr-http-kernel/references/listeners.md +0 -0
  15. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/.agents/skills/xtr-http-kernel/references/routing.md +0 -0
  16. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/__init__.py +0 -0
  17. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/_kernel_middleware.py +0 -0
  18. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/_route_contexts.py +0 -0
  19. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/_route_mount.py +0 -0
  20. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/_state.py +0 -0
  21. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bridge/__init__.py +0 -0
  22. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bridge/_headers.py +0 -0
  23. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bridge/_scope_uri.py +0 -0
  24. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bridge/http_message_factory.py +0 -0
  25. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bridge/http_message_factory_interface.py +0 -0
  26. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bridge/response.py +0 -0
  27. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bridge/response_factory.py +0 -0
  28. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bridge/starlette_http_factory.py +0 -0
  29. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bridge/starlette_http_factory_interface.py +0 -0
  30. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bundle/__init__.py +0 -0
  31. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bundle/_messages.py +0 -0
  32. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bundle/_routing.py +0 -0
  33. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bundle/http_kernel_config.py +0 -0
  34. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bundle/request_lifecycle_middleware_factory.py +0 -0
  35. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/bundle/routing_resolver_pass.py +0 -0
  36. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/command/__init__.py +0 -0
  37. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/command/debug_router_command.py +0 -0
  38. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/command/route_description.py +0 -0
  39. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/command/router_command.py +0 -0
  40. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/command/router_match_command.py +0 -0
  41. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event/__init__.py +0 -0
  42. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event/exception_event.py +0 -0
  43. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event/finish_request_event.py +0 -0
  44. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event/request_event.py +0 -0
  45. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event/response_event.py +0 -0
  46. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event/terminate_event.py +0 -0
  47. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event_listener/disallow_robots_indexing_listener.py +0 -0
  48. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event_listener/error_logging_listener.py +0 -0
  49. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/event_listener/rate_limit_headers_listener.py +0 -0
  50. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/__init__.py +0 -0
  51. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/http_kernel_error.py +0 -0
  52. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/invalid_argument_error.py +0 -0
  53. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/invalid_cookie_error.py +0 -0
  54. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/invalid_middleware_priority_error.py +0 -0
  55. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/invalid_rate_limit_error.py +0 -0
  56. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/ranged_response_body_error.py +0 -0
  57. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/response_already_a_message_error.py +0 -0
  58. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/streamed_response_body_error.py +0 -0
  59. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/too_many_requests_error.py +0 -0
  60. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/unknown_rate_limiter_error.py +0 -0
  61. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/exception/unsupported_connection_error.py +0 -0
  62. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/kernel_events.py +0 -0
  63. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/middleware_stack.py +0 -0
  64. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/middleware_tag.py +0 -0
  65. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/py.typed +0 -0
  66. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/rate_limiter/_applied_rate_limit.py +0 -0
  67. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/rate_limiter/rate_limited.py +0 -0
  68. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/recipe/__init__.py +0 -0
  69. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/recipe/manifest.toml +0 -0
  70. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/request_lifecycle_middleware.py +0 -0
  71. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/__init__.py +0 -0
  72. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/alias.py +0 -0
  73. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/alias_deprecation.py +0 -0
  74. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/decorator/__init__.py +0 -0
  75. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/decorator/as_route_loader.py +0 -0
  76. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/decorator/as_routes.py +0 -0
  77. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/decorator/route_loader_marker.py +0 -0
  78. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/exception/__init__.py +0 -0
  79. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/exception/invalid_argument_error.py +0 -0
  80. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/exception/route_circular_reference_error.py +0 -0
  81. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/exception/route_conflict_error.py +0 -0
  82. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/exception/routing_error.py +0 -0
  83. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/loader/__init__.py +0 -0
  84. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/loader/configurator/__init__.py +0 -0
  85. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/loader/configurator/_step_interface.py +0 -0
  86. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/loader/configurator/alias_configurator.py +0 -0
  87. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/loader/configurator/collection_configurator.py +0 -0
  88. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/loader/configurator/import_configurator.py +0 -0
  89. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/loader/configurator/route_configurator.py +0 -0
  90. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/loader/configurator/routing_configurator.py +0 -0
  91. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/loader/routes_file_loader.py +0 -0
  92. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/route.py +0 -0
  93. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/route_collection.py +0 -0
  94. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/route_loader_interface.py +0 -0
  95. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/route_table_parameter.py +0 -0
  96. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/router.py +0 -0
  97. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/routing/router_interface.py +0 -0
  98. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/setup.py +0 -0
  99. {xtr_http_kernel-4.0.4 → xtr_http_kernel-4.1.0}/src/xtr_http_kernel/testing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xtr-http-kernel
3
- Version: 4.0.4
3
+ Version: 4.1.0
4
4
  Summary: Requests turned into responses through events: a request lifecycle for FastAPI applications on the xtr kernel.
5
5
  Keywords: http,kernel,request,lifecycle,events,middleware,fastapi
6
6
  Author: Xterr
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.14
16
16
  Classifier: Typing :: Typed
17
17
  Requires-Dist: fastapi>=0.121.3
18
18
  Requires-Dist: starlette>=0.40
19
- Requires-Dist: xtr-dependency-injection[fastapi]>=4.0,<5
19
+ Requires-Dist: xtr-dependency-injection>=4.0,<5
20
20
  Requires-Dist: xtr-event-dispatcher>=4.0,<5
21
21
  Requires-Dist: xtr-event-dispatcher-contracts>=4.0,<5
22
22
  Requires-Dist: xtr-http-message>=4.0,<5
@@ -25,14 +25,7 @@ Requires-Dist: xtr-logging-contracts>=4.0,<5
25
25
  Requires-Dist: xtr-service-contracts>=4.0,<5
26
26
  Requires-Dist: typing-extensions>=4.4
27
27
  Requires-Dist: python-multipart>=0.0.18
28
- Requires-Dist: xtr-console>=4.0,<5 ; extra == 'console'
29
- Requires-Dist: xtr-logging>=4.0,<5 ; extra == 'logging'
30
- Requires-Dist: xtr-clock>=4.0,<5 ; extra == 'rate-limiter'
31
- Requires-Dist: xtr-rate-limiter[di]>=4.0,<5 ; extra == 'rate-limiter'
32
28
  Requires-Python: >=3.11
33
- Provides-Extra: console
34
- Provides-Extra: logging
35
- Provides-Extra: rate-limiter
36
29
  Description-Content-Type: text/markdown
37
30
 
38
31
  <div align="center">
@@ -75,16 +68,17 @@ Listeners are services, so they come from the container with everything else the
75
68
  ## Install
76
69
 
77
70
  ```sh
78
- uv add xtr-http-kernel # the lifecycle, its bundle and setup
79
- uv add "xtr-http-kernel[logging]" # + the listeners that log
80
- uv add "xtr-http-kernel[console]" # + the commands that report on the router
81
- uv add "xtr-http-kernel[rate-limiter]" # + rate limits on routes, routers and the app
71
+ uv add xtr-http-kernel # the lifecycle, its bundle and setup
72
+ uv add xtr-logging # beside it: the listeners that log
73
+ uv add xtr-console # beside it: the commands that report on the router
74
+ uv add xtr-rate-limiter # beside it: rate limits on routes, routers and the app
82
75
  ```
83
76
 
84
77
  Requires Python 3.11+. The web framework and the container layer come with the package
85
- itself — this *is* the integration — so neither is an extra, and neither is the
86
- [HTTP message contract](../xtr-http-message-contracts) or
87
- [its implementation](../xtr-http-message): the bridge below is made of them.
78
+ itself — this *is* the integration — and so do the
79
+ [HTTP message contract](../xtr-http-message-contracts) and
80
+ [its implementation](../xtr-http-message): the bridge below is made of them. The three
81
+ packages beside it are optional: each is used when it is installed and left alone when not.
88
82
 
89
83
  ## Quick start
90
84
 
@@ -375,9 +369,10 @@ id. The request id settles right after the unit opens, for the same reason.
375
369
 
376
370
  ## Rate limits
377
371
 
378
- With the `rate-limiter` extra, a route, a router or the whole application can be held to a
379
- limiter configured in [xtr-rate-limiter](../xtr-rate-limiter)'s bundle. `RateLimited` is one
380
- declaration, written as a decorator or wherever the framework takes a dependency:
372
+ With [xtr-rate-limiter](../xtr-rate-limiter) installed beside this package, a route, a router or
373
+ the whole application can be held to a limiter configured in that package's bundle.
374
+ `RateLimited` is one declaration, written as a decorator or wherever the framework takes a
375
+ dependency:
381
376
 
382
377
  ```python
383
378
  from fastapi import APIRouter, FastAPI, Request
@@ -454,11 +449,12 @@ Everything adding this package to an application on
454
449
  [xtr-dependency-injection](../xtr-dependency-injection) takes — and, read backwards, what
455
450
  removing it undoes.
456
451
 
457
- - **Install** — `uv add "xtr-http-kernel[logging,console]"`; `logging` brings the listeners
458
- that write to a log, `console` the commands that report on the router, `rate-limiter` the
459
- [rate limits](#rate-limits). None is needed to serve requests. The
452
+ - **Install** — `uv add xtr-http-kernel`; install [xtr-logging](../xtr-logging) beside it for
453
+ the listeners that write to a log, [xtr-console](../xtr-console) for the commands that report
454
+ on the router, [xtr-rate-limiter](../xtr-rate-limiter) for the [rate limits](#rate-limits).
455
+ None is needed to serve requests. The
460
456
  [HTTP message contract](../xtr-http-message-contracts) and
461
- [its implementation](../xtr-http-message) come with the package, not behind an extra: the
457
+ [its implementation](../xtr-http-message) come with the package: the
462
458
  [messages](#the-request-and-the-response-as-messages) are part of what it does. So does the
463
459
  parser a submitted form with files in it is read with: building the request as a message
464
460
  asks the web framework for the form behind every multipart body, and the framework refuses
@@ -470,10 +466,11 @@ removing it undoes.
470
466
  from `xtr_http_kernel.bundle`. Then call `setup(app, kernel)` where the application is built.
471
467
  - **Brings along** — the [event dispatcher](../xtr-event-dispatcher) bundle always, because the
472
468
  lifecycle dispatches through it; the [logging](../xtr-logging), [console](../xtr-console) and
473
- [rate limiter](../xtr-rate-limiter) bundles whenever those packages are *installed* — they are required peers, pulled in and made
474
- active without being listed, and left out silently when the package is not installed. Listing
475
- is not what activates them; installing the extra is. No bundle comes along for the messages:
476
- neither message package ships one, and this bundle registers their services itself.
469
+ [rate limiter](../xtr-rate-limiter) bundles whenever those packages are *installed* — they are
470
+ required peers, pulled in and made active without being listed, and left out silently when the
471
+ package is not installed. Listing is not what activates them; installing the package is. No
472
+ bundle comes along for the messages: neither message package ships one, and this bundle
473
+ registers their services itself.
477
474
  - **Configure** — nothing is required: the zero-config path gives every request a fresh `uuid4`
478
475
  id under `X-Request-Id` — an inbound one is not trusted — no robots header, and the `request`
479
476
  log channel, and makes the request and the response of a request askable as
@@ -485,8 +482,8 @@ removing it undoes.
485
482
  - **Remove** — drop the `setup(app, kernel)` call, drop the `BUNDLES` entry, delete
486
483
  `<app>/config/http_kernel.py` if you wrote one, then `uv remove xtr-http-kernel`.
487
484
  - **Check** — `debug:bundles` shows `http_kernel` as `listed` and `active`, `event_dispatcher`
488
- as `required`, and (with the extras) `logging` and `console` as `required`; `debug:router`
489
- lists the application's routes.
485
+ as `required`, and (when those packages are installed) `logging` and `console` as `required`;
486
+ `debug:router` lists the application's routes.
490
487
 
491
488
  ## Configure
492
489
 
@@ -762,7 +759,7 @@ xtr_http_kernel/
762
759
  ├── request_lifecycle_middleware.py the middleware that dispatches the events
763
760
  ├── middleware_stack.py the ordered chain a bundle contributes to
764
761
  ├── middleware_tag.py MIDDLEWARE_TAG, the tag bundles agree on
765
- ├── rate_limiter/ RateLimited, with the rate-limiter extra
762
+ ├── rate_limiter/ RateLimited, when xtr-rate-limiter is installed
766
763
  ├── routing/ Route, RouteCollection, Router, the loaders and configurators
767
764
  ├── command/ debug:router and router:match
768
765
  ├── exception/ HttpKernelError, the root of everything this library raises
@@ -776,7 +773,7 @@ Developed in the [python-xtr](https://github.com/xterr/python-xtr) monorepo, und
776
773
  repository is a read-only copy, so send issues and pull requests to the monorepo.
777
774
 
778
775
  ```sh
779
- uv sync --all-extras
776
+ uv sync
780
777
  uv run ruff check
781
778
  uv run ruff format --check
782
779
  uv run basedpyright
@@ -38,16 +38,17 @@ Listeners are services, so they come from the container with everything else the
38
38
  ## Install
39
39
 
40
40
  ```sh
41
- uv add xtr-http-kernel # the lifecycle, its bundle and setup
42
- uv add "xtr-http-kernel[logging]" # + the listeners that log
43
- uv add "xtr-http-kernel[console]" # + the commands that report on the router
44
- uv add "xtr-http-kernel[rate-limiter]" # + rate limits on routes, routers and the app
41
+ uv add xtr-http-kernel # the lifecycle, its bundle and setup
42
+ uv add xtr-logging # beside it: the listeners that log
43
+ uv add xtr-console # beside it: the commands that report on the router
44
+ uv add xtr-rate-limiter # beside it: rate limits on routes, routers and the app
45
45
  ```
46
46
 
47
47
  Requires Python 3.11+. The web framework and the container layer come with the package
48
- itself — this *is* the integration — so neither is an extra, and neither is the
49
- [HTTP message contract](../xtr-http-message-contracts) or
50
- [its implementation](../xtr-http-message): the bridge below is made of them.
48
+ itself — this *is* the integration — and so do the
49
+ [HTTP message contract](../xtr-http-message-contracts) and
50
+ [its implementation](../xtr-http-message): the bridge below is made of them. The three
51
+ packages beside it are optional: each is used when it is installed and left alone when not.
51
52
 
52
53
  ## Quick start
53
54
 
@@ -338,9 +339,10 @@ id. The request id settles right after the unit opens, for the same reason.
338
339
 
339
340
  ## Rate limits
340
341
 
341
- With the `rate-limiter` extra, a route, a router or the whole application can be held to a
342
- limiter configured in [xtr-rate-limiter](../xtr-rate-limiter)'s bundle. `RateLimited` is one
343
- declaration, written as a decorator or wherever the framework takes a dependency:
342
+ With [xtr-rate-limiter](../xtr-rate-limiter) installed beside this package, a route, a router or
343
+ the whole application can be held to a limiter configured in that package's bundle.
344
+ `RateLimited` is one declaration, written as a decorator or wherever the framework takes a
345
+ dependency:
344
346
 
345
347
  ```python
346
348
  from fastapi import APIRouter, FastAPI, Request
@@ -417,11 +419,12 @@ Everything adding this package to an application on
417
419
  [xtr-dependency-injection](../xtr-dependency-injection) takes — and, read backwards, what
418
420
  removing it undoes.
419
421
 
420
- - **Install** — `uv add "xtr-http-kernel[logging,console]"`; `logging` brings the listeners
421
- that write to a log, `console` the commands that report on the router, `rate-limiter` the
422
- [rate limits](#rate-limits). None is needed to serve requests. The
422
+ - **Install** — `uv add xtr-http-kernel`; install [xtr-logging](../xtr-logging) beside it for
423
+ the listeners that write to a log, [xtr-console](../xtr-console) for the commands that report
424
+ on the router, [xtr-rate-limiter](../xtr-rate-limiter) for the [rate limits](#rate-limits).
425
+ None is needed to serve requests. The
423
426
  [HTTP message contract](../xtr-http-message-contracts) and
424
- [its implementation](../xtr-http-message) come with the package, not behind an extra: the
427
+ [its implementation](../xtr-http-message) come with the package: the
425
428
  [messages](#the-request-and-the-response-as-messages) are part of what it does. So does the
426
429
  parser a submitted form with files in it is read with: building the request as a message
427
430
  asks the web framework for the form behind every multipart body, and the framework refuses
@@ -433,10 +436,11 @@ removing it undoes.
433
436
  from `xtr_http_kernel.bundle`. Then call `setup(app, kernel)` where the application is built.
434
437
  - **Brings along** — the [event dispatcher](../xtr-event-dispatcher) bundle always, because the
435
438
  lifecycle dispatches through it; the [logging](../xtr-logging), [console](../xtr-console) and
436
- [rate limiter](../xtr-rate-limiter) bundles whenever those packages are *installed* — they are required peers, pulled in and made
437
- active without being listed, and left out silently when the package is not installed. Listing
438
- is not what activates them; installing the extra is. No bundle comes along for the messages:
439
- neither message package ships one, and this bundle registers their services itself.
439
+ [rate limiter](../xtr-rate-limiter) bundles whenever those packages are *installed* — they are
440
+ required peers, pulled in and made active without being listed, and left out silently when the
441
+ package is not installed. Listing is not what activates them; installing the package is. No
442
+ bundle comes along for the messages: neither message package ships one, and this bundle
443
+ registers their services itself.
440
444
  - **Configure** — nothing is required: the zero-config path gives every request a fresh `uuid4`
441
445
  id under `X-Request-Id` — an inbound one is not trusted — no robots header, and the `request`
442
446
  log channel, and makes the request and the response of a request askable as
@@ -448,8 +452,8 @@ removing it undoes.
448
452
  - **Remove** — drop the `setup(app, kernel)` call, drop the `BUNDLES` entry, delete
449
453
  `<app>/config/http_kernel.py` if you wrote one, then `uv remove xtr-http-kernel`.
450
454
  - **Check** — `debug:bundles` shows `http_kernel` as `listed` and `active`, `event_dispatcher`
451
- as `required`, and (with the extras) `logging` and `console` as `required`; `debug:router`
452
- lists the application's routes.
455
+ as `required`, and (when those packages are installed) `logging` and `console` as `required`;
456
+ `debug:router` lists the application's routes.
453
457
 
454
458
  ## Configure
455
459
 
@@ -725,7 +729,7 @@ xtr_http_kernel/
725
729
  ├── request_lifecycle_middleware.py the middleware that dispatches the events
726
730
  ├── middleware_stack.py the ordered chain a bundle contributes to
727
731
  ├── middleware_tag.py MIDDLEWARE_TAG, the tag bundles agree on
728
- ├── rate_limiter/ RateLimited, with the rate-limiter extra
732
+ ├── rate_limiter/ RateLimited, when xtr-rate-limiter is installed
729
733
  ├── routing/ Route, RouteCollection, Router, the loaders and configurators
730
734
  ├── command/ debug:router and router:match
731
735
  ├── exception/ HttpKernelError, the root of everything this library raises
@@ -739,7 +743,7 @@ Developed in the [python-xtr](https://github.com/xterr/python-xtr) monorepo, und
739
743
  repository is a read-only copy, so send issues and pull requests to the monorepo.
740
744
 
741
745
  ```sh
742
- uv sync --all-extras
746
+ uv sync
743
747
  uv run ruff check
744
748
  uv run ruff format --check
745
749
  uv run basedpyright
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xtr-http-kernel"
3
- version = "4.0.4"
3
+ version = "4.1.0"
4
4
  description = "Requests turned into responses through events: a request lifecycle for FastAPI applications on the xtr kernel."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -27,7 +27,7 @@ classifiers = [
27
27
  dependencies = [
28
28
  "fastapi>=0.121.3",
29
29
  "starlette>=0.40",
30
- "xtr-dependency-injection[fastapi]>=4.0,<5",
30
+ "xtr-dependency-injection>=4.0,<5",
31
31
  "xtr-event-dispatcher>=4.0,<5",
32
32
  "xtr-event-dispatcher-contracts>=4.0,<5",
33
33
  "xtr-http-message>=4.0,<5",
@@ -42,14 +42,6 @@ dependencies = [
42
42
  name = "Xterr"
43
43
  email = "me@xterr.dev"
44
44
 
45
- [project.optional-dependencies]
46
- logging = ["xtr-logging>=4.0,<5"]
47
- console = ["xtr-console>=4.0,<5"]
48
- rate-limiter = [
49
- "xtr-clock>=4.0,<5",
50
- "xtr-rate-limiter[di]>=4.0,<5",
51
- ]
52
-
53
45
  [project.entry-points."xtr_dependency_injection.bundles"]
54
46
  http_kernel = "xtr_http_kernel.bundle:HttpKernelBundle"
55
47
 
@@ -67,7 +59,7 @@ dev = [
67
59
  "xtr-logging>=4.0,<5",
68
60
  "xtr-console>=4.0,<5",
69
61
  "xtr-clock>=4.0,<5",
70
- "xtr-rate-limiter[di]>=4.0,<5",
62
+ "xtr-rate-limiter>=4.0,<5",
71
63
  "httpx>=0.27",
72
64
  ]
73
65
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xtr-http-kernel"
3
- version = "4.0.4"
3
+ version = "4.1.0"
4
4
  description = "Requests turned into responses through events: a request lifecycle for FastAPI applications on the xtr kernel."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -26,7 +26,7 @@ dependencies = [
26
26
  "fastapi>=0.121.3",
27
27
  # Imported directly — requests, responses, middleware — not only through fastapi.
28
28
  "starlette>=0.40",
29
- "xtr-dependency-injection[fastapi]>=4.0,<5",
29
+ "xtr-dependency-injection>=4.0,<5",
30
30
  "xtr-event-dispatcher>=4.0,<5",
31
31
  "xtr-event-dispatcher-contracts>=4.0,<5",
32
32
  # The bridge builds messages and is the one place a message meets a route,
@@ -44,18 +44,6 @@ dependencies = [
44
44
  "python-multipart>=0.0.18",
45
45
  ]
46
46
 
47
- [project.optional-dependencies]
48
- logging = [
49
- "xtr-logging>=4.0,<5",
50
- ]
51
- console = [
52
- "xtr-console>=4.0,<5",
53
- ]
54
- rate-limiter = [
55
- "xtr-clock>=4.0,<5",
56
- "xtr-rate-limiter[di]>=4.0,<5",
57
- ]
58
-
59
47
  # Advertises the bundle so debug:bundles can name it when installed but not listed.
60
48
  # Advertising activates nothing: an application lists the bundles it wants.
61
49
  [project.entry-points."xtr_dependency_injection.bundles"]
@@ -76,7 +64,7 @@ dev = [
76
64
  "xtr-logging>=4.0,<5",
77
65
  "xtr-console>=4.0,<5",
78
66
  "xtr-clock>=4.0,<5",
79
- "xtr-rate-limiter[di]>=4.0,<5",
67
+ "xtr-rate-limiter>=4.0,<5",
80
68
  # Requests are driven straight at the application through an ASGI
81
69
  # transport, so the suite never binds a socket.
82
70
  "httpx>=0.27",
@@ -253,8 +253,8 @@ gone caller or a shutdown reached the lifecycle, not that anything is broken.
253
253
 
254
254
  ## Rate limits
255
255
 
256
- With the `rate-limiter` extra, `RateLimited` holds a route, a router or the whole application to
257
- a limiter configured in xtr-rate-limiter's bundle:
256
+ With xtr-rate-limiter installed beside this package, `RateLimited` holds a route, a router or the
257
+ whole application to a limiter configured in xtr-rate-limiter's bundle:
258
258
 
259
259
  ```python
260
260
  from xtr_http_kernel.rate_limiter import RateLimited
@@ -324,15 +324,15 @@ tests serving one application must not run at the same time.
324
324
  `HttpKernelBundle`. That is the steps below a recipe can do; the `setup(app, kernel)` step it
325
325
  prints for you to make.
326
326
 
327
- 1. **Install** `uv add "xtr-http-kernel[logging,console]"`. The extras: `logging` adds the
328
- listeners that write to a log, `console` the router commands, `rate-limiter` the rate limits.
329
- None is needed to serve requests. The two message packages come with it, not behind an extra,
330
- and so does the parser a submitted form with files in it is read with: building the request as
331
- a message asks the framework for the form behind every multipart body.
327
+ 1. **Install** `uv add xtr-http-kernel`. Installed beside it, xtr-logging adds the listeners that
328
+ write to a log, xtr-console the router commands, xtr-rate-limiter the rate limits. None is
329
+ needed to serve requests. The two message packages come with it, and so does the parser a
330
+ submitted form with files in it is read with: building the request as a message asks the
331
+ framework for the form behind every multipart body.
332
332
  2. **Activate** `HttpKernelBundle: {"all": True}` in `BUNDLES` in `<app>/bundles.py`, imported
333
333
  from `xtr_http_kernel.bundle`, then call `setup(app, kernel)` where the application is built.
334
334
  3. **Brings along** the event dispatcher bundle always; the logging, console and rate limiter
335
- bundles whenever those packages are installed. Installing the extra is what activates them,
335
+ bundles whenever those packages are installed. Installing the package is what activates them,
336
336
  not listing.
337
337
  4. **Configure** nothing by default: a fresh `uuid4` id under
338
338
  `X-Request-Id` per request (an inbound one is not trusted), no robots header, the `request`
@@ -1,7 +1,7 @@
1
1
  # Rate limits
2
2
 
3
- Needs the `rate-limiter` extra (`uv add "xtr-http-kernel[rate-limiter]"`) and limiters
4
- configured in [xtr-rate-limiter](https://github.com/xterr/python-xtr-rate-limiter)'s bundle.
3
+ Needs [xtr-rate-limiter](https://github.com/xterr/python-xtr-rate-limiter) installed beside this
4
+ package (`uv add xtr-rate-limiter`) and limiters configured in its bundle.
5
5
  `RateLimited` names one of those limiters; everything else is where you put the declaration.
6
6
 
7
7
  ```python
@@ -162,8 +162,8 @@ class HttpKernelBundle(Bundle[HttpKernelConfig]):
162
162
  .add_tag(LISTENER_TAG, event=ResponseEvent, method="on_response")
163
163
  )
164
164
  if bundle_active(builder, "logging"):
165
- # Needs the optional logging extra, which being here proves installed.
166
- from xtr_http_kernel.event_listener.log_unit_listener import ( # noqa: PLC0415 — optional extra
165
+ # Needs xtr-logging, which the logging bundle being active proves installed.
166
+ from xtr_http_kernel.event_listener.log_unit_listener import ( # noqa: PLC0415 — xtr-logging is optional
167
167
  LogUnitListener,
168
168
  )
169
169
 
@@ -186,7 +186,8 @@ class HttpKernelBundle(Bundle[HttpKernelConfig]):
186
186
  LISTENER_TAG, event=ExceptionEvent, method="on_exception"
187
187
  )
188
188
  if bundle_active(builder, "rate_limiter"):
189
- # Reads what the rate-limit dependency leaves on a request; the extra is installed.
189
+ # Reads what the rate-limit dependency leaves on a request; xtr-rate-limiter is
190
+ # installed, since its bundle is active.
190
191
  from xtr_http_kernel.event_listener.rate_limit_headers_listener import ( # noqa: PLC0415
191
192
  RateLimitHeadersListener,
192
193
  )
@@ -6,8 +6,8 @@ page out of a search index, a unit of work per request. The bundle registers
6
6
  them; outside a container each is an ordinary object to register by hand.
7
7
 
8
8
  :class:`~xtr_http_kernel.event_listener.log_unit_listener.LogUnitListener`
9
- is not re-exported here: it needs the optional logging extra, so it is
10
- imported from its own module by whoever knows that extra is installed.
9
+ is not re-exported here: it needs xtr-logging, which is optional, so it is
10
+ imported from its own module by whoever knows xtr-logging is installed.
11
11
  """
12
12
 
13
13
  from __future__ import annotations
@@ -1,7 +1,7 @@
1
1
  """Each request framed as one unit of work for the logging package.
2
2
 
3
- This module needs the optional logging extra: it is deliberately left out of
4
- the package's eager re-exports, and the bundle registers the listener only
3
+ This module needs xtr-logging, which is optional: it is deliberately left out
4
+ of the package's eager re-exports, and the bundle registers the listener only
5
5
  when the logging bundle is active.
6
6
  """
7
7
 
@@ -18,13 +18,13 @@ __all__ = ["RequestIdListener"]
18
18
  _VALID_REQUEST_ID: Final = re.compile(r"[A-Za-z0-9._-]{1,200}")
19
19
  """What an incoming id may look like before it is worth keeping."""
20
20
 
21
- # Binding the id to the ambient log context is a courtesy to the logging
22
- # package, which is an optional extra: without it there is nothing to bind to
23
- # and the listener still does its job.
21
+ # Binding the id to the ambient log context is a courtesy to xtr-logging,
22
+ # which is optional: without it installed there is nothing to bind to and the
23
+ # listener still does its job.
24
24
  _bind_context: Callable[[Context], None] | None
25
25
  try:
26
26
  from xtr_logging import bind_context as _bind_context
27
- except ImportError: # pragma: no cover — exercised only without the logging extra.
27
+ except ImportError: # pragma: no cover — exercised only without xtr-logging installed.
28
28
  _bind_context = None
29
29
 
30
30
 
@@ -1,7 +1,7 @@
1
1
  """Rate limits on routes, routers and whole applications, through the rate limiter bundle.
2
2
 
3
- Needs the ``rate-limiter`` extra, which brings xtr-rate-limiter; importing
4
- this package without it fails, which is why nothing else here imports it.
3
+ Needs xtr-rate-limiter, installed beside this package; importing this
4
+ package without it fails, which is why nothing else here imports it.
5
5
  """
6
6
 
7
7
  from __future__ import annotations
File without changes