__init__.py 3.1 KB

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