summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Häggström <kalvdans@gmail.com>2020-03-30 13:42:15 +0200
committerChristian Häggström <kalvdans@gmail.com>2020-03-30 13:42:15 +0200
commitb92365a082b659459db78bc8b6fb509eb6737e8d (patch)
treeb6f2fc9376e13aced89f985196e507b7887b1c87
parent3a6ae5a630589a29af8d8bd45616d7aadb2fb3db (diff)
downloadpyserial-git-b92365a082b659459db78bc8b6fb509eb6737e8d.tar.gz
Don't catch the SerialException we just raised
In Python3 we get double tracebacks for this error: Traceback (most recent call last): File "/home/chn/repo/pyserial/serial/serialposix.py", line 557, in read raise SerialException( serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "test/test_exceptions.py", line 26, in <module> test_unexpected_eof() File "/usr/lib/python3.8/unittest/mock.py", line 1348, in patched return func(*newargs, **newkeywargs) File "test/test_exceptions.py", line 21, in test_unexpected_eof s.read() File "/home/chn/repo/pyserial/serial/serialposix.py", line 566, in read raise SerialException('read failed: {}'.format(e)) serial.serialutil.SerialException: read failed: device reports readiness to read but returned no data (device disconnected or multiple access on port?) The patch moves the checking for EOF to after the IO block, resulting in a much nicer traceback. This is the test script (Python3-specific): from unittest import mock import serial import select import os @mock.patch('select.select') @mock.patch('os.read') def test_unexpected_eof(mock_read, mock_select): s = serial.Serial() s.is_open = True s.fd = 99 s.pipe_abort_read_r = 98 mock_select.return_value = ([99],[],[]) mock_read.return_value = b'' try: s.read() except serial.SerialException as e: if e.__context__: raise if __name__ == '__main__': test_unexpected_eof()
-rw-r--r--serial/serialposix.py22
1 files changed, 12 insertions, 10 deletions
diff --git a/serial/serialposix.py b/serial/serialposix.py
index 334ba9f..d5d6397 100644
--- a/serial/serialposix.py
+++ b/serial/serialposix.py
@@ -548,16 +548,6 @@ class Serial(SerialBase, PlatformSpecific):
if not ready:
break # timeout
buf = os.read(self.fd, size - len(read))
- # read should always return some data as select reported it was
- # ready to read when we get to this point.
- if not buf:
- # Disconnected devices, at least on Linux, show the
- # behavior that they are always ready to read immediately
- # but reading returns nothing.
- raise SerialException(
- 'device reports readiness to read but returned no data '
- '(device disconnected or multiple access on port?)')
- read.extend(buf)
except OSError as e:
# this is for Python 3.x where select.error is a subclass of
# OSError ignore BlockingIOErrors and EINTR. other errors are shown
@@ -570,6 +560,18 @@ class Serial(SerialBase, PlatformSpecific):
# see also http://www.python.org/dev/peps/pep-3151/#select
if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
raise SerialException('read failed: {}'.format(e))
+ else:
+ # read should always return some data as select reported it was
+ # ready to read when we get to this point.
+ if not buf:
+ # Disconnected devices, at least on Linux, show the
+ # behavior that they are always ready to read immediately
+ # but reading returns nothing.
+ raise SerialException(
+ 'device reports readiness to read but returned no data '
+ '(device disconnected or multiple access on port?)')
+ read.extend(buf)
+
if timeout.expired():
break
return bytes(read)