xtr-http-client 5.0.1__tar.gz → 5.2.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 (53) hide show
  1. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/PKG-INFO +15 -13
  2. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/README.md +14 -12
  3. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/pyproject.toml +1 -1
  4. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/pyproject.toml.orig +1 -1
  5. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/.agents/skills/xtr-http-client/SKILL.md +9 -7
  6. xtr_http_client-5.2.0/src/xtr_http_client/recipe/files/config/http_client.py.tmpl +34 -0
  7. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/recipe/manifest.toml +6 -4
  8. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/LICENSE +0 -0
  9. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/__init__.py +0 -0
  10. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/bundle/__init__.py +0 -0
  11. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/bundle/_clients.py +0 -0
  12. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/bundle/client_options_config.py +0 -0
  13. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/bundle/http_client_bundle.py +0 -0
  14. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/bundle/http_client_config.py +0 -0
  15. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/bundle/retry_failed_config.py +0 -0
  16. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/bundle/scoped_client_config.py +0 -0
  17. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/exception/__init__.py +0 -0
  18. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/exception/_http_error_message.py +0 -0
  19. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/exception/logic_error.py +0 -0
  20. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/http_client.py +0 -0
  21. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/http_client_mixin.py +0 -0
  22. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/httpx_http_client.py +0 -0
  23. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/__init__.py +0 -0
  24. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/debug_type.py +0 -0
  25. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/httpx_body.py +0 -0
  26. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/httpx_clients.py +0 -0
  27. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/httpx_errors.py +0 -0
  28. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/httpx_redirect.py +0 -0
  29. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/httpx_request.py +0 -0
  30. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/mock_head.py +0 -0
  31. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/mock_info.py +0 -0
  32. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/option_merge.py +0 -0
  33. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/response_body.py +0 -0
  34. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/retry_count_response.py +0 -0
  35. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/retry_delay.py +0 -0
  36. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/internal/retry_options.py +0 -0
  37. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/mock_http_client.py +0 -0
  38. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/no_private_network_http_client.py +0 -0
  39. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/py.typed +0 -0
  40. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/recipe/__init__.py +0 -0
  41. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/response/__init__.py +0 -0
  42. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/response/http_response.py +0 -0
  43. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/response/httpx_response.py +0 -0
  44. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/response/json_mock_response.py +0 -0
  45. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/response/mock_response.py +0 -0
  46. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/retry/__init__.py +0 -0
  47. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/retry/generic_retry_strategy.py +0 -0
  48. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/retry/retry_context.py +0 -0
  49. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/retry/retry_strategy_interface.py +0 -0
  50. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/retryable_http_client.py +0 -0
  51. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/scoping_http_client.py +0 -0
  52. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/throttling_http_client.py +0 -0
  53. {xtr_http_client-5.0.1 → xtr_http_client-5.2.0}/src/xtr_http_client/traceable_http_client.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xtr-http-client
3
- Version: 5.0.1
3
+ Version: 5.2.0
4
4
  Summary: An async HTTP client behind one interface: typed request options, bodies read on demand, scoped clients, a private-network guard and a mock client for tests.
5
5
  Keywords: http,http-client,request,response,mock,asyncio
6
6
  Author: Xterr
@@ -393,22 +393,24 @@ removing it undoes.
393
393
  - **Install** — `uv add xtr-http-client xtr-dependency-injection`: the bundle needs the container
394
394
  installed beside it, never as an extra. Add `http2` to ask for HTTP/2, and install
395
395
  [xtr-rate-limiter](../xtr-rate-limiter) beside it to pace a client with one of its limiters.
