without-http 0.0.2__tar.gz → 0.0.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: without-http
3
- Version: 0.0.2
3
+ Version: 0.0.4
4
4
  Summary: A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets.
5
5
  Author: Josh Karpel
6
6
  Author-email: Josh Karpel <josh.karpel@gmail.com>
@@ -16,11 +16,13 @@ Classifier: Topic :: Internet :: WWW/HTTP
16
16
  Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
17
17
  Classifier: Topic :: Software Development :: Libraries
18
18
  Classifier: Typing :: Typed
19
- Requires-Dist: without-core==0.0.2
20
- Requires-Dist: without-asgi==0.0.2
19
+ Requires-Dist: without-core==0.0.4
20
+ Requires-Dist: without-asgi==0.0.4
21
21
  Requires-Dist: h11>=0.16
22
22
  Requires-Dist: h2>=4.1
23
23
  Requires-Dist: wsproto>=1.2
24
+ Requires-Dist: aiohappyeyeballs>=2.6
25
+ Requires-Dist: brotli>=1.1
24
26
  Requires-Python: >=3.14
25
27
  Description-Content-Type: text/markdown
26
28
 
@@ -43,15 +45,15 @@ translate between typed events and the ASGI dicts an app expects.
43
45
  ```python
44
46
  from without import sleep_forever
45
47
  from without_asgi import make_asgi_app
46
- from without_http import ConnectionPool, serving
48
+ from without_http import ConnectionPool, request, serving
47
49
 
48
50
  app = make_asgi_app(lifespan, http=router.dispatch, websocket=sockets.dispatch)
49
51
 
50
52
  async with serving(app, host="127.0.0.1", port=8000):
51
- await sleep_forever() # run until cancelled
53
+ await sleep_forever() # run until cancelled
52
54
 
53
55
  async with ConnectionPool() as pool:
54
- async with pool.request("GET", "http://127.0.0.1:8000/items") as (head, body):
56
+ async with request(pool, "GET", "http://127.0.0.1:8000/items") as (head, body):
55
57
  assert head.status == 200
56
58
  data = await body.read()
57
59
  ```
@@ -59,13 +61,21 @@ async with ConnectionPool() as pool:
59
61
  Because `without-http` speaks plain ASGI to the app, *any* ASGI app runs over it,
60
62
  interchangeably with uvicorn. The server handles TLS, HTTP/2 (by ALPN or prior
61
63
  knowledge), keep-alive, WebSockets over the HTTP/1.1 upgrade, per-handler
62
- isolation, and flow control. The client is a `ConnectionPool` with a `(head,
63
- body)` response split, buffered and streaming bodies in both directions,
64
- opt-in trailers, HTTP/2 multiplexing, per-host connection bounds, per-phase
65
- request timeouts, consumer-driven duplex (with bidirectional streaming over
66
- HTTP/2), and `stack`-composed middleware.
64
+ isolation, and flow control. A client is a function from a request to a response, and
65
+ a `ConnectionPool` is the one that answers over the network: a `(head, body)` response
66
+ split, buffered and streaming bodies in both directions, opt-in trailers, HTTP/2
67
+ multiplexing, per-host connection bounds, per-phase request timeouts, consumer-driven
68
+ duplex (with bidirectional streaming over HTTP/2), and `stack`-composed middleware.
69
+
70
+ `without_http.testing` carries the same interface into a test: a mock client that answers
71
+ from a function, an ASGI client that drives an app in memory, and a loopback client that
72
+ runs the real wire protocols over no socket at all, plus the raw in-memory endpoints
73
+ those are built from, for a test that writes frames rather than requests.
67
74
 
68
75
  See the
