without-http 0.0.1__tar.gz → 0.0.3__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.1
3
+ Version: 0.0.3
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,8 +16,8 @@ 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.1
20
- Requires-Dist: without-asgi==0.0.1
19
+ Requires-Dist: without-core==0.0.3
20
+ Requires-Dist: without-asgi==0.0.3
21
21
  Requires-Dist: h11>=0.16
22
22
  Requires-Dist: h2>=4.1
23
23
  Requires-Dist: wsproto>=1.2
@@ -43,15 +43,15 @@ translate between typed events and the ASGI dicts an app expects.
43
43
  ```python
44
44
  from without import sleep_forever
45
45
  from without_asgi import make_asgi_app
46
- from without_http import ConnectionPool, serving
46
+ from without_http import ConnectionPool, request, serving
47
47
 
48
48
  app = make_asgi_app(lifespan, http=router.dispatch, websocket=sockets.dispatch)
49
49
 
50
50
  async with serving(app, host="127.0.0.1", port=8000):
51
- await sleep_forever() # run until cancelled
51
+ await sleep_forever() # run until cancelled
52
52
 
53
53
  async with ConnectionPool() as pool:
54
- async with pool.request("GET", "http://127.0.0.1:8000/items") as (head, body):
54
+ async with request(pool, "GET", "http://127.0.0.1:8000/items") as (head, body):
55
55
  assert head.status == 200
56
56
  data = await body.read()
57
57
  ```
@@ -59,12 +59,18 @@ async with ConnectionPool() as pool:
59
59
  Because `without-http` speaks plain ASGI to the app, *any* ASGI app runs over it,
