diff options
-rw-r--r-- | documentation/examples.rst | 2 | ||||
-rw-r--r-- | documentation/pyserial_api.rst | 13 | ||||
-rw-r--r-- | documentation/shortintro.rst | 17 | ||||
-rw-r--r-- | documentation/url_handlers.rst | 11 | ||||
-rw-r--r-- | serial/serialutil.py | 2 | ||||
-rw-r--r-- | serial/tools/list_ports_linux.py | 17 | ||||
-rw-r--r-- | serial/tools/list_ports_posix.py | 32 | ||||
-rw-r--r-- | serial/tools/miniterm.py | 29 | ||||
-rw-r--r-- | serial/urlhandler/protocol_hwgrep.py | 2 | ||||
-rw-r--r-- | serial/urlhandler/protocol_spy.py | 47 | ||||
-rwxr-xr-x | test/test_context.py | 2 |
11 files changed, 122 insertions, 52 deletions
diff --git a/documentation/examples.rst b/documentation/examples.rst index 0430267..197c015 100644 --- a/documentation/examples.rst +++ b/documentation/examples.rst @@ -199,7 +199,7 @@ port_publisher.sh_ Example init.d script. .. _port_publisher.py: https://github.com/pyserial/pyserial/blob/master/examples/port_publisher.py -.. _port_publisher.sh: https://github.com/pyserial/pyserial/blob/master/examples/http://sourceforge.net/p/pyserial/code/HEAD/tree/trunk/pyserial/examples/port_publisher.sh +.. _port_publisher.sh: https://github.com/pyserial/pyserial/blob/master/examples/port_publisher.sh wxPython examples diff --git a/documentation/pyserial_api.rst b/documentation/pyserial_api.rst index efd82c1..fd15db5 100644 --- a/documentation/pyserial_api.rst +++ b/documentation/pyserial_api.rst @@ -150,7 +150,7 @@ Native ports :rtype: bytes 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 + return fewer characters than requested. With no timeout it will block until the requested number of bytes is read. .. versionchanged:: 2.5 @@ -166,13 +166,16 @@ Native ports Read until an expected sequence is found ('\\n' by default), the size is exceeded or until timeout occurs. If a timeout is set it may - return less characters as requested. With no timeout it will block + return fewer characters than 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` otherwise. + .. versionchanged:: 3.5 + First argument was called ``terminator`` in previous versions. + .. method:: write(data) :param data: Data to send. @@ -483,11 +486,11 @@ Native ports .. method:: readline(size=-1) - Provided via :meth:`io.IOBase.readline` + Provided via :meth:`io.IOBase.readline` See also ref:`shortintro_readline`. .. method:: readlines(hint=-1) - Provided via :meth:`io.IOBase.readlines` + Provided via :meth:`io.IOBase.readlines`. See also ref:`shortintro_readline`. .. method:: writelines(lines) @@ -1185,7 +1188,7 @@ This module provides classes to simplify working with threads and protocols. .. attribute:: UNICODE_HANDLING = 'replace' - Unicode error handly policy. + Unicode error handling policy. .. method:: handle_packet(packet) diff --git a/documentation/shortintro.rst b/documentation/shortintro.rst index b9230e3..11b2ea0 100644 --- a/documentation/shortintro.rst +++ b/documentation/shortintro.rst @@ -53,13 +53,24 @@ Also supported with :ref:`context manager <context-manager>`:: ser.write(b'hello') +.. _shortintro_readline: + Readline ======== +:meth:`readline` reads up to one line, including the `\n` at the end. Be careful when using :meth:`readline`. Do specify a timeout when opening the serial port otherwise it could block forever if no newline character is -received. Also note that :meth:`readlines` only works with a timeout. -:meth:`readlines` depends on having a timeout and interprets that as EOF (end -of file). It raises an exception if the port is not opened correctly. +received. If the `\n` is missing in the return value, it returned on timeout. + +:meth:`readlines` tries to read "all" lines which is not well defined for a +serial port that is still open. Therefore :meth:`readlines` depends on having +a timeout on the port and interprets that as EOF (end of file). It raises an +exception if the port is not opened correctly. The returned list of lines do +not include the `\n`. + +Both functions call :meth:`read` to get their data and the serial port timeout +is acting on this function. Therefore the effective timeout, especially for +:meth:`readlines`, can be much larger. Do also have a look at the example files in the examples directory in the source distribution or online. diff --git a/documentation/url_handlers.rst b/documentation/url_handlers.rst index 42a53fa..5c57615 100644 --- a/documentation/url_handlers.rst +++ b/documentation/url_handlers.rst @@ -140,6 +140,13 @@ Supported options in the URL are: hex dump). In this mode, no control line and other commands are logged. - ``all`` also show ``in_waiting`` and empty ``read()`` calls (hidden by default because of high traffic). +- ``log`` or ``log=LOGGERNAME`` output to stdlib ``logging`` module. Default + channel name is ``serial``. This variant outputs hex dump. +- ``rawlog`` or ``rawlog=LOGGERNAME`` output to stdlib ``logging`` module. Default + channel name is ``serial``. This variant outputs text (``repr``). + +The ``log`` and ``rawlog`` options require that the logging is set up, in order +to see the log output. Example:: @@ -208,6 +215,7 @@ not interpreted by the shell:: The spy output will be live in the second terminal window. .. versionadded:: 3.0 +.. versionchanged:: 3.6 Added ``log`` and ``rawlog`` options ``alt://`` @@ -236,9 +244,9 @@ Examples:: .. versionadded:: 3.0 + ``cp2110://`` ============= - This backend implements support for HID-to-UART devices manufactured by Silicon Labs and marketed as CP2110 and CP2114. The implementation is (mostly) OS-independent and in userland. It relies on `cython-hidapi`_. @@ -264,4 +272,3 @@ Examples - ``spy://COM54?file=log.txt`` - ``alt:///dev/ttyUSB0?class=PosixPollSerial`` - ``cp2110://0001:004a:00`` - diff --git a/serial/serialutil.py b/serial/serialutil.py index 789219e..f554472 100644 --- a/serial/serialutil.py +++ b/serial/serialutil.py @@ -653,7 +653,7 @@ class SerialBase(io.RawIOBase): def read_until(self, expected=LF, size=None): """\ - Read until an expected sequence is found ('\n' by default), the size + Read until an expected sequence is found (line feed by default), the size is exceeded or until timeout occurs. """ lenterm = len(expected) diff --git a/serial/tools/list_ports_linux.py b/serial/tools/list_ports_linux.py index c8c1cfc..ec2e0ca 100644 --- a/serial/tools/list_ports_linux.py +++ b/serial/tools/list_ports_linux.py @@ -89,15 +89,16 @@ class SysFS(list_ports_common.ListPortInfo): def comports(include_links=False): - devices = glob.glob('/dev/ttyS*') # built-in serial ports - devices.extend(glob.glob('/dev/ttyUSB*')) # usb-serial with own driver - devices.extend(glob.glob('/dev/ttyXRUSB*')) # xr-usb-serial port exar (DELL Edge 3001) - devices.extend(glob.glob('/dev/ttyACM*')) # usb-serial with CDC-ACM profile - devices.extend(glob.glob('/dev/ttyAMA*')) # ARM internal port (raspi) - devices.extend(glob.glob('/dev/rfcomm*')) # BT serial devices - devices.extend(glob.glob('/dev/ttyAP*')) # Advantech multi-port serial controllers + devices = set() + devices.update(glob.glob('/dev/ttyS*')) # built-in serial ports + devices.update(glob.glob('/dev/ttyUSB*')) # usb-serial with own driver + devices.update(glob.glob('/dev/ttyXRUSB*')) # xr-usb-serial port exar (DELL Edge 3001) + devices.update(glob.glob('/dev/ttyACM*')) # usb-serial with CDC-ACM profile + devices.update(glob.glob('/dev/ttyAMA*')) # ARM internal port (raspi) + devices.update(glob.glob('/dev/rfcomm*')) # BT serial devices + devices.update(glob.glob('/dev/ttyAP*')) # Advantech multi-port serial controllers if include_links: - devices.extend(list_ports_common.list_links(devices)) + devices.update(list_ports_common.list_links(devices)) return [info for info in [SysFS(d) for d in devices] if info.subsystem != "platform"] # hide non-present internal serial ports diff --git a/serial/tools/list_ports_posix.py b/serial/tools/list_ports_posix.py index 79bc8ed..b115754 100644 --- a/serial/tools/list_ports_posix.py +++ b/serial/tools/list_ports_posix.py @@ -37,63 +37,63 @@ elif plat == 'cygwin': # cygwin/win32 # (such as 'open' call, explicit 'ls'), but 'glob.glob' # and bare 'ls' do not; so use /dev/ttyS* instead def comports(include_links=False): - devices = glob.glob('/dev/ttyS*') + devices = set(glob.glob('/dev/ttyS*')) if include_links: - devices.extend(list_ports_common.list_links(devices)) + devices.update(list_ports_common.list_links(devices)) return [list_ports_common.ListPortInfo(d) for d in devices] elif plat[:7] == 'openbsd': # OpenBSD def comports(include_links=False): - devices = glob.glob('/dev/cua*') + devices = set(glob.glob('/dev/cua*')) if include_links: - devices.extend(list_ports_common.list_links(devices)) + devices.update(list_ports_common.list_links(devices)) return [list_ports_common.ListPortInfo(d) for d in devices] elif plat[:3] == 'bsd' or plat[:7] == 'freebsd': def comports(include_links=False): - devices = glob.glob('/dev/cua*[!.init][!.lock]') + devices = set(glob.glob('/dev/cua*[!.init][!.lock]')) if include_links: - devices.extend(list_ports_common.list_links(devices)) + devices.update(list_ports_common.list_links(devices)) return [list_ports_common.ListPortInfo(d) for d in devices] elif plat[:6] == 'netbsd': # NetBSD def comports(include_links=False): """scan for available ports. return a list of device names.""" - devices = glob.glob('/dev/dty*') + devices = set(glob.glob('/dev/dty*')) if include_links: - devices.extend(list_ports_common.list_links(devices)) + devices.update(list_ports_common.list_links(devices)) return [list_ports_common.ListPortInfo(d) for d in devices] elif plat[:4] == 'irix': # IRIX def comports(include_links=False): """scan for available ports. return a list of device names.""" - devices = glob.glob('/dev/ttyf*') + devices = set(glob.glob('/dev/ttyf*')) if include_links: - devices.extend(list_ports_common.list_links(devices)) + devices.update(list_ports_common.list_links(devices)) return [list_ports_common.ListPortInfo(d) for d in devices] elif plat[:2] == 'hp': # HP-UX (not tested) def comports(include_links=False): """scan for available ports. return a list of device names.""" - devices = glob.glob('/dev/tty*p0') + devices = set(glob.glob('/dev/tty*p0')) if include_links: - devices.extend(list_ports_common.list_links(devices)) + devices.update(list_ports_common.list_links(devices)) return [list_ports_common.ListPortInfo(d) for d in devices] elif plat[:5] == 'sunos': # Solaris/SunOS def comports(include_links=False): """scan for available ports. return a list of device names.""" - devices = glob.glob('/dev/tty*c') + devices = set(glob.glob('/dev/tty*c')) if include_links: - devices.extend(list_ports_common.list_links(devices)) + devices.update(list_ports_common.list_links(devices)) return [list_ports_common.ListPortInfo(d) for d in devices] elif plat[:3] == 'aix': # AIX def comports(include_links=False): """scan for available ports. return a list of device names.""" - devices = glob.glob('/dev/tty*') + devices = set(glob.glob('/dev/tty*')) if include_links: - devices.extend(list_ports_common.list_links(devices)) + devices.update(list_ports_common.list_links(devices)) return [list_ports_common.ListPortInfo(d) for d in devices] else: diff --git a/serial/tools/miniterm.py b/serial/tools/miniterm.py index 2cceff6..236d917 100644 --- a/serial/tools/miniterm.py +++ b/serial/tools/miniterm.py @@ -104,16 +104,16 @@ if os.name == 'nt': # noqa class Console(ConsoleBase): fncodes = { - ';': '\1bOP', # F1 - '<': '\1bOQ', # F2 - '=': '\1bOR', # F3 - '>': '\1bOS', # F4 - '?': '\1b[15~', # F5 - '@': '\1b[17~', # F6 - 'A': '\1b[18~', # F7 - 'B': '\1b[19~', # F8 - 'C': '\1b[20~', # F9 - 'D': '\1b[21~', # F10 + ';': '\x1bOP', # F1 + '<': '\x1bOQ', # F2 + '=': '\x1bOR', # F3 + '>': '\x1bOS', # F4 + '?': '\x1b[15~', # F5 + '@': '\x1b[17~', # F6 + 'A': '\x1b[18~', # F7 + 'B': '\x1b[19~', # F8 + 'C': '\x1b[20~', # F9 + 'D': '\x1b[21~', # F10 } navcodes = { 'H': '\x1b[A', # UP @@ -372,7 +372,8 @@ def ask_for_port(): sys.stderr.write('--- {:2}: {:20} {!r}\n'.format(n, port, desc)) ports.append(port) while True: - port = raw_input('--- Enter port index or full name: ') + sys.stderr.write('--- Enter port index or full name: ') + port = raw_input('') try: index = int(port) - 1 if not 0 <= index < len(ports): @@ -635,7 +636,7 @@ class Miniterm(object): sys.stderr.write('--- unknown menu character {} --\n'.format(key_description(c))) def upload_file(self): - """Ask user for filenname and send its contents""" + """Ask user for filename and send its contents""" sys.stderr.write('\n--- File to upload: ') sys.stderr.flush() with self.console: @@ -810,7 +811,7 @@ class Miniterm(object): # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # default args can be used to override when calling main() from an other script # e.g to create a miniterm-my-device.py -def main(default_port=None, default_baudrate=9600, default_rts=None, default_dtr=None): +def main(default_port=None, default_baudrate=9600, default_rts=None, default_dtr=None, serial_instance=None): """Command line tool, entry point""" import argparse @@ -959,7 +960,7 @@ def main(default_port=None, default_baudrate=9600, default_rts=None, default_dtr else: filters = ['default'] - while True: + while serial_instance is None: # no port given on command line -> ask user now if args.port is None or args.port == '-': try: diff --git a/serial/urlhandler/protocol_hwgrep.py b/serial/urlhandler/protocol_hwgrep.py index 1a288c9..22805cc 100644 --- a/serial/urlhandler/protocol_hwgrep.py +++ b/serial/urlhandler/protocol_hwgrep.py @@ -12,7 +12,7 @@ # # where <regexp> is a Python regexp according to the re module # -# violating the normal definition for URLs, the charachter `&` is used to +# violating the normal definition for URLs, the character `&` is used to # separate parameters from the arguments (instead of `?`, but the question mark # is heavily used in regexp'es) # diff --git a/serial/urlhandler/protocol_spy.py b/serial/urlhandler/protocol_spy.py index 67c700b..55e3765 100644 --- a/serial/urlhandler/protocol_spy.py +++ b/serial/urlhandler/protocol_spy.py @@ -22,6 +22,7 @@ from __future__ import absolute_import +import logging import sys import time @@ -152,6 +153,46 @@ class FormatHexdump(object): self.write_line(time.time() - self.start_time, name, value) +class FormatLog(object): + """\ + Write data to logging module. + """ + + def __init__(self, output, color): + # output and color is ignored + self.log = logging.getLogger(output) + + def rx(self, data): + """show received data""" + if data: + self.log.info('RX {!r}'.format(data)) + + def tx(self, data): + """show transmitted data""" + self.log.info('TX {!r}'.format(data)) + + def control(self, name, value): + """show control calls""" + self.log.info('{}: {}'.format(name, value)) + + +class FormatLogHex(FormatLog): + """\ + Write data to logging module. + """ + + def rx(self, data): + """show received data""" + if data: + for offset, row in hexdump(data): + self.log.info('RX {}{}'.format('{:04X} '.format(offset), row)) + + def tx(self, data): + """show transmitted data""" + for offset, row in hexdump(data): + self.log.info('TX {}{}'.format('{:04X} '.format(offset), row)) + + class Serial(serial.Serial): """\ Inherit the native Serial port implementation and wrap all the methods and @@ -189,6 +230,12 @@ class Serial(serial.Serial): color = True elif option == 'raw': formatter = FormatRaw + elif option == 'rawlog': + formatter = FormatLog + output = values[0] if values[0] else 'serial' + elif option == 'log': + formatter = FormatLogHex + output = values[0] if values[0] else 'serial' elif option == 'all': self.show_all = True else: diff --git a/test/test_context.py b/test/test_context.py index 456c85a..a65a626 100755 --- a/test/test_context.py +++ b/test/test_context.py @@ -11,7 +11,7 @@ Part of pySerial (http://pyserial.sf.net) (C)2001-2011 cliechti@gmx.net Intended to be run on different platforms, to ensure portability of
the code.
-Cover some of the aspects of context managment
+Cover some of the aspects of context management
"""
import unittest
|