summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liechti <cliechti@gmx.net>2015-08-21 00:28:53 +0200
committerChris Liechti <cliechti@gmx.net>2015-08-21 00:28:53 +0200
commitd14b1ab6ecdf39020c7a2f6a1efee1c21254d176 (patch)
treea0b3e7b49f63b4fd310c02d0042a85a5d11284d6
parente9e27ff3da9d9a54f5b6e1f8bd41c6791df01683 (diff)
downloadpyserial-git-d14b1ab6ecdf39020c7a2f6a1efee1c21254d176.tar.gz
URLs: changed paramter delimiter from / to ? and & as it is usual for URLs, update docs
-rw-r--r--CHANGES.rst12
-rw-r--r--documentation/pyserial_api.rst34
-rw-r--r--serial/rfc2217.py20
-rw-r--r--serial/urlhandler/protocol_loop.py18
-rw-r--r--serial/urlhandler/protocol_socket.py18
-rw-r--r--serial/urlhandler/protocol_spy.py19
6 files changed, 63 insertions, 58 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 7eb2a1c..ffc6e26 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -507,22 +507,24 @@ Version 3.0a 2015-xx-xx
--------------------------
- Starting from this release, only 2.7 and 3.4 (or newer) are supported. The
- sourcecode is compatible to the 2.x and 3.x series without any changes. The
+ source code is compatible to the 2.x and 3.x series without any changes. The
support for earlier Python versions than 2.7 is removed, please refer to the
pyserial-legacy (V2.x) series if older Python versions are a requirement).
- remove file ``FileLike`` class, add ``read_until`` and ``iread_until`` to
``SerialBase``
- remove set* functions, please use the properties instead
-- RS485 support changed (rts_toggle removed, added serial.rs485 module and
- rs485_mode property)
-- socket:// and rfc2217:// handlers use the IPv6 compatible socket.create_connection
+- RS485 support changed (rts_toggle removed, added ``serial.rs485`` module and
+ ``rs485_mode`` property)
+- ``socket://`` and ``rfc2217://`` handlers use the IPv6 compatible ``socket.create_connection``
- remove obsolete examples
- finish update to BSD license
- update links to point to github
- [Patch pyserial:34] Improvements to port_publisher.py example
- [Feature pyserial:39] Support BlueTooth serial port discovery on Linux
-- Use setuptools if aviliable, fall back to distutils if unaviliable.
+- Use setuptools if available, fall back to distutils if unavailable.
- miniterm: changed command line options, translations, support encodings
+- URL handlers now require the proper format (``?`` and ``&``) for arguments
+ instead of ``/`` (e.g. ``rfc2217://localhost:7000?ign_set_control&timeout=5.5``)
Bugfixes:
diff --git a/documentation/pyserial_api.rst b/documentation/pyserial_api.rst
index 771b673..c32cece 100644
--- a/documentation/pyserial_api.rst
+++ b/documentation/pyserial_api.rst
@@ -800,6 +800,17 @@ Module functions and attributes
.. versionadded:: 2.5
+.. function:: iterbytes(b)
+
+ :param b: bytes, bytearray or memoryview
+ :returns: a generator that yields bytes
+
+ Some versions of Python (3.x) would return integers instead of bytes when
+ looping over an instance of ``bytes``. This helper function ensures that
+ bytes are returned.
+
+ .. versionadded:: 3.0
+
.. _URLs:
@@ -807,11 +818,13 @@ URLs
----
The function :func:`serial_for_url` accepts the following types of URLs:
-- ``rfc2217://<host>:<port>[/<option>[/<option>]]``
-- ``socket://<host>:<port>[/<option>[/<option>]]``
-- ``loop://[<option>[/<option>]]``
+- ``rfc2217://<host>:<port>[?<option>[&<option>...]]``
+- ``socket://<host>:<port>[?logging={debug|info|warning|error}]``
+- ``loop://[?logging={debug|info|warning|error}]``
- ``spy://port[?option[=value][&option[=value]]]``
+.. versionchanged:: 3.0 Options are specified with ``?`` and ``&`` instead of ``/``
+
Device names are also supported, e.g.:
- ``/dev/ttyUSB0`` (Linux)
@@ -842,7 +855,7 @@ possible for the user to add protocol handlers using
timeout applies to the initial Telnet / :rfc:`2271` negotiation as well
as changing port settings or control line change commands.
- - ``logging=[debug|info|warning|error]``: Prints diagnostic messages (not
+ - ``logging={debug|info|warning|error}``: Prints diagnostic messages (not
useful for end users). It uses the logging module and a logger called
``pySerial.rfc2217`` so that the application can setup up logging
handlers etc. It will call :meth:`logging.basicConfig` which initializes
@@ -857,7 +870,7 @@ possible for the user to add protocol handlers using
Supported options in the URL are:
- - ``logging=[debug|info|warning|error]``: Prints diagnostic messages (not
+ - ``logging={debug|info|warning|error}``: Prints diagnostic messages (not
useful for end users). It uses the logging module and a logger called
``pySerial.socket`` so that the application can setup up logging handlers
etc. It will call :meth:`logging.basicConfig` which initializes for
@@ -870,7 +883,7 @@ possible for the user to add protocol handlers using
Supported options in the URL are:
- - ``logging=[debug|info|warning|error]``: Prints diagnostic messages (not
+ - ``logging={debug|info|warning|error}``: Prints diagnostic messages (not
useful for end users). It uses the logging module and a logger called
``pySerial.loop`` so that the application can setup up logging handlers
etc. It will call :meth:`logging.basicConfig` which initializes for
@@ -958,16 +971,19 @@ possible for the user to add protocol handlers using
000002.284 RX 00F0 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF ........ ........
000002.284 BRK sendBreak 0.25
+ .. versionadded:: 3.0
+
Examples:
- ``rfc2217://localhost:7000``
-- ``rfc2217://localhost:7000/poll_modem``
-- ``rfc2217://localhost:7000/ign_set_control/timeout=5.5``
+- ``rfc2217://localhost:7000?poll_modem``
+- ``rfc2217://localhost:7000?ign_set_control&timeout=5.5``
- ``socket://localhost:7777``
-- ``loop://logging=debug``
+- ``loop://?logging=debug``
- ``hwgrep://0451:f432`` (USB VID:PID)
+- ``spy://COM54?dev=log.txt``
Tools
=====
diff --git a/serial/rfc2217.py b/serial/rfc2217.py
index 9c5d68b..c87b14b 100644
--- a/serial/rfc2217.py
+++ b/serial/rfc2217.py
@@ -535,35 +535,29 @@ class Serial(SerialBase):
def fromURL(self, url):
"""extract host and port from an URL string"""
parts = urlparse.urlsplit(url)
- if parts.scheme.lower() != "rfc2217":
- raise SerialException('expected a string in the form "rfc2217://<host>:<port>[/option[/option...]]": not starting with rfc2217:// (%r)' % (parts.scheme,))
+ if parts.scheme != "rfc2217":
+ raise SerialException('expected a string in the form "rfc2217://<host>:<port>[?option[&option...]]": not starting with rfc2217:// (%r)' % (parts.scheme,))
try:
# process options now, directly altering self
- for option in parts.path.lower().split('/'):
- if '=' in option:
- option, value = option.split('=', 1)
- else:
- value = None
- if not option:
- pass
- elif option == 'logging':
+ for option, values in urlparse.parse_qs(parts.query, True).items():
+ if option == 'logging':
logging.basicConfig() # XXX is that good to call it here?
self.logger = logging.getLogger('pySerial.rfc2217')
- self.logger.setLevel(LOGGER_LEVELS[value])
+ self.logger.setLevel(LOGGER_LEVELS[values[0]])
self.logger.debug('enabled logging')
elif option == 'ign_set_control':
self._ignore_set_control_answer = True
elif option == 'poll_modem':
self._poll_modem_state = True
elif option == 'timeout':
- self._network_timeout = float(value)
+ self._network_timeout = float(values[0])
else:
raise ValueError('unknown option: %r' % (option,))
# get host and port
host, port = parts.hostname, parts.port
if not 0 <= port < 65536: raise ValueError("port not in range 0...65535")
except ValueError as e:
- raise SerialException('expected a string in the form "rfc2217://<host>:<port>[/option[/option...]]": %s' % e)
+ raise SerialException('expected a string in the form "rfc2217://<host>:<port>[?option[&option...]]": %s' % e)
return (host, port)
# - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/serial/urlhandler/protocol_loop.py b/serial/urlhandler/protocol_loop.py
index 02167e5..10dedeb 100644
--- a/serial/urlhandler/protocol_loop.py
+++ b/serial/urlhandler/protocol_loop.py
@@ -102,26 +102,20 @@ class Serial(SerialBase):
def fromURL(self, url):
"""extract host and port from an URL string"""
parts = urlparse.urlsplit(url)
- if parts.scheme.lower() != "loop":
- raise SerialException('expected a string in the form "loop://[option[/option...]]": not starting with loop:// (%r)' % (parts.scheme,))
+ if parts.scheme != "loop":
+ raise SerialException('expected a string in the form "loop://[?logging={debug|info|warning|error}]": not starting with loop:// (%r)' % (parts.scheme,))
try:
# process options now, directly altering self
- for option in parts.path.split('/'):
- if '=' in option:
- option, value = option.split('=', 1)
- else:
- value = None
- if not option:
- pass
- elif option == 'logging':
+ for option, values in urlparse.parse_qs(parts.query, True).items():
+ if option == 'logging':
logging.basicConfig() # XXX is that good to call it here?
self.logger = logging.getLogger('pySerial.loop')
- self.logger.setLevel(LOGGER_LEVELS[value])
+ self.logger.setLevel(LOGGER_LEVELS[values[0]])
self.logger.debug('enabled logging')
else:
raise ValueError('unknown option: %r' % (option,))
except ValueError as e:
- raise SerialException('expected a string in the form "[loop://][option[/option...]]": %s' % e)
+ raise SerialException('expected a string in the form "loop://[?logging={debug|info|warning|error}]": %s' % e)
# - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/serial/urlhandler/protocol_socket.py b/serial/urlhandler/protocol_socket.py
index 4538e17..3dedb48 100644
--- a/serial/urlhandler/protocol_socket.py
+++ b/serial/urlhandler/protocol_socket.py
@@ -104,21 +104,15 @@ class Serial(SerialBase):
def fromURL(self, url):
"""extract host and port from an URL string"""
parts = urlparse.urlsplit(url)
- if parts.scheme.lower() != "socket":
- raise SerialException('expected a string in the form "socket://<host>:<port>[/option[/option...]]": not starting with socket:// (%r)' % (parts.scheme,))
+ if parts.scheme != "socket":
+ raise SerialException('expected a string in the form "socket://<host>:<port>[?logging={debug|info|warning|error}]": not starting with socket:// (%r)' % (parts.scheme,))
try:
# process options now, directly altering self
- for option in parts.path.lower().split('/'):
- if '=' in option:
- option, value = option.split('=', 1)
- else:
- value = None
- if not option:
- pass
- elif option == 'logging':
+ for option, values in urlparse.parse_qs(parts.query, True).items():
+ if option == 'logging':
logging.basicConfig() # XXX is that good to call it here?
self.logger = logging.getLogger('pySerial.socket')
- self.logger.setLevel(LOGGER_LEVELS[value])
+ self.logger.setLevel(LOGGER_LEVELS[values[0]])
self.logger.debug('enabled logging')
else:
raise ValueError('unknown option: %r' % (option,))
@@ -126,7 +120,7 @@ class Serial(SerialBase):
host, port = parts.hostname, parts.port
if not 0 <= port < 65536: raise ValueError("port not in range 0...65535")
except ValueError as e:
- raise SerialException('expected a string in the form "socket://<host>:<port>[/option[/option...]]": %s' % e)
+ raise SerialException('expected a string in the form "socket://<host>:<port>[?logging={debug|info|warning|error}]": %s' % e)
return (host, port)
# - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/serial/urlhandler/protocol_spy.py b/serial/urlhandler/protocol_spy.py
index a4deaef..d6ed458 100644
--- a/serial/urlhandler/protocol_spy.py
+++ b/serial/urlhandler/protocol_spy.py
@@ -165,13 +165,18 @@ class Serial(serial.Serial):
formatter = FormatHexdump
color = False
output = sys.stderr
- for option, values in urlparse.parse_qs(parts.query, True).items():
- if option == 'dev':
- output = open(values[0], 'w')
- elif option == 'color':
- color = True
- elif option == 'raw':
- formatter = FormatRaw
+ try:
+ for option, values in urlparse.parse_qs(parts.query, True).items():
+ if option == 'dev':
+ output = open(values[0], 'w')
+ elif option == 'color':
+ color = True
+ elif option == 'raw':
+ formatter = FormatRaw
+ else:
+ raise ValueError('unknown option: %r' % (option,))
+ except ValueError as e:
+ raise SerialException('expected a string in the form "spy://port[?option[=value][&option[=value]]]": %s' % e)
self.formatter = formatter(output, color)
return ''.join([parts.netloc, parts.path])