# Posted to python-ideas on 2016 Feb 26 by Maxime S(chmeii) via gmane # User Maxime S has not yet signed CLA, so this is not a 'contribution'. # Use of self.app.createfilehandler limits this to unix-based systems. class TkSelector(selectors._BaseSelectorImpl): """Selector based on the Tk event loop.""" def __init__(self, app): super().__init__() self.app = app self.ready = [] self.is_timeout = False self.after_key = None def _file_cb(self, fileobj, mask): fd = self._fileobj_lookup(fileobj) self.ready.append((fd, mask)) def _timeout_cb(self): self.is_timeout = True def _reset_state(self): del self.ready[:] self.is_timeout = False if self.after_key: self.app.after_cancel(self.after_key) self.after_key = None def register(self, fileobj, events, data=None): key = super().register(fileobj, events, data) flags = 0 if events & EVENT_READ: flags |= tkinter.READABLE if events & EVENT_WRITE: flags |= tkinter.WRITABLE self.app.createfilehandler(fileobj, flags, self._file_cb) return key def unregister(self, fileobj): key = super().unregister(fileobj) self.app.deletefilehandler(fileobj) return key def select(self, timeout=None): if timeout is None: pass elif timeout <= 0: while self.app.dooneevent(_tkinter.DONT_WAIT): pass self.is_timeout = True else: self.after_key = self.app.after( math.ceil(timeout*1000), self._timeout_cb) while not (self.is_timeout or self.ready): self.app.dooneevent() ret = [] for fd, mask in self.ready: events = 0 if mask & tkinter.WRITABLE: events |= EVENT_WRITE if mask & tkinter.READABLE: events |= EVENT_READ key = self._key_from_fd(fd) if key: ret.append((key, events & key.events)) self._reset_state() return ret class TkEventLoop(asyncio.SelectorEventLoop): """Asyncio-compatible tkinter event loop.""" def __init__(self, app): selector = TkSelector(app) super().__init__(selector=selector)