text: #         Python Stream Deck Library
  #      Released under the MIT license
  #
  #   dean [at] fourwalledcubicle [dot] com
  #         www.fourwalledcubicle.com
  #
  
  from abc import ABC, abstractmethod
  
  
  class TransportError(Exception):
      """
      Exception thrown when attempting to access a device using a backend
      transport that has failed (for example, if the requested device could not
      be accessed).
      """
  
      pass
  
  
  class Transport(ABC):
      """
      Base transport layer, representing an abstract communication back-end which
      can be used to discovery attached streamdeck devices.
      """
  
      class Device(ABC):
          """
          Base connection device, representing an abstract connected device which
          can be communicated with by an upper layer high level protocol.
          """
  
          @abstractmethod
          def open(self):
              """
              Opens the device for input/output. This must be called prior to
              sending or receiving any reports.
  
              .. seealso:: See :func:`~Transport.Device.close` for the
                           corresponding close method.
              """
              pass
  
          @abstractmethod
          def close(self):
              """
              Closes the device for input/output.
  
              .. seealso:: See :func:`~~Transport.Device.open` for the
                           corresponding open method.
              """
              pass
  
          @abstractmethod
          def connected(self):
              """
              Indicates if the physical device object this instance is attached
              to is still connected to the host.
  
              :rtype: bool
              :return: `True` if the device is still connected, `False` otherwise.
              """
              pass
  
          @abstractmethod
          def path(self):
              """
              Retrieves the logical path of the attached device within the
              current system. This can be used to uniquely differentiate one
              device from another.
  
              :rtype: str
              :return: Logical device path for the attached device.
              """
              pass
  
          @abstractmethod
          def write_feature(self, payload):
              """
              Sends a HID Feature report to the open HID device.
  
              :param enumerable() payload: Enumerate list of bytes to send to the
                                           device, as a feature report. The first
                                           byte of the report should be the Report
                                           ID of the report being sent.
  
              :rtype: int
              :return: Number of bytes successfully sent to the device.
              """
              pass
  
          @abstractmethod
          def read_feature(self, report_id, length):
              """
              Reads a HID Feature report from the open HID device.
  
              :param int report_id: Report ID of the report being read.
              :param int length: Maximum length of the Feature report to read..
  
              :rtype: list(byte)
              :return: List of bytes containing the read Feature report. The
                       first byte of the report will be the Report ID of the
                       report that was read.
              """
              pass
  
          @abstractmethod
          def write(self, payload):
              """
              Sends a HID Out report to the open HID device.
  
              :param enumerable() payload: Enumerate list of bytes to send to the
                                           device, as an Out report. The first
                                           byte of the report should be the Report
                                           ID of the report being sent.
  
              :rtype: int
              :return: Number of bytes successfully sent to the device.
              """
              pass
  
          @abstractmethod
          def read(self, length):
              """
              Performs a blocking read of a HID In report from the open HID device.
  
              :param int length: Maximum length of the In report to read.
  
              :rtype: list(byte)
              :return: List of bytes containing the read In report. The first byte
                       of the report will be the Report ID of the report that was
                       read.
              """
              pass
  
      @abstractmethod
      def probe():
          """
          Attempts to determine if the back-end is installed and usable. It is
          expected that probe failures throw exceptions detailing their exact
          cause of failure.
          """
          pass
  
      @abstractmethod
      def enumerate(self, vid, pid):
          """
          Enumerates all available devices on the system using the current
          transport back-end.
  
          :param int vid: USB Vendor ID to filter all devices by, `None` if the
                          device list should not be filtered by vendor.
          :param int pid: USB Product ID to filter all devices by, `None` if the
                          device list should not be filtered by product.
  
          :rtype: list(Transport.Device)
          :return: List of discovered devices that are available through this
                   transport back-end.
          """
          pass
  