blob: a5d123309a61a5481487343205406311523f9435 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001#!/usr/bin/env python
2#
3# This is a wrapper module for different platform implementations
4#
5# This file is part of pySerial. https://github.com/pyserial/pyserial
6# (C) 2001-2016 Chris Liechti <cliechti@gmx.net>
7#
8# SPDX-License-Identifier: BSD-3-Clause
9
10import importlib
11import sys
12
13from pyserial.serialutil import *
14#~ SerialBase, SerialException, to_bytes, iterbytes
15
16VERSION = '3.0.1'
17
18if sys.platform == 'cli':
19 from serial.serialcli import Serial
20else:
21 import os
22 # chose an implementation, depending on os
23 if os.name == 'nt': # sys.platform == 'win32':
24 from pyserial.serialwin32 import Serial
25 elif os.name == 'posix':
26 from pyserial.serialposix import Serial, PosixPollSerial, VTIMESerial # noqa
27 elif os.name == 'java':
28 from pyserial.serialjava import Serial
29 else:
30 raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))
31
32
33protocol_handler_packages = [
34 'pyserial.urlhandler',
35]
36
37
38def serial_for_url(url, *args, **kwargs):
39 """\
40 Get an instance of the Serial class, depending on port/url. The port is not
41 opened when the keyword parameter 'do_not_open' is true, by default it
42 is. All other parameters are directly passed to the __init__ method when
43 the port is instantiated.
44
45 The list of package names that is searched for protocol handlers is kept in
46 ``protocol_handler_packages``.
47
48 e.g. we want to support a URL ``foobar://``. A module
49 ``my_handlers.protocol_foobar`` is provided by the user. Then
50 ``protocol_handler_packages.append("my_handlers")`` would extend the search
51 path so that ``serial_for_url("foobar://"))`` would work.
52 """
53 # check and remove extra parameter to not confuse the Serial class
54 do_open = not kwargs.pop('do_not_open', False)
55 # the default is to use the native implementation
56 klass = Serial
57 try:
58 url_lowercase = url.lower()
59 except AttributeError:
60 # it's not a string, use default
61 pass
62 else:
63 # if it is an URL, try to import the handler module from the list of possible packages
64 if '://' in url_lowercase:
65 protocol = url_lowercase.split('://', 1)[0]
66 module_name = '.protocol_%s' % (protocol,)
67 for package_name in protocol_handler_packages:
68 try:
69 package = importlib.import_module(package_name)
70 handler_module = importlib.import_module(module_name, package_name)
71 except ImportError:
72 continue
73 else:
74 if hasattr(handler_module, 'serial_class_for_url'):
75 url, klass = handler_module.serial_class_for_url(url)
76 else:
77 klass = handler_module.Serial
78 break
79 else:
80 raise ValueError('invalid URL, protocol %r not known' % (protocol,))
81 # instantiate and open when desired
82 instance = klass(None, *args, **kwargs)
83 instance.port = url
84 if do_open:
85 instance.open()
86 return instance