code: def openable(cls):
      
  
      def open(self, initial_msg, seed):
          pass
  
      def on_message(self, msg):
          raise NotImplementedError()
  
      def on_close(self, ex):
          logging.error('on_close() called due to %s: %s', type(ex).__name__, ex)
  
      def close(self, ex=None):
          raise ex if ex else exception.StopListening()
  
      @property
      def listener(self):
          raise NotImplementedError()
  
      def ensure_method(name, fn):
          if getattr(cls, name, None) is None:
              setattr(cls, name, fn)
  
      # set attribute if no such attribute
      ensure_method('open', open)
      ensure_method('on_message', on_message)
      ensure_method('on_close', on_close)
      ensure_method('close', close)
      ensure_method('listener', listener)
  
      return cls
docs: A class decorator to fill in certain methods and properties to ensure
      a class can be used by :func:`.create_open`.
  
      These instance methods and property will be added, if not defined
      by the class:
  
      - ``open(self, initial_msg, seed)``
      - ``on_message(self, msg)``
      - ``on_close(self, ex)``
      - ``close(self, ex=None)``
      - property ``listener``