text: """This is the pyusb implementation of the seabreeze library
  
  Author: Andreas Poehlmann
  
  most of this code is based on implementations from
      http://github.com/ap--/python-oceanoptics
  
  """
  import logging
  import weakref
  
  from seabreeze.pyseabreeze.devices import SeaBreezeDevice, _model_class_registry
  from seabreeze.pyseabreeze.transport import (
      USBTransport,
      USBTransportDeviceInUse,
      USBTransportError,
      USBTransportHandle,
  )
  
  __all__ = ["SeaBreezeAPI"]
  
  # create only one SeaBreezeDevice instance per handle
  _seabreeze_device_instance_registry = weakref.WeakValueDictionary()
  
  
  def _seabreeze_device_factory(device):
      """return existing instances instead of creating temporary ones
  
      Parameters
      ----------
      device : USBTransportHandle
  
      Returns
      -------
      dev : SeaBreezeDevice
      """
      global _seabreeze_device_instance_registry
      if not isinstance(device, USBTransportHandle):
          raise TypeError("needs to be instance of USBTransportHandle")
      ident = device.identity
      try:
          return _seabreeze_device_instance_registry[ident]
      except KeyError:
          dev = _seabreeze_device_instance_registry[ident] = SeaBreezeDevice(device)
          return dev
  
  
  class SeaBreezeAPI(object):
      """SeaBreeze API interface"""
  
      _log = logging.getLogger(__name__)
  
      def __init__(self, initialize=True, **_kwargs):
          self._kwargs = _kwargs  # allow passing additional kwargs to transports
          if initialize:
              self.initialize()
  
      def initialize(self):
          """initialize the api backend
  
          normally this function does not have to be called directly by the user.
          it resets all usb devices on load
          """
          USBTransport.initialize(**self._kwargs)
  
      def shutdown(self):
          """shutdown the api backend
  
          normally this function does not have to be called directly by the user
          """
          # dispose usb resources
          _seabreeze_device_instance_registry.clear()
          USBTransport.shutdown(**self._kwargs)
  
      def add_rs232_device_location(self, device_type, bus_path, baudrate):
          """add RS232 device location"""
          # RS232Transport.register_device(device_type, bus_path, baudrate)
          raise NotImplementedError("rs232 communication not implemented for pyseabreeze")
  
      def add_ipv4_device_location(self, device_type, ip_address, port):
          """add ipv4 device location"""
          # IPV4Transport.register_device(device_type, ip_address, port)
          raise NotImplementedError("ipv4 communication not implemented for pyseabreeze")
  
      def list_devices(self):
          """returns available SeaBreezeDevices
  
          list all connected Ocean Optics devices supported
          by libseabreeze.
  
          Returns
          -------
          devices: list of SeaBreezeDevice
              connected Spectrometer instances
          """
          # get all matching devices
          devices = []
          for usb_dev in USBTransport.list_devices(**self._kwargs):
              # get the correct communication interface
              dev = _seabreeze_device_factory(usb_dev)
              if not dev.is_open:
                  # opening the device will populate its serial number
                  try:
                      dev.open()
                  except USBTransportDeviceInUse:
                      # device used by another thread? -> exclude
                      continue
                  except USBTransportError:
                      # todo: investigate if there are ways to recover from here
                      raise
                  else:
                      dev.close()
              devices.append(dev)
          return devices
  
      # note: to be fully consistent with cseabreeze this shouldn't be a staticmethod
      @staticmethod
      def supported_models():
          """returns SeaBreezeDevices supported by the backend
  
          models supported by the backend
  
          Returns
          -------
          devices: list of str
              list of model names that are supported by this backend
          """
          return [
              x for x in sorted(_model_class_registry.keys()) if not x.startswith("_")
          ]
  