396
- - **Recipe** — `uv run xtr-recipes recipes:sync` does the *Activate* step below: it lists
397
- `HttpClientBundle`. There is no config file, environment or ignore line to write; it prints the
398
- step to name the services the application calls in `config/http_client.py`, which a recipe
399
- cannot make for you (see [xtr-recipes](../xtr-recipes)).
400
- - **Activate** — `HttpClientBundle: {"all": True}` in `BUNDLES` in `<app>/bundles.py`,
396
+ - **Recipe** — `uv run xtr-recipes recipes:sync` does the *Activate* and *Configure* steps below:
397
+ it lists `HttpClientBundle` and writes `<app>/config/packages/http_client.py` with the bundle's
398
+ own defaults. There is no environment or ignore line to write; it prints the step to name the
399
+ services the application calls in that file, which a recipe cannot make for you (see
400
+ [xtr-recipes](../xtr-recipes)).
401
+ - **Activate** — `HttpClientBundle: {"all": True}` in `BUNDLES` in `<app>/config/bundles.py`,
401
402
  imported from `xtr_http_client.bundle`.
402
403
  - **Brings along** — the rate limiter bundle when xtr-rate-limiter is installed.
403
- - **Configure** — optional: with no configuration there is one client, an
404
- `HttpClientInterface` sending requests as they are given. Default options, a client per
405
- service, retries, a pace and a mock for tests go in `<app>/config/http_client.py`, a
404
+ - **Configure** — optional: the recipe writes `<app>/config/packages/http_client.py` holding the
405
+ defaults, one client — an `HttpClientInterface` sending requests as they are given. Default
406
+ options, a client per service, retries, a pace and a mock for tests go in that same
406
407
  `@configure` function returning `HttpClientConfig` — see [Kernel / bundle](#kernel--bundle).
407
408
  - **Environment** — nothing. A credential given as `env(...)` is read when the client needing
408
409
  it is built.
409
410
  - **Ignore** — nothing.
410
- - **Remove** — drop the `BUNDLES` entry, delete `<app>/config/http_client.py`, then
411
- `uv remove xtr-http-client`.
411
+ - **Remove** — drop the `BUNDLES` entry; `uv run xtr-recipes recipes:remove xtr-http-client`
412
+ deletes `<app>/config/packages/http_client.py`, unless you edited it, in which case it is
413
+ moved aside to `http_client.py.removed`. Then `uv remove xtr-http-client`.
412
414
  - **Check** — `debug:bundles` shows `http_client` as `listed` and `active`.
413
415
 
414
416
  ## Kernel / bundle
@@ -418,14 +420,14 @@ not a dependency, and nothing outside `xtr_http_client.bundle` needs it — list
418
420
  configure the clients:
419
421
 
420
422
  ```python
421
- # app/bundles.py
423
+ # app/config/bundles.py
422
424
  from xtr_http_client.bundle import HttpClientBundle
423
425
 
424
426
  BUNDLES = {HttpClientBundle: {"all": True}}
425
427
  ```
426
428
 
427
429
  ```python
428
- # app/config/http_client.py
430
+ # app/config/packages/http_client.py
429
431
  from xtr_dependency_injection import configure, env
430
432
 
431
433
  from xtr_http_client.bundle import (
@@ -362,22 +362,24 @@ removing it undoes.
362
362
  - **Install** — `uv add xtr-http-client xtr-dependency-injection`: the bundle needs the container
363
363
  installed beside it, never as an extra. Add `http2` to ask for HTTP/2, and install
364
364
  [xtr-rate-limiter](../xtr-rate-limiter) beside it to pace a client with one of its limiters.
365
- - **Recipe** — `uv run xtr-recipes recipes:sync` does the *Activate* step below: it lists
366
- `HttpClientBundle`. There is no config file, environment or ignore line to write; it prints the
367
- step to name the services the application calls in `config/http_client.py`, which a recipe
368
- cannot make for you (see [xtr-recipes](../xtr-recipes)).
369
- - **Activate** — `HttpClientBundle: {"all": True}` in `BUNDLES` in `<app>/bundles.py`,
365
+ - **Recipe** — `uv run xtr-recipes recipes:sync` does the *Activate* and *Configure* steps below:
366
+ it lists `HttpClientBundle` and writes `<app>/config/packages/http_client.py` with the bundle's
367
+ own defaults. There is no environment or ignore line to write; it prints the step to name the
368
+ services the application calls in that file, which a recipe cannot make for you (see
369
+ [xtr-recipes](../xtr-recipes)).
370
+ - **Activate** — `HttpClientBundle: {"all": True}` in `BUNDLES` in `<app>/config/bundles.py`,
370
371
  imported from `xtr_http_client.bundle`.
371
372
  - **Brings along** — the rate limiter bundle when xtr-rate-limiter is installed.
372
- - **Configure** — optional: with no configuration there is one client, an
373
- `HttpClientInterface` sending requests as they are given. Default options, a client per
374
- service, retries, a pace and a mock for tests go in `<app>/config/http_client.py`, a
373
+ - **Configure** — optional: the recipe writes `<app>/config/packages/http_client.py` holding the
374
+ defaults, one client — an `HttpClientInterface` sending requests as they are given. Default
375
+ options, a client per service, retries, a pace and a mock for tests go in that same
375
376
  `@configure` function returning `HttpClientConfig` — see [Kernel / bundle](#kernel--bundle).
376
377
  - **Environment** — nothing. A credential given as `env(...)` is read when the client needing
377
378
  it is built.
378
379
  - **Ignore** — nothing.
379
- - **Remove** — drop the `BUNDLES` entry, delete `<app>/config/http_client.py`, then
380
- `uv remove xtr-http-client`.
380
+ - **Remove** — drop the `BUNDLES` entry; `uv run xtr-recipes recipes:remove xtr-http-client`
381
+ deletes `<app>/config/packages/http_client.py`, unless you edited it, in which case it is
382
+ moved aside to `http_client.py.removed`. Then `uv remove xtr-http-client`.
381
383
  - **Check** — `debug:bundles` shows `http_client` as `listed` and `active`.
382
384
 
383
385
  ## Kernel / bundle
@@ -387,14 +389,14 @@ not a dependency, and nothing outside `xtr_http_client.bundle` needs it — list
387
389
  configure the clients:
388
390
 
389
391
  ```python
390
- # app/bundles.py
392
+ # app/config/bundles.py
391
393
  from xtr_http_client.bundle import HttpClientBundle
392
394
 
393
395
  BUNDLES = {HttpClientBundle: {"all": True}}
394
396
  ```
395
397
 
396
398
  ```python
397
- # app/config/http_client.py
399
+ # app/config/packages/http_client.py
398
400
  from xtr_dependency_injection import configure, env
399
401
 
400
402
  from xtr_http_client.bundle import (
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xtr-http-client"
3
- version = "5.0.1"
3
+ version = "5.2.0"
4
4
  description = "An async HTTP client behind one interface: typed request options, bodies read on demand, scoped clients, a private-network guard and a mock client for tests."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xtr-http-client"
3
- version = "5.0.1"
3
+ version = "5.2.0"
4
4
  description = "An async HTTP client behind one interface: typed request options, bodies read on demand, scoped clients, a private-network guard and a mock client for tests."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -208,17 +208,18 @@ async def test_it_reads_the_created_order() -> None:
208
208
  ## Use in an application
209
209
 
210
210
  `uv run xtr-recipes recipes:sync` applies the recipe shipped with this package: it lists
211
- `HttpClientBundle`. There is no config file, environment or ignore line to write; it prints the
212
- step to name the services the application calls, which a recipe cannot make for you.
211
+ `HttpClientBundle` and writes `<app>/config/packages/http_client.py` with the bundle's own
212
+ defaults. There is no environment or ignore line to write; it prints the step to name the services
213
+ the application calls, which a recipe cannot make for you.
213
214
 
214
215
  1. **Install** — `uv add xtr-http-client xtr-dependency-injection`: the bundle needs the container
215
216
  installed beside it, never as an extra. Add `http2` to ask for HTTP/2, and install
216
217
  xtr-rate-limiter beside it to pace a client with one of its limiters.
217
- 2. **Activate** — `HttpClientBundle: {"all": True}` in `BUNDLES` in `<app>/bundles.py`
218
+ 2. **Activate** — `HttpClientBundle: {"all": True}` in `BUNDLES` in `<app>/config/bundles.py`
218
219
  (`from xtr_http_client.bundle import HttpClientBundle`).
219
220
  3. **Brings along** — the rate limiter bundle when xtr-rate-limiter is installed.
220
- 4. **Configure** — optional: with no configuration there is one client sending requests as they
221
- are given. Otherwise `<app>/config/http_client.py`:
221
+ 4. **Configure** — the recipe writes `<app>/config/packages/http_client.py` holding the defaults,
222
+ one client sending requests as they are given, and that is where the rest goes:
222
223
 
223
224
  ```python
224
225
  from xtr_dependency_injection import configure, env
@@ -269,8 +270,9 @@ step to name the services the application calls, which a recipe cannot make for
269
270
  ```
270
271
 
271
272
  7. **Check** — `debug:bundles` shows `http_client` as `listed` and `active`.
272
- 8. **Remove** — drop the `BUNDLES` entry, delete `<app>/config/http_client.py`, then
273
- `uv remove xtr-http-client`.
273
+ 8. **Remove** — drop the `BUNDLES` entry; `uv run xtr-recipes recipes:remove xtr-http-client`
274
+ deletes `<app>/config/packages/http_client.py`, unless you edited it, in which case it is
275
+ moved aside to `http_client.py.removed`. Then `uv remove xtr-http-client`.
274
276
 
275
277
  ## Errors
276
278
 
@@ -0,0 +1,34 @@
1
+ """The HTTP clients: the default one, and one per service the application calls.
2
+
3
+ ```python
4
+ HttpClientConfig(
5
+ default_options=ClientOptionsConfig(
6
+ timeout=10, retry_failed=RetryFailedConfig(enabled=True)
7
+ ),
8
+ scoped_clients={
9
+ "github": ScopedClientConfig(
10
+ base_uri="https://api.github.com/", auth_bearer=env("GITHUB_TOKEN")
11
+ ),
12
+ },
13
+ )
14
+ ```
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from xtr_dependency_injection import configure
20
+ from xtr_http_client.bundle import HttpClientConfig
21
+
22
+ __all__ = ["http_client"]
23
+
24
+
25
+ @configure
26
+ def http_client() -> HttpClientConfig:
27
+ """One client, sending requests as they are given."""
28
+ # default_options is what every request starts from: a timeout, headers, retries.
29
+ #
30
+ # A client in scoped_clients is qualified by its name and carries its own base URI,
31
+ # headers and credentials, over what default_options sets.
32
+ #
33
+ # max_host_connections caps the connections one pool holds at once, six unless set.
34
+ return HttpClientConfig()
@@ -5,9 +5,11 @@
5
5
  # "<module>:<class>" = the environments it is listed with, exactly as in BUNDLES.
6
6
  "xtr_http_client.bundle:HttpClientBundle" = { all = true }
7
7
 
8
- # No [files]: configuring is optional. With none there is one client sending
9
- # requests as they are given; an application naming the services it calls
10
- # writes config/http_client.py itself, which is what [notes] asks for.
8
+ [files]
9
+ # Destination under the application package = template under this recipe.
10
+ # The bundle's own defaults written out — one client sending requests as they
11
+ # are given — as the place the services it calls are named, as [notes] asks.
12
+ "config/packages/http_client.py" = "files/config/http_client.py.tmpl"
11
13
 
12
14
  # No [env]: nothing is required. A credential an application gives as env(...)
13
15
  # is read when the client needing it is built.
@@ -18,6 +20,6 @@ lines = []
18
20
 
19
21
  [notes]
20
22
  steps = [
21
- "Name the services the application calls in config/http_client.py — a scoped client per base URI, with its headers and credentials — when one client with no defaults is not enough.",
23
+ "Name the services the application calls in config/packages/http_client.py — a scoped client per base URI, with its headers and credentials — when one client with no defaults is not enough.",
22
24
  ]
23
25
  check = ["<script> debug:bundles — http_client is listed and active"]
File without changes