def openable(cls):
    """
    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``
    """

    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
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``