punkreq 0.2.2__tar.gz → 0.2.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.
- {punkreq-0.2.2 → punkreq-0.2.4}/PKG-INFO +3 -3
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_connect.py +32 -14
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_pool.py +46 -17
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_proxies.py +6 -4
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_transport.py +30 -4
- punkreq-0.2.4/punkreq/_version.py +1 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/pyproject.toml +3 -3
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/fakes.py +1 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_connect.py +2 -2
- punkreq-0.2.2/punkreq/_version.py +0 -1
- {punkreq-0.2.2 → punkreq-0.2.4}/.gitignore +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/LICENSE +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/README.md +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/__init__.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_auth.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_client.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_config.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_content.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_cookies.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_decoders.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_exceptions.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_headers.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_models.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_multipart.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_redirects.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/_urls.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/asyncio.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/py.typed +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/punkreq/tonio.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/__init__.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/conftest.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/e2e.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/servers.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/servers_tonio.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_client.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_config.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_content.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_cookies.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_decoders.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_e2e_asyncio.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_e2e_tonio.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_exceptions.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_headers.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_models.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_multipart.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_pool.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_redirects.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_transport.py +0 -0
- {punkreq-0.2.2 → punkreq-0.2.4}/tests/test_urls.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: punkreq
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: An async HTTP client built on httpunk
|
|
5
5
|
Project-URL: Homepage, https://github.com/gi0baro/punkreq
|
|
6
6
|
Project-URL: Funding, https://github.com/sponsors/gi0baro
|
|
@@ -24,11 +24,11 @@ Classifier: Programming Language :: Python :: 3.15
|
|
|
24
24
|
Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable
|
|
25
25
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
26
26
|
Requires-Python: >=3.10
|
|
27
|
-
Requires-Dist: httpunk~=0.4.
|
|
27
|
+
Requires-Dist: httpunk~=0.4.4
|
|
28
28
|
Provides-Extra: brotli
|
|
29
29
|
Requires-Dist: brotli~=1.2.0; extra == 'brotli'
|
|
30
30
|
Provides-Extra: tonio
|
|
31
|
-
Requires-Dist: tonio~=0.
|
|
31
|
+
Requires-Dist: tonio~=0.10.0; (python_version >= '3.14') and extra == 'tonio'
|
|
32
32
|
Description-Content-Type: text/markdown
|
|
33
33
|
|
|
34
34
|
# punkreq
|
|
@@ -4,13 +4,14 @@ import os
|
|
|
4
4
|
import ssl
|
|
5
5
|
import typing
|
|
6
6
|
|
|
7
|
+
from httpunk.exceptions import HTTPunkError
|
|
7
8
|
from httpunk.h1.client import H1Connection
|
|
8
9
|
from httpunk.h2.client import H2Connection
|
|
9
10
|
|
|
10
11
|
from ._exceptions import ConnectError, UnsupportedProtocol
|
|
11
12
|
|
|
12
13
|
|
|
13
|
-
__all__ = ["Connector", "Origin", "connect_errors", "create_ssl_context", "origin_for_url"]
|
|
14
|
+
__all__ = ["Connector", "Origin", "connect_errors", "create_ssl_context", "enter_connection", "origin_for_url"]
|
|
14
15
|
|
|
15
16
|
DEFAULT_PORTS = {"http": 80, "https": 443}
|
|
16
17
|
|
|
@@ -83,17 +84,32 @@ def create_ssl_context(verify: VerifyTypes = True, cert: CertTypes | None = None
|
|
|
83
84
|
|
|
84
85
|
|
|
85
86
|
def connect_errors(backend: typing.Any) -> tuple[type[BaseException], ...]:
|
|
86
|
-
"""What a dial
|
|
87
|
-
errors,
|
|
87
|
+
"""What a dial, a TLS handshake or the HTTP handshake fails with on
|
|
88
|
+
`backend`: the OS and ssl errors, the backend's own transport failure, and
|
|
89
|
+
httpunk's errors (the peer hanging up or misbehaving while the connection
|
|
90
|
+
is entered, or during a proxy's CONNECT). tonio's `ResourceBroken`
|
|
88
91
|
is a plain `Exception`, not an `OSError`, and its TLS layer raises it in
|
|
89
92
|
place of the ssl error, so `(OSError, ssl.SSLError)` alone lets a failed
|
|
90
93
|
handshake on tonio escape as an unmapped exception."""
|
|
91
|
-
return (OSError, ssl.SSLError, *backend.broken_transport_errors)
|
|
94
|
+
return (OSError, ssl.SSLError, HTTPunkError, *backend.broken_transport_errors)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
async def enter_connection(conn: typing.Any, transport: typing.Any, backend: typing.Any) -> typing.Any:
|
|
98
|
+
"""Run `conn`'s HTTP handshake (`__aenter__`) and return it. Until that
|
|
99
|
+
completes the transport we dialed is still ours to close: httpunk closes
|
|
100
|
+
it on `__aexit__`, which a failed or interrupted `__aenter__` never
|
|
101
|
+
reaches (h2 waits there for the peer's SETTINGS, pumps already running)."""
|
|
102
|
+
try:
|
|
103
|
+
await conn.__aenter__()
|
|
104
|
+
except BaseException:
|
|
105
|
+
backend.close_transport(transport)
|
|
106
|
+
raise
|
|
107
|
+
return conn
|
|
92
108
|
|
|
93
109
|
|
|
94
110
|
class Connector:
|
|
95
|
-
"""The default connector: dial `origin` and return the protocol-matching
|
|
96
|
-
|
|
111
|
+
"""The default connector: dial `origin` and return the protocol-matching
|
|
112
|
+
httpunk connection, entered."""
|
|
97
113
|
|
|
98
114
|
def __init__(
|
|
99
115
|
self,
|
|
@@ -126,12 +142,14 @@ class Connector:
|
|
|
126
142
|
async def __call__(self, origin: Origin) -> H1Connection | H2Connection:
|
|
127
143
|
try:
|
|
128
144
|
if origin.scheme == "https":
|
|
129
|
-
|
|
130
|
-
|
|
145
|
+
conn, stream = await self._connect_tls(origin)
|
|
146
|
+
else:
|
|
147
|
+
conn, stream = await self._connect_tcp(origin)
|
|
148
|
+
return await enter_connection(conn, stream, self._backend)
|
|
131
149
|
except connect_errors(self._backend) as exc:
|
|
132
150
|
raise ConnectError(f"Failed to connect to {origin}: {exc}")
|
|
133
151
|
|
|
134
|
-
async def _connect_tls(self, origin: Origin) -> H1Connection | H2Connection:
|
|
152
|
+
async def _connect_tls(self, origin: Origin) -> tuple[H1Connection | H2Connection, typing.Any]:
|
|
135
153
|
# our context already carries the offer; a backend-created default one
|
|
136
154
|
# (no context given) is configured per dial
|
|
137
155
|
alpn = None if self._ssl_context is not None else self.alpn
|
|
@@ -139,12 +157,12 @@ class Connector:
|
|
|
139
157
|
origin.host, origin.port, alpn=alpn, ssl_context=self._ssl_context
|
|
140
158
|
)
|
|
141
159
|
if selected == "h2" or not self._http1:
|
|
142
|
-
return H2Connection(stream, authority=origin.authority, scheme="https", backend=self._backend)
|
|
143
|
-
return H1Connection(stream, authority=origin.authority, backend=self._backend)
|
|
160
|
+
return H2Connection(stream, authority=origin.authority, scheme="https", backend=self._backend), stream
|
|
161
|
+
return H1Connection(stream, authority=origin.authority, backend=self._backend), stream
|
|
144
162
|
|
|
145
|
-
async def _connect_tcp(self, origin: Origin) -> H1Connection | H2Connection:
|
|
163
|
+
async def _connect_tcp(self, origin: Origin) -> tuple[H1Connection | H2Connection, typing.Any]:
|
|
146
164
|
stream = await self._backend.connect_tcp(origin.host, origin.port)
|
|
147
165
|
if not self._http1:
|
|
148
166
|
# h2 prior knowledge over cleartext (reqwest's http2_prior_knowledge)
|
|
149
|
-
return H2Connection(stream, authority=origin.authority, scheme="http", backend=self._backend)
|
|
150
|
-
return H1Connection(stream, authority=origin.authority, backend=self._backend)
|
|
167
|
+
return H2Connection(stream, authority=origin.authority, scheme="http", backend=self._backend), stream
|
|
168
|
+
return H1Connection(stream, authority=origin.authority, backend=self._backend), stream
|
|
@@ -133,7 +133,11 @@ class ConnectionPool:
|
|
|
133
133
|
|
|
134
134
|
if action == "dial":
|
|
135
135
|
conn = await self._dial(origin, connect_timeout)
|
|
136
|
-
|
|
136
|
+
installed = self._install(origin, conn)
|
|
137
|
+
if installed is None:
|
|
138
|
+
await self._close_conn(conn)
|
|
139
|
+
raise RuntimeError("The connection pool is closed.")
|
|
140
|
+
return installed
|
|
137
141
|
|
|
138
142
|
# action == "wait": either a coalesced dial or pool capacity
|
|
139
143
|
await self._wait(value, deadline)
|
|
@@ -181,12 +185,19 @@ class ConnectionPool:
|
|
|
181
185
|
with self._lock:
|
|
182
186
|
self._closed = True
|
|
183
187
|
conns = []
|
|
188
|
+
dialing = []
|
|
184
189
|
for host in self._hosts.values():
|
|
185
190
|
if host.shared is not None:
|
|
186
191
|
conns.append(host.shared)
|
|
187
192
|
conns.extend(conn for conn, _ in host.idle)
|
|
193
|
+
if host.dialing is not None:
|
|
194
|
+
dialing.append(host.dialing)
|
|
188
195
|
self._hosts.clear()
|
|
189
196
|
self._count = 0
|
|
197
|
+
# acquirers coalesced on a dial still in flight: its entry is gone, so
|
|
198
|
+
# nothing else would ever set their event
|
|
199
|
+
for event in dialing:
|
|
200
|
+
event.set()
|
|
190
201
|
for conn in conns:
|
|
191
202
|
await self._close_conn(conn)
|
|
192
203
|
self._wake_waiters()
|
|
@@ -250,24 +261,38 @@ class ConnectionPool:
|
|
|
250
261
|
return "wait", event, stale
|
|
251
262
|
|
|
252
263
|
async def _dial(self, origin: Origin, connect_timeout: float | None) -> typing.Any:
|
|
264
|
+
if connect_timeout is None:
|
|
265
|
+
try:
|
|
266
|
+
return await self._connector(origin)
|
|
267
|
+
except BaseException:
|
|
268
|
+
self._abandon_dial(origin)
|
|
269
|
+
raise
|
|
270
|
+
|
|
271
|
+
abandoned, dialed, lock = False, [], threading.Lock()
|
|
272
|
+
|
|
273
|
+
async def dial():
|
|
274
|
+
conn = await self._connector(origin)
|
|
275
|
+
with lock:
|
|
276
|
+
if not abandoned:
|
|
277
|
+
dialed.append(conn)
|
|
278
|
+
return
|
|
279
|
+
# the caller is gone: nobody takes it
|
|
280
|
+
await self._close_conn(conn)
|
|
281
|
+
|
|
253
282
|
try:
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
else:
|
|
258
|
-
result, completed = await self._backend.timeout(self._dial_inner(origin), connect_timeout)
|
|
259
|
-
if not completed:
|
|
260
|
-
raise ConnectTimeout(f"Timed out connecting to {origin}")
|
|
261
|
-
conn = result
|
|
283
|
+
_, completed = await self._backend.timeout(dial(), connect_timeout)
|
|
284
|
+
if not completed:
|
|
285
|
+
raise ConnectTimeout(f"Timed out connecting to {origin}")
|
|
262
286
|
except BaseException:
|
|
287
|
+
with lock:
|
|
288
|
+
abandoned = True
|
|
289
|
+
conn = dialed.pop() if dialed else None
|
|
290
|
+
if conn is not None:
|
|
291
|
+
# the caller gave up: hand over closing
|
|
292
|
+
self._backend.spawn_detached(self._close_conn(conn))
|
|
263
293
|
self._abandon_dial(origin)
|
|
264
294
|
raise
|
|
265
|
-
return
|
|
266
|
-
|
|
267
|
-
async def _dial_inner(self, origin: Origin) -> typing.Any:
|
|
268
|
-
conn = await self._connector(origin)
|
|
269
|
-
await conn.__aenter__()
|
|
270
|
-
return conn
|
|
295
|
+
return dialed.pop()
|
|
271
296
|
|
|
272
297
|
def _abandon_dial(self, origin: Origin) -> None:
|
|
273
298
|
with self._lock:
|
|
@@ -281,9 +306,13 @@ class ConnectionPool:
|
|
|
281
306
|
event.set()
|
|
282
307
|
self._wake_waiters()
|
|
283
308
|
|
|
284
|
-
def _install(self, origin: Origin, conn: typing.Any) -> tuple[typing.Any, bool, bool]:
|
|
285
|
-
"""Record a freshly-dialed connection and settle the origin's mode.
|
|
309
|
+
def _install(self, origin: Origin, conn: typing.Any) -> tuple[typing.Any, bool, bool] | None:
|
|
310
|
+
"""Record a freshly-dialed connection and settle the origin's mode.
|
|
311
|
+
None when the pool was closed while dialing: the connection is not
|
|
312
|
+
recorded, and is the caller's to close."""
|
|
286
313
|
with self._lock:
|
|
314
|
+
if self._closed:
|
|
315
|
+
return None
|
|
287
316
|
host = self._hosts.setdefault(origin, _HostState())
|
|
288
317
|
event, host.dialing = host.dialing, None
|
|
289
318
|
if _is_multiplexed(conn):
|
|
@@ -10,7 +10,7 @@ from httpunk.h2.client import H2Connection
|
|
|
10
10
|
from httpunk.util.proxy import Matcher
|
|
11
11
|
|
|
12
12
|
from ._config import Proxy
|
|
13
|
-
from ._connect import Connector, Origin, connect_errors
|
|
13
|
+
from ._connect import Connector, Origin, connect_errors, enter_connection
|
|
14
14
|
from ._exceptions import ConnectError, ProxyError
|
|
15
15
|
from ._headers import Headers
|
|
16
16
|
from ._urls import URL
|
|
@@ -112,7 +112,7 @@ class ProxyConnector:
|
|
|
112
112
|
transport = await self._dial_proxy(intercept)
|
|
113
113
|
conn = H1Connection(transport, authority=origin.authority, backend=self._backend)
|
|
114
114
|
setattr(conn, PROXY_ATTR, ProxyInfo(auth=intercept.basic_auth(), headers=self._config.headers))
|
|
115
|
-
return conn
|
|
115
|
+
return await enter_connection(conn, transport, self._backend)
|
|
116
116
|
|
|
117
117
|
async def _tunnel(self, origin: Origin, intercept: typing.Any) -> typing.Any:
|
|
118
118
|
transport = await self._dial_proxy(intercept)
|
|
@@ -149,5 +149,7 @@ class ProxyConnector:
|
|
|
149
149
|
raise ProxyError(f"Cannot open a TLS tunnel to {origin} via proxy {intercept.uri}: {exc}")
|
|
150
150
|
|
|
151
151
|
if selected == "h2" or not self._http1:
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
conn = H2Connection(tls, authority=origin.authority, scheme="https", backend=self._backend)
|
|
153
|
+
else:
|
|
154
|
+
conn = H1Connection(tls, authority=origin.authority, backend=self._backend)
|
|
155
|
+
return await enter_connection(conn, tls, self._backend)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
3
4
|
import functools
|
|
4
5
|
import threading
|
|
5
6
|
import typing
|
|
@@ -302,12 +303,37 @@ class PoolTransport:
|
|
|
302
303
|
raise TimeoutException("Exceeded the total request timeout", request=request)
|
|
303
304
|
return remaining if phase is None else min(phase, remaining)
|
|
304
305
|
|
|
306
|
+
async def _abort_response(self, response):
|
|
307
|
+
with contextlib.suppress(Exception):
|
|
308
|
+
await response.aclose()
|
|
309
|
+
|
|
305
310
|
async def _send_on(self, conn: typing.Any, request: Request, read_timeout: float | None) -> typing.Any:
|
|
306
311
|
proxy_info = getattr(conn, PROXY_ATTR, None)
|
|
307
312
|
httpunk_request = _to_httpunk_request(request, h2=_is_multiplexed(conn), proxy=proxy_info)
|
|
308
313
|
if read_timeout is None:
|
|
309
314
|
return await conn.send_request(httpunk_request)
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
315
|
+
|
|
316
|
+
abandoned, sent, lock = False, [], threading.Lock()
|
|
317
|
+
|
|
318
|
+
async def send():
|
|
319
|
+
response = await conn.send_request(httpunk_request)
|
|
320
|
+
with lock:
|
|
321
|
+
if not abandoned:
|
|
322
|
+
sent.append(response)
|
|
323
|
+
return
|
|
324
|
+
# the caller is gone: nobody takes it
|
|
325
|
+
await self._abort_response(response)
|
|
326
|
+
|
|
327
|
+
try:
|
|
328
|
+
_, completed = await self._backend.timeout(send(), read_timeout)
|
|
329
|
+
if not completed:
|
|
330
|
+
raise ReadTimeout("Timed out waiting for the response", request=request)
|
|
331
|
+
except BaseException:
|
|
332
|
+
with lock:
|
|
333
|
+
abandoned = True
|
|
334
|
+
response = sent.pop() if sent else None
|
|
335
|
+
if response is not None:
|
|
336
|
+
# the caller gave up: hand over closing
|
|
337
|
+
self._backend.spawn_detached(self._abort_response(response))
|
|
338
|
+
raise
|
|
339
|
+
return sent.pop()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.4"
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "punkreq"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
description = "An async HTTP client built on httpunk"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "BSD-3-Clause"
|
|
@@ -32,12 +32,12 @@ classifiers = [
|
|
|
32
32
|
]
|
|
33
33
|
|
|
34
34
|
dependencies = [
|
|
35
|
-
"httpunk~=0.4.
|
|
35
|
+
"httpunk~=0.4.4",
|
|
36
36
|
]
|
|
37
37
|
|
|
38
38
|
[project.optional-dependencies]
|
|
39
39
|
brotli = ["brotli~=1.2.0"]
|
|
40
|
-
tonio = ["tonio~=0.
|
|
40
|
+
tonio = ["tonio~=0.10.0; python_version >= '3.14'"]
|
|
41
41
|
|
|
42
42
|
[dependency-groups]
|
|
43
43
|
lint = [
|
|
@@ -117,6 +117,7 @@ class FakeConnector:
|
|
|
117
117
|
raise punkreq.ConnectError(f"boom dialing {origin}")
|
|
118
118
|
conn = FakeConnection(self.handler, multiplexed=self.multiplexed)
|
|
119
119
|
self.connections.append(conn)
|
|
120
|
+
await conn.__aenter__() # a connector hands back an entered connection
|
|
120
121
|
return conn
|
|
121
122
|
|
|
122
123
|
@property
|
|
@@ -41,12 +41,12 @@ async def test_connector_alpn_offer_from_flags(http1, http2, offer):
|
|
|
41
41
|
context = ssl.create_default_context()
|
|
42
42
|
connector = Connector(backend=backend, ssl_context=context, http1=http1, http2=http2)
|
|
43
43
|
assert connector.alpn == offer
|
|
44
|
-
await connector(Origin("https", "example.com", 443))
|
|
44
|
+
await connector._connect_tls(Origin("https", "example.com", 443))
|
|
45
45
|
assert backend.calls == [(None, context)] # already on the context: no per-dial offer
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
async def test_connector_default_context_configured_per_dial():
|
|
49
49
|
backend = RecordingBackend("h2")
|
|
50
50
|
connector = Connector(backend=backend)
|
|
51
|
-
await connector(Origin("https", "example.com", 443))
|
|
51
|
+
await connector._connect_tls(Origin("https", "example.com", 443))
|
|
52
52
|
assert backend.calls == [(("h2", "http/1.1"), None)]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|