From b22f4601548934378ed1f023e331bfcffee7eb7b Mon Sep 17 00:00:00 2001 From: Jakub Stasiak Date: Thu, 7 Jan 2016 11:36:17 +0100 Subject: [PATCH] Fall back to select if poll does not exist select.poll will be missing when Gevent (or Eventlet, soon) monkey patchiing is applied. Closes: https://github.com/seb-m/pyinotify/issues/78 --- python2/pyinotify.py | 35 ++++++++++++++++++++++++++++++++++- python3/pyinotify.py | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/python2/pyinotify.py b/python2/pyinotify.py index d2f0816..180d016 100755 --- a/python2/pyinotify.py +++ b/python2/pyinotify.py @@ -1098,6 +1098,39 @@ def __init__(self, err): PyinotifyError.__init__(self, err) +try: + _poll_class = select.poll +except AttributeError: + class _Poll(object): + """ + poll emulator implemented using select. + + This is used to make the client code happy in case of select.poll missing. + Select.poll will be missing when Gevent or (soon) Eventlet monkey patching + is applied, see https://github.com/seb-m/pyinotify/issues/78. + """ + def __init__(self): + self._fds = [] + + def register(self, fd, eventmask): + assert eventmask == select.POLLIN, 'Only POLLIN supported right now' + self._fds.append(fd) + + def poll(self, timeout): + timeout_in_seconds = timeout / 1000.0 if timeout is not None else None + can_read, _, _ = select.select(self._fds, [], [], timeout_in_seconds) + return [(fd, select.POLLIN) for fd in can_read] + + def unregister(self, fd): + try: + self._fds.remove(fd) + except ValueError: + # poll.unregister is supposed to raise KeyError in case of + # attempting to unregister a descriptor that's not registered. + raise KeyError(fd) + + _poll_class = _Poll + class Notifier: """ Read notifications, process events. @@ -1138,7 +1171,7 @@ def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, # File descriptor self._fd = self._watch_manager.get_fd() # Poll object and registration - self._pollobj = select.poll() + self._pollobj = _poll_class() self._pollobj.register(self._fd, select.POLLIN) # This pipe is correctely initialized and used by ThreadedNotifier self._pipe = (-1, -1) diff --git a/python3/pyinotify.py b/python3/pyinotify.py index bc24313..bc8cacd 100755 --- a/python3/pyinotify.py +++ b/python3/pyinotify.py @@ -1081,6 +1081,40 @@ def __init__(self, err): PyinotifyError.__init__(self, err) +try: + _poll_class = select.poll +except AttributeError: + class _Poll(object): + """ + poll emulator implemented using select. + + This is used to make the client code happy in case of select.poll missing. + Select.poll will be missing when Gevent or (soon) Eventlet monkey patching + is applied, see https://github.com/seb-m/pyinotify/issues/78. + """ + def __init__(self): + self._fds = [] + + def register(self, fd, eventmask): + assert eventmask == select.POLLIN, 'Only POLLIN supported right now' + self._fds.append(fd) + + def poll(self, timeout): + timeout_in_seconds = timeout / 1000.0 if timeout is not None else None + can_read, _, _ = select.select(self._fds, [], [], timeout_in_seconds) + return [(fd, select.POLLIN) for fd in can_read] + + def unregister(self, fd): + try: + self._fds.remove(fd) + except ValueError: + # poll.unregister is supposed to raise KeyError in case of + # attempting to unregister a descriptor that's not registered. + raise KeyError(fd) + + _poll_class = _Poll + + class Notifier: """ Read notifications, process events. @@ -1121,7 +1155,7 @@ def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, # File descriptor self._fd = self._watch_manager.get_fd() # Poll object and registration - self._pollobj = select.poll() + self._pollobj = _poll_class() self._pollobj.register(self._fd, select.POLLIN) # This pipe is correctely initialized and used by ThreadedNotifier self._pipe = (-1, -1)