# Path: uchroma/util.py
# def ensure_future(coro, loop=None):
#     """
#     Wrapper for asyncio.ensure_future which dumps exceptions
#     """
#     if loop is None:
#         loop = asyncio.get_event_loop()
#     fut = asyncio.ensure_future(coro, loop=loop)
#     def exception_logging_done_cb(fut):
#         try:
#             e = fut.exception()
#         except asyncio.CancelledError:
#             return
#         if e is not None:
#             loop.call_exception_handler({
#                 'message': 'Unhandled exception in async future',
#                 'future': fut,
#                 'exception': e,
#             })
#     fut.add_done_callback(exception_logging_done_cb)
#     return fut


import asyncio
import functools
import evdev
from concurrent import futures
from uchroma.util import ensure_future
                if not self._opened:
                    return

                if event.type == evdev.ecodes.EV_KEY:
                    ev = evdev.categorize(event)

                    for callback in self._event_callbacks:
                        await callback(ev)

                if not self._opened:
                    return

            except (OSError, IOError) as err:
                self._logger.exception("Event device error", exc_info=err)
                break


    def _evdev_close(self, event_device, future):
        self._logger.info('Closing event device %s', event_device)


    def _open_input_devices(self):
        if self._opened:
            return True

        for input_device in self._input_devices:
            try:
                event_device = evdev.InputDevice(input_device)
                self._event_devices.append(event_device)


# Path: uchroma/util.py
# def ensure_future(coro, loop=None):
#     """
#     Wrapper for asyncio.ensure_future which dumps exceptions
#     """
#     if loop is None:
#         loop = asyncio.get_event_loop()
#     fut = asyncio.ensure_future(coro, loop=loop)
#     def exception_logging_done_cb(fut):
#         try:
#             e = fut.exception()
#         except asyncio.CancelledError:
#             return
#         if e is not None:
#             loop.call_exception_handler({
#                 'message': 'Unhandled exception in async future',
#                 'future': fut,
#                 'exception': e,
#             })
#     fut.add_done_callback(exception_logging_done_cb)
#     return fut


# Path: uchroma/server/input.py
import asyncio
import functools
import evdev
from concurrent import futures
from uchroma.util import ensure_future

                if not self._opened:
                    return

                if event.type == evdev.ecodes.EV_KEY:
                    ev = evdev.categorize(event)

                    for callback in self._event_callbacks:
                        await callback(ev)

                if not self._opened:
                    return

            except (OSError, IOError) as err:
                self._logger.exception("Event device error", exc_info=err)
                break


    def _evdev_close(self, event_device, future):
        self._logger.info('Closing event device %s', event_device)


    def _open_input_devices(self):
        if self._opened:
            return True

        for input_device in self._input_devices:
            try:
                event_device = evdev.InputDevice(input_device)
                self._event_devices.append(event_device)


                task = ensure_future(self._evdev_callback(event_device))