mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
Все подряд
This commit is contained in:
146
.venv2/Lib/site-packages/httpcore/_backends/anyio.py
Normal file
146
.venv2/Lib/site-packages/httpcore/_backends/anyio.py
Normal file
@@ -0,0 +1,146 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import ssl
|
||||
import typing
|
||||
|
||||
import anyio
|
||||
|
||||
from .._exceptions import (
|
||||
ConnectError,
|
||||
ConnectTimeout,
|
||||
ReadError,
|
||||
ReadTimeout,
|
||||
WriteError,
|
||||
WriteTimeout,
|
||||
map_exceptions,
|
||||
)
|
||||
from .._utils import is_socket_readable
|
||||
from .base import SOCKET_OPTION, AsyncNetworkBackend, AsyncNetworkStream
|
||||
|
||||
|
||||
class AnyIOStream(AsyncNetworkStream):
|
||||
def __init__(self, stream: anyio.abc.ByteStream) -> None:
|
||||
self._stream = stream
|
||||
|
||||
async def read(self, max_bytes: int, timeout: float | None = None) -> bytes:
|
||||
exc_map = {
|
||||
TimeoutError: ReadTimeout,
|
||||
anyio.BrokenResourceError: ReadError,
|
||||
anyio.ClosedResourceError: ReadError,
|
||||
anyio.EndOfStream: ReadError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
with anyio.fail_after(timeout):
|
||||
try:
|
||||
return await self._stream.receive(max_bytes=max_bytes)
|
||||
except anyio.EndOfStream: # pragma: nocover
|
||||
return b""
|
||||
|
||||
async def write(self, buffer: bytes, timeout: float | None = None) -> None:
|
||||
if not buffer:
|
||||
return
|
||||
|
||||
exc_map = {
|
||||
TimeoutError: WriteTimeout,
|
||||
anyio.BrokenResourceError: WriteError,
|
||||
anyio.ClosedResourceError: WriteError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
with anyio.fail_after(timeout):
|
||||
await self._stream.send(item=buffer)
|
||||
|
||||
async def aclose(self) -> None:
|
||||
await self._stream.aclose()
|
||||
|
||||
async def start_tls(
|
||||
self,
|
||||
ssl_context: ssl.SSLContext,
|
||||
server_hostname: str | None = None,
|
||||
timeout: float | None = None,
|
||||
) -> AsyncNetworkStream:
|
||||
exc_map = {
|
||||
TimeoutError: ConnectTimeout,
|
||||
anyio.BrokenResourceError: ConnectError,
|
||||
anyio.EndOfStream: ConnectError,
|
||||
ssl.SSLError: ConnectError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
try:
|
||||
with anyio.fail_after(timeout):
|
||||
ssl_stream = await anyio.streams.tls.TLSStream.wrap(
|
||||
self._stream,
|
||||
ssl_context=ssl_context,
|
||||
hostname=server_hostname,
|
||||
standard_compatible=False,
|
||||
server_side=False,
|
||||
)
|
||||
except Exception as exc: # pragma: nocover
|
||||
await self.aclose()
|
||||
raise exc
|
||||
return AnyIOStream(ssl_stream)
|
||||
|
||||
def get_extra_info(self, info: str) -> typing.Any:
|
||||
if info == "ssl_object":
|
||||
return self._stream.extra(anyio.streams.tls.TLSAttribute.ssl_object, None)
|
||||
if info == "client_addr":
|
||||
return self._stream.extra(anyio.abc.SocketAttribute.local_address, None)
|
||||
if info == "server_addr":
|
||||
return self._stream.extra(anyio.abc.SocketAttribute.remote_address, None)
|
||||
if info == "socket":
|
||||
return self._stream.extra(anyio.abc.SocketAttribute.raw_socket, None)
|
||||
if info == "is_readable":
|
||||
sock = self._stream.extra(anyio.abc.SocketAttribute.raw_socket, None)
|
||||
return is_socket_readable(sock)
|
||||
return None
|
||||
|
||||
|
||||
class AnyIOBackend(AsyncNetworkBackend):
|
||||
async def connect_tcp(
|
||||
self,
|
||||
host: str,
|
||||
port: int,
|
||||
timeout: float | None = None,
|
||||
local_address: str | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> AsyncNetworkStream: # pragma: nocover
|
||||
if socket_options is None:
|
||||
socket_options = []
|
||||
exc_map = {
|
||||
TimeoutError: ConnectTimeout,
|
||||
OSError: ConnectError,
|
||||
anyio.BrokenResourceError: ConnectError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
with anyio.fail_after(timeout):
|
||||
stream: anyio.abc.ByteStream = await anyio.connect_tcp(
|
||||
remote_host=host,
|
||||
remote_port=port,
|
||||
local_host=local_address,
|
||||
)
|
||||
# By default TCP sockets opened in `asyncio` include TCP_NODELAY.
|
||||
for option in socket_options:
|
||||
stream._raw_socket.setsockopt(*option) # type: ignore[attr-defined] # pragma: no cover
|
||||
return AnyIOStream(stream)
|
||||
|
||||
async def connect_unix_socket(
|
||||
self,
|
||||
path: str,
|
||||
timeout: float | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> AsyncNetworkStream: # pragma: nocover
|
||||
if socket_options is None:
|
||||
socket_options = []
|
||||
exc_map = {
|
||||
TimeoutError: ConnectTimeout,
|
||||
OSError: ConnectError,
|
||||
anyio.BrokenResourceError: ConnectError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
with anyio.fail_after(timeout):
|
||||
stream: anyio.abc.ByteStream = await anyio.connect_unix(path)
|
||||
for option in socket_options:
|
||||
stream._raw_socket.setsockopt(*option) # type: ignore[attr-defined] # pragma: no cover
|
||||
return AnyIOStream(stream)
|
||||
|
||||
async def sleep(self, seconds: float) -> None:
|
||||
await anyio.sleep(seconds) # pragma: nocover
|
52
.venv2/Lib/site-packages/httpcore/_backends/auto.py
Normal file
52
.venv2/Lib/site-packages/httpcore/_backends/auto.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
|
||||
from .._synchronization import current_async_library
|
||||
from .base import SOCKET_OPTION, AsyncNetworkBackend, AsyncNetworkStream
|
||||
|
||||
|
||||
class AutoBackend(AsyncNetworkBackend):
|
||||
async def _init_backend(self) -> None:
|
||||
if not (hasattr(self, "_backend")):
|
||||
backend = current_async_library()
|
||||
if backend == "trio":
|
||||
from .trio import TrioBackend
|
||||
|
||||
self._backend: AsyncNetworkBackend = TrioBackend()
|
||||
else:
|
||||
from .anyio import AnyIOBackend
|
||||
|
||||
self._backend = AnyIOBackend()
|
||||
|
||||
async def connect_tcp(
|
||||
self,
|
||||
host: str,
|
||||
port: int,
|
||||
timeout: float | None = None,
|
||||
local_address: str | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> AsyncNetworkStream:
|
||||
await self._init_backend()
|
||||
return await self._backend.connect_tcp(
|
||||
host,
|
||||
port,
|
||||
timeout=timeout,
|
||||
local_address=local_address,
|
||||
socket_options=socket_options,
|
||||
)
|
||||
|
||||
async def connect_unix_socket(
|
||||
self,
|
||||
path: str,
|
||||
timeout: float | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> AsyncNetworkStream: # pragma: nocover
|
||||
await self._init_backend()
|
||||
return await self._backend.connect_unix_socket(
|
||||
path, timeout=timeout, socket_options=socket_options
|
||||
)
|
||||
|
||||
async def sleep(self, seconds: float) -> None: # pragma: nocover
|
||||
await self._init_backend()
|
||||
return await self._backend.sleep(seconds)
|
101
.venv2/Lib/site-packages/httpcore/_backends/base.py
Normal file
101
.venv2/Lib/site-packages/httpcore/_backends/base.py
Normal file
@@ -0,0 +1,101 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import ssl
|
||||
import time
|
||||
import typing
|
||||
|
||||
SOCKET_OPTION = typing.Union[
|
||||
typing.Tuple[int, int, int],
|
||||
typing.Tuple[int, int, typing.Union[bytes, bytearray]],
|
||||
typing.Tuple[int, int, None, int],
|
||||
]
|
||||
|
||||
|
||||
class NetworkStream:
|
||||
def read(self, max_bytes: int, timeout: float | None = None) -> bytes:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
def write(self, buffer: bytes, timeout: float | None = None) -> None:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
def close(self) -> None:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
def start_tls(
|
||||
self,
|
||||
ssl_context: ssl.SSLContext,
|
||||
server_hostname: str | None = None,
|
||||
timeout: float | None = None,
|
||||
) -> NetworkStream:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
def get_extra_info(self, info: str) -> typing.Any:
|
||||
return None # pragma: nocover
|
||||
|
||||
|
||||
class NetworkBackend:
|
||||
def connect_tcp(
|
||||
self,
|
||||
host: str,
|
||||
port: int,
|
||||
timeout: float | None = None,
|
||||
local_address: str | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> NetworkStream:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
def connect_unix_socket(
|
||||
self,
|
||||
path: str,
|
||||
timeout: float | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> NetworkStream:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
def sleep(self, seconds: float) -> None:
|
||||
time.sleep(seconds) # pragma: nocover
|
||||
|
||||
|
||||
class AsyncNetworkStream:
|
||||
async def read(self, max_bytes: int, timeout: float | None = None) -> bytes:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
async def write(self, buffer: bytes, timeout: float | None = None) -> None:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
async def aclose(self) -> None:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
async def start_tls(
|
||||
self,
|
||||
ssl_context: ssl.SSLContext,
|
||||
server_hostname: str | None = None,
|
||||
timeout: float | None = None,
|
||||
) -> AsyncNetworkStream:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
def get_extra_info(self, info: str) -> typing.Any:
|
||||
return None # pragma: nocover
|
||||
|
||||
|
||||
class AsyncNetworkBackend:
|
||||
async def connect_tcp(
|
||||
self,
|
||||
host: str,
|
||||
port: int,
|
||||
timeout: float | None = None,
|
||||
local_address: str | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> AsyncNetworkStream:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
async def connect_unix_socket(
|
||||
self,
|
||||
path: str,
|
||||
timeout: float | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> AsyncNetworkStream:
|
||||
raise NotImplementedError() # pragma: nocover
|
||||
|
||||
async def sleep(self, seconds: float) -> None:
|
||||
raise NotImplementedError() # pragma: nocover
|
143
.venv2/Lib/site-packages/httpcore/_backends/mock.py
Normal file
143
.venv2/Lib/site-packages/httpcore/_backends/mock.py
Normal file
@@ -0,0 +1,143 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import ssl
|
||||
import typing
|
||||
|
||||
from .._exceptions import ReadError
|
||||
from .base import (
|
||||
SOCKET_OPTION,
|
||||
AsyncNetworkBackend,
|
||||
AsyncNetworkStream,
|
||||
NetworkBackend,
|
||||
NetworkStream,
|
||||
)
|
||||
|
||||
|
||||
class MockSSLObject:
|
||||
def __init__(self, http2: bool):
|
||||
self._http2 = http2
|
||||
|
||||
def selected_alpn_protocol(self) -> str:
|
||||
return "h2" if self._http2 else "http/1.1"
|
||||
|
||||
|
||||
class MockStream(NetworkStream):
|
||||
def __init__(self, buffer: list[bytes], http2: bool = False) -> None:
|
||||
self._buffer = buffer
|
||||
self._http2 = http2
|
||||
self._closed = False
|
||||
|
||||
def read(self, max_bytes: int, timeout: float | None = None) -> bytes:
|
||||
if self._closed:
|
||||
raise ReadError("Connection closed")
|
||||
if not self._buffer:
|
||||
return b""
|
||||
return self._buffer.pop(0)
|
||||
|
||||
def write(self, buffer: bytes, timeout: float | None = None) -> None:
|
||||
pass
|
||||
|
||||
def close(self) -> None:
|
||||
self._closed = True
|
||||
|
||||
def start_tls(
|
||||
self,
|
||||
ssl_context: ssl.SSLContext,
|
||||
server_hostname: str | None = None,
|
||||
timeout: float | None = None,
|
||||
) -> NetworkStream:
|
||||
return self
|
||||
|
||||
def get_extra_info(self, info: str) -> typing.Any:
|
||||
return MockSSLObject(http2=self._http2) if info == "ssl_object" else None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<httpcore.MockStream>"
|
||||
|
||||
|
||||
class MockBackend(NetworkBackend):
|
||||
def __init__(self, buffer: list[bytes], http2: bool = False) -> None:
|
||||
self._buffer = buffer
|
||||
self._http2 = http2
|
||||
|
||||
def connect_tcp(
|
||||
self,
|
||||
host: str,
|
||||
port: int,
|
||||
timeout: float | None = None,
|
||||
local_address: str | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> NetworkStream:
|
||||
return MockStream(list(self._buffer), http2=self._http2)
|
||||
|
||||
def connect_unix_socket(
|
||||
self,
|
||||
path: str,
|
||||
timeout: float | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> NetworkStream:
|
||||
return MockStream(list(self._buffer), http2=self._http2)
|
||||
|
||||
def sleep(self, seconds: float) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class AsyncMockStream(AsyncNetworkStream):
|
||||
def __init__(self, buffer: list[bytes], http2: bool = False) -> None:
|
||||
self._buffer = buffer
|
||||
self._http2 = http2
|
||||
self._closed = False
|
||||
|
||||
async def read(self, max_bytes: int, timeout: float | None = None) -> bytes:
|
||||
if self._closed:
|
||||
raise ReadError("Connection closed")
|
||||
if not self._buffer:
|
||||
return b""
|
||||
return self._buffer.pop(0)
|
||||
|
||||
async def write(self, buffer: bytes, timeout: float | None = None) -> None:
|
||||
pass
|
||||
|
||||
async def aclose(self) -> None:
|
||||
self._closed = True
|
||||
|
||||
async def start_tls(
|
||||
self,
|
||||
ssl_context: ssl.SSLContext,
|
||||
server_hostname: str | None = None,
|
||||
timeout: float | None = None,
|
||||
) -> AsyncNetworkStream:
|
||||
return self
|
||||
|
||||
def get_extra_info(self, info: str) -> typing.Any:
|
||||
return MockSSLObject(http2=self._http2) if info == "ssl_object" else None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<httpcore.AsyncMockStream>"
|
||||
|
||||
|
||||
class AsyncMockBackend(AsyncNetworkBackend):
|
||||
def __init__(self, buffer: list[bytes], http2: bool = False) -> None:
|
||||
self._buffer = buffer
|
||||
self._http2 = http2
|
||||
|
||||
async def connect_tcp(
|
||||
self,
|
||||
host: str,
|
||||
port: int,
|
||||
timeout: float | None = None,
|
||||
local_address: str | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> AsyncNetworkStream:
|
||||
return AsyncMockStream(list(self._buffer), http2=self._http2)
|
||||
|
||||
async def connect_unix_socket(
|
||||
self,
|
||||
path: str,
|
||||
timeout: float | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> AsyncNetworkStream:
|
||||
return AsyncMockStream(list(self._buffer), http2=self._http2)
|
||||
|
||||
async def sleep(self, seconds: float) -> None:
|
||||
pass
|
241
.venv2/Lib/site-packages/httpcore/_backends/sync.py
Normal file
241
.venv2/Lib/site-packages/httpcore/_backends/sync.py
Normal file
@@ -0,0 +1,241 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
import socket
|
||||
import ssl
|
||||
import sys
|
||||
import typing
|
||||
|
||||
from .._exceptions import (
|
||||
ConnectError,
|
||||
ConnectTimeout,
|
||||
ExceptionMapping,
|
||||
ReadError,
|
||||
ReadTimeout,
|
||||
WriteError,
|
||||
WriteTimeout,
|
||||
map_exceptions,
|
||||
)
|
||||
from .._utils import is_socket_readable
|
||||
from .base import SOCKET_OPTION, NetworkBackend, NetworkStream
|
||||
|
||||
|
||||
class TLSinTLSStream(NetworkStream): # pragma: no cover
|
||||
"""
|
||||
Because the standard `SSLContext.wrap_socket` method does
|
||||
not work for `SSLSocket` objects, we need this class
|
||||
to implement TLS stream using an underlying `SSLObject`
|
||||
instance in order to support TLS on top of TLS.
|
||||
"""
|
||||
|
||||
# Defined in RFC 8449
|
||||
TLS_RECORD_SIZE = 16384
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
sock: socket.socket,
|
||||
ssl_context: ssl.SSLContext,
|
||||
server_hostname: str | None = None,
|
||||
timeout: float | None = None,
|
||||
):
|
||||
self._sock = sock
|
||||
self._incoming = ssl.MemoryBIO()
|
||||
self._outgoing = ssl.MemoryBIO()
|
||||
|
||||
self.ssl_obj = ssl_context.wrap_bio(
|
||||
incoming=self._incoming,
|
||||
outgoing=self._outgoing,
|
||||
server_hostname=server_hostname,
|
||||
)
|
||||
|
||||
self._sock.settimeout(timeout)
|
||||
self._perform_io(self.ssl_obj.do_handshake)
|
||||
|
||||
def _perform_io(
|
||||
self,
|
||||
func: typing.Callable[..., typing.Any],
|
||||
) -> typing.Any:
|
||||
ret = None
|
||||
|
||||
while True:
|
||||
errno = None
|
||||
try:
|
||||
ret = func()
|
||||
except (ssl.SSLWantReadError, ssl.SSLWantWriteError) as e:
|
||||
errno = e.errno
|
||||
|
||||
self._sock.sendall(self._outgoing.read())
|
||||
|
||||
if errno == ssl.SSL_ERROR_WANT_READ:
|
||||
buf = self._sock.recv(self.TLS_RECORD_SIZE)
|
||||
|
||||
if buf:
|
||||
self._incoming.write(buf)
|
||||
else:
|
||||
self._incoming.write_eof()
|
||||
if errno is None:
|
||||
return ret
|
||||
|
||||
def read(self, max_bytes: int, timeout: float | None = None) -> bytes:
|
||||
exc_map: ExceptionMapping = {socket.timeout: ReadTimeout, OSError: ReadError}
|
||||
with map_exceptions(exc_map):
|
||||
self._sock.settimeout(timeout)
|
||||
return typing.cast(
|
||||
bytes, self._perform_io(functools.partial(self.ssl_obj.read, max_bytes))
|
||||
)
|
||||
|
||||
def write(self, buffer: bytes, timeout: float | None = None) -> None:
|
||||
exc_map: ExceptionMapping = {socket.timeout: WriteTimeout, OSError: WriteError}
|
||||
with map_exceptions(exc_map):
|
||||
self._sock.settimeout(timeout)
|
||||
while buffer:
|
||||
nsent = self._perform_io(functools.partial(self.ssl_obj.write, buffer))
|
||||
buffer = buffer[nsent:]
|
||||
|
||||
def close(self) -> None:
|
||||
self._sock.close()
|
||||
|
||||
def start_tls(
|
||||
self,
|
||||
ssl_context: ssl.SSLContext,
|
||||
server_hostname: str | None = None,
|
||||
timeout: float | None = None,
|
||||
) -> NetworkStream:
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_extra_info(self, info: str) -> typing.Any:
|
||||
if info == "ssl_object":
|
||||
return self.ssl_obj
|
||||
if info == "client_addr":
|
||||
return self._sock.getsockname()
|
||||
if info == "server_addr":
|
||||
return self._sock.getpeername()
|
||||
if info == "socket":
|
||||
return self._sock
|
||||
if info == "is_readable":
|
||||
return is_socket_readable(self._sock)
|
||||
return None
|
||||
|
||||
|
||||
class SyncStream(NetworkStream):
|
||||
def __init__(self, sock: socket.socket) -> None:
|
||||
self._sock = sock
|
||||
|
||||
def read(self, max_bytes: int, timeout: float | None = None) -> bytes:
|
||||
exc_map: ExceptionMapping = {socket.timeout: ReadTimeout, OSError: ReadError}
|
||||
with map_exceptions(exc_map):
|
||||
self._sock.settimeout(timeout)
|
||||
return self._sock.recv(max_bytes)
|
||||
|
||||
def write(self, buffer: bytes, timeout: float | None = None) -> None:
|
||||
if not buffer:
|
||||
return
|
||||
|
||||
exc_map: ExceptionMapping = {socket.timeout: WriteTimeout, OSError: WriteError}
|
||||
with map_exceptions(exc_map):
|
||||
while buffer:
|
||||
self._sock.settimeout(timeout)
|
||||
n = self._sock.send(buffer)
|
||||
buffer = buffer[n:]
|
||||
|
||||
def close(self) -> None:
|
||||
self._sock.close()
|
||||
|
||||
def start_tls(
|
||||
self,
|
||||
ssl_context: ssl.SSLContext,
|
||||
server_hostname: str | None = None,
|
||||
timeout: float | None = None,
|
||||
) -> NetworkStream:
|
||||
exc_map: ExceptionMapping = {
|
||||
socket.timeout: ConnectTimeout,
|
||||
OSError: ConnectError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
try:
|
||||
if isinstance(self._sock, ssl.SSLSocket): # pragma: no cover
|
||||
# If the underlying socket has already been upgraded
|
||||
# to the TLS layer (i.e. is an instance of SSLSocket),
|
||||
# we need some additional smarts to support TLS-in-TLS.
|
||||
return TLSinTLSStream(
|
||||
self._sock, ssl_context, server_hostname, timeout
|
||||
)
|
||||
else:
|
||||
self._sock.settimeout(timeout)
|
||||
sock = ssl_context.wrap_socket(
|
||||
self._sock, server_hostname=server_hostname
|
||||
)
|
||||
except Exception as exc: # pragma: nocover
|
||||
self.close()
|
||||
raise exc
|
||||
return SyncStream(sock)
|
||||
|
||||
def get_extra_info(self, info: str) -> typing.Any:
|
||||
if info == "ssl_object" and isinstance(self._sock, ssl.SSLSocket):
|
||||
return self._sock._sslobj # type: ignore
|
||||
if info == "client_addr":
|
||||
return self._sock.getsockname()
|
||||
if info == "server_addr":
|
||||
return self._sock.getpeername()
|
||||
if info == "socket":
|
||||
return self._sock
|
||||
if info == "is_readable":
|
||||
return is_socket_readable(self._sock)
|
||||
return None
|
||||
|
||||
|
||||
class SyncBackend(NetworkBackend):
|
||||
def connect_tcp(
|
||||
self,
|
||||
host: str,
|
||||
port: int,
|
||||
timeout: float | None = None,
|
||||
local_address: str | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> NetworkStream:
|
||||
# Note that we automatically include `TCP_NODELAY`
|
||||
# in addition to any other custom socket options.
|
||||
if socket_options is None:
|
||||
socket_options = [] # pragma: no cover
|
||||
address = (host, port)
|
||||
source_address = None if local_address is None else (local_address, 0)
|
||||
exc_map: ExceptionMapping = {
|
||||
socket.timeout: ConnectTimeout,
|
||||
OSError: ConnectError,
|
||||
}
|
||||
|
||||
with map_exceptions(exc_map):
|
||||
sock = socket.create_connection(
|
||||
address,
|
||||
timeout,
|
||||
source_address=source_address,
|
||||
)
|
||||
for option in socket_options:
|
||||
sock.setsockopt(*option) # pragma: no cover
|
||||
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
return SyncStream(sock)
|
||||
|
||||
def connect_unix_socket(
|
||||
self,
|
||||
path: str,
|
||||
timeout: float | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> NetworkStream: # pragma: nocover
|
||||
if sys.platform == "win32":
|
||||
raise RuntimeError(
|
||||
"Attempted to connect to a UNIX socket on a Windows system."
|
||||
)
|
||||
if socket_options is None:
|
||||
socket_options = []
|
||||
|
||||
exc_map: ExceptionMapping = {
|
||||
socket.timeout: ConnectTimeout,
|
||||
OSError: ConnectError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
for option in socket_options:
|
||||
sock.setsockopt(*option)
|
||||
sock.settimeout(timeout)
|
||||
sock.connect(path)
|
||||
return SyncStream(sock)
|
159
.venv2/Lib/site-packages/httpcore/_backends/trio.py
Normal file
159
.venv2/Lib/site-packages/httpcore/_backends/trio.py
Normal file
@@ -0,0 +1,159 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import ssl
|
||||
import typing
|
||||
|
||||
import trio
|
||||
|
||||
from .._exceptions import (
|
||||
ConnectError,
|
||||
ConnectTimeout,
|
||||
ExceptionMapping,
|
||||
ReadError,
|
||||
ReadTimeout,
|
||||
WriteError,
|
||||
WriteTimeout,
|
||||
map_exceptions,
|
||||
)
|
||||
from .base import SOCKET_OPTION, AsyncNetworkBackend, AsyncNetworkStream
|
||||
|
||||
|
||||
class TrioStream(AsyncNetworkStream):
|
||||
def __init__(self, stream: trio.abc.Stream) -> None:
|
||||
self._stream = stream
|
||||
|
||||
async def read(self, max_bytes: int, timeout: float | None = None) -> bytes:
|
||||
timeout_or_inf = float("inf") if timeout is None else timeout
|
||||
exc_map: ExceptionMapping = {
|
||||
trio.TooSlowError: ReadTimeout,
|
||||
trio.BrokenResourceError: ReadError,
|
||||
trio.ClosedResourceError: ReadError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
with trio.fail_after(timeout_or_inf):
|
||||
data: bytes = await self._stream.receive_some(max_bytes=max_bytes)
|
||||
return data
|
||||
|
||||
async def write(self, buffer: bytes, timeout: float | None = None) -> None:
|
||||
if not buffer:
|
||||
return
|
||||
|
||||
timeout_or_inf = float("inf") if timeout is None else timeout
|
||||
exc_map: ExceptionMapping = {
|
||||
trio.TooSlowError: WriteTimeout,
|
||||
trio.BrokenResourceError: WriteError,
|
||||
trio.ClosedResourceError: WriteError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
with trio.fail_after(timeout_or_inf):
|
||||
await self._stream.send_all(data=buffer)
|
||||
|
||||
async def aclose(self) -> None:
|
||||
await self._stream.aclose()
|
||||
|
||||
async def start_tls(
|
||||
self,
|
||||
ssl_context: ssl.SSLContext,
|
||||
server_hostname: str | None = None,
|
||||
timeout: float | None = None,
|
||||
) -> AsyncNetworkStream:
|
||||
timeout_or_inf = float("inf") if timeout is None else timeout
|
||||
exc_map: ExceptionMapping = {
|
||||
trio.TooSlowError: ConnectTimeout,
|
||||
trio.BrokenResourceError: ConnectError,
|
||||
}
|
||||
ssl_stream = trio.SSLStream(
|
||||
self._stream,
|
||||
ssl_context=ssl_context,
|
||||
server_hostname=server_hostname,
|
||||
https_compatible=True,
|
||||
server_side=False,
|
||||
)
|
||||
with map_exceptions(exc_map):
|
||||
try:
|
||||
with trio.fail_after(timeout_or_inf):
|
||||
await ssl_stream.do_handshake()
|
||||
except Exception as exc: # pragma: nocover
|
||||
await self.aclose()
|
||||
raise exc
|
||||
return TrioStream(ssl_stream)
|
||||
|
||||
def get_extra_info(self, info: str) -> typing.Any:
|
||||
if info == "ssl_object" and isinstance(self._stream, trio.SSLStream):
|
||||
# Type checkers cannot see `_ssl_object` attribute because trio._ssl.SSLStream uses __getattr__/__setattr__.
|
||||
# Tracked at https://github.com/python-trio/trio/issues/542
|
||||
return self._stream._ssl_object # type: ignore[attr-defined]
|
||||
if info == "client_addr":
|
||||
return self._get_socket_stream().socket.getsockname()
|
||||
if info == "server_addr":
|
||||
return self._get_socket_stream().socket.getpeername()
|
||||
if info == "socket":
|
||||
stream = self._stream
|
||||
while isinstance(stream, trio.SSLStream):
|
||||
stream = stream.transport_stream
|
||||
assert isinstance(stream, trio.SocketStream)
|
||||
return stream.socket
|
||||
if info == "is_readable":
|
||||
socket = self.get_extra_info("socket")
|
||||
return socket.is_readable()
|
||||
return None
|
||||
|
||||
def _get_socket_stream(self) -> trio.SocketStream:
|
||||
stream = self._stream
|
||||
while isinstance(stream, trio.SSLStream):
|
||||
stream = stream.transport_stream
|
||||
assert isinstance(stream, trio.SocketStream)
|
||||
return stream
|
||||
|
||||
|
||||
class TrioBackend(AsyncNetworkBackend):
|
||||
async def connect_tcp(
|
||||
self,
|
||||
host: str,
|
||||
port: int,
|
||||
timeout: float | None = None,
|
||||
local_address: str | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> AsyncNetworkStream:
|
||||
# By default for TCP sockets, trio enables TCP_NODELAY.
|
||||
# https://trio.readthedocs.io/en/stable/reference-io.html#trio.SocketStream
|
||||
if socket_options is None:
|
||||
socket_options = [] # pragma: no cover
|
||||
timeout_or_inf = float("inf") if timeout is None else timeout
|
||||
exc_map: ExceptionMapping = {
|
||||
trio.TooSlowError: ConnectTimeout,
|
||||
trio.BrokenResourceError: ConnectError,
|
||||
OSError: ConnectError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
with trio.fail_after(timeout_or_inf):
|
||||
stream: trio.abc.Stream = await trio.open_tcp_stream(
|
||||
host=host, port=port, local_address=local_address
|
||||
)
|
||||
for option in socket_options:
|
||||
stream.setsockopt(*option) # type: ignore[attr-defined] # pragma: no cover
|
||||
return TrioStream(stream)
|
||||
|
||||
async def connect_unix_socket(
|
||||
self,
|
||||
path: str,
|
||||
timeout: float | None = None,
|
||||
socket_options: typing.Iterable[SOCKET_OPTION] | None = None,
|
||||
) -> AsyncNetworkStream: # pragma: nocover
|
||||
if socket_options is None:
|
||||
socket_options = []
|
||||
timeout_or_inf = float("inf") if timeout is None else timeout
|
||||
exc_map: ExceptionMapping = {
|
||||
trio.TooSlowError: ConnectTimeout,
|
||||
trio.BrokenResourceError: ConnectError,
|
||||
OSError: ConnectError,
|
||||
}
|
||||
with map_exceptions(exc_map):
|
||||
with trio.fail_after(timeout_or_inf):
|
||||
stream: trio.abc.Stream = await trio.open_unix_socket(path)
|
||||
for option in socket_options:
|
||||
stream.setsockopt(*option) # type: ignore[attr-defined] # pragma: no cover
|
||||
return TrioStream(stream)
|
||||
|
||||
async def sleep(self, seconds: float) -> None:
|
||||
await trio.sleep(seconds) # pragma: nocover
|
Reference in New Issue
Block a user