diff --git a/src/easynetwork/lowlevel/asyncio/_utils.py b/src/easynetwork/lowlevel/asyncio/_asyncio_utils.py similarity index 97% rename from src/easynetwork/lowlevel/asyncio/_utils.py rename to src/easynetwork/lowlevel/asyncio/_asyncio_utils.py index 5ddbf81b..1c8d0d34 100644 --- a/src/easynetwork/lowlevel/asyncio/_utils.py +++ b/src/easynetwork/lowlevel/asyncio/_asyncio_utils.py @@ -25,7 +25,7 @@ from collections.abc import Iterable, Sequence from typing import Any -from easynetwork.lowlevel._utils import set_reuseport as _set_reuseport +from .. import _utils async def ensure_resolved( @@ -159,7 +159,7 @@ def open_listener_sockets_from_getaddrinfo_result( # Will fail later on bind() pass if reuse_port: - _set_reuseport(sock) + _utils.set_reuseport(sock) # Disable IPv4/IPv6 dual stack support (enabled by # default on Linux) which makes a single socket # listen on both address families. @@ -179,7 +179,7 @@ def open_listener_sockets_from_getaddrinfo_result( if errors: # No need to call errors.clear(), this is done by exit stack - raise ExceptionGroup("Error when trying to create TCP listeners", errors) + raise ExceptionGroup("Error when trying to create listeners", errors) # There were no errors, therefore do not close the sockets socket_exit_stack.pop_all() diff --git a/src/easynetwork/lowlevel/asyncio/backend.py b/src/easynetwork/lowlevel/asyncio/backend.py index 73d4780b..6ab29064 100644 --- a/src/easynetwork/lowlevel/asyncio/backend.py +++ b/src/easynetwork/lowlevel/asyncio/backend.py @@ -40,10 +40,9 @@ ssl = _ssl del _ssl -from easynetwork.lowlevel.api_async.backend.abc import AsyncBackend as AbstractAsyncBackend -from easynetwork.lowlevel.api_async.backend.sniffio import current_async_library_cvar as _sniffio_current_async_library_cvar - -from ._utils import create_connection, ensure_resolved, open_listener_sockets_from_getaddrinfo_result +from ..api_async.backend.abc import AsyncBackend as AbstractAsyncBackend +from ..api_async.backend.sniffio import current_async_library_cvar as _sniffio_current_async_library_cvar +from ._asyncio_utils import create_connection, ensure_resolved, open_listener_sockets_from_getaddrinfo_result from .datagram.endpoint import create_datagram_endpoint from .datagram.listener import AsyncioTransportDatagramListenerSocketAdapter, RawDatagramListenerSocketAdapter from .datagram.socket import AsyncioTransportDatagramSocketAdapter, RawDatagramSocketAdapter @@ -56,7 +55,7 @@ import concurrent.futures from ssl import SSLContext as _SSLContext - from easynetwork.lowlevel.api_async.backend.abc import ILock + from ..api_async.backend.abc import ILock _P = ParamSpec("_P") _T = TypeVar("_T") diff --git a/src/easynetwork/lowlevel/asyncio/datagram/endpoint.py b/src/easynetwork/lowlevel/asyncio/datagram/endpoint.py index 5bd6d8ec..708b7448 100644 --- a/src/easynetwork/lowlevel/asyncio/datagram/endpoint.py +++ b/src/easynetwork/lowlevel/asyncio/datagram/endpoint.py @@ -30,8 +30,7 @@ import socket as _socket from typing import TYPE_CHECKING, Any, final -from easynetwork.lowlevel._utils import error_from_errno as _error_from_errno - +from ... import _utils from ..tasks import TaskUtils if TYPE_CHECKING: @@ -111,7 +110,7 @@ async def recvfrom(self) -> tuple[bytes, tuple[Any, ...]]: except asyncio.QueueEmpty: data_and_address = None if data_and_address is None: - raise _error_from_errno(_errno.ECONNABORTED) + raise _utils.error_from_errno(_errno.ECONNABORTED) await TaskUtils.cancel_shielded_coro_yield() else: data_and_address = await self.__recv_queue.get() @@ -121,13 +120,13 @@ async def recvfrom(self) -> tuple[bytes, tuple[Any, ...]]: # Connection lost otherwise assert self.__transport.is_closing() # nosec assert_used - raise _error_from_errno(_errno.ECONNABORTED) + raise _utils.error_from_errno(_errno.ECONNABORTED) return data_and_address async def sendto(self, data: bytes | bytearray | memoryview, address: tuple[Any, ...] | None = None, /) -> None: self.__check_exceptions() if self.__transport.is_closing(): - raise _error_from_errno(_errno.ECONNABORTED) + raise _utils.error_from_errno(_errno.ECONNABORTED) self.__transport.sendto(data, address) await self.__protocol._drain_helper() @@ -247,7 +246,7 @@ def resume_writing(self) -> None: async def _drain_helper(self) -> None: if self.__connection_lost: - raise _error_from_errno(_errno.ECONNABORTED) + raise _utils.error_from_errno(_errno.ECONNABORTED) if not self.__write_paused: return waiter = self.__loop.create_future() diff --git a/src/easynetwork/lowlevel/asyncio/datagram/listener.py b/src/easynetwork/lowlevel/asyncio/datagram/listener.py index 4faf8d6d..b1246661 100644 --- a/src/easynetwork/lowlevel/asyncio/datagram/listener.py +++ b/src/easynetwork/lowlevel/asyncio/datagram/listener.py @@ -25,10 +25,8 @@ from collections.abc import Callable, Mapping from typing import TYPE_CHECKING, Any, final -from easynetwork.lowlevel.api_async.transports import abc as transports -from easynetwork.lowlevel.constants import MAX_DATAGRAM_BUFSIZE -from easynetwork.lowlevel.socket import _get_socket_extra - +from ... import constants, socket as socket_tools +from ...api_async.transports import abc as transports from ..socket import AsyncSocket if TYPE_CHECKING: @@ -79,7 +77,7 @@ async def send_to(self, data: bytes | bytearray | memoryview, address: tuple[Any @property def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: socket = self.__socket - return _get_socket_extra(socket, wrap_in_proxy=False) + return socket_tools._get_socket_extra(socket, wrap_in_proxy=False) @final @@ -101,7 +99,7 @@ async def aclose(self) -> None: return await self.__socket.aclose() async def recv_from(self) -> tuple[bytes, tuple[Any, ...]]: - return await self.__socket.recvfrom(MAX_DATAGRAM_BUFSIZE) + return await self.__socket.recvfrom(constants.MAX_DATAGRAM_BUFSIZE) async def send_to(self, data: bytes | bytearray | memoryview, address: tuple[Any, ...]) -> None: await self.__socket.sendto(data, address) @@ -109,4 +107,4 @@ async def send_to(self, data: bytes | bytearray | memoryview, address: tuple[Any @property def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: socket = self.__socket.socket - return _get_socket_extra(socket, wrap_in_proxy=False) + return socket_tools._get_socket_extra(socket, wrap_in_proxy=False) diff --git a/src/easynetwork/lowlevel/asyncio/datagram/socket.py b/src/easynetwork/lowlevel/asyncio/datagram/socket.py index c2535b78..5e2ec142 100644 --- a/src/easynetwork/lowlevel/asyncio/datagram/socket.py +++ b/src/easynetwork/lowlevel/asyncio/datagram/socket.py @@ -24,10 +24,8 @@ from collections.abc import Callable, Mapping from typing import TYPE_CHECKING, Any, final -from easynetwork.lowlevel.api_async.transports import abc as transports -from easynetwork.lowlevel.constants import MAX_DATAGRAM_BUFSIZE -from easynetwork.lowlevel.socket import _get_socket_extra - +from ... import constants, socket as socket_tools +from ...api_async.transports import abc as transports from ..socket import AsyncSocket if TYPE_CHECKING: @@ -79,7 +77,7 @@ async def send(self, data: bytes | bytearray | memoryview) -> None: @property def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: socket = self.__socket - return _get_socket_extra(socket, wrap_in_proxy=False) + return socket_tools._get_socket_extra(socket, wrap_in_proxy=False) @final @@ -105,7 +103,7 @@ def is_closing(self) -> bool: return self.__socket.is_closing() async def recv(self) -> bytes: - data, _ = await self.__socket.recvfrom(MAX_DATAGRAM_BUFSIZE) + data, _ = await self.__socket.recvfrom(constants.MAX_DATAGRAM_BUFSIZE) return data async def send(self, data: bytes | bytearray | memoryview) -> None: @@ -114,4 +112,4 @@ async def send(self, data: bytes | bytearray | memoryview) -> None: @property def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: socket = self.__socket.socket - return _get_socket_extra(socket, wrap_in_proxy=False) + return socket_tools._get_socket_extra(socket, wrap_in_proxy=False) diff --git a/src/easynetwork/lowlevel/asyncio/socket.py b/src/easynetwork/lowlevel/asyncio/socket.py index c09ea8f0..0934e6e7 100644 --- a/src/easynetwork/lowlevel/asyncio/socket.py +++ b/src/easynetwork/lowlevel/asyncio/socket.py @@ -28,8 +28,7 @@ from typing import TYPE_CHECKING, Literal, Self, TypeAlias from weakref import WeakSet -from easynetwork.lowlevel._utils import check_socket_no_ssl as _check_socket_no_ssl, error_from_errno as _error_from_errno - +from .. import _utils from .tasks import CancelScope, TaskUtils if TYPE_CHECKING: @@ -55,7 +54,7 @@ class AsyncSocket: def __init__(self, socket: _socket.socket, loop: asyncio.AbstractEventLoop) -> None: super().__init__() - _check_socket_no_ssl(socket) + _utils.check_socket_no_ssl(socket) socket.setblocking(False) self.__socket: _socket.socket | None = socket @@ -151,7 +150,7 @@ async def shutdown(self, how: int, /) -> None: @contextlib.contextmanager def __conflict_detection(self, task_id: _SocketTaskId, *, abort_errno: int = _errno.EINTR) -> Iterator[None]: if task_id in self.__waiters: - raise _error_from_errno(_errno.EBUSY) + raise _utils.error_from_errno(_errno.EBUSY) _ = TaskUtils.current_asyncio_task(self.__loop) @@ -168,11 +167,11 @@ def __conflict_detection(self, task_id: _SocketTaskId, *, abort_errno: int = _er yield if scope.cancelled_caught(): - raise _error_from_errno(abort_errno) + raise _utils.error_from_errno(abort_errno) def __check_not_closed(self) -> _socket.socket: if (socket := self.__socket) is None: - raise _error_from_errno(_errno.ENOTSOCK) + raise _utils.error_from_errno(_errno.ENOTSOCK) return socket @property diff --git a/src/easynetwork/lowlevel/asyncio/stream/listener.py b/src/easynetwork/lowlevel/asyncio/stream/listener.py index 988f1465..53d13a74 100644 --- a/src/easynetwork/lowlevel/asyncio/stream/listener.py +++ b/src/easynetwork/lowlevel/asyncio/stream/listener.py @@ -30,10 +30,8 @@ from collections.abc import Callable, Coroutine, Mapping from typing import TYPE_CHECKING, Any, Generic, NoReturn, TypeVar, final -from easynetwork.lowlevel.api_async.transports import abc as transports -from easynetwork.lowlevel.constants import ACCEPT_CAPACITY_ERRNOS, ACCEPT_CAPACITY_ERROR_SLEEP_TIME, NOT_CONNECTED_SOCKET_ERRNOS -from easynetwork.lowlevel.socket import _get_socket_extra - +from ... import constants, socket as socket_tools +from ...api_async.transports import abc as transports from ..socket import AsyncSocket from ..tasks import TaskUtils from .socket import AsyncioTransportStreamSocketAdapter, RawStreamSocketAdapter @@ -42,7 +40,7 @@ import asyncio.trsock import ssl as _ssl - from easynetwork.lowlevel.api_async.backend.abc import TaskGroup as AbstractTaskGroup + from ...api_async.backend.abc import TaskGroup as AbstractTaskGroup _T_Stream = TypeVar("_T_Stream", bound=AsyncioTransportStreamSocketAdapter | RawStreamSocketAdapter) @@ -107,7 +105,7 @@ async def client_task(client_socket: _socket.socket) -> None: except BaseException as exc: client_socket.close() - if isinstance(exc, OSError) and exc.errno in NOT_CONNECTED_SOCKET_ERRNOS: + if isinstance(exc, OSError) and exc.errno in constants.NOT_CONNECTED_SOCKET_ERRNOS: # The remote host closed the connection before starting the task. # See this test for details: # test____serve_forever____accept_client____client_sent_RST_packet_right_after_accept @@ -125,15 +123,15 @@ async def client_task(client_socket: _socket.socket) -> None: try: client_socket = await self.__socket.accept() except OSError as exc: - if exc.errno in ACCEPT_CAPACITY_ERRNOS: + if exc.errno in constants.ACCEPT_CAPACITY_ERRNOS: logger.error( "accept returned %s (%s); retrying in %s seconds", _errno.errorcode[exc.errno], os.strerror(exc.errno), - ACCEPT_CAPACITY_ERROR_SLEEP_TIME, + constants.ACCEPT_CAPACITY_ERROR_SLEEP_TIME, exc_info=exc, ) - await asyncio.sleep(ACCEPT_CAPACITY_ERROR_SLEEP_TIME) + await asyncio.sleep(constants.ACCEPT_CAPACITY_ERROR_SLEEP_TIME) else: raise else: @@ -144,7 +142,7 @@ async def client_task(client_socket: _socket.socket) -> None: @property def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: socket = self.__socket.socket - return _get_socket_extra(socket, wrap_in_proxy=False) + return socket_tools._get_socket_extra(socket, wrap_in_proxy=False) class AbstractAcceptedSocketFactory(Generic[_T_Stream]): diff --git a/src/easynetwork/lowlevel/asyncio/stream/socket.py b/src/easynetwork/lowlevel/asyncio/stream/socket.py index e4afdae9..a7ddc81e 100644 --- a/src/easynetwork/lowlevel/asyncio/stream/socket.py +++ b/src/easynetwork/lowlevel/asyncio/stream/socket.py @@ -25,9 +25,8 @@ from collections.abc import Callable, Iterable, Mapping from typing import TYPE_CHECKING, Any, final -from easynetwork.lowlevel.api_async.transports import abc as transports -from easynetwork.lowlevel.socket import TLSAttribute, _get_socket_extra, _get_tls_extra - +from ... import socket as socket_tools +from ...api_async.transports import abc as transports from ..socket import AsyncSocket if TYPE_CHECKING: @@ -108,12 +107,16 @@ async def send_eof(self) -> None: @property def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: socket = self.__socket - socket_extra: dict[Any, Callable[[], Any]] = _get_socket_extra(socket, wrap_in_proxy=False) + socket_extra: dict[Any, Callable[[], Any]] = socket_tools._get_socket_extra(socket, wrap_in_proxy=False) ssl_obj: _typing_ssl.SSLObject | _typing_ssl.SSLSocket | None = self.__writer.get_extra_info("ssl_object") if ssl_obj is None: return socket_extra - return ChainMap(socket_extra, _get_tls_extra(ssl_obj), {TLSAttribute.standard_compatible: lambda: True}) + return ChainMap( + socket_extra, + socket_tools._get_tls_extra(ssl_obj), + {socket_tools.TLSAttribute.standard_compatible: lambda: True}, + ) @final @@ -155,4 +158,4 @@ async def send_eof(self) -> None: @property def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: socket = self.__socket.socket - return _get_socket_extra(socket, wrap_in_proxy=False) + return socket_tools._get_socket_extra(socket, wrap_in_proxy=False) diff --git a/src/easynetwork/lowlevel/asyncio/tasks.py b/src/easynetwork/lowlevel/asyncio/tasks.py index 85ebd867..2713033f 100644 --- a/src/easynetwork/lowlevel/asyncio/tasks.py +++ b/src/easynetwork/lowlevel/asyncio/tasks.py @@ -28,11 +28,7 @@ from typing import TYPE_CHECKING, Any, NamedTuple, Self, TypeVar, final from weakref import WeakKeyDictionary -from easynetwork.lowlevel.api_async.backend.abc import ( - CancelScope as AbstractCancelScope, - Task as AbstractTask, - TaskGroup as AbstractTaskGroup, -) +from ..api_async.backend.abc import CancelScope as AbstractCancelScope, Task as AbstractTask, TaskGroup as AbstractTaskGroup if TYPE_CHECKING: from types import TracebackType diff --git a/src/easynetwork/lowlevel/asyncio/threads.py b/src/easynetwork/lowlevel/asyncio/threads.py index 90ebcf05..342dbb04 100644 --- a/src/easynetwork/lowlevel/asyncio/threads.py +++ b/src/easynetwork/lowlevel/asyncio/threads.py @@ -26,11 +26,9 @@ from collections.abc import Awaitable, Callable from typing import TYPE_CHECKING, ParamSpec, Self, TypeVar, final -from easynetwork.lowlevel._lock import ForkSafeLock -from easynetwork.lowlevel._utils import exception_with_notes as _exception_with_notes -from easynetwork.lowlevel.api_async.backend.abc import ThreadsPortal as AbstractThreadsPortal -from easynetwork.lowlevel.api_async.backend.sniffio import current_async_library_cvar as _sniffio_current_async_library_cvar - +from .. import _lock, _utils +from ..api_async.backend.abc import ThreadsPortal as AbstractThreadsPortal +from ..api_async.backend.sniffio import current_async_library_cvar as _sniffio_current_async_library_cvar from .tasks import TaskUtils if TYPE_CHECKING: @@ -47,7 +45,7 @@ class ThreadsPortal(AbstractThreadsPortal): def __init__(self) -> None: super().__init__() self.__loop: asyncio.AbstractEventLoop | None = None - self.__lock = ForkSafeLock() + self.__lock = _lock.ForkSafeLock() self.__task_group: asyncio.TaskGroup = asyncio.TaskGroup() self.__call_soon_waiters: set[asyncio.Future[None]] = set() @@ -134,7 +132,7 @@ def callback() -> None: result.close() # Prevent ResourceWarnings msg = "func is a coroutine function." note = "You should use run_coroutine() or run_coroutine_soon() instead." - raise _exception_with_notes(TypeError(msg), note) + raise _utils.exception_with_notes(TypeError(msg), note) except BaseException as exc: future.set_exception(exc) if isinstance(exc, (SystemExit, KeyboardInterrupt)): diff --git a/tests/functional_test/test_communication/test_async/test_server/test_tcp.py b/tests/functional_test/test_communication/test_async/test_server/test_tcp.py index b59d208f..d1f87f22 100644 --- a/tests/functional_test/test_communication/test_async/test_server/test_tcp.py +++ b/tests/functional_test/test_communication/test_async/test_server/test_tcp.py @@ -20,7 +20,7 @@ StreamProtocolParseError, ) from easynetwork.lowlevel.api_async.backend.abc import AsyncBackend -from easynetwork.lowlevel.asyncio._utils import create_connection +from easynetwork.lowlevel.asyncio._asyncio_utils import create_connection from easynetwork.lowlevel.asyncio.backend import AsyncIOBackend from easynetwork.lowlevel.asyncio.stream.listener import ListenerSocketAdapter from easynetwork.lowlevel.asyncio.stream.socket import AsyncioTransportStreamSocketAdapter, RawStreamSocketAdapter diff --git a/tests/unit_test/test_async/test_asyncio_backend/test_utils.py b/tests/unit_test/test_async/test_asyncio_backend/test_utils.py index 536caa93..871d0c6e 100644 --- a/tests/unit_test/test_async/test_asyncio_backend/test_utils.py +++ b/tests/unit_test/test_async/test_asyncio_backend/test_utils.py @@ -26,7 +26,11 @@ from typing import TYPE_CHECKING, Any, Literal, assert_never, cast from easynetwork.lowlevel._utils import error_from_errno -from easynetwork.lowlevel.asyncio._utils import create_connection, ensure_resolved, open_listener_sockets_from_getaddrinfo_result +from easynetwork.lowlevel.asyncio._asyncio_utils import ( + create_connection, + ensure_resolved, + open_listener_sockets_from_getaddrinfo_result, +) import pytest @@ -592,7 +596,7 @@ def test____open_listener_sockets_from_getaddrinfo_result____bind_failed( s2.bind.side_effect = OSError(1234, "error message") # Act - with pytest.raises(ExceptionGroup) as exc_info: + with pytest.raises(ExceptionGroup, match=r"^Error when trying to create listeners \(1 sub-exception\)$") as exc_info: open_listener_sockets_from_getaddrinfo_result(addrinfo_list, backlog=10, reuse_address=True, reuse_port=False) # Assert