diff options
-rw-r--r-- | documentation/pyserial_api.rst | 276 | ||||
-rw-r--r-- | pyserial/serial/serialcli.py | 49 | ||||
-rw-r--r-- | pyserial/serial/serialjava.py | 57 | ||||
-rw-r--r-- | pyserial/serial/serialposix.py | 44 | ||||
-rw-r--r-- | pyserial/serial/serialutil.py | 218 | ||||
-rw-r--r-- | pyserial/serial/serialwin32.py | 53 |
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!! |