summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a>2009-07-27 22:09:31 +0000
committercliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a>2009-07-27 22:09:31 +0000
commit4a567a01240557afc88c7294b08beda4a03039b1 (patch)
tree909d598ef2ae21ab748cf757270c15f61611f983
parent97fa6e8e8c209c81e61195f25a3f9873045bb643 (diff)
downloadpyserial-git-4a567a01240557afc88c7294b08beda4a03039b1.tar.gz
- read/write now work with bytes when available on older Pythons that is equal to a str (implemented compatibility objects in serualutil)
- improve conversion result of 2to3 - remove RawSerial object again - update docs
-rw-r--r--documentation/pyserial_api.rst276
-rw-r--r--pyserial/serial/serialcli.py49
-rw-r--r--pyserial/serial/serialjava.py57
-rw-r--r--pyserial/serial/serialposix.py44
-rw-r--r--pyserial/serial/serialutil.py218
-rw-r--r--pyserial/serial/serialwin32.py53
6 files changed, 380 insertions, 317 deletions
diff --git a/documentation/pyserial_api.rst b/documentation/pyserial_api.rst
index f5fa01a..6b913a5 100644
--- a/documentation/pyserial_api.rst
+++ b/documentation/pyserial_api.rst
@@ -12,19 +12,25 @@ Classes
.. method:: __init__(port=None, baudrate=9600, bytesize=EIGHTBITS, parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=None, xonxoff=0, rtscts=0, interCharTimeout=None)
:param port:
- Device name or port number number or None.
+ Device name or port number number or :const:`None`.
:param baudrate:
Baud rate such as 9600 or 115200 etc.
:param bytesize:
- Number of data bits. Possible values: FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS
+ Number of data bits. Possible values:
+ :const:`FIVEBITS`, :const:`SIXBITS`, :const:`SEVENBITS`,
+ :const:`EIGHTBITS`
:param parity:
- Enable parity checking. Possible values: PARITY_NONE PARITY_EVEN PARITY_ODD PARITY_MARK PARITY_SPACE
+ Enable parity checking. Possible values:
+ :const:`PARITY_NONE` :const:`PARITY_EVEN` :const:`PARITY_ODD`
+ :const:`PARITY_MARK` :const:`PARITY_SPACE`
:param stopbits:
- Number of stop bits. Possible values: STOPBITS_ONE STOPBITS_ONE_POINT_FIVE STOPBITS_TWO
+ Number of stop bits. Possible values:
+ :const:`STOPBITS_ONE` :const:`STOPBITS_ONE_POINT_FIVE`
+ :const:`STOPBITS_TWO`
:param timeout:
Set a read timeout value.
@@ -36,23 +42,26 @@ Classes
Enable hardware (RTS/CTS) flow control.
:param interCharTimeout:
- Inter-character timeout, None to disable.
+ Inter-character timeout, :const:`None` to disable (default).
:exception ValueError:
- Will be raised when parameter are out of range, e.g. baudrate, data bits.
+ Will be raised when parameter are out of range, e.g. baud rate, data bits.
:exception SerialException:
In case the device can not be found or can not be configured.
- The port is immediately opened on object creation, when a ``port`` is
- given. It is not opened when port is None.
+ The port is immediately opened on object creation, when a *port* is
+ given. It is not opened when *port* is :const:`None` and a successive call
+ to :meth:`open` will be needed.
+
+ Possible values for the parameter *port*:
- Number: number of device, numbering starts at zero.
- Device name: depending on operating system. e.g. ``/dev/ttyUSB0``
on GNU/Linux or ``COM3`` on Windows.
- Possible values for the parameter ``timeout``:
+ Possible values for the parameter *timeout*:
- ``timeout = None``: wait forever
- ``timeout = 0``: non-blocking mode (return immediately on read)
@@ -68,32 +77,41 @@ Classes
Close port immediately.
- The following methods may rise :exc:`ValueError` when applied to a closed port.
-
- .. method:: inWaiting()
-
- Return the number of chars in the receive buffer.
+ The following methods may raise :exc:`ValueError` when applied to a closed
+ port.
.. method:: read(size=1)
:param size: Number of bytes to read.
:return: Bytes read from the port.
- Read ``size`` bytes from the serial port. If a timeout is set it may
+ Read *size* bytes from the serial port. If a timeout is set it may
return less characters as requested. With no timeout it will block
until the requested number of bytes is read.
+ .. versionchanged:: 2.5
+ Returns an instance of :class:`bytes` when available (Python 2.6
+ and newer) and :class:`str` otherwiese.
+
.. method:: write(data)
:param data: Data to send.
-
+ :return: Number of bytes written.
:exception SerialTimeoutException:
In case a write timeout is configured for the port and the time is
exceeded.
- Write the string ``data`` to the port.
+ Write the string *data* to the port.
+
+ .. versionchanged:: 2.5
+ Accepts an instance of :class:`bytes` when available (Python 2.6
+ and newer) and :class:`str` otherwiese.
- .. method:: flush():
+ .. method:: inWaiting()
+
+ Return the number of chars in the receive buffer.
+
+ .. method:: flush()
Flush of file like objects. In this case, wait until all data is
written.
@@ -188,7 +206,8 @@ Classes
A list of valid stop bit widths for the device (Read Only).
- New values can be assigned to the following attributes, the port will be reconfigured, even if it's opened at that time:
+ New values can be assigned to the following attributes, the port will be
+ reconfigured, even if it's opened at that time:
.. attribute:: port
@@ -248,180 +267,198 @@ Classes
Set software flow control state.
-.. class:: RawSerial
+.. class:: SerialBase
- This class is only present when run with Python 2.6 and newer that prides
- the module :mod:`io`. It shares the same interface with :class:`Serial`
- with the difference that :meth:`read` and :meth:`write` work with
- :class:`bytes`and :class:`bytearrays`.
+ The following attributes are implemented as properties. They work with open
+ and closed ports.
- This also means that readline is borrowed from the :mod:`io` module and
- lacks the ``eol`` parameter.
+ .. attribute:: port
- .. versionadded:: 2.5
+ Read or write port. When the port is already open, it will be closed
+ and reopened with the new setting.
+ .. attribute:: baudrate
-.. class:: FileLike
+ Read or write current baud rate setting.
- An abstract file like class. It is used as base class for :class:`Serial`.
+ .. attribute:: bytesize
- This class implements readline and readlines based on read and
- writelines based on write.
- This class is used to provide the above functions for to Serial
- port objects.
+ Read or write current data byte size setting.
- Note that when the serial port was opened with no timeout that
- readline blocks until it sees a newline (or the specified size is
- reached) and that readlines would never return and therefore
- refuses to work (it raises an exception in this case)!
+ .. attribute:: parity
- .. method:: readline(size=None, eol='\n')
+ Read or write current parity setting.
- :param size: Max number of bytes to read, ``None`` -> no limit.
- :param eol: The end of line character.
+ .. attribute:: stopbits
- Read a line which is terminated with end-of-line (eol) character
- ('\n' by default) or until timeout.
+ Read or write current stop bit width setting.
- .. method:: readlines(sizehint=None, eol='\n')
+ .. attribute:: timeout
- :param size: Ignored parameter.
- :param eol: The end of line character.
+ Read or write current read timeout setting.
- Read a list of lines, until timeout. ``sizehint`` is ignored and only
- present for API compatibility with built-in File objects.
+ .. attribute:: writeTimeout
- .. method:: xreadlines(sizehint=None)
+ Read or write current write timeout setting.
- Just calls ``readlines`` - here for compatibility.
+ .. attribute:: xonxoff
- .. method:: writelines(sequence)
+ Read or write current software flow control rate setting.
- Write a list of strings to the port.
+ .. attribute:: rtscts
+ Read or write current hardware flow control setting.
- The following three methods are overridden in :class:`Serial`.
+ .. attribute:: dsrdtr
- .. method:: flush()
+ Read or write current hardware flow control setting.
- Flush of file like objects. It's a no-op in this class, may be overridden.
+ .. attribute:: interCharTimeout
- .. method:: read()
+ Read or write current inter character timeout setting.
- Raises NotImplementedError, needs to be overridden by subclass.
+ The following constants are also provided:
- .. method:: write(data)
+ .. attribute:: BAUDRATES
- Raises NotImplementedError, needs to be overridden by subclass.
+ A tuple of standard baud rate values. The actual device may support more
+ or less...
- The following functions are implemented for compatibility with other
- file-like objects, however serial ports are not seekable.
+ .. attribute:: BYTESIZES
+ A tuple of supported byte size values.
- .. method:: seek(pos, whence=0)
+ .. attribute:: PARITIES
- :exception IOError: always, as method is not supported on serial port
+ A tuple of supported parity settings.
- .. versionadded:: 2.5
+ .. attribute:: STOPBITS
- .. method:: tell()
+ A tuple of supported stop bit settings.
- :exception IOError: always, as method is not supported on serial port
+ .. method:: readline(size=None, eol='\\n')
- .. versionadded:: 2.5
+ :param size: Max number of bytes to read, ``None`` -> no limit.
+ :param eol: The end of line character.
- .. method:: truncate(self, n=None):
+ Read a line which is terminated with end-of-line (*eol*) character
+ (``\\n`` by default) or until timeout.
- :exception IOError: always, as method is not supported on serial port
+ .. method:: readlines(sizehint=None, eol='\\n')
+
+ :param size: Ignored parameter.
+ :param eol: The end of line character.
+
+ Read a list of lines, until timeout. *sizehint* is ignored and only
+ present for API compatibility with built-in File objects.
+
+ .. method:: xreadlines(sizehint=None)
+ Just calls :meth:`readlines` - here for compatibility.
+
+ For compatibility with the :mod:`io` library are the following methods.
+
+ .. method:: readable()
+
+ :return: True
.. versionadded:: 2.5
- .. method:: isatty()
+ .. method:: writable()
- :exception IOError: always, as method is not supported on serial port
+ :return: True
+ .. versionadded:: 2.5
+ .. method:: seekable()
+
+ :return: False
.. versionadded:: 2.5
- To be able to use the file like object as iterator for e.g.
- ``for line in Serial(0): ...`` usage:
+ .. method:: readinto(b)
- .. method:: next()
+ :param b: bytearray or array instace
+ :return: Number of byte read
- Return the next line by calling :meth:`readline`.
+ Read up to len(b) bytes into bytearray b and return the number of bytes read.
- .. method:: __iter__()
+ .. versionadded:: 2.5
- Returns self.
+
+.. note::
+ For systems that provide the :mod:`io` library (Python 2.6 and newer), the
+ class :class:`Serial` will derrive from :class:`io.RawIOBase`. For all
+ others from :class:`FileLike`.
-.. class:: SerialBase
+.. class:: FileLike
- The following attributes are implemented as properties. They work with open
- and closed ports.
+ An abstract file like class. It is used as base class for :class:`Serial`.
- .. attribute:: port
+ This class implements :meth:`readline` and :meth:`readlines` based on read
+ and :meth:`writelines` based on write. This class is used to provide the
+ above functions for to Serial port objects.
- Read or write port. When the port is already open, it will be closed
- and reopened with the new setting.
+ Note that when the serial port was opened with no timeout that
+ :meth:`readline` blocks until it sees a newline (or the specified size is
+ reached) and that :meth:`readlines` would never return and therefore
+ refuses to work (it raises an exception in this case)!
- .. attribute:: baudrate
+ .. method:: writelines(sequence)
- Read or write current baud rate setting.
+ Write a list of strings to the port.
- .. attribute:: bytesize
- Read or write current data byte size setting.
+ The following three methods are overridden in :class:`Serial`.
- .. attribute:: parity
+ .. method:: flush()
- Read or write current parity setting.
+ Flush of file like objects. It's a no-op in this class, may be overridden.
- .. attribute:: stopbits
+ .. method:: read()
- Read or write current stop bit width setting.
+ Raises NotImplementedError, needs to be overridden by subclass.
- .. attribute:: timeout
+ .. method:: write(data)
- Read or write current read timeout setting.
+ Raises NotImplementedError, needs to be overridden by subclass.
- .. attribute:: writeTimeout
+ The following functions are implemented for compatibility with other
+ file-like objects, however serial ports are not seekable.
- Read or write current write timeout setting.
- .. attribute:: xonxoff
+ .. method:: seek(pos, whence=0)
- Read or write current software flow control rate setting.
+ :exception IOError: always, as method is not supported on serial port
- .. attribute:: rtscts
+ .. versionadded:: 2.5
- Read or write current hardware flow control setting.
+ .. method:: tell()
- .. attribute:: dsrdtr
+ :exception IOError: always, as method is not supported on serial port
- Read or write current hardware flow control setting.
+ .. versionadded:: 2.5
- .. attribute:: interCharTimeout
+ .. method:: truncate(self, n=None)
- Read or write current inter character timeout setting.
+ :exception IOError: always, as method is not supported on serial port
- The following constants are also provided:
+ .. versionadded:: 2.5
- .. attribute:: BAUDRATES
+ .. method:: isatty()
- A tuple of standard baud rate values. The actual device may support more
- or less...
+ :exception IOError: always, as method is not supported on serial port
- .. attribute:: BYTESIZES
+ .. versionadded:: 2.5
- A tuple of supported byte size values.
+ To be able to use the file like object as iterator for e.g.
+ ``for line in Serial(0): ...`` usage:
- .. attribute:: PARITIES
+ .. method:: next()
- A tuple of supported parity settings.
+ Return the next line by calling :meth:`readline`.
- .. attribute:: STOPBITS
+ .. method:: __iter__()
- A tuple of supported stop bit settings.
+ Returns self.
@@ -432,6 +469,9 @@ Exceptions
Base class for serial port exceptions.
+ .. versionchanged:: 2.5
+ Now derrives from :exc:`IOError` instead of :exc:`Exception`
+
.. exception:: SerialTimeoutException
Exception that is raised on write timeouts.
@@ -448,14 +488,14 @@ Parity
.. data:: PARITY_MARK
.. data:: PARITY_SPACE
-Stopbits
---------
+Stop bits
+---------
.. data:: STOPBITS_ONE
.. data:: STOPBITS_ONE_POINT_FIVE
.. data:: STOPBITS_TWO
-Bytesize
---------
+Byte size
+---------
.. data:: FIVEBITS
.. data:: SIXBITS
.. data:: SEVENBITS
@@ -463,12 +503,12 @@ Bytesize
Others
-------
-Default control characters for software flow control.
+Default control characters for software flow control:
.. data:: XON
.. data:: XOFF
-Version
+Module version:
.. data:: VERSION
diff --git a/pyserial/serial/serialcli.py b/pyserial/serial/serialcli.py
index 5360cb3..5cb76aa 100644
--- a/pyserial/serial/serialcli.py
+++ b/pyserial/serial/serialcli.py
@@ -11,21 +11,23 @@ import System
import System.IO.Ports
from serialutil import *
+
def device(portnum):
"""Turn a port number into a device name"""
return System.IO.Ports.SerialPort.GetPortNames()[portnum]
+
# must invoke function with byte array, make a helper to convert strings
# to byte arrays
sab = System.Array[System.Byte]
def as_byte_array(string):
- return sab([ord(x) for x in string])
+ return sab([ord(x) for x in string]) # XXX will require adaption when run with a 3.x compatible IronPython
class IronSerial(SerialBase):
"""Serial port implemenation for .NET/Mono."""
- BAUDRATES = (50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,
- 19200,38400,57600,115200)
+ BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200)
def open(self):
"""Open port with current settings. This may throw a SerialException
@@ -145,28 +147,28 @@ class IronSerial(SerialBase):
if not self._port_handle: raise portNotOpenError
return self._port_handle.BytesToRead
- def _read(self, size=1):
+ def read(self, size=1):
"""Read size bytes from the serial port. If a timeout is set it may
return less characters as requested. With no timeout it will block
until the requested number of bytes is read."""
if not self._port_handle: raise portNotOpenError
- # must use single byte reads as this is the only way to read
- # without applying encodings
- data = []
+ # must use single byte reads as this is the only way to read
+ # without applying encodings
+ data = bytearray()
while size:
try:
- data.append(chr(self._port_handle.ReadByte()))
+ data.append(self._port_handle.ReadByte())
except System.TimeoutException, e:
break
else:
size -= 1
- return ''.join(data)
+ return bytes(data)
- def _write(self, data):
+ def write(self, data):
"""Output the given string over the serial port."""
if not self._port_handle: raise portNotOpenError
- if not isinstance(data, str):
- raise TypeError('expected str, got %s' % type(data))
+ if not isinstance(data, bytes):
+ raise TypeError('expected %s, got %s' % (bytes, type(data)))
try:
# must call overloaded method with byte array argument
# as this is the only one not applying encodings
@@ -234,19 +236,22 @@ class IronSerial(SerialBase):
# none
-# assemble Serial class with the platform specifc implementation and the base
-# for file-like behavior
-class Serial(IronSerial, FileLike):
- pass
-
-# for Python 2.6 and newer, that provide the new I/O library, implement a
-# RawSerial object that plays nice with it.
-if support_io_module:
- class RawSerial(IronSerial, RawSerialBase):
+# assemble Serial class with the platform specific implementation and the base
+# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
+# library, derive from io.RawIOBase
+try:
+ import io
+except ImportError:
+ # classic version with our own file-like emulation
+ class Serial(IronSerial, FileLike):
+ pass
+else:
+ # io library present
+ class Serial(IronSerial, io.RawIOBase):
pass
-#Nur Testfunktion!!
+# Nur Testfunktion!!
if __name__ == '__main__':
import sys
diff --git a/pyserial/serial/serialjava.py b/pyserial/serial/serialjava.py
index 50356ea..4a0edb3 100644
--- a/pyserial/serial/serialjava.py
+++ b/pyserial/serial/serialjava.py
@@ -16,6 +16,7 @@ def my_import(name):
mod = getattr(mod, comp)
return mod
+
def detect_java_comm(names):
"""try given list of modules and return that imports"""
for name in names:
@@ -27,6 +28,7 @@ def detect_java_comm(names):
pass
raise ImportError("No Java Communications API implementation found")
+
# Java Communications API implementations
# http://mho.republika.pl/java/comm/
@@ -56,10 +58,10 @@ class JavaSerial(SerialBase):
if the port cannot be opened."""
if self._port is None:
raise SerialException("Port must be configured before it can be used.")
- if type(self._port) == type(''): #strings are taken directly
+ if type(self._port) == type(''): # strings are taken directly
portId = comm.CommPortIdentifier.getPortIdentifier(self._port)
else:
- portId = comm.CommPortIdentifier.getPortIdentifier(device(self._port)) #numbers are transformed to a comportid obj
+ portId = comm.CommPortIdentifier.getPortIdentifier(device(self._port)) # numbers are transformed to a comport id obj
try:
self.sPort = portId.open("python serial module", 10)
except Exception, msg:
@@ -71,7 +73,7 @@ class JavaSerial(SerialBase):
self._isOpen = True
def _reconfigurePort(self):
- """Set commuication parameters on opened port."""
+ """Set communication parameters on opened port."""
if not self.sPort:
raise SerialException("Can only operate on a valid port handle")
@@ -145,12 +147,12 @@ class JavaSerial(SerialBase):
if not self.sPort: raise portNotOpenError
return self._instream.available()
- def _read(self, size=1):
+ def read(self, size=1):
"""Read size bytes from the serial port. If a timeout is set it may
return less characters as requested. With no timeout it will block
until the requested number of bytes is read."""
if not self.sPort: raise portNotOpenError
- read = ''
+ read = bytearray()
if size > 0:
while len(read) < size:
x = self._instream.read()
@@ -158,12 +160,14 @@ class JavaSerial(SerialBase):
if self.timeout >= 0:
break
else:
- read = read + chr(x)
- return read
+ read.append(x)
+ return bytes(read)
- def _write(self, data):
+ def write(self, data):
"""Output the given string over the serial port."""
if not self.sPort: raise portNotOpenError
+ if not isinstance(data, bytes):
+ raise TypeError('expected %s, got %s' % (bytes, type(data)))
self._outstream.write(data)
return len(data)
@@ -219,28 +223,31 @@ class JavaSerial(SerialBase):
self.sPort.isCD()
-# assemble Serial class with the platform specifc implementation and the base
-# for file-like behavior
-class Serial(JaveSerial, FileLike):
- pass
-
-# for Python 2.6 and newer, that provide the new I/O library, implement a
-# RawSerial object that plays nice with it.
-if support_io_module:
- class RawSerial(JavaSerial, RawSerialBase):
+# assemble Serial class with the platform specific implementation and the base
+# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
+# library, derive from io.RawIOBase
+try:
+ import io
+except ImportError:
+ # classic version with our own file-like emulation
+ class Serial(JavaSerial, FileLike):
+ pass
+else:
+ # io library present
+ class Serial(JavaSerial, io.RawIOBase):
pass
if __name__ == '__main__':
s = Serial(0,
- baudrate=19200, #baudrate
- bytesize=EIGHTBITS, #number of databits
- parity=PARITY_EVEN, #enable parity checking
- stopbits=STOPBITS_ONE, #number of stopbits
- timeout=3, #set a timeout value, None for waiting forever
- xonxoff=0, #enable software flow control
- rtscts=0, #enable RTS/CTS flow control
- )
+ baudrate=19200, # baudrate
+ bytesize=EIGHTBITS, # number of databits
+ parity=PARITY_EVEN, # enable parity checking
+ stopbits=STOPBITS_ONE, # number of stopbits
+ timeout=3, # set a timeout value, None for waiting forever
+ xonxoff=0, # enable software flow control
+ rtscts=0, # enable RTS/CTS flow control
+ )
s.setRTS(1)
s.setDTR(1)
s.flushInput()
diff --git a/pyserial/serial/serialposix.py b/pyserial/serial/serialposix.py
index 2a989fd..41bac8b 100644
--- a/pyserial/serial/serialposix.py
+++ b/pyserial/serial/serialposix.py
@@ -434,47 +434,46 @@ class PosixSerial(SerialBase):
s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
return struct.unpack('I',s)[0]
- def _read(self, size=1):
+ def read(self, size=1):
"""Read size bytes from the serial port. If a timeout is set it may
return less characters as requested. With no timeout it will block
until the requested number of bytes is read."""
if self.fd is None: raise portNotOpenError
- read = ''
+ read = bytearray()
inp = None
if size > 0:
while len(read) < size:
# print "\tread(): size",size, "have", len(read) #debug
- ready,_,_ = select.select([self.fd],[],[], self._timeout)
+ ready,_,_ = select.select([self.fd], [], [], self._timeout)
if not ready:
break # timeout
- buf = os.read(self.fd, size-len(read))
- read = read + buf
+ buf = os.read(self.fd, size - len(read))
+ read.extend(buf)
if (self._timeout >= 0 or self._interCharTimeout > 0) and not buf:
break # early abort on timeout
- return read
+ return bytes(read)
- def _write(self, data):
+ def write(self, data):
"""Output the given string over the serial port."""
if self.fd is None: raise portNotOpenError
- #~ if not isinstance(port, basestring):
- if not isinstance(data, str):
- raise TypeError('expected str, got %s' % type(data))
+ if not isinstance(data, bytes):
+ raise TypeError('expected %s, got %s' % (bytes, type(data)))
t = len(data)
d = data
while t > 0:
try:
if self._writeTimeout is not None and self._writeTimeout > 0:
- _,ready,_ = select.select([],[self.fd],[], self._writeTimeout)
+ _, ready, _ = select.select([], [self.fd], [], self._writeTimeout)
if not ready:
raise writeTimeoutError
n = os.write(self.fd, d)
if self._writeTimeout is not None and self._writeTimeout > 0:
- _,ready,_ = select.select([],[self.fd],[], self._writeTimeout)
+ _, ready, _ = select.select([], [self.fd], [], self._writeTimeout)
if not ready:
raise writeTimeoutError
d = d[n:]
t = t - n
- except OSError,v:
+ except OSError, v:
if v.errno != errno.EAGAIN:
raise
return len(data)
@@ -572,14 +571,17 @@ class PosixSerial(SerialBase):
# assemble Serial class with the platform specifc implementation and the base
-# for file-like behavior
-class Serial(PosixSerial, FileLike):
- pass
-
-# for Python 2.6 and newer, that provide the new I/O library, implement a
-# RawSerial object that plays nice with it.
-if support_io_module:
- class RawSerial(PosixSerial, RawSerialBase):
+# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
+# library, derrive from io.RawIOBase
+try:
+ import io
+except ImportError:
+ # classic version with our own file-like emulation
+ class Serial(PosixSerial, FileLike):
+ pass
+else:
+ # io library present
+ class Serial(PosixSerial, io.RawIOBase):
pass
diff --git a/pyserial/serial/serialutil.py b/pyserial/serial/serialutil.py
index 8b65c0f..92bbcdd 100644
--- a/pyserial/serial/serialutil.py
+++ b/pyserial/serial/serialutil.py
@@ -5,31 +5,54 @@
# (C) 2001-2009 Chris Liechti <cliechti@gmx.net>
# this is distributed under a free software license, see license.txt
+# compatibility folder Python < 2.6
+try:
+ bytes
+ bytearray
+except AttributeError:
+ # Python older than 2.6 do not have these types. Like for Python 2.6 they
+ # should behave like str. for Python older than 3.0 we want to work with
+ # strings anyway, only later versions have a trues bytes type.
+ bytes = str
+ # bytearray is a mutable type that is easily turned into an instance of
+ # bytes
+ class bytearray(list):
+ # for bytes(bytearray()) usage
+ def __str__(self): return ''.join(self)
+ # append automatically converts integers to characters
+ def append(self, item):
+ if isinstance(item, str):
+ list.append(self, item)
+ else:
+ list.append(self, chr(item))
+
+
PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S'
STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO = (1, 1.5, 2)
FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5, 6, 7, 8)
PARITY_NAMES = {
- PARITY_NONE: 'None',
- PARITY_EVEN: 'Even',
- PARITY_ODD: 'Odd',
- PARITY_MARK: 'Mark',
- PARITY_SPACE:'Space',
+ PARITY_NONE: 'None',
+ PARITY_EVEN: 'Even',
+ PARITY_ODD: 'Odd',
+ PARITY_MARK: 'Mark',
+ PARITY_SPACE: 'Space',
}
XON = chr(17)
XOFF = chr(19)
-class SerialException(Exception):
+class SerialException(IOError):
"""Base class for serial port related exceptions."""
-portNotOpenError = ValueError('Attempting to use a port that is not open')
class SerialTimeoutException(SerialException):
"""Write timeouts give an exception"""
+
writeTimeoutError = SerialTimeoutException("Write timeout")
+portNotOpenError = ValueError('Attempting to use a port that is not open')
class FileLike(object):
@@ -65,49 +88,6 @@ class FileLike(object):
except:
pass
- # read and write directly use the platform dependent implementation
- def read(self, size=1):
- return self._read(size)
-
- def write(self, data):
- return self._write(data)
-
- def readline(self, size=None, eol='\n'):
- """read a line which is terminated with end-of-line (eol) character
- ('\n' by default) or until timeout"""
- line = ''
- while 1:
- c = self.read(1)
- if c:
- line += c # not very efficient but lines are usually not that long
- if c == eol:
- break
- if size is not None and len(line) >= size:
- break
- else:
- break
- return line
-
- def readlines(self, sizehint=None, eol='\n'):
- """read a list of lines, until timeout
- sizehint is ignored"""
- if self.timeout is None:
- raise ValueError("Serial port MUST have enabled timeout for this function!")
- lines = []
- while 1:
- line = self.readline(eol=eol)
- if line:
- lines.append(line)
- if line[-1] != eol: # was the line received with a timeout?
- break
- else:
- break
- return lines
-
- def xreadlines(self, sizehint=None):
- """just call readlines - here for compatibility"""
- return self.readlines()
-
def writelines(self, sequence):
for line in sequence:
self.write(line)
@@ -177,17 +157,17 @@ class SerialBase(object):
is returned."""
self._isOpen = False
- self._port = None # correct value is assigned below trough properties
- self._baudrate = None # correct value is assigned below trough properties
- self._bytesize = None # correct value is assigned below trough properties
- self._parity = None # correct value is assigned below trough properties
- self._stopbits = None # correct value is assigned below trough properties
- self._timeout = None # correct value is assigned below trough properties
- self._writeTimeout = None # correct value is assigned below trough properties
- self._xonxoff = None # correct value is assigned below trough properties
- self._rtscts = None # correct value is assigned below trough properties
- self._dsrdtr = None # correct value is assigned below trough properties
- self._interCharTimeout = None # correct value is assigned below trough properties
+ self._port = None # correct value is assigned below through properties
+ self._baudrate = None # correct value is assigned below through properties
+ self._bytesize = None # correct value is assigned below through properties
+ self._parity = None # correct value is assigned below through properties
+ self._stopbits = None # correct value is assigned below through properties
+ self._timeout = None # correct value is assigned below through properties
+ self._writeTimeout = None # correct value is assigned below through properties
+ self._xonxoff = None # correct value is assigned below through properties
+ self._rtscts = None # correct value is assigned below through properties
+ self._dsrdtr = None # correct value is assigned below through properties
+ self._interCharTimeout = None # correct value is assigned below through properties
# assign values using get/set methods using the properties feature
self.port = port
@@ -255,10 +235,9 @@ class SerialBase(object):
def setBaudrate(self, baudrate):
- """Change baudrate. It raises a ValueError if the port is open and the
- baudrate is not possible. If the port is closed, then tha value is
+ """Change baud rate. It raises a ValueError if the port is open and the
+ baud rate is not possible. If the port is closed, then tha value is
accepted and the exception is raised when the port is opened."""
- #~ if baudrate not in self.BAUDRATES: raise ValueError("Not a valid baudrate: %r" % baudrate)
try:
self._baudrate = int(baudrate)
except TypeError:
@@ -267,10 +246,10 @@ class SerialBase(object):
if self._isOpen: self._reconfigurePort()
def getBaudrate(self):
- """Get the current baudrate setting."""
+ """Get the current baud rate setting."""
return self._baudrate
- baudrate = property(getBaudrate, setBaudrate, doc="Baudrate setting")
+ baudrate = property(getBaudrate, setBaudrate, doc="Baud rate setting")
def setByteSize(self, bytesize):
@@ -300,16 +279,16 @@ class SerialBase(object):
def setStopbits(self, stopbits):
- """Change stopbits size."""
- if stopbits not in self.STOPBITS: raise ValueError("Not a valid stopbit size: %r" % (stopbits,))
+ """Change stop bits size."""
+ if stopbits not in self.STOPBITS: raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
self._stopbits = stopbits
if self._isOpen: self._reconfigurePort()
def getStopbits(self):
- """Get the current stopbits setting."""
+ """Get the current stop bits setting."""
return self._stopbits
- stopbits = property(getStopbits, setStopbits, doc="Stopbits setting")
+ stopbits = property(getStopbits, setStopbits, doc="Stop bits setting")
def setTimeout(self, timeout):
@@ -351,23 +330,23 @@ class SerialBase(object):
def setXonXoff(self, xonxoff):
- """Change XonXoff setting."""
+ """Change XON/XOFF setting."""
self._xonxoff = xonxoff
if self._isOpen: self._reconfigurePort()
def getXonXoff(self):
- """Get the current XonXoff setting."""
+ """Get the current XON/XOFF setting."""
return self._xonxoff
- xonxoff = property(getXonXoff, setXonXoff, doc="Xon/Xoff setting")
+ xonxoff = property(getXonXoff, setXonXoff, doc="XON/XOFF setting")
def setRtsCts(self, rtscts):
- """Change RtsCts flow control setting."""
+ """Change RTS/CTS flow control setting."""
self._rtscts = rtscts
if self._isOpen: self._reconfigurePort()
def getRtsCts(self):
- """Get the current RtsCts flow control setting."""
+ """Get the current RTS/CTS flow control setting."""
return self._rtscts
rtscts = property(getRtsCts, setRtsCts, doc="RTS/CTS flow control setting")
@@ -383,7 +362,7 @@ class SerialBase(object):
if self._isOpen: self._reconfigurePort()
def getDsrDtr(self):
- """Get the current DsrDtr flow control setting."""
+ """Get the current DSR/DTR flow control setting."""
return self._dsrdtr
dsrdtr = property(getDsrDtr, setDsrDtr, "DSR/DTR flow control setting")
@@ -426,40 +405,61 @@ class SerialBase(object):
self.dsrdtr,
)
-# for Python 2.6 and newer, that provide the new I/O library, implement a
-# RawSerial object that plays nice with it.
-try:
- import io
-except ImportError:
- support_io_module = False
-else:
- support_io_module = True
-
- class RawSerialBase(io.RawIOBase):
- def readable(self): return True
- def writable(self): return True
- def readinto(self, b):
- data = self._read(len(b))
- n = len(data)
- try:
- b[:n] = data
- except TypeError, err:
- import array
- if not isinstance(b, array.array):
- raise err
- b[:n] = array.array(b'b', data)
- return n
-
- def write(self, b):
- if self.closed:
- raise ValueError("write to closed file")
- if isinstance(b, unicode):
- raise TypeError("can't write unicode to binary stream")
- n = len(b)
- if n == 0:
- return 0
- self._write(b)
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+
+ def readline(self, size=None, eol='\n'):
+ """read a line which is terminated with end-of-line (eol) character
+ ('\n' by default) or until timeout"""
+ line = ''
+ while 1:
+ c = self.read(1)
+ if c:
+ line += c # not very efficient but lines are usually not that long
+ if c == eol:
+ break
+ if size is not None and len(line) >= size:
+ break
+ else:
+ break
+ return bytes(line)
+
+ def readlines(self, sizehint=None, eol='\n'):
+ """read a list of lines, until timeout
+ sizehint is ignored"""
+ if self.timeout is None:
+ raise ValueError("Serial port MUST have enabled timeout for this function!")
+ lines = []
+ while 1:
+ line = self.readline(eol=eol)
+ if line:
+ lines.append(line)
+ if line[-1] != eol: # was the line received with a timeout?
+ break
+ else:
+ break
+ return lines
+
+ def xreadlines(self, sizehint=None):
+ """just call readlines - here for compatibility"""
+ return self.readlines()
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+ # compatibility with io library
+
+ def readable(self): return True
+ def writable(self): return True
+ def seekable(self): return False
+ def readinto(self, b):
+ data = self.read(len(b))
+ n = len(data)
+ try:
+ b[:n] = data
+ except TypeError, err:
+ import array
+ if not isinstance(b, array.array):
+ raise err
+ b[:n] = array.array('b', data)
+ return n
if __name__ == '__main__':
diff --git a/pyserial/serial/serialwin32.py b/pyserial/serial/serialwin32.py
index 7df6236..59572d2 100644
--- a/pyserial/serial/serialwin32.py
+++ b/pyserial/serial/serialwin32.py
@@ -13,15 +13,17 @@ import win32
from serialutil import *
+
def device(portnum):
"""Turn a port number into a device name"""
- return 'COM%d' % (portnum+1) #numbers are transformed to a string
+ return 'COM%d' % (portnum+1) # numbers are transformed to a string
+
class Win32Serial(SerialBase):
"""Serial port implementation for Win32 based on ctypes."""
- BAUDRATES = (50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,
- 19200,38400,57600,115200)
+ BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200)
def open(self):
"""Open port with current settings. This may throw a SerialException
@@ -33,8 +35,12 @@ class Win32Serial(SerialBase):
# not all versions of windows seem to support this properly
# so that the first few ports are used with the DOS device name
port = self.portstr
- if port.upper().startswith('COM') and int(port[3:]) > 8:
- port = '\\\\.\\' + port
+ try:
+ if port.upper().startswith('COM') and int(port[3:]) > 8:
+ port = '\\\\.\\' + port
+ except ValueError:
+ # for like COMnotanumber
+ pass
self.hComPort = win32.CreateFile(port,
win32.GENERIC_READ | win32.GENERIC_WRITE,
0, # exclusive access
@@ -43,7 +49,7 @@ class Win32Serial(SerialBase):
win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED,
0)
if self.hComPort == win32.INVALID_HANDLE_VALUE:
- self.hComPort = None #'cause __del__ is called anyway
+ self.hComPort = None # 'cause __del__ is called anyway
raise SerialException("could not open port %s: %s" % (self.portstr, ctypes.WinError()))
# Setup a 4k buffer
@@ -196,7 +202,7 @@ class Win32Serial(SerialBase):
raise SerialException('call to ClearCommError failed')
return comstat.cbInQue
- def _read(self, size=1):
+ def read(self, size=1):
"""Read size bytes from the serial port. If a timeout is set it may
return less characters as requested. With no timeout it will block
until the requested number of bytes is read."""
@@ -218,7 +224,7 @@ class Win32Serial(SerialBase):
err = win32.WaitForSingleObject(self._overlappedRead.hEvent, win32.INFINITE)
read = buf.raw[:rc.value]
else:
- read = ''
+ read = bytes()
else:
buf = ctypes.create_string_buffer(size)
rc = win32.DWORD()
@@ -228,14 +234,14 @@ class Win32Serial(SerialBase):
err = win32.GetOverlappedResult(self.hComPort, ctypes.byref(self._overlappedRead), ctypes.byref(rc), True)
read = buf.raw[:rc.value]
else:
- read = ''
- return read
+ read = bytes()
+ return bytes(read)
- def _write(self, data):
+ def write(self, data):
"""Output the given string over the serial port."""
if not self.hComPort: raise portNotOpenError
- if not isinstance(data, str):
- raise TypeError('expected str, got %s' % type(data))
+ if not isinstance(data, bytes):
+ raise TypeError('expected %s, got %s' % (bytes, type(data)))
if data:
#~ win32event.ResetEvent(self._overlappedWrite.hEvent)
n = win32.DWORD()
@@ -340,17 +346,20 @@ class Win32Serial(SerialBase):
raise SerialException('call to ClearCommError failed')
return comstat.cbOutQue
-# assemble Serial class with the platform specifc implementation and the base
-# for file-like behavior
-class Serial(Win32Serial, FileLike):
- pass
-# for Python 2.6 and newer, that provide the new I/O library, implement a
-# RawSerial object that plays nice with it.
-if support_io_module:
- class RawSerial(Win32Serial, RawSerialBase):
+# assemble Serial class with the platform specific implementation and the base
+# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
+# library, derive from io.RawIOBase
+try:
+ import io
+except ImportError:
+ # classic version with our own file-like emulation
+ class Serial(Win32Serial, FileLike):
+ pass
+else:
+ # io library present
+ class Serial(Win32Serial, io.RawIOBase):
pass
-
# Nur Testfunktion!!