69
76
  [`without-http` guide](https://without.help/without-http/)
70
77
  (with the [API reference](https://without.help/reference/without_http/))
71
- for the full surface, including the deferred work (WebSockets over HTTP/2, HTTP/3).
78
+ for the full surface, and
79
+ [Alternatives](https://without.help/without-http/alternatives/) for where the
80
+ client and server stand against httpx, aiohttp, niquests, and the ASGI servers,
81
+ including which absences are gaps and which are positions.
@@ -17,15 +17,15 @@ translate between typed events and the ASGI dicts an app expects.
17
17
  ```python
18
18
  from without import sleep_forever
19
19
  from without_asgi import make_asgi_app
20
- from without_http import ConnectionPool, serving
20
+ from without_http import ConnectionPool, request, serving
21
21
 
22
22
  app = make_asgi_app(lifespan, http=router.dispatch, websocket=sockets.dispatch)
23
23
 
24
24
  async with serving(app, host="127.0.0.1", port=8000):
25
- await sleep_forever() # run until cancelled
25
+ await sleep_forever() # run until cancelled
26
26
 
27
27
  async with ConnectionPool() as pool:
28
- async with pool.request("GET", "http://127.0.0.1:8000/items") as (head, body):
28
+ async with request(pool, "GET", "http://127.0.0.1:8000/items") as (head, body):
29
29
  assert head.status == 200
30
30
  data = await body.read()
31
31
  ```
@@ -33,13 +33,21 @@ async with ConnectionPool() as pool:
33
33
  Because `without-http` speaks plain ASGI to the app, *any* ASGI app runs over it,
34
34
  interchangeably with uvicorn. The server handles TLS, HTTP/2 (by ALPN or prior
35
35
  knowledge), keep-alive, WebSockets over the HTTP/1.1 upgrade, per-handler
36
- isolation, and flow control. The client is a `ConnectionPool` with a `(head,
37
- body)` response split, buffered and streaming bodies in both directions,
38
- opt-in trailers, HTTP/2 multiplexing, per-host connection bounds, per-phase
39
- request timeouts, consumer-driven duplex (with bidirectional streaming over
40
- HTTP/2), and `stack`-composed middleware.
36
+ isolation, and flow control. A client is a function from a request to a response, and
37
+ a `ConnectionPool` is the one that answers over the network: a `(head, body)` response
38
+ split, buffered and streaming bodies in both directions, opt-in trailers, HTTP/2
39
+ multiplexing, per-host connection bounds, per-phase request timeouts, consumer-driven
40
+ duplex (with bidirectional streaming over HTTP/2), and `stack`-composed middleware.
41
+
42
+ `without_http.testing` carries the same interface into a test: a mock client that answers
43
+ from a function, an ASGI client that drives an app in memory, and a loopback client that
44
+ runs the real wire protocols over no socket at all, plus the raw in-memory endpoints
45
+ those are built from, for a test that writes frames rather than requests.
41
46
 
42
47
  See the
43
48
  [`without-http` guide](https://without.help/without-http/)
44
49
  (with the [API reference](https://without.help/reference/without_http/))
45
- for the full surface, including the deferred work (WebSockets over HTTP/2, HTTP/3).
50
+ for the full surface, and
51
+ [Alternatives](https://without.help/without-http/alternatives/) for where the
52
+ client and server stand against httpx, aiohttp, niquests, and the ASGI servers,
53
+ including which absences are gaps and which are positions.
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["uv_build>=0.11.32,<0.12"]
2
+ requires = ["uv_build>=0.12.3,<0.13"]
3
3
  build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "without-http"
7
- version = "0.0.2"
7
+ version = "0.0.4"
8
8
  description = "A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -23,11 +23,13 @@ classifiers = [
23
23
  "Typing :: Typed",
24
24
  ]
25
25
  dependencies = [
26
- "without-core==0.0.2",
27
- "without-asgi==0.0.2",
26
+ "without-core==0.0.4",
27
+ "without-asgi==0.0.4",
28
28
  "h11>=0.16",
29
29
  "h2>=4.1",
30
30
  "wsproto>=1.2",
31
+ "aiohappyeyeballs>=2.6",
32
+ "brotli>=1.1",
31
33
  ]
32
34
 
33
35
  [[project.authors]]
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["uv_build>=0.11.32,<0.12"]
2
+ requires = ["uv_build>=0.12.3,<0.13"]
3
3
  build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "without-http"
7
- version = "0.0.2"
7
+ version = "0.0.4"
8
8
  description = "A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -26,11 +26,13 @@ classifiers = [
26
26
  "Typing :: Typed",
27
27
  ]
28
28
  dependencies = [
29
- "without-core==0.0.2",
30
- "without-asgi==0.0.2",
29
+ "without-core==0.0.4",
30
+ "without-asgi==0.0.4",
31
31
  "h11>=0.16",
32
32
  "h2>=4.1",
33
33
  "wsproto>=1.2",
34
+ "aiohappyeyeballs>=2.6",
35
+ "brotli>=1.1",
34
36
  ]
35
37
 
36
38
  [tool.uv.sources]
@@ -1,17 +1,35 @@
1
- from without_http.client import ClientExchange
1
+ from without_http.client import DEFAULT_DECOMPRESSORS
2
+ from without_http.client import USER_AGENT
3
+ from without_http.client import Client
2
4
  from without_http.client import ClientMiddleware
3
5
  from without_http.client import ClientRequest
4
6
  from without_http.client import ClientResponse
7
+ from without_http.client import Compressor
8
+ from without_http.client import Connect
5
9
  from without_http.client import ConnectionPool
6
10
  from without_http.client import CookieJar
11
+ from without_http.client import Decompressor
12
+ from without_http.client import Resolve
7
13
  from without_http.client import ResponseBody
8
14
  from without_http.client import ResponseHead
9
15
  from without_http.client import ResponseTrailers
10
16
  from without_http.client import add_headers
17
+ from without_http.client import basic_auth
18
+ from without_http.client import bearer_auth
19
+ from without_http.client import brotli_compress
20
+ from without_http.client import compressing
11
21
  from without_http.client import cookies
22
+ from without_http.client import deadline
23
+ from without_http.client import decompress
24
+ from without_http.client import default_headers
12
25
  from without_http.client import follow_redirects
26
+ from without_http.client import gzip_compress
27
+ from without_http.client import request
13
28
  from without_http.client import stack
29
+ from without_http.client import tcp_connect
30
+ from without_http.client import user_agent
14
31
  from without_http.client import wrap
32
+ from without_http.client import zstd_compress
15
33
  from without_http.h2_wire import early_hint_headers
16
34
  from without_http.h2_wire import request_headers
17
35
  from without_http.h2_wire import response_headers
@@ -35,24 +53,33 @@ from without_http.timeouts import ReadTimeout
35
53
  from without_http.timeouts import Timeout
36
54
  from without_http.timeouts import WriteTimeout
37
55
  from without_http.tls import ALPN_PROTOCOLS
56
+ from without_http.tls import distinguished_name
57
+ from without_http.tls import extensions_with_tls
38
58
  from without_http.tls import server_ssl_context
59
+ from without_http.tls import tls_extension
39
60
  from without_http.ws_wire import is_websocket_upgrade
40
61
  from without_http.ws_wire import websocket_scope_from_request
41
62
  from without_http.ws_wire import ws_events_from_outbound
42
63
 
43
64
  __all__ = [
44
65
  "ALPN_PROTOCOLS",
45
- "ClientExchange",
66
+ "DEFAULT_DECOMPRESSORS",
67
+ "USER_AGENT",
68
+ "Client",
46
69
  "ClientMiddleware",
47
70
  "ClientRequest",
48
71
  "ClientResponse",
72
+ "Compressor",
73
+ "Connect",
49
74
  "ConnectTimeout",
50
75
  "ConnectionPool",
51
76
  "CookieJar",
77
+ "Decompressor",
52
78
  "HTTPTimeout",
53
79
  "LifespanError",
54
80
  "PoolTimeout",
55
81
  "ReadTimeout",
82
+ "Resolve",
56
83
  "ResponseBody",
57
84
  "ResponseHead",
58
85
  "ResponseTrailers",
@@ -61,13 +88,24 @@ __all__ = [
61
88
  "Timeout",
62
89
  "WriteTimeout",
63
90
  "add_headers",
91
+ "basic_auth",
92
+ "bearer_auth",
93
+ "brotli_compress",
94
+ "compressing",
64
95
  "cookies",
96
+ "deadline",
97
+ "decompress",
98
+ "default_headers",
99
+ "distinguished_name",
65
100
  "early_hint_headers",
101
+ "extensions_with_tls",
66
102
  "follow_redirects",
103
+ "gzip_compress",
67
104
  "h11_events_from_outbound",
68
105
  "inbound_from_event",
69
106
  "is_websocket_upgrade",
70
107
  "receive_buffer_size",
108
+ "request",
71
109
  "request_headers",
72
110
  "response_headers",
73
111
  "response_status_and_headers",
@@ -78,8 +116,12 @@ __all__ = [
78
116
  "server_ssl_context",
79
117
  "serving",
80
118
  "stack",
119
+ "tcp_connect",
81
120
  "tcp_keepalive",
121
+ "tls_extension",
122
+ "user_agent",
82
123
  "websocket_scope_from_request",
83
124
  "wrap",
84
125
  "ws_events_from_outbound",
126
+ "zstd_compress",
85
127
  ]