10000 Specific Exceptions: Adapting udp_multicast interface by felixdivo · Pull Request #1089 · hardbyte/python-can · GitHub
[go: up one dir, main page]

Skip to content

Specific Exceptions: Adapting udp_multicast interface #1089

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions can/interfaces/udp_multicast/bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ def __init__(
check_msgpack_installed()

if receive_own_messages:
raise NotImplementedError("receiving own messages is not yet implemented")
raise can.CanInterfaceNotImplementedError(
"receiving own messages is not yet implemented"
)

super().__init__(channel, **kwargs)

Expand All @@ -105,7 +107,14 @@ def _recv_internal(self, timeout: Optional[float]):
return None, False

data, _, timestamp = result
can_message = unpack_message(data, replace={"timestamp": timestamp})
try:
can_message = unpack_message(
data, replace={"timestamp": timestamp}, check=True
)
except Exception as exception:
raise can.CanOperationError(
"could not unpack received message"
) from exception

if not self.is_fd and can_message.is_fd:
return None, False
Expand All @@ -114,7 +123,9 @@ def _recv_internal(self, timeout: Optional[float]):

def send(self, message: can.Message, timeout: Optional[float] = None) -> None:
if not self.is_fd and message.is_fd:
raise RuntimeError("cannot send FD message over bus with CAN FD disabled")
raise can.CanOperationError(
"cannot send FD message over bus with CAN FD disabled"
)

data = pack_message(message)
self._multicast.send(data, timeout)
Expand Down Expand Up @@ -149,7 +160,10 @@ def _detect_available_configs() -> List[AutoDetectedConfig]:


class GeneralPurposeUdpMulticastBus:
"""A general purpose send and receive handler for multicast over IP/UDP."""
"""A general purpose send and receive handler for multicast over IP/UDP.

However, it raises CAN-specific exceptions for convenience.
"""

def __init__(
self, group: str, port: int, hop_limit: int, max_buffer: int = 4096
Expand Down Expand Up @@ -178,7 +192,9 @@ def __init__(
if sock is not None:
self._socket = sock
else:
raise RuntimeError("could not connect to a multicast IP network")
raise can.CanInitializationError(
"could not connect to a multicast IP network"
)

# used in recv()
self.received_timestamp_struct = "@ll"
Expand All @@ -193,8 +209,10 @@ def _create_socket(self, address_family: socket.AddressFamily) -> socket.socket:
"""Creates a new socket. This might fail and raise an exception!

:param address_family: whether this is of type `socket.AF_INET` or `socket.AF_INET6`
:raises OSError: if the socket could not be opened or configured correctly; in this case, it is
guaranteed to be closed/cleaned up

:raises can.CanInitializationError:
if the socket could not be opened or configured correctly; in this case, it is
guaranteed to be closed/cleaned up
"""
# create the UDP socket
# this might already fail but then there is nothing to clean up
Expand Down Expand Up @@ -243,7 +261,9 @@ def _create_socket(self, address_family: socket.AddressFamily) -> socket.socket:
log.warning("Could not close partly configured socket: %s", close_error)

# still raise the error
raise error
raise can.CanInitializationError(
"could not create or configure socket"
) from error

def send(self, data: bytes, timeout: Optional[float] = None) -> None:
"""Send data to all group members. This call blocks.
Expand Down Expand Up @@ -283,7 +303,9 @@ def recv(
ready_receive_sockets, _, _ = select.select([self._socket], [], [], timeout)
except socket.error as exc:
# something bad (not a timeout) happened (e.g. the interface went down)
raise can.CanError(f"Failed to wait for IP/UDP socket: {exc}")
raise can.CanOperationError(
f"Failed to wait for IP/UDP socket: {exc}"
) from exc

if ready_receive_sockets: # not empty
# fetch data & source address
Expand Down
5 changes: 3 additions & 2 deletions can/interfaces/udp_multicast/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import Optional

from can import Message
from can import CanInterfaceNotImplementedError
from can.typechecking import ReadableBytesLike

try:
Expand All @@ -16,9 +17,9 @@


def check_msgpack_installed() -> None:
"""Raises a `RuntimeError` if `msgpack` is not installed."""
"""Raises a :class:`can.CanInterfaceNotImplementedError` if `msgpack` is not installed."""
if msgpack is None:
raise RuntimeError("msgpack not installed")
raise CanInterfaceNotImplementedError("msgpack not installed")


def pack_message(message: Message) -> bytes:
Expand Down
0