1#! python
2#
3# This module implements a special URL handler that allows selecting an
4# alternate implementation provided by some backends.
5#
6# This file is part of pySerial. https://github.com/pyserial/pyserial
7# (C) 2015 Chris Liechti <[email protected]>
8#
9# SPDX-License-Identifier:    BSD-3-Clause
10#
11# URL format:    alt://port[?option[=value][&option[=value]]]
12# options:
13# - class=X used class named X instead of Serial
14#
15# example:
16#   use poll based implementation on Posix (Linux):
17#   python -m serial.tools.miniterm alt:///dev/ttyUSB0?class=PosixPollSerial
18
19from __future__ import absolute_import
20
21try:
22    import urlparse
23except ImportError:
24    import urllib.parse as urlparse
25
26import serial
27
28
29def serial_class_for_url(url):
30    """extract host and port from an URL string"""
31    parts = urlparse.urlsplit(url)
32    if parts.scheme != 'alt':
33        raise serial.SerialException(
34            'expected a string in the form "alt://port[?option[=value][&option[=value]]]": '
35            'not starting with alt:// ({!r})'.format(parts.scheme))
36    class_name = 'Serial'
37    try:
38        for option, values in urlparse.parse_qs(parts.query, True).items():
39            if option == 'class':
40                class_name = values[0]
41            else:
42                raise ValueError('unknown option: {!r}'.format(option))
43    except ValueError as e:
44        raise serial.SerialException(
45            'expected a string in the form '
46            '"alt://port[?option[=value][&option[=value]]]": {!r}'.format(e))
47    if not hasattr(serial, class_name):
48        raise ValueError('unknown class: {!r}'.format(class_name))
49    cls = getattr(serial, class_name)
50    if not issubclass(cls, serial.Serial):
51        raise ValueError('class {!r} is not an instance of Serial'.format(class_name))
52    return (''.join([parts.netloc, parts.path]), cls)
53
54# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
55if __name__ == '__main__':
56    s = serial.serial_for_url('alt:///dev/ttyS0?class=PosixPollSerial')
57    print(s)
58