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