60
60
  interchangeably with uvicorn. The server handles TLS, HTTP/2 (by ALPN or prior
61
61
  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, and `stack`-composed middleware.
62
+ isolation, and flow control. A client is a function from a request to a response, and
63
+ a `ConnectionPool` is the one that answers over the network: a `(head, body)` response
64
+ split, buffered and streaming bodies in both directions, opt-in trailers, HTTP/2
65
+ multiplexing, per-host connection bounds, per-phase request timeouts, consumer-driven
66
+ duplex (with bidirectional streaming over HTTP/2), and `stack`-composed middleware.
67
+
68
+ `without_http.testing` carries the same interface into a test: a mock client that answers
69
+ from a function, an ASGI client that drives an app in memory, and a loopback client that
70
+ runs the real wire protocols over no socket at all, plus the raw in-memory endpoints
71
+ those are built from, for a test that writes frames rather than requests.
65
72
 
66
73
  See the
67
- [`without-http` guide](https://without.help/guides/without-http/)
74
+ [`without-http` guide](https://without.help/without-http/)
68
75
  (with the [API reference](https://without.help/reference/without_http/))
69
- for the full surface, including the deferred work (WebSockets over HTTP/2, HTTP/3,
70
- duplex).
76
+ for the full surface, including the deferred work (WebSockets over HTTP/2, HTTP/3).
@@ -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,12 +33,18 @@ 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, 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.
39
46
 
40
47
  See the
41
- [`without-http` guide](https://without.help/guides/without-http/)
48
+ [`without-http` guide](https://without.help/without-http/)
42
49
  (with the [API reference](https://without.help/reference/without_http/))
43
- for the full surface, including the deferred work (WebSockets over HTTP/2, HTTP/3,
44
- duplex).
50
+ for the full surface, including the deferred work (WebSockets over HTTP/2, HTTP/3).
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.11.32,<0.12"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "without-http"
7
+ version = "0.0.3"
8
+ description = "A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.14"
12
+ classifiers = [
13
+ "Development Status :: 2 - Pre-Alpha",
14
+ "Framework :: AsyncIO",
15
+ "Intended Audience :: Developers",
16
+ "Operating System :: OS Independent",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3 :: Only",
19
+ "Programming Language :: Python :: 3.14",
20
+ "Topic :: Internet :: WWW/HTTP",
21
+ "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
22
+ "Topic :: Software Development :: Libraries",
23
+ "Typing :: Typed",
24
+ ]
25
+ dependencies = [
26
+ "without-core==0.0.3",
27
+ "without-asgi==0.0.3",
28
+ "h11>=0.16",
29
+ "h2>=4.1",
30
+ "wsproto>=1.2",
31
+ ]
32
+
33
+ [[project.authors]]
34
+ name = "Josh Karpel"
35
+ email = "josh.karpel@gmail.com"
36
+
37
+ [tool.uv.sources.without-core]
38
+ workspace = true
39
+
40
+ [tool.uv.sources.without-asgi]
41
+ workspace = true
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["uv_build>=0.11.25,<0.12"]
2
+ requires = ["uv_build>=0.11.32,<0.12"]
3
3
  build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "without-http"
7
- version = "0.0.1"
7
+ version = "0.0.3"
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,8 +26,8 @@ classifiers = [
26
26
  "Typing :: Typed",
27
27
  ]
28
28
  dependencies = [
29
- "without-core==0.0.1",
30
- "without-asgi==0.0.1",
29
+ "without-core==0.0.3",
30
+ "without-asgi==0.0.3",
31
31
  "h11>=0.16",
32
32
  "h2>=4.1",
33
33
  "wsproto>=1.2",
@@ -1,7 +1,8 @@
1
- from without_http.client import ClientExchange
1
+ from without_http.client import Client
2
2
  from without_http.client import ClientMiddleware
3
3
  from without_http.client import ClientRequest
4
4
  from without_http.client import ClientResponse
5
+ from without_http.client import Connect
5
6
  from without_http.client import ConnectionPool
6
7
  from without_http.client import CookieJar
7
8
  from without_http.client import ResponseBody
@@ -9,7 +10,9 @@ from without_http.client import ResponseHead
9
10
  from without_http.client import ResponseTrailers
10
11
  from without_http.client import add_headers
11
12
  from without_http.client import cookies
13
+ from without_http.client import deadline
12
14
  from without_http.client import follow_redirects
15
+ from without_http.client import request
13
16
  from without_http.client import stack
14
17
  from without_http.client import wrap
15
18
  from without_http.h2_wire import early_hint_headers
@@ -24,6 +27,16 @@ from without_http.lifespan import LifespanError
24
27
  from without_http.lifespan import run_lifespan
25
28
  from without_http.server import Server
26
29
  from without_http.server import serving
30
+ from without_http.socket_options import SocketOptions
31
+ from without_http.socket_options import receive_buffer_size
32
+ from without_http.socket_options import send_buffer_size
33
+ from without_http.socket_options import tcp_keepalive
34
+ from without_http.timeouts import ConnectTimeout
35
+ from without_http.timeouts import HTTPTimeout
36
+ from without_http.timeouts import PoolTimeout
37
+ from without_http.timeouts import ReadTimeout
38
+ from without_http.timeouts import Timeout
39
+ from without_http.timeouts import WriteTimeout
27
40
  from without_http.tls import ALPN_PROTOCOLS
28
41
  from without_http.tls import server_ssl_context
29
42
  from without_http.ws_wire import is_websocket_upgrade
@@ -32,33 +45,46 @@ from without_http.ws_wire import ws_events_from_outbound
32
45
 
33
46
  __all__ = [
34
47
  "ALPN_PROTOCOLS",
35
- "ClientExchange",
48
+ "Client",
36
49
  "ClientMiddleware",
37
50
  "ClientRequest",
38
51
  "ClientResponse",
52
+ "Connect",
53
+ "ConnectTimeout",
39
54
  "ConnectionPool",
40
55
  "CookieJar",
56
+ "HTTPTimeout",
41
57
  "LifespanError",
58
+ "PoolTimeout",
59
+ "ReadTimeout",
42
60
  "ResponseBody",
43
61
  "ResponseHead",
44
62
  "ResponseTrailers",
45
63
  "Server",
64
+ "SocketOptions",
65
+ "Timeout",
66
+ "WriteTimeout",
46
67
  "add_headers",
47
68
  "cookies",
69
+ "deadline",
48
70
  "early_hint_headers",
49
71
  "follow_redirects",
50
72
  "h11_events_from_outbound",
51
73
  "inbound_from_event",
52
74
  "is_websocket_upgrade",
75
+ "receive_buffer_size",
76
+ "request",
53
77
  "request_headers",
54
78
  "response_headers",
55
79
  "response_status_and_headers",
56
80
  "run_lifespan",
57
81
  "scope_from_h2_headers",
58
82
  "scope_from_request",
83
+ "send_buffer_size",
59
84
  "server_ssl_context",
60
85
  "serving",
61
86
  "stack",
87
+ "tcp_keepalive",
62
88
  "websocket_scope_from_request",
63
89
  "wrap",
64
90
  "ws_events_from_outbound",