def event_emitter(cls_=None, *, events=('*', )):
    event_dict = dict.fromkeys(events, [])
    allow_any_eventname = event_dict.pop('*', False) == []
    def _event_emitter(cls):
        def on(self, name, callback):
            if not (callable(callback) or isawaitable(callback)):
                raise ValueError("Callback not callable: %r" % callback)
            try:
                event_dict[name].append(callback)
            except KeyError:
                if allow_any_eventname:
                    event_dict[name] = [callback]
                else:
                    msg = "Event Emitter has no event {!r}".format(name)
                    raise KeyError(msg)
            return self
        async def emit(self, name):
            for cb in event_dict[name]:
                if isawaitable(cb):
                    await cb
                else:
                    cb()
        cls.on = on
        cls.emit = emit
        return cls
    if cls_ is None:
        return _event_emitter
    else:
        return _event_emitter(cls_)