blob: 38741939154709b077bb3d1b2da6fb4023c22026 [file] [log] [blame]
Steven Michalske2a9486d2015-08-06 22:35:21 -07001#!/usr/bin/env python
Chris Liechtifbdd8a02015-08-09 02:37:45 +02002#
Chris Liechti3e02f702015-12-16 23:06:04 +01003# This is a wrapper module for different platform implementations
cliechti89b4af12002-02-12 23:24:41 +00004#
Chris Liechti3e02f702015-12-16 23:06:04 +01005# This file is part of pySerial. https://github.com/pyserial/pyserial
Chris Liechti91dc0872016-01-11 23:48:41 +01006# (C) 2001-2016 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02007#
8# SPDX-License-Identifier: BSD-3-Clause
cliechti89b4af12002-02-12 23:24:41 +00009
Chris Liechtibaec2a32015-08-07 14:42:15 +020010import importlib
cliechti0bfe5252008-06-21 01:36:52 +000011import sys
Robert Smallshire05f6e0e2016-06-14 08:54:18 +020012from pkgutil import extend_path
13
cliechti0bfe5252008-06-21 01:36:52 +000014
Chris Liechti033f17c2015-08-30 21:28:04 +020015from serial.serialutil import *
16#~ SerialBase, SerialException, to_bytes, iterbytes
17
Chris Liechtif1dec6a2016-06-12 22:47:09 +020018__version__ = '3.1.1'
Robert Smallshirefa3abd62016-03-22 21:39:42 +010019
20VERSION = __version__
Chris Liechti033f17c2015-08-30 21:28:04 +020021
Robert Smallshire05f6e0e2016-06-14 08:54:18 +020022# serial is a namespace package
23__path__ = extend_path(__path__, __name__)
24
Chris Liechti409e10b2016-02-10 22:40:34 +010025# pylint: disable=wrong-import-position
cliechti4ff97242008-06-21 18:14:46 +000026if sys.platform == 'cli':
Chris Liechti033f17c2015-08-30 21:28:04 +020027 from serial.serialcli import Serial
cliechti89b4af12002-02-12 23:24:41 +000028else:
cliechti4ff97242008-06-21 18:14:46 +000029 import os
cliechtifab09872009-02-07 00:25:44 +000030 # chose an implementation, depending on os
Chris Liechti033f17c2015-08-30 21:28:04 +020031 if os.name == 'nt': # sys.platform == 'win32':
32 from serial.serialwin32 import Serial
cliechti0bfe5252008-06-21 01:36:52 +000033 elif os.name == 'posix':
Chris Liechticb6ce1b2016-02-02 01:53:56 +010034 from serial.serialposix import Serial, PosixPollSerial, VTIMESerial # noqa
cliechti0bfe5252008-06-21 01:36:52 +000035 elif os.name == 'java':
Chris Liechti033f17c2015-08-30 21:28:04 +020036 from serial.serialjava import Serial
cliechti0bfe5252008-06-21 01:36:52 +000037 else:
Chris Liechtic8f3f822016-06-08 03:35:28 +020038 raise ImportError("Sorry: no implementation for your platform ('{}') available".format(os.name))
cliechti330185e2011-08-18 22:45:17 +000039
cliechti89b4af12002-02-12 23:24:41 +000040
cliechtie542b362011-03-18 00:49:16 +000041protocol_handler_packages = [
Chris Liechtiba45c522016-02-06 23:53:23 +010042 'serial.urlhandler',
43]
cliechti109486b2009-08-02 00:00:11 +000044
Chris Liechti033f17c2015-08-30 21:28:04 +020045
cliechtie3ab3532009-08-05 12:40:38 +000046def serial_for_url(url, *args, **kwargs):
cliechtie542b362011-03-18 00:49:16 +000047 """\
cliechti330185e2011-08-18 22:45:17 +000048 Get an instance of the Serial class, depending on port/url. The port is not
49 opened when the keyword parameter 'do_not_open' is true, by default it
50 is. All other parameters are directly passed to the __init__ method when
51 the port is instantiated.
cliechtie542b362011-03-18 00:49:16 +000052
53 The list of package names that is searched for protocol handlers is kept in
cliechti330185e2011-08-18 22:45:17 +000054 ``protocol_handler_packages``.
cliechtie542b362011-03-18 00:49:16 +000055
56 e.g. we want to support a URL ``foobar://``. A module
57 ``my_handlers.protocol_foobar`` is provided by the user. Then
58 ``protocol_handler_packages.append("my_handlers")`` would extend the search
59 path so that ``serial_for_url("foobar://"))`` would work.
60 """
Chris Liechti4afb6c92015-10-16 01:11:28 +020061 # check and remove extra parameter to not confuse the Serial class
62 do_open = not kwargs.pop('do_not_open', False)
63 # the default is to use the native implementation
64 klass = Serial
cliechtiaaf778a2009-08-05 17:59:15 +000065 try:
Chris Liechtibaec2a32015-08-07 14:42:15 +020066 url_lowercase = url.lower()
cliechtiaaf778a2009-08-05 17:59:15 +000067 except AttributeError:
cliechti2a6d5332011-03-04 02:08:32 +000068 # it's not a string, use default
cliechtiaaf778a2009-08-05 17:59:15 +000069 pass
cliechti109486b2009-08-02 00:00:11 +000070 else:
Chris Liechti4afb6c92015-10-16 01:11:28 +020071 # if it is an URL, try to import the handler module from the list of possible packages
Chris Liechtibaec2a32015-08-07 14:42:15 +020072 if '://' in url_lowercase:
73 protocol = url_lowercase.split('://', 1)[0]
Chris Liechtic8f3f822016-06-08 03:35:28 +020074 module_name = '.protocol_{}'.format(protocol)
cliechtie542b362011-03-18 00:49:16 +000075 for package_name in protocol_handler_packages:
cliechtie542b362011-03-18 00:49:16 +000076 try:
Chris Liechti6c63da62016-01-25 21:39:32 +010077 importlib.import_module(package_name)
Chris Liechtibaec2a32015-08-07 14:42:15 +020078 handler_module = importlib.import_module(module_name, package_name)
cliechtie542b362011-03-18 00:49:16 +000079 except ImportError:
Chris Liechti4afb6c92015-10-16 01:11:28 +020080 continue
cliechtie542b362011-03-18 00:49:16 +000081 else:
Chris Liechti8ce75fa2015-10-17 23:36:15 +020082 if hasattr(handler_module, 'serial_class_for_url'):
83 url, klass = handler_module.serial_class_for_url(url)
84 else:
85 klass = handler_module.Serial
cliechtie542b362011-03-18 00:49:16 +000086 break
cliechti2a6d5332011-03-04 02:08:32 +000087 else:
Chris Liechtic8f3f822016-06-08 03:35:28 +020088 raise ValueError('invalid URL, protocol {!r} not known'.format(protocol))
cliechti9b1d3ad2009-08-02 23:47:04 +000089 # instantiate and open when desired
cliechti109486b2009-08-02 00:00:11 +000090 instance = klass(None, *args, **kwargs)
91 instance.port = url
cliechti9b1d3ad2009-08-02 23:47:04 +000092 if do_open:
cliechti109486b2009-08-02 00:00:11 +000093 instance.open()
94 return instance