8000 Merge branch 'develop' into fix-cantact-detect_available_configs · hardbyte/python-can@ad155b0 · GitHub
[go: up one dir, main page]

Skip to content

Commit ad155b0

Browse files
authored
Merge branch 'develop' into fix-cantact-detect_available_configs
2 parents e83f05c + 0e0c64f commit ad155b0

File tree

5 files changed

+68
-46
lines changed

5 files changed

+68
-46
lines changed

can/exceptions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class CanOperationError(CanError):
8585
- The driver rejected a message that was meant to be sent
8686
- Cyclic redundancy check (CRC) failed
8787
- A message remained unacknowledged
88+
- A buffer is full
8889
"""
8990

9091

can/interfaces/serial/serial_can.py

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111
import struct
1212
from typing import Any, List, Tuple, Optional
1313

14-
from can import BusABC, Message, CanError
14+
from can import BusABC, Message
15+
from can import (
16+
CanInterfaceNotImplementedError,
17+
CanInitializationError,
18+
CanOperationError,
19+
CanTimeoutError,
20+
)
1521
from can.typechecking import AutoDetectedConfig
1622

1723
logger = logging.getLogger("can.serial")
@@ -67,14 +73,26 @@ def __init__(
6773
:param rtscts:
6874
turn hardware handshake (RTS/CTS) on and off
6975
76+
:raises can.CanInitializationError: If the given parameters are invalid.
77+
:raises can.CanInterfaceNotImplementedError: If the serial module is not installed.
7078
"""
79+
80+
if not serial:
81+
raise CanInterfaceNotImplementedError("the serial module is not installed")
82+
7183
if not channel:
72-
raise ValueError("Must specify a serial port.")
84+
raise TypeError("Must specify a serial port.")
7385

7486
self.channel_info = f"Serial interface: {channel}"
75-
self._ser = serial.serial_for_url(
76-
channel, baudrate=baudrate, timeout=timeout, rtscts=rtscts
77-
)
87+
88+
try:
89+
self._ser = serial.serial_for_url(
90+
channel, baudrate=baudrate, timeout=timeout, rtscts=rtscts
91+
)
92+
except ValueError as error:
93+
raise CanInitializationError(
94+
"could not create the serial device"
95+
) from error
7896

7997
super().__init__(channel, *args, **kwargs)
8098

@@ -124,7 +142,12 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None:
124142
byte_msg.append(0xBB)
125143

126144
# Write to serial device
127-
self._ser.write(byte_msg)
145+
try:
146+
self._ser.write(byte_msg)
147+
except serial.PortNotOpenError as error:
148+
raise CanOperationError("writing to closed port") from error
149+
except serial.SerialTimeoutException as error:
150+
raise CanTimeoutError() from error
128151

129152
def _recv_internal(
130153
self, timeout: Optional[float]
@@ -153,12 +176,12 @@ def _recv_internal(
153176
timestamp = struct.unpack("<I", s)[0]
154177
dlc = ord(self._ser.read())
155178
if dlc > 8:
156-
raise CanError("received DLC may not exceed 8 bytes")
179+
raise ValueError("received DLC may not exceed 8 bytes")
157180

158181
s = self._ser.read(4)
159182
arbitration_id = struct.unpack("<I", s)[0]
160183
if arbitration_id >= 0x20000000:
161-
raise CanError(
184+
raise ValueError(
162185
"received arbitration id may not exceed 2^29 (0x20000000)"
163186
)
164187

@@ -177,15 +200,15 @@ def _recv_internal(
177200
return msg, False
178201

179202
else:
180-
raise CanError(
203+
raise CanOperationError(
181204
f"invalid delimiter byte while reading message: {delimiter_byte}"
182205
)
183206

184207
else:
185208
return None, False
186209

187210
except serial.SerialException as error:
188-
raise CanError("could not read from serial") from error
211+
raise CanOperationError("could not read from serial") from error
189212

190213
def fileno(self) -> int:
191214
if hasattr(self._ser, "fileno"):

can/interfaces/socketcan/socketcan.py

Lines changed: 31 additions & 33 deletions

test/logformats_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,24 +278,19 @@ def send_bcm(bcm_socket: socket.socket, data: bytes) -> int:
278278
"""
279279
try:
280280
return bcm_socket.send(data)
281-
except OSError as e:
282-
base = "Couldn't send CAN BCM frame. OS Error {}: {}\n".format(
283-
e.errno, e.strerror
284-
)
285-
286-
if e.errno == errno.EINVAL:
287-
raise can.CanError(
288-
base + "You are probably referring to a non-existing frame."
289-
)
290-
291-
elif e.errno == errno.ENETDOWN:
292-
raise can.CanError(base + "The CAN interface appears to be down.")
293-
294-
elif e.errno == errno.EBADF:
295-
raise can.CanError(base + "The CAN socket appears to be closed.")
296-
281+
except OSError as error:
282+
base = f"Couldn't send CAN BCM frame due to OS Error: {error.strerror}"
283+
284+
if error.errno == errno.EINVAL:
285+
specific_message = " You are probably referring to a non-existing frame."
286+
elif error.errno == errno.ENETDOWN:
287+
specific_message = " The CAN interface appears to be down."
288+
elif error.errno == errno.EBADF:
289+
specific_message = " The CAN socket appears to be closed."
297290
else:
298-
raise e
291+
specific_message = ""
292+
293+
raise can.CanOperationError(base + specific_message, error.errno) from error
299294

300295

301296
def _compose_arbitration_id(message: Message) -> int:
@@ -330,7 +325,7 @@ def __init__(
330325
messages: Union[Sequence[Message], Message],
331326
period: float,
332327
duration: Optional[float] = None,
333-
):
328+
) -> None:
334329
"""Construct and :meth:`~start` a task.
335330
336331
:param bcm_socket: An open BCM socket on the desired CAN channel.
@@ -378,7 +373,7 @@ def _tx_setup(self, messages: Sequence[Message]) -> None:
378373
log.debug("Sending BCM command")
379374
send_bcm(self.bcm_socket, header + body)
380375

381-
def _check_bcm_task(self):
376+
def _check_bcm_task(self) -> None:
382377
# Do a TX_READ on a task ID, and check if we get EINVAL. If so,
383378
# then we are referring to a CAN message with the existing ID
384379
check_header = build_bcm_header(
@@ -394,14 +389,13 @@ def _check_bcm_task(self):
394389
)
395390
try:
396391
self.bcm_socket.send(check_header)
397-
except OSError as e:
398-
if e.errno != errno.EINVAL:
399-
raise e
392+
except OSError as error:
393+
if error.errno != errno.EINVAL:
394+
raise can.CanOperationError("failed to check", error.errno) from error
400395
else:
401-
raise ValueError(
402-
"A periodic task for Task ID {} is already in progress by SocketCAN Linux layer".format(
403-
self.task_id
404-
)
396+
raise can.CanOperationError(
397+
f"A periodic task for task ID {self.task_id} is already in progress "
398+
"by the SocketCAN Linux layer"
405399
)
406400

407401
def stop(self) -> None:
@@ -537,7 +531,7 @@ def capture_message(
537531
else:
538532
channel = None
539533
except socket.error as error:
540-
raise can.CanError(f"Error receiving: {error}")
534+
raise can.CanOperationError(f"Error receiving: {error.strerror}", error.errno)
541535

542536
can_id, can_dlc, flags, data = dissect_can_frame(cf)
543537

@@ -550,7 +544,7 @@ def capture_message(
550544
# see https://man7.org/linux/man-pages/man3/timespec.3.html -> struct timespec for details
551545
seconds, nanoseconds = RECEIVED_TIMESTAMP_STRUCT.unpack_from(cmsg_data)
552546
if nanoseconds >= 1e9:
553-
raise can.CanError(
547+
raise can.CanOperationError(
554548
f"Timestamp nanoseconds field was out of range: {nanoseconds} not less than 1e9"
555549
)
556550
timestamp = seconds + nanoseconds * 1e-9
@@ -716,9 +710,11 @@ def _recv_internal(
716710
# get all sockets that are ready (can be a list with a single value
717711
# being self.socket or an empty list if self.socket is not ready)
718712
ready_receive_sockets, _, _ = select.select([self.socket], [], [], timeout)
719-
except socket.error as exc:
713+
except socket.error as error:
720714
# something bad happened (e.g. the interface went down)
721-
raise can.CanError(f"Failed to receive: {exc}")
715+
raise can.CanOperationError(
716+
f"Failed to receive: {error.strerror}", error.errno
717+
)
722718

723719
if ready_receive_sockets: # not empty
724720
get_channel = self.channel == ""
@@ -767,7 +763,7 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None:
767763
data = data[sent:]
768764
time_left = timeout - (time.time() - started)
769765

770-
raise can.CanError("Transmit buffer full")
766+
raise can.CanOperationError("Transmit buffer full")
771767

772768
def _send_once(self, data: bytes, channel: Optional[str] = None) -> int:
773769
try:
@@ -776,8 +772,10 @@ def _send_once(self, data: bytes, channel: Optional[str] = None) -> int:
776772
sent = self.socket.sendto(data, (channel,))
777773
else:
778774
sent = self.socket.send(data)
779-
except socket.error as exc:
780-
raise can.CanError("Failed to transmit: %s" % exc)
775+
except socket.error as error:
776+
raise can.CanOperationError(
777+
f"Failed to transmit: {error.strerror}", error.errno
778+
)
781779
return sent
782780

783781
def _send_periodic_internal(
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ def test_append_mode(self):
316316
try:
317317
writer = self.writer_constructor(self.test_file_name)
318318
except TypeError:
319-
# is the is still a problem, raise the initial error
319+
# if it is still a problem, raise the initial error
320320
raise e
321321
with writer:
322322
for message in second_part:

test/test_cyclic_socketcan.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,10 @@ def test_start_already_started_task(self):
255255
time.sleep(0.1)
256256

257257
# Try to start it again, task_id is not incremented in this case
258-
with self.assertRaises(ValueError) as ctx:
258+
with self.assertRaises(can.CanOperationError) as ctx:
259259
task_a.start()
260260
self.assertEqual(
261-
"A periodic task for Task ID 1 is already in progress by SocketCAN Linux layer",
261+
"A periodic task for task ID 1 is already in progress by the SocketCAN Linux layer",
262262
str(ctx.exception),
263263
)
264264

0 commit comments

Comments
 (0)
0