Skip to content

Commit

Permalink
[ADD] Added UnsupportedOperation exception
Browse files Browse the repository at this point in the history
  • Loading branch information
francis-clairicia committed Nov 11, 2023
1 parent 8e2c1d7 commit c1e20e9
Show file tree
Hide file tree
Showing 16 changed files with 53 additions and 32 deletions.
7 changes: 7 additions & 0 deletions src/easynetwork/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"ServerClosedError",
"StreamProtocolParseError",
"TypedAttributeLookupError",
"UnsupportedOperation",
]

from typing import TYPE_CHECKING, Any
Expand Down Expand Up @@ -174,3 +175,9 @@ class TypedAttributeLookupError(LookupError):
Raised by :meth:`~.TypedAttributeProvider.extra` when the given typed attribute
is not found and no default value has been given.
"""


class UnsupportedOperation(NotImplementedError):
"""
The requested action is currently unavailable.
"""
5 changes: 3 additions & 2 deletions src/easynetwork/lowlevel/api_async/endpoints/datagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from .... import protocol as protocol_module
from ...._typevars import _ReceivedPacketT, _SentPacketT
from ....exceptions import UnsupportedOperation
from ... import _utils, typed_attr
from ..transports import abc as transports

Expand Down Expand Up @@ -97,7 +98,7 @@ async def send_packet(self, packet: _SentPacketT) -> None:
protocol = self.__protocol

if not self.__supports_write(transport):
raise NotImplementedError("transport does not support sending data")
raise UnsupportedOperation("transport does not support sending data")

await transport.send(protocol.make_datagram(packet))

Expand All @@ -116,7 +117,7 @@ async def recv_packet(self) -> _ReceivedPacketT:
protocol = self.__protocol

if not self.__supports_read(transport):
raise NotImplementedError("transport does not support receiving data")
raise UnsupportedOperation("transport does not support receiving data")

return protocol.build_packet_from_datagram(await transport.recv())

Expand Down
7 changes: 4 additions & 3 deletions src/easynetwork/lowlevel/api_async/endpoints/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from .... import protocol as protocol_module
from ...._typevars import _ReceivedPacketT, _SentPacketT
from ....exceptions import UnsupportedOperation
from ... import _stream, _utils, typed_attr
from ..transports import abc as transports

Expand Down Expand Up @@ -116,7 +117,7 @@ async def send_packet(self, packet: _SentPacketT) -> None:
producer = self.__producer

if not self.__supports_write(transport):
raise NotImplementedError("transport does not support sending data")
raise UnsupportedOperation("transport does not support sending data")

producer.enqueue(packet)
await transport.send_all_from_iterable(producer)
Expand All @@ -137,7 +138,7 @@ async def send_eof(self) -> None:
producer = self.__producer

if not self.__supports_sending_eof(transport):
raise NotImplementedError("transport does not support sending EOF")
raise UnsupportedOperation("transport does not support sending EOF")

await transport.send_eof()
self.__eof_sent = True
Expand All @@ -159,7 +160,7 @@ async def recv_packet(self) -> _ReceivedPacketT:
consumer = self.__consumer

if not self.__supports_read(transport):
raise NotImplementedError("transport does not support receiving data")
raise UnsupportedOperation("transport does not support receiving data")

try:
return next(consumer) # If there is enough data from last call to create a packet, return immediately
Expand Down
5 changes: 3 additions & 2 deletions src/easynetwork/lowlevel/api_sync/endpoints/datagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from .... import protocol as protocol_module
from ...._typevars import _ReceivedPacketT, _SentPacketT
from ....exceptions import UnsupportedOperation
from ... import typed_attr
from ..transports import abc as transports

Expand Down Expand Up @@ -109,7 +110,7 @@ def send_packet(self, packet: _SentPacketT, *, timeout: float | None = None) ->
protocol = self.__protocol

if not self.__supports_write(transport):
raise NotImplementedError("transport does not support sending data")
raise UnsupportedOperation("transport does not support sending data")

transport.send(protocol.make_datagram(packet), timeout)

Expand All @@ -136,7 +137,7 @@ def recv_packet(self, *, timeout: float | None = None) -> _ReceivedPacketT:
protocol = self.__protocol

if not self.__supports_read(transport):
raise NotImplementedError("transport does not support receiving data")
raise UnsupportedOperation("transport does not support receiving data")

return protocol.build_packet_from_datagram(transport.recv(timeout))

Expand Down
7 changes: 4 additions & 3 deletions src/easynetwork/lowlevel/api_sync/endpoints/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

from .... import protocol as protocol_module
from ...._typevars import _ReceivedPacketT, _SentPacketT
from ....exceptions import UnsupportedOperation
from ... import _stream, _utils, typed_attr
from ..transports import abc as transports

Expand Down Expand Up @@ -130,7 +131,7 @@ def send_packet(self, packet: _SentPacketT, *, timeout: float | None = None) ->
producer = self.__producer

if not self.__supports_write(transport):
raise NotImplementedError("transport does not support sending data")
raise UnsupportedOperation("transport does not support sending data")

producer.enqueue(packet)
transport.send_all_from_iterable(producer, timeout)
Expand All @@ -150,7 +151,7 @@ def send_eof(self) -> None:
producer = self.__producer

if not self.__supports_sending_eof(transport):
raise NotImplementedError("transport does not support sending EOF")
raise UnsupportedOperation("transport does not support sending EOF")

transport.send_eof()
self.__eof_sent = True
Expand Down Expand Up @@ -180,7 +181,7 @@ def recv_packet(self, *, timeout: float | None = None) -> _ReceivedPacketT:
consumer = self.__consumer

if not self.__supports_read(transport):
raise NotImplementedError("transport does not support receiving data")
raise UnsupportedOperation("transport does not support receiving data")

try:
return next(consumer) # If there is enough data from last call to create a packet, return immediately
Expand Down
3 changes: 2 additions & 1 deletion src/easynetwork/lowlevel/api_sync/transports/socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
_ssl_module = ssl
del ssl

from ....exceptions import UnsupportedOperation
from ... import _utils, constants, socket as socket_tools
from . import base_selector

Expand Down Expand Up @@ -194,7 +195,7 @@ def send_noblock(self, data: bytes | bytearray | memoryview) -> int:
@_utils.inherit_doc(base_selector.SelectorStreamTransport)
def send_eof(self) -> None:
# ssl.SSLSocket.shutdown() would close both read and write streams
raise NotImplementedError("SSL/TLS API does not support sending EOF.")
raise UnsupportedOperation("SSL/TLS API does not support sending EOF.")

def _try_ssl_method(self, socket_method: Callable[_P, _R], /, *args: _P.args, **kwargs: _P.kwargs) -> _R:
if _ssl_module is None:
Expand Down
3 changes: 2 additions & 1 deletion src/easynetwork/lowlevel/asyncio/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
ssl = _ssl
del _ssl

from ...exceptions import UnsupportedOperation
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, open_listener_sockets_from_getaddrinfo_result, resolve_local_addresses
Expand Down Expand Up @@ -426,7 +427,7 @@ def using_asyncio_transport(self) -> bool:
def _check_asyncio_transport(self, context: str) -> None:
transport = self.__use_asyncio_transport
if not transport:
raise ValueError(f"{context} not supported with {transport=}")
raise UnsupportedOperation(f"{context} not supported with {transport=}")

def _check_ssl_support(self) -> None:
self._check_asyncio_transport("SSL/TLS")
Expand Down
3 changes: 3 additions & 0 deletions src/easynetwork/lowlevel/asyncio/stream/socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from collections.abc import Callable, Iterable, Mapping
from typing import TYPE_CHECKING, Any, final

from ....exceptions import UnsupportedOperation
from ... import socket as socket_tools
from ...api_async.transports import abc as transports
from ..socket import AsyncSocket
Expand Down Expand Up @@ -101,6 +102,8 @@ async def send_all_from_iterable(self, iterable_of_data: Iterable[bytes | bytear
await self.__writer.drain()

async def send_eof(self) -> None:
if not self.__writer.can_write_eof():
raise UnsupportedOperation("transport does not support sending EOF")
self.__writer.write_eof()
await asyncio.sleep(0)

Expand Down
2 changes: 1 addition & 1 deletion tests/functional_test/test_communication/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def localhost_ip(socket_family: int) -> str:

@pytest.fixture
def socket_factory(socket_family: int) -> Iterator[Callable[[int], Socket]]:
if not HAS_IPV6:
if not HAS_IPV6 and socket_family == AF_INET6:
pytest.skip("socket.has_ipv6 is False")

socket_stack = ExitStack()
Expand Down
11 changes: 6 additions & 5 deletions tests/unit_test/test_async/test_asyncio_backend/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from socket import AF_INET, AF_INET6, AF_UNSPEC, AI_ADDRCONFIG, AI_PASSIVE, IPPROTO_TCP, IPPROTO_UDP, SOCK_DGRAM, SOCK_STREAM
from typing import TYPE_CHECKING, Any, cast

from easynetwork.exceptions import UnsupportedOperation
from easynetwork.lowlevel.asyncio import AsyncIOBackend
from easynetwork.lowlevel.asyncio.stream.listener import (
AbstractAcceptedSocketFactory,
Expand Down Expand Up @@ -419,7 +420,7 @@ async def test____create_tcp_connection____happy_eyeballs_delay_not_supported(
)

# Act
with pytest.raises(ValueError, match=r"^'happy_eyeballs_delay' option not supported with transport=False$"):
with pytest.raises(UnsupportedOperation, match=r"^'happy_eyeballs_delay' option not supported with transport=False$"):
await backend.create_tcp_connection(
*remote_address,
happy_eyeballs_delay=42,
Expand Down Expand Up @@ -459,7 +460,7 @@ async def test____create_ssl_over_tcp_connection____ssl_not_supported(
)

# Act
with pytest.raises(ValueError, match=r"^SSL\/TLS not supported with transport=False$"):
with pytest.raises(UnsupportedOperation, match=r"^SSL\/TLS not supported with transport=False$"):
await backend.create_ssl_over_tcp_connection(
*remote_address,
ssl_context=mock_ssl_context,
Expand Down Expand Up @@ -612,7 +613,7 @@ async def test____wrap_ssl_over_stream_socket____use_asyncio_open_connection(

# Act
with (
pytest.raises(ValueError, match=r"^SSL\/TLS not supported with transport=False$")
pytest.raises(UnsupportedOperation, match=r"^SSL\/TLS not supported with transport=False$")
if not use_asyncio_transport
else contextlib.nullcontext()
):
Expand Down Expand Up @@ -668,7 +669,7 @@ async def test____wrap_ssl_over_stream_socket____ssl_not_supported(
)

# Act
with pytest.raises(ValueError, match=r"^SSL\/TLS not supported with transport=False$"):
with pytest.raises(UnsupportedOperation, match=r"^SSL\/TLS not supported with transport=False$"):
await backend.wrap_ssl_over_stream_socket_client_side(
mock_tcp_socket,
ssl_context=mock_ssl_context,
Expand Down Expand Up @@ -1154,7 +1155,7 @@ async def test____create_ssl_over_tcp_listeners____ssl_not_supported(
)

# Act
with pytest.raises(ValueError, match=r"^SSL\/TLS not supported with transport=False$"):
with pytest.raises(UnsupportedOperation, match=r"^SSL\/TLS not supported with transport=False$"):
await backend.create_ssl_over_tcp_listeners(
remote_host,
remote_port,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import contextlib
from typing import TYPE_CHECKING, Any

from easynetwork.exceptions import UnsupportedOperation
from easynetwork.lowlevel.api_async.endpoints.datagram import AsyncDatagramEndpoint
from easynetwork.lowlevel.api_async.transports.abc import (
AsyncDatagramReadTransport,
Expand Down Expand Up @@ -134,7 +135,7 @@ async def test____send_packet____send_bytes_to_transport(

# Act
with (
pytest.raises(NotImplementedError, match=r"^transport does not support sending data$")
pytest.raises(UnsupportedOperation, match=r"^transport does not support sending data$")
if mock_datagram_transport.__class__ not in (AsyncDatagramWriteTransport, AsyncDatagramTransport)
else contextlib.nullcontext()
):
Expand All @@ -161,7 +162,7 @@ async def test____recv_packet____receive_bytes_from_transport(
# Act
packet: Any = mocker.sentinel.packet_not_received
with (
pytest.raises(NotImplementedError, match=r"^transport does not support receiving data$")
pytest.raises(UnsupportedOperation, match=r"^transport does not support receiving data$")
if mock_datagram_transport.__class__ not in (AsyncDatagramReadTransport, AsyncDatagramTransport)
else contextlib.nullcontext()
):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from collections.abc import Generator
from typing import TYPE_CHECKING, Any

from easynetwork.exceptions import UnsupportedOperation
from easynetwork.lowlevel._stream import StreamDataConsumer
from easynetwork.lowlevel.api_async.endpoints.stream import AsyncStreamEndpoint
from easynetwork.lowlevel.api_async.transports.abc import (
Expand Down Expand Up @@ -183,7 +184,7 @@ async def test____send_packet____send_bytes_to_transport(

# Act
with (
pytest.raises(NotImplementedError, match=r"^transport does not support sending data$")
pytest.raises(UnsupportedOperation, match=r"^transport does not support sending data$")
if mock_stream_transport.__class__ not in (AsyncStreamWriteTransport, AsyncStreamTransport)
else contextlib.nullcontext()
):
Expand Down Expand Up @@ -212,7 +213,7 @@ async def test____send_eof____default(

# Act
with (
pytest.raises(NotImplementedError, match=r"^transport does not support sending EOF$")
pytest.raises(UnsupportedOperation, match=r"^transport does not support sending EOF$")
if mock_stream_transport.__class__ is not AsyncStreamTransport
else contextlib.nullcontext()
):
Expand Down Expand Up @@ -262,7 +263,7 @@ async def test____recv_packet____receive_bytes_from_transport(
# Act
packet: Any = mocker.sentinel.packet_not_received
with (
pytest.raises(NotImplementedError, match=r"^transport does not support receiving data$")
pytest.raises(UnsupportedOperation, match=r"^transport does not support receiving data$")
if mock_stream_transport.__class__ not in (AsyncStreamReadTransport, AsyncStreamTransport)
else contextlib.nullcontext()
):
Expand Down
4 changes: 2 additions & 2 deletions tests/unit_test/test_sync/test_client/test_tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from typing import TYPE_CHECKING, Any

from easynetwork.api_sync.client.tcp import TCPNetworkClient
from easynetwork.exceptions import ClientClosedError, IncrementalDeserializeError
from easynetwork.exceptions import ClientClosedError, IncrementalDeserializeError, UnsupportedOperation
from easynetwork.lowlevel._stream import StreamDataConsumer
from easynetwork.lowlevel.constants import (
CLOSED_SOCKET_ERRNOS,
Expand Down Expand Up @@ -1467,7 +1467,7 @@ def test____send_eof____ssl____operation_not_supported(
mock_used_socket.shutdown.return_value = None

# Act
with pytest.raises(NotImplementedError):
with pytest.raises(UnsupportedOperation):
client.send_eof()

# Assert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import math
from typing import TYPE_CHECKING, Any

from easynetwork.exceptions import UnsupportedOperation
from easynetwork.lowlevel.api_sync.endpoints.datagram import DatagramEndpoint
from easynetwork.lowlevel.api_sync.transports.abc import DatagramReadTransport, DatagramTransport, DatagramWriteTransport

Expand Down Expand Up @@ -166,7 +167,7 @@ def test____send_packet____send_bytes_to_transport(

# Act
with (
pytest.raises(NotImplementedError, match=r"^transport does not support sending data$")
pytest.raises(UnsupportedOperation, match=r"^transport does not support sending data$")
if mock_datagram_transport.__class__ not in (DatagramWriteTransport, DatagramTransport)
else contextlib.nullcontext()
):
Expand Down Expand Up @@ -195,7 +196,7 @@ def test____recv_packet____receive_bytes_from_transport(
# Act
packet: Any = mocker.sentinel.packet_not_received
with (
pytest.raises(NotImplementedError, match=r"^transport does not support receiving data$")
pytest.raises(UnsupportedOperation, match=r"^transport does not support receiving data$")
if mock_datagram_transport.__class__ not in (DatagramReadTransport, DatagramTransport)
else contextlib.nullcontext()
):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from collections.abc import Generator
from typing import TYPE_CHECKING, Any

from easynetwork.exceptions import UnsupportedOperation
from easynetwork.lowlevel._stream import StreamDataConsumer
from easynetwork.lowlevel.api_sync.endpoints.stream import StreamEndpoint
from easynetwork.lowlevel.api_sync.transports.abc import StreamReadTransport, StreamTransport, StreamWriteTransport
Expand Down Expand Up @@ -224,7 +225,7 @@ def test____send_packet____send_bytes_to_transport(

# Act
with (
pytest.raises(NotImplementedError, match=r"^transport does not support sending data$")
pytest.raises(UnsupportedOperation, match=r"^transport does not support sending data$")
if mock_stream_transport.__class__ not in (StreamWriteTransport, StreamTransport)
else contextlib.nullcontext()
):
Expand Down Expand Up @@ -253,7 +254,7 @@ def test____send_eof____default(

# Act
with (
pytest.raises(NotImplementedError, match=r"^transport does not support sending EOF$")
pytest.raises(UnsupportedOperation, match=r"^transport does not support sending EOF$")
if mock_stream_transport.__class__ is not StreamTransport
else contextlib.nullcontext()
):
Expand Down Expand Up @@ -305,7 +306,7 @@ def test____recv_packet____blocking_or_not____receive_bytes_from_transport(
# Act
packet: Any = mocker.sentinel.packet_not_received
with (
pytest.raises(NotImplementedError, match=r"^transport does not support receiving data$")
pytest.raises(UnsupportedOperation, match=r"^transport does not support receiving data$")
if mock_stream_transport.__class__ not in (StreamReadTransport, StreamTransport)
else contextlib.nullcontext()
):
Expand Down
Loading

0 comments on commit c1e20e9

Please sign in to comment.