]> granicus.if.org Git - python/commitdiff
bpo-31938: Convert selectmodule.c to Argument Clinic (GH-4265)
authorTal Einat <taleinat+github@gmail.com>
Sat, 30 Jun 2018 20:02:48 +0000 (23:02 +0300)
committerGitHub <noreply@github.com>
Sat, 30 Jun 2018 20:02:48 +0000 (23:02 +0300)
Doc/library/select.rst
Modules/clinic/selectmodule.c.h [new file with mode: 0644]
Modules/selectmodule.c

index 5ffb21583fa5992eaf7ebcb4dc53004273350117..8feedaa4770c6a483095a9e22a8d385e38f1cd69 100644 (file)
@@ -351,7 +351,7 @@ Edge and Level Trigger Polling (epoll) Objects
    Remove a registered file descriptor from the epoll object.
 
 
-.. method:: epoll.poll(timeout=-1, maxevents=-1)
+.. method:: epoll.poll(timeout=None, maxevents=-1)
 
    Wait for events. timeout in seconds (float)
 
diff --git a/Modules/clinic/selectmodule.c.h b/Modules/clinic/selectmodule.c.h
new file mode 100644 (file)
index 0000000..f66ceaa
--- /dev/null
@@ -0,0 +1,1050 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(select_select__doc__,
+"select($module, rlist, wlist, xlist, timeout=None, /)\n"
+"--\n"
+"\n"
+"Wait until one or more file descriptors are ready for some kind of I/O.\n"
+"\n"
+"The first three arguments are sequences of file descriptors to be waited for:\n"
+"rlist -- wait until ready for reading\n"
+"wlist -- wait until ready for writing\n"
+"xlist -- wait for an \"exceptional condition\"\n"
+"If only one kind of condition is required, pass [] for the other lists.\n"
+"\n"
+"A file descriptor is either a socket or file object, or a small integer\n"
+"gotten from a fileno() method call on one of those.\n"
+"\n"
+"The optional 4th argument specifies a timeout in seconds; it may be\n"
+"a floating point number to specify fractions of seconds.  If it is absent\n"
+"or None, the call will never time out.\n"
+"\n"
+"The return value is a tuple of three lists corresponding to the first three\n"
+"arguments; each contains the subset of the corresponding file descriptors\n"
+"that are ready.\n"
+"\n"
+"*** IMPORTANT NOTICE ***\n"
+"On Windows, only sockets are supported; on Unix, all file\n"
+"descriptors can be used.");
+
+#define SELECT_SELECT_METHODDEF    \
+    {"select", (PyCFunction)select_select, METH_FASTCALL, select_select__doc__},
+
+static PyObject *
+select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist,
+                   PyObject *xlist, PyObject *timeout_obj);
+
+static PyObject *
+select_select(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *rlist;
+    PyObject *wlist;
+    PyObject *xlist;
+    PyObject *timeout_obj = Py_None;
+
+    if (!_PyArg_UnpackStack(args, nargs, "select",
+        3, 4,
+        &rlist, &wlist, &xlist, &timeout_obj)) {
+        goto exit;
+    }
+    return_value = select_select_impl(module, rlist, wlist, xlist, timeout_obj);
+
+exit:
+    return return_value;
+}
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL))
+
+PyDoc_STRVAR(select_poll_register__doc__,
+"register($self, fd, eventmask=POLLIN | POLLPRI | POLLOUT, /)\n"
+"--\n"
+"\n"
+"Register a file descriptor with the polling object.\n"
+"\n"
+"  fd\n"
+"    either an integer, or an object with a fileno() method returning an int\n"
+"  eventmask\n"
+"    an optional bitmask describing the type of events to check for");
+
+#define SELECT_POLL_REGISTER_METHODDEF    \
+    {"register", (PyCFunction)select_poll_register, METH_FASTCALL, select_poll_register__doc__},
+
+static PyObject *
+select_poll_register_impl(pollObject *self, int fd, unsigned short eventmask);
+
+static PyObject *
+select_poll_register(pollObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    int fd;
+    unsigned short eventmask = POLLIN | POLLPRI | POLLOUT;
+
+    if (!_PyArg_ParseStack(args, nargs, "O&|O&:register",
+        fildes_converter, &fd, ushort_converter, &eventmask)) {
+        goto exit;
+    }
+    return_value = select_poll_register_impl(self, fd, eventmask);
+
+exit:
+    return return_value;
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL))
+
+PyDoc_STRVAR(select_poll_modify__doc__,
+"modify($self, fd, eventmask, /)\n"
+"--\n"
+"\n"
+"Modify an already registered file descriptor.\n"
+"\n"
+"  fd\n"
+"    either an integer, or an object with a fileno() method returning\n"
+"    an int\n"
+"  eventmask\n"
+"    a bitmask describing the type of events to check for");
+
+#define SELECT_POLL_MODIFY_METHODDEF    \
+    {"modify", (PyCFunction)select_poll_modify, METH_FASTCALL, select_poll_modify__doc__},
+
+static PyObject *
+select_poll_modify_impl(pollObject *self, int fd, unsigned short eventmask);
+
+static PyObject *
+select_poll_modify(pollObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    int fd;
+    unsigned short eventmask;
+
+    if (!_PyArg_ParseStack(args, nargs, "O&O&:modify",
+        fildes_converter, &fd, ushort_converter, &eventmask)) {
+        goto exit;
+    }
+    return_value = select_poll_modify_impl(self, fd, eventmask);
+
+exit:
+    return return_value;
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL))
+
+PyDoc_STRVAR(select_poll_unregister__doc__,
+"unregister($self, fd, /)\n"
+"--\n"
+"\n"
+"Remove a file descriptor being tracked by the polling object.");
+
+#define SELECT_POLL_UNREGISTER_METHODDEF    \
+    {"unregister", (PyCFunction)select_poll_unregister, METH_O, select_poll_unregister__doc__},
+
+static PyObject *
+select_poll_unregister_impl(pollObject *self, int fd);
+
+static PyObject *
+select_poll_unregister(pollObject *self, PyObject *arg)
+{
+    PyObject *return_value = NULL;
+    int fd;
+
+    if (!PyArg_Parse(arg, "O&:unregister", fildes_converter, &fd)) {
+        goto exit;
+    }
+    return_value = select_poll_unregister_impl(self, fd);
+
+exit:
+    return return_value;
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL))
+
+PyDoc_STRVAR(select_poll_poll__doc__,
+"poll($self, timeout=None, /)\n"
+"--\n"
+"\n"
+"Polls the set of registered file descriptors.\n"
+"\n"
+"Returns a list containing any descriptors that have events or errors to\n"
+"report, as a list of (fd, event) 2-tuples.");
+
+#define SELECT_POLL_POLL_METHODDEF    \
+    {"poll", (PyCFunction)select_poll_poll, METH_FASTCALL, select_poll_poll__doc__},
+
+static PyObject *
+select_poll_poll_impl(pollObject *self, PyObject *timeout_obj);
+
+static PyObject *
+select_poll_poll(pollObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *timeout_obj = Py_None;
+
+    if (!_PyArg_UnpackStack(args, nargs, "poll",
+        0, 1,
+        &timeout_obj)) {
+        goto exit;
+    }
+    return_value = select_poll_poll_impl(self, timeout_obj);
+
+exit:
+    return return_value;
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+
+PyDoc_STRVAR(select_devpoll_register__doc__,
+"register($self, fd, eventmask=POLLIN | POLLPRI | POLLOUT, /)\n"
+"--\n"
+"\n"
+"Register a file descriptor with the polling object.\n"
+"\n"
+"  fd\n"
+"    either an integer, or an object with a fileno() method returning\n"
+"    an int\n"
+"  eventmask\n"
+"    an optional bitmask describing the type of events to check for");
+
+#define SELECT_DEVPOLL_REGISTER_METHODDEF    \
+    {"register", (PyCFunction)select_devpoll_register, METH_FASTCALL, select_devpoll_register__doc__},
+
+static PyObject *
+select_devpoll_register_impl(devpollObject *self, int fd,
+                             unsigned short eventmask);
+
+static PyObject *
+select_devpoll_register(devpollObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    int fd;
+    unsigned short eventmask = POLLIN | POLLPRI | POLLOUT;
+
+    if (!_PyArg_ParseStack(args, nargs, "O&|O&:register",
+        fildes_converter, &fd, ushort_converter, &eventmask)) {
+        goto exit;
+    }
+    return_value = select_devpoll_register_impl(self, fd, eventmask);
+
+exit:
+    return return_value;
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+
+PyDoc_STRVAR(select_devpoll_modify__doc__,
+"modify($self, fd, eventmask=POLLIN | POLLPRI | POLLOUT, /)\n"
+"--\n"
+"\n"
+"Modify a possible already registered file descriptor.\n"
+"\n"
+"  fd\n"
+"    either an integer, or an object with a fileno() method returning\n"
+"    an int\n"
+"  eventmask\n"
+"    an optional bitmask describing the type of events to check for");
+
+#define SELECT_DEVPOLL_MODIFY_METHODDEF    \
+    {"modify", (PyCFunction)select_devpoll_modify, METH_FASTCALL, select_devpoll_modify__doc__},
+
+static PyObject *
+select_devpoll_modify_impl(devpollObject *self, int fd,
+                           unsigned short eventmask);
+
+static PyObject *
+select_devpoll_modify(devpollObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    int fd;
+    unsigned short eventmask = POLLIN | POLLPRI | POLLOUT;
+
+    if (!_PyArg_ParseStack(args, nargs, "O&|O&:modify",
+        fildes_converter, &fd, ushort_converter, &eventmask)) {
+        goto exit;
+    }
+    return_value = select_devpoll_modify_impl(self, fd, eventmask);
+
+exit:
+    return return_value;
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+
+PyDoc_STRVAR(select_devpoll_unregister__doc__,
+"unregister($self, fd, /)\n"
+"--\n"
+"\n"
+"Remove a file descriptor being tracked by the polling object.");
+
+#define SELECT_DEVPOLL_UNREGISTER_METHODDEF    \
+    {"unregister", (PyCFunction)select_devpoll_unregister, METH_O, select_devpoll_unregister__doc__},
+
+static PyObject *
+select_devpoll_unregister_impl(devpollObject *self, int fd);
+
+static PyObject *
+select_devpoll_unregister(devpollObject *self, PyObject *arg)
+{
+    PyObject *return_value = NULL;
+    int fd;
+
+    if (!PyArg_Parse(arg, "O&:unregister", fildes_converter, &fd)) {
+        goto exit;
+    }
+    return_value = select_devpoll_unregister_impl(self, fd);
+
+exit:
+    return return_value;
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+
+PyDoc_STRVAR(select_devpoll_poll__doc__,
+"poll($self, timeout=None, /)\n"
+"--\n"
+"\n"
+"Polls the set of registered file descriptors.\n"
+"\n"
+"Returns a list containing any descriptors that have events or errors to\n"
+"report, as a list of (fd, event) 2-tuples.");
+
+#define SELECT_DEVPOLL_POLL_METHODDEF    \
+    {"poll", (PyCFunction)select_devpoll_poll, METH_FASTCALL, select_devpoll_poll__doc__},
+
+static PyObject *
+select_devpoll_poll_impl(devpollObject *self, PyObject *timeout_obj);
+
+static PyObject *
+select_devpoll_poll(devpollObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *timeout_obj = Py_None;
+
+    if (!_PyArg_UnpackStack(args, nargs, "poll",
+        0, 1,
+        &timeout_obj)) {
+        goto exit;
+    }
+    return_value = select_devpoll_poll_impl(self, timeout_obj);
+
+exit:
+    return return_value;
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+
+PyDoc_STRVAR(select_devpoll_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n"
+"Close the devpoll file descriptor.\n"
+"\n"
+"Further operations on the devpoll object will raise an exception.");
+
+#define SELECT_DEVPOLL_CLOSE_METHODDEF    \
+    {"close", (PyCFunction)select_devpoll_close, METH_NOARGS, select_devpoll_close__doc__},
+
+static PyObject *
+select_devpoll_close_impl(devpollObject *self);
+
+static PyObject *
+select_devpoll_close(devpollObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return select_devpoll_close_impl(self);
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+
+PyDoc_STRVAR(select_devpoll_fileno__doc__,
+"fileno($self, /)\n"
+"--\n"
+"\n"
+"Return the file descriptor.");
+
+#define SELECT_DEVPOLL_FILENO_METHODDEF    \
+    {"fileno", (PyCFunction)select_devpoll_fileno, METH_NOARGS, select_devpoll_fileno__doc__},
+
+static PyObject *
+select_devpoll_fileno_impl(devpollObject *self);
+
+static PyObject *
+select_devpoll_fileno(devpollObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return select_devpoll_fileno_impl(self);
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL))
+
+PyDoc_STRVAR(select_poll__doc__,
+"poll($module, /)\n"
+"--\n"
+"\n"
+"Returns a polling object.\n"
+"\n"
+"This object supports registering and unregistering file descriptors, and then\n"
+"polling them for I/O events.");
+
+#define SELECT_POLL_METHODDEF    \
+    {"poll", (PyCFunction)select_poll, METH_NOARGS, select_poll__doc__},
+
+static PyObject *
+select_poll_impl(PyObject *module);
+
+static PyObject *
+select_poll(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+    return select_poll_impl(module);
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) */
+
+#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+
+PyDoc_STRVAR(select_devpoll__doc__,
+"devpoll($module, /)\n"
+"--\n"
+"\n"
+"Returns a polling object.\n"
+"\n"
+"This object supports registering and unregistering file descriptors, and then\n"
+"polling them for I/O events.");
+
+#define SELECT_DEVPOLL_METHODDEF    \
+    {"devpoll", (PyCFunction)select_devpoll, METH_NOARGS, select_devpoll__doc__},
+
+static PyObject *
+select_devpoll_impl(PyObject *module);
+
+static PyObject *
+select_devpoll(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+    return select_devpoll_impl(module);
+}
+
+#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+
+#if defined(HAVE_EPOLL)
+
+PyDoc_STRVAR(select_epoll__doc__,
+"epoll(sizehint=-1, flags=0)\n"
+"--\n"
+"\n"
+"Returns an epolling object.\n"
+"\n"
+"  sizehint\n"
+"    The expected number of events to be registered.  It must be positive,\n"
+"    or -1 to use the default.  It is only used on older systems where\n"
+"    epoll_create1() is not available; otherwise it has no effect (though its\n"
+"    value is still checked).\n"
+"  flags\n"
+"    Deprecated and completely ignored.  However, when supplied, its value\n"
+"    must be 0 or select.EPOLL_CLOEXEC, otherwise OSError is raised.");
+
+static PyObject *
+select_epoll_impl(PyTypeObject *type, int sizehint, int flags);
+
+static PyObject *
+select_epoll(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"sizehint", "flags", NULL};
+    static _PyArg_Parser _parser = {"|ii:epoll", _keywords, 0};
+    int sizehint = -1;
+    int flags = 0;
+
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
+        &sizehint, &flags)) {
+        goto exit;
+    }
+    return_value = select_epoll_impl(type, sizehint, flags);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_EPOLL) */
+
+#if defined(HAVE_EPOLL)
+
+PyDoc_STRVAR(select_epoll_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n"
+"Close the epoll control file descriptor.\n"
+"\n"
+"Further operations on the epoll object will raise an exception.");
+
+#define SELECT_EPOLL_CLOSE_METHODDEF    \
+    {"close", (PyCFunction)select_epoll_close, METH_NOARGS, select_epoll_close__doc__},
+
+static PyObject *
+select_epoll_close_impl(pyEpoll_Object *self);
+
+static PyObject *
+select_epoll_close(pyEpoll_Object *self, PyObject *Py_UNUSED(ignored))
+{
+    return select_epoll_close_impl(self);
+}
+
+#endif /* defined(HAVE_EPOLL) */
+
+#if defined(HAVE_EPOLL)
+
+PyDoc_STRVAR(select_epoll_fileno__doc__,
+"fileno($self, /)\n"
+"--\n"
+"\n"
+"Return the epoll control file descriptor.");
+
+#define SELECT_EPOLL_FILENO_METHODDEF    \
+    {"fileno", (PyCFunction)select_epoll_fileno, METH_NOARGS, select_epoll_fileno__doc__},
+
+static PyObject *
+select_epoll_fileno_impl(pyEpoll_Object *self);
+
+static PyObject *
+select_epoll_fileno(pyEpoll_Object *self, PyObject *Py_UNUSED(ignored))
+{
+    return select_epoll_fileno_impl(self);
+}
+
+#endif /* defined(HAVE_EPOLL) */
+
+#if defined(HAVE_EPOLL)
+
+PyDoc_STRVAR(select_epoll_fromfd__doc__,
+"fromfd($type, fd, /)\n"
+"--\n"
+"\n"
+"Create an epoll object from a given control fd.");
+
+#define SELECT_EPOLL_FROMFD_METHODDEF    \
+    {"fromfd", (PyCFunction)select_epoll_fromfd, METH_O|METH_CLASS, select_epoll_fromfd__doc__},
+
+static PyObject *
+select_epoll_fromfd_impl(PyTypeObject *type, int fd);
+
+static PyObject *
+select_epoll_fromfd(PyTypeObject *type, PyObject *arg)
+{
+    PyObject *return_value = NULL;
+    int fd;
+
+    if (!PyArg_Parse(arg, "i:fromfd", &fd)) {
+        goto exit;
+    }
+    return_value = select_epoll_fromfd_impl(type, fd);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_EPOLL) */
+
+#if defined(HAVE_EPOLL)
+
+PyDoc_STRVAR(select_epoll_register__doc__,
+"register($self, /, fd, eventmask=EPOLLIN | EPOLLPRI | EPOLLOUT)\n"
+"--\n"
+"\n"
+"Registers a new fd or raises an OSError if the fd is already registered.\n"
+"\n"
+"  fd\n"
+"    the target file descriptor of the operation\n"
+"  eventmask\n"
+"    a bit set composed of the various EPOLL constants\n"
+"\n"
+"The epoll interface supports all file descriptors that support poll.");
+
+#define SELECT_EPOLL_REGISTER_METHODDEF    \
+    {"register", (PyCFunction)select_epoll_register, METH_FASTCALL|METH_KEYWORDS, select_epoll_register__doc__},
+
+static PyObject *
+select_epoll_register_impl(pyEpoll_Object *self, int fd,
+                           unsigned int eventmask);
+
+static PyObject *
+select_epoll_register(pyEpoll_Object *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"fd", "eventmask", NULL};
+    static _PyArg_Parser _parser = {"O&|I:register", _keywords, 0};
+    int fd;
+    unsigned int eventmask = EPOLLIN | EPOLLPRI | EPOLLOUT;
+
+    if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
+        fildes_converter, &fd, &eventmask)) {
+        goto exit;
+    }
+    return_value = select_epoll_register_impl(self, fd, eventmask);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_EPOLL) */
+
+#if defined(HAVE_EPOLL)
+
+PyDoc_STRVAR(select_epoll_modify__doc__,
+"modify($self, /, fd, eventmask)\n"
+"--\n"
+"\n"
+"Modify event mask for a registered file descriptor.\n"
+"\n"
+"  fd\n"
+"    the target file descriptor of the operation\n"
+"  eventmask\n"
+"    a bit set composed of the various EPOLL constants");
+
+#define SELECT_EPOLL_MODIFY_METHODDEF    \
+    {"modify", (PyCFunction)select_epoll_modify, METH_FASTCALL|METH_KEYWORDS, select_epoll_modify__doc__},
+
+static PyObject *
+select_epoll_modify_impl(pyEpoll_Object *self, int fd,
+                         unsigned int eventmask);
+
+static PyObject *
+select_epoll_modify(pyEpoll_Object *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"fd", "eventmask", NULL};
+    static _PyArg_Parser _parser = {"O&I:modify", _keywords, 0};
+    int fd;
+    unsigned int eventmask;
+
+    if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
+        fildes_converter, &fd, &eventmask)) {
+        goto exit;
+    }
+    return_value = select_epoll_modify_impl(self, fd, eventmask);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_EPOLL) */
+
+#if defined(HAVE_EPOLL)
+
+PyDoc_STRVAR(select_epoll_unregister__doc__,
+"unregister($self, /, fd)\n"
+"--\n"
+"\n"
+"Remove a registered file descriptor from the epoll object.\n"
+"\n"
+"  fd\n"
+"    the target file descriptor of the operation");
+
+#define SELECT_EPOLL_UNREGISTER_METHODDEF    \
+    {"unregister", (PyCFunction)select_epoll_unregister, METH_FASTCALL|METH_KEYWORDS, select_epoll_unregister__doc__},
+
+static PyObject *
+select_epoll_unregister_impl(pyEpoll_Object *self, int fd);
+
+static PyObject *
+select_epoll_unregister(pyEpoll_Object *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"fd", NULL};
+    static _PyArg_Parser _parser = {"O&:unregister", _keywords, 0};
+    int fd;
+
+    if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
+        fildes_converter, &fd)) {
+        goto exit;
+    }
+    return_value = select_epoll_unregister_impl(self, fd);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_EPOLL) */
+
+#if defined(HAVE_EPOLL)
+
+PyDoc_STRVAR(select_epoll_poll__doc__,
+"poll($self, /, timeout=None, maxevents=-1)\n"
+"--\n"
+"\n"
+"Wait for events on the epoll file descriptor.\n"
+"\n"
+"  timeout\n"
+"    the maximum time to wait in seconds (as float);\n"
+"    a timeout of None or -1 makes poll wait indefinitely\n"
+"  maxevents\n"
+"    the maximum number of events returned; -1 means no limit\n"
+"\n"
+"Returns a list containing any descriptors that have events to report,\n"
+"as a list of (fd, events) 2-tuples.");
+
+#define SELECT_EPOLL_POLL_METHODDEF    \
+    {"poll", (PyCFunction)select_epoll_poll, METH_FASTCALL|METH_KEYWORDS, select_epoll_poll__doc__},
+
+static PyObject *
+select_epoll_poll_impl(pyEpoll_Object *self, PyObject *timeout_obj,
+                       int maxevents);
+
+static PyObject *
+select_epoll_poll(pyEpoll_Object *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"timeout", "maxevents", NULL};
+    static _PyArg_Parser _parser = {"|Oi:poll", _keywords, 0};
+    PyObject *timeout_obj = Py_None;
+    int maxevents = -1;
+
+    if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
+        &timeout_obj, &maxevents)) {
+        goto exit;
+    }
+    return_value = select_epoll_poll_impl(self, timeout_obj, maxevents);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_EPOLL) */
+
+#if defined(HAVE_EPOLL)
+
+PyDoc_STRVAR(select_epoll___enter____doc__,
+"__enter__($self, /)\n"
+"--\n"
+"\n");
+
+#define SELECT_EPOLL___ENTER___METHODDEF    \
+    {"__enter__", (PyCFunction)select_epoll___enter__, METH_NOARGS, select_epoll___enter____doc__},
+
+static PyObject *
+select_epoll___enter___impl(pyEpoll_Object *self);
+
+static PyObject *
+select_epoll___enter__(pyEpoll_Object *self, PyObject *Py_UNUSED(ignored))
+{
+    return select_epoll___enter___impl(self);
+}
+
+#endif /* defined(HAVE_EPOLL) */
+
+#if defined(HAVE_EPOLL)
+
+PyDoc_STRVAR(select_epoll___exit____doc__,
+"__exit__($self, exc_type=None, exc_value=None, exc_tb=None, /)\n"
+"--\n"
+"\n");
+
+#define SELECT_EPOLL___EXIT___METHODDEF    \
+    {"__exit__", (PyCFunction)select_epoll___exit__, METH_FASTCALL, select_epoll___exit____doc__},
+
+static PyObject *
+select_epoll___exit___impl(pyEpoll_Object *self, PyObject *exc_type,
+                           PyObject *exc_value, PyObject *exc_tb);
+
+static PyObject *
+select_epoll___exit__(pyEpoll_Object *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *exc_type = Py_None;
+    PyObject *exc_value = Py_None;
+    PyObject *exc_tb = Py_None;
+
+    if (!_PyArg_UnpackStack(args, nargs, "__exit__",
+        0, 3,
+        &exc_type, &exc_value, &exc_tb)) {
+        goto exit;
+    }
+    return_value = select_epoll___exit___impl(self, exc_type, exc_value, exc_tb);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_EPOLL) */
+
+#if defined(HAVE_KQUEUE)
+
+PyDoc_STRVAR(select_kqueue__doc__,
+"kqueue()\n"
+"--\n"
+"\n"
+"Kqueue syscall wrapper.\n"
+"\n"
+"For example, to start watching a socket for input:\n"
+">>> kq = kqueue()\n"
+">>> sock = socket()\n"
+">>> sock.connect((host, port))\n"
+">>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_ADD)], 0)\n"
+"\n"
+"To wait one second for it to become writeable:\n"
+">>> kq.control(None, 1, 1000)\n"
+"\n"
+"To stop listening:\n"
+">>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_DELETE)], 0)");
+
+static PyObject *
+select_kqueue_impl(PyTypeObject *type);
+
+static PyObject *
+select_kqueue(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+
+    if ((type == &kqueue_queue_Type) &&
+        !_PyArg_NoPositional("kqueue", args)) {
+        goto exit;
+    }
+    if ((type == &kqueue_queue_Type) &&
+        !_PyArg_NoKeywords("kqueue", kwargs)) {
+        goto exit;
+    }
+    return_value = select_kqueue_impl(type);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_KQUEUE) */
+
+#if defined(HAVE_KQUEUE)
+
+PyDoc_STRVAR(select_kqueue_close__doc__,
+"close($self, /)\n"
+"--\n"
+"\n"
+"Close the kqueue control file descriptor.\n"
+"\n"
+"Further operations on the kqueue object will raise an exception.");
+
+#define SELECT_KQUEUE_CLOSE_METHODDEF    \
+    {"close", (PyCFunction)select_kqueue_close, METH_NOARGS, select_kqueue_close__doc__},
+
+static PyObject *
+select_kqueue_close_impl(kqueue_queue_Object *self);
+
+static PyObject *
+select_kqueue_close(kqueue_queue_Object *self, PyObject *Py_UNUSED(ignored))
+{
+    return select_kqueue_close_impl(self);
+}
+
+#endif /* defined(HAVE_KQUEUE) */
+
+#if defined(HAVE_KQUEUE)
+
+PyDoc_STRVAR(select_kqueue_fileno__doc__,
+"fileno($self, /)\n"
+"--\n"
+"\n"
+"Return the kqueue control file descriptor.");
+
+#define SELECT_KQUEUE_FILENO_METHODDEF    \
+    {"fileno", (PyCFunction)select_kqueue_fileno, METH_NOARGS, select_kqueue_fileno__doc__},
+
+static PyObject *
+select_kqueue_fileno_impl(kqueue_queue_Object *self);
+
+static PyObject *
+select_kqueue_fileno(kqueue_queue_Object *self, PyObject *Py_UNUSED(ignored))
+{
+    return select_kqueue_fileno_impl(self);
+}
+
+#endif /* defined(HAVE_KQUEUE) */
+
+#if defined(HAVE_KQUEUE)
+
+PyDoc_STRVAR(select_kqueue_fromfd__doc__,
+"fromfd($type, fd, /)\n"
+"--\n"
+"\n"
+"Create a kqueue object from a given control fd.");
+
+#define SELECT_KQUEUE_FROMFD_METHODDEF    \
+    {"fromfd", (PyCFunction)select_kqueue_fromfd, METH_O|METH_CLASS, select_kqueue_fromfd__doc__},
+
+static PyObject *
+select_kqueue_fromfd_impl(PyTypeObject *type, int fd);
+
+static PyObject *
+select_kqueue_fromfd(PyTypeObject *type, PyObject *arg)
+{
+    PyObject *return_value = NULL;
+    int fd;
+
+    if (!PyArg_Parse(arg, "i:fromfd", &fd)) {
+        goto exit;
+    }
+    return_value = select_kqueue_fromfd_impl(type, fd);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_KQUEUE) */
+
+#if defined(HAVE_KQUEUE)
+
+PyDoc_STRVAR(select_kqueue_control__doc__,
+"control($self, changelist, maxevents, timeout=None, /)\n"
+"--\n"
+"\n"
+"Calls the kernel kevent function.\n"
+"\n"
+"  changelist\n"
+"    Must be an iterable of kevent objects describing the changes to be made\n"
+"    to the kernel\'s watch list or None.\n"
+"  maxevents\n"
+"    The maximum number of events that the kernel will return.\n"
+"  timeout\n"
+"    The maximum time to wait in seconds, or else None to wait forever.\n"
+"    This accepts floats for smaller timeouts, too.");
+
+#define SELECT_KQUEUE_CONTROL_METHODDEF    \
+    {"control", (PyCFunction)select_kqueue_control, METH_FASTCALL, select_kqueue_control__doc__},
+
+static PyObject *
+select_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist,
+                           int maxevents, PyObject *otimeout);
+
+static PyObject *
+select_kqueue_control(kqueue_queue_Object *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *changelist;
+    int maxevents;
+    PyObject *otimeout = Py_None;
+
+    if (!_PyArg_ParseStack(args, nargs, "Oi|O:control",
+        &changelist, &maxevents, &otimeout)) {
+        goto exit;
+    }
+    return_value = select_kqueue_control_impl(self, changelist, maxevents, otimeout);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_KQUEUE) */
+
+#ifndef SELECT_POLL_REGISTER_METHODDEF
+    #define SELECT_POLL_REGISTER_METHODDEF
+#endif /* !defined(SELECT_POLL_REGISTER_METHODDEF) */
+
+#ifndef SELECT_POLL_MODIFY_METHODDEF
+    #define SELECT_POLL_MODIFY_METHODDEF
+#endif /* !defined(SELECT_POLL_MODIFY_METHODDEF) */
+
+#ifndef SELECT_POLL_UNREGISTER_METHODDEF
+    #define SELECT_POLL_UNREGISTER_METHODDEF
+#endif /* !defined(SELECT_POLL_UNREGISTER_METHODDEF) */
+
+#ifndef SELECT_POLL_POLL_METHODDEF
+    #define SELECT_POLL_POLL_METHODDEF
+#endif /* !defined(SELECT_POLL_POLL_METHODDEF) */
+
+#ifndef SELECT_DEVPOLL_REGISTER_METHODDEF
+    #define SELECT_DEVPOLL_REGISTER_METHODDEF
+#endif /* !defined(SELECT_DEVPOLL_REGISTER_METHODDEF) */
+
+#ifndef SELECT_DEVPOLL_MODIFY_METHODDEF
+    #define SELECT_DEVPOLL_MODIFY_METHODDEF
+#endif /* !defined(SELECT_DEVPOLL_MODIFY_METHODDEF) */
+
+#ifndef SELECT_DEVPOLL_UNREGISTER_METHODDEF
+    #define SELECT_DEVPOLL_UNREGISTER_METHODDEF
+#endif /* !defined(SELECT_DEVPOLL_UNREGISTER_METHODDEF) */
+
+#ifndef SELECT_DEVPOLL_POLL_METHODDEF
+    #define SELECT_DEVPOLL_POLL_METHODDEF
+#endif /* !defined(SELECT_DEVPOLL_POLL_METHODDEF) */
+
+#ifndef SELECT_DEVPOLL_CLOSE_METHODDEF
+    #define SELECT_DEVPOLL_CLOSE_METHODDEF
+#endif /* !defined(SELECT_DEVPOLL_CLOSE_METHODDEF) */
+
+#ifndef SELECT_DEVPOLL_FILENO_METHODDEF
+    #define SELECT_DEVPOLL_FILENO_METHODDEF
+#endif /* !defined(SELECT_DEVPOLL_FILENO_METHODDEF) */
+
+#ifndef SELECT_POLL_METHODDEF
+    #define SELECT_POLL_METHODDEF
+#endif /* !defined(SELECT_POLL_METHODDEF) */
+
+#ifndef SELECT_DEVPOLL_METHODDEF
+    #define SELECT_DEVPOLL_METHODDEF
+#endif /* !defined(SELECT_DEVPOLL_METHODDEF) */
+
+#ifndef SELECT_EPOLL_CLOSE_METHODDEF
+    #define SELECT_EPOLL_CLOSE_METHODDEF
+#endif /* !defined(SELECT_EPOLL_CLOSE_METHODDEF) */
+
+#ifndef SELECT_EPOLL_FILENO_METHODDEF
+    #define SELECT_EPOLL_FILENO_METHODDEF
+#endif /* !defined(SELECT_EPOLL_FILENO_METHODDEF) */
+
+#ifndef SELECT_EPOLL_FROMFD_METHODDEF
+    #define SELECT_EPOLL_FROMFD_METHODDEF
+#endif /* !defined(SELECT_EPOLL_FROMFD_METHODDEF) */
+
+#ifndef SELECT_EPOLL_REGISTER_METHODDEF
+    #define SELECT_EPOLL_REGISTER_METHODDEF
+#endif /* !defined(SELECT_EPOLL_REGISTER_METHODDEF) */
+
+#ifndef SELECT_EPOLL_MODIFY_METHODDEF
+    #define SELECT_EPOLL_MODIFY_METHODDEF
+#endif /* !defined(SELECT_EPOLL_MODIFY_METHODDEF) */
+
+#ifndef SELECT_EPOLL_UNREGISTER_METHODDEF
+    #define SELECT_EPOLL_UNREGISTER_METHODDEF
+#endif /* !defined(SELECT_EPOLL_UNREGISTER_METHODDEF) */
+
+#ifndef SELECT_EPOLL_POLL_METHODDEF
+    #define SELECT_EPOLL_POLL_METHODDEF
+#endif /* !defined(SELECT_EPOLL_POLL_METHODDEF) */
+
+#ifndef SELECT_EPOLL___ENTER___METHODDEF
+    #define SELECT_EPOLL___ENTER___METHODDEF
+#endif /* !defined(SELECT_EPOLL___ENTER___METHODDEF) */
+
+#ifndef SELECT_EPOLL___EXIT___METHODDEF
+    #define SELECT_EPOLL___EXIT___METHODDEF
+#endif /* !defined(SELECT_EPOLL___EXIT___METHODDEF) */
+
+#ifndef SELECT_KQUEUE_CLOSE_METHODDEF
+    #define SELECT_KQUEUE_CLOSE_METHODDEF
+#endif /* !defined(SELECT_KQUEUE_CLOSE_METHODDEF) */
+
+#ifndef SELECT_KQUEUE_FILENO_METHODDEF
+    #define SELECT_KQUEUE_FILENO_METHODDEF
+#endif /* !defined(SELECT_KQUEUE_FILENO_METHODDEF) */
+
+#ifndef SELECT_KQUEUE_FROMFD_METHODDEF
+    #define SELECT_KQUEUE_FROMFD_METHODDEF
+#endif /* !defined(SELECT_KQUEUE_FROMFD_METHODDEF) */
+
+#ifndef SELECT_KQUEUE_CONTROL_METHODDEF
+    #define SELECT_KQUEUE_CONTROL_METHODDEF
+#endif /* !defined(SELECT_KQUEUE_CONTROL_METHODDEF) */
+/*[clinic end generated code: output=3e425445d49c49e2 input=a9049054013a1b77]*/
index 6976fb5139aac11ba1ca362a036a8174adbf9e1a..9ad6f8bdb7aee42b2c353a9faaf92614073a64c6 100644 (file)
@@ -58,6 +58,34 @@ extern void bzero(void *, int);
 #  define SOCKET int
 #endif
 
+/*[clinic input]
+module select
+class select.poll "pollObject *" "&poll_Type"
+class select.devpoll "devpollObject *" "&devpoll_Type"
+class select.epoll "pyEpoll_Object *" "&pyEpoll_Type"
+class select.kqueue "kqueue_queue_Object *" "&kqueue_queue_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ded80abdad2b7552]*/
+
+static int
+fildes_converter(PyObject *o, void *p)
+{
+    int fd;
+    int *pointer = (int *)p;
+    fd = PyObject_AsFileDescriptor(o);
+    if (fd == -1)
+        return 0;
+    *pointer = fd;
+    return 1;
+}
+
+/*[python input]
+class fildes_converter(CConverter):
+    type = 'int'
+    converter = 'fildes_converter'
+[python start generated code]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=ca54eb5aa476e20a]*/
+
 /* list of Python objects and their file descriptor */
 typedef struct {
     PyObject *obj;                           /* owned reference */
@@ -179,8 +207,43 @@ set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
 #define SELECT_USES_HEAP
 #endif /* FD_SETSIZE > 1024 */
 
+/*[clinic input]
+select.select
+
+    rlist: object
+    wlist: object
+    xlist: object
+    timeout as timeout_obj: object = None
+    /
+
+Wait until one or more file descriptors are ready for some kind of I/O.
+
+The first three arguments are sequences of file descriptors to be waited for:
+rlist -- wait until ready for reading
+wlist -- wait until ready for writing
+xlist -- wait for an "exceptional condition"
+If only one kind of condition is required, pass [] for the other lists.
+
+A file descriptor is either a socket or file object, or a small integer
+gotten from a fileno() method call on one of those.
+
+The optional 4th argument specifies a timeout in seconds; it may be
+a floating point number to specify fractions of seconds.  If it is absent
+or None, the call will never time out.
+
+The return value is a tuple of three lists corresponding to the first three
+arguments; each contains the subset of the corresponding file descriptors
+that are ready.
+
+*** IMPORTANT NOTICE ***
+On Windows, only sockets are supported; on Unix, all file
+descriptors can be used.
+[clinic start generated code]*/
+
 static PyObject *
-select_select(PyObject *self, PyObject *args)
+select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist,
+                   PyObject *xlist, PyObject *timeout_obj)
+/*[clinic end generated code: output=2b3cfa824f7ae4cf input=177e72184352df25]*/
 {
 #ifdef SELECT_USES_HEAP
     pylist *rfd2obj, *wfd2obj, *efd2obj;
@@ -195,20 +258,13 @@ select_select(PyObject *self, PyObject *args)
     pylist wfd2obj[FD_SETSIZE + 1];
     pylist efd2obj[FD_SETSIZE + 1];
 #endif /* SELECT_USES_HEAP */
-    PyObject *ifdlist, *ofdlist, *efdlist;
     PyObject *ret = NULL;
-    PyObject *timeout_obj = Py_None;
     fd_set ifdset, ofdset, efdset;
     struct timeval tv, *tvp;
     int imax, omax, emax, max;
     int n;
     _PyTime_t timeout, deadline = 0;
 
-    /* convert arguments */
-    if (!PyArg_UnpackTuple(args, "select", 3, 4,
-                          &ifdlist, &ofdlist, &efdlist, &timeout_obj))
-        return NULL;
-
     if (timeout_obj == Py_None)
         tvp = (struct timeval *)NULL;
     else {
@@ -249,11 +305,11 @@ select_select(PyObject *self, PyObject *args)
     rfd2obj[0].sentinel = -1;
     wfd2obj[0].sentinel = -1;
     efd2obj[0].sentinel = -1;
-    if ((imax=seq2set(ifdlist, &ifdset, rfd2obj)) < 0)
+    if ((imax = seq2set(rlist, &ifdset, rfd2obj)) < 0)
         goto finally;
-    if ((omax=seq2set(ofdlist, &ofdset, wfd2obj)) < 0)
+    if ((omax = seq2set(wlist, &ofdset, wfd2obj)) < 0)
         goto finally;
-    if ((emax=seq2set(efdlist, &efdset, efd2obj)) < 0)
+    if ((emax = seq2set(xlist, &efdset, efd2obj)) < 0)
         goto finally;
 
     max = imax;
@@ -301,17 +357,17 @@ select_select(PyObject *self, PyObject *args)
            convenient to test for this after all three calls... but
            is that acceptable?
         */
-        ifdlist = set2list(&ifdset, rfd2obj);
-        ofdlist = set2list(&ofdset, wfd2obj);
-        efdlist = set2list(&efdset, efd2obj);
+        rlist = set2list(&ifdset, rfd2obj);
+        wlist = set2list(&ofdset, wfd2obj);
+        xlist = set2list(&efdset, efd2obj);
         if (PyErr_Occurred())
             ret = NULL;
         else
-            ret = PyTuple_Pack(3, ifdlist, ofdlist, efdlist);
+            ret = PyTuple_Pack(3, rlist, wlist, xlist);
 
-        Py_XDECREF(ifdlist);
-        Py_XDECREF(ofdlist);
-        Py_XDECREF(efdlist);
+        Py_XDECREF(rlist);
+        Py_XDECREF(wlist);
+        Py_XDECREF(xlist);
     }
 
   finally:
@@ -392,33 +448,31 @@ ushort_converter(PyObject *obj, void *ptr)
     return 1;
 }
 
-PyDoc_STRVAR(poll_register_doc,
-"register(fd [, eventmask] ) -> None\n\n\
-Register a file descriptor with the polling object.\n\
-fd -- either an integer, or an object with a fileno() method returning an\n\
-      int.\n\
-events -- an optional bitmask describing the type of events to check for");
+/*[clinic input]
+select.poll.register
+
+    fd: fildes
+      either an integer, or an object with a fileno() method returning an int
+    eventmask: object(converter="ushort_converter", type="unsigned short", c_default="POLLIN | POLLPRI | POLLOUT") = POLLIN | POLLPRI | POLLOUT
+      an optional bitmask describing the type of events to check for
+    /
+
+Register a file descriptor with the polling object.
+[clinic start generated code]*/
 
 static PyObject *
-poll_register(pollObject *self, PyObject *args)
+select_poll_register_impl(pollObject *self, int fd, unsigned short eventmask)
+/*[clinic end generated code: output=0dc7173c800a4a65 input=499d96a2836217f5]*/
 {
-    PyObject *o, *key, *value;
-    int fd;
-    unsigned short events = POLLIN | POLLPRI | POLLOUT;
+    PyObject *key, *value;
     int err;
 
-    if (!PyArg_ParseTuple(args, "O|O&:register", &o, ushort_converter, &events))
-        return NULL;
-
-    fd = PyObject_AsFileDescriptor(o);
-    if (fd == -1) return NULL;
-
     /* Add entry to the internal dictionary: the key is the
        file descriptor, and the value is the event mask. */
     key = PyLong_FromLong(fd);
     if (key == NULL)
         return NULL;
-    value = PyLong_FromLong(events);
+    value = PyLong_FromLong(eventmask);
     if (value == NULL) {
         Py_DECREF(key);
         return NULL;
@@ -434,27 +488,27 @@ poll_register(pollObject *self, PyObject *args)
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(poll_modify_doc,
-"modify(fd, eventmask) -> None\n\n\
-Modify an already registered file descriptor.\n\
-fd -- either an integer, or an object with a fileno() method returning an\n\
-      int.\n\
-events -- an optional bitmask describing the type of events to check for");
+
+/*[clinic input]
+select.poll.modify
+
+    fd: fildes
+      either an integer, or an object with a fileno() method returning
+      an int
+    eventmask: object(converter="ushort_converter", type="unsigned short")
+      a bitmask describing the type of events to check for
+    /
+
+Modify an already registered file descriptor.
+[clinic start generated code]*/
 
 static PyObject *
-poll_modify(pollObject *self, PyObject *args)
+select_poll_modify_impl(pollObject *self, int fd, unsigned short eventmask)
+/*[clinic end generated code: output=1a7b88bf079eff17 input=b8e0e04a1264b78f]*/
 {
-    PyObject *o, *key, *value;
-    int fd;
-    unsigned short events;
+    PyObject *key, *value;
     int err;
 
-    if (!PyArg_ParseTuple(args, "OO&:modify", &o, ushort_converter, &events))
-        return NULL;
-
-    fd = PyObject_AsFileDescriptor(o);
-    if (fd == -1) return NULL;
-
     /* Modify registered fd */
     key = PyLong_FromLong(fd);
     if (key == NULL)
@@ -465,7 +519,7 @@ poll_modify(pollObject *self, PyObject *args)
         Py_DECREF(key);
         return NULL;
     }
-    value = PyLong_FromLong(events);
+    value = PyLong_FromLong(eventmask);
     if (value == NULL) {
         Py_DECREF(key);
         return NULL;
@@ -482,19 +536,20 @@ poll_modify(pollObject *self, PyObject *args)
 }
 
 
-PyDoc_STRVAR(poll_unregister_doc,
-"unregister(fd) -> None\n\n\
-Remove a file descriptor being tracked by the polling object.");
+/*[clinic input]
+select.poll.unregister
+
+    fd: fildes
+    /
+
+Remove a file descriptor being tracked by the polling object.
+[clinic start generated code]*/
 
 static PyObject *
-poll_unregister(pollObject *self, PyObject *o)
+select_poll_unregister_impl(pollObject *self, int fd)
+/*[clinic end generated code: output=8c9f42e75e7d291b input=4b4fccc1040e79cb]*/
 {
     PyObject *key;
-    int fd;
-
-    fd = PyObject_AsFileDescriptor( o );
-    if (fd == -1)
-        return NULL;
 
     /* Check whether the fd is already in the array */
     key = PyLong_FromLong(fd);
@@ -514,25 +569,29 @@ poll_unregister(pollObject *self, PyObject *o)
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(poll_poll_doc,
-"poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\
-Polls the set of registered file descriptors, returning a list containing\n\
-any descriptors that have events or errors to report.");
+/*[clinic input]
+select.poll.poll
+
+    timeout as timeout_obj: object = None
+    /
+
+Polls the set of registered file descriptors.
+
+Returns a list containing any descriptors that have events or errors to
+report, as a list of (fd, event) 2-tuples.
+[clinic start generated code]*/
 
 static PyObject *
-poll_poll(pollObject *self, PyObject *args)
+select_poll_poll_impl(pollObject *self, PyObject *timeout_obj)
+/*[clinic end generated code: output=876e837d193ed7e4 input=7a446ed45189e894]*/
 {
-    PyObject *result_list = NULL, *timeout_obj = NULL;
+    PyObject *result_list = NULL;
     int poll_result, i, j;
     PyObject *value = NULL, *num = NULL;
     _PyTime_t timeout = -1, ms = -1, deadline = 0;
     int async_err = 0;
 
-    if (!PyArg_ParseTuple(args, "|O:poll", &timeout_obj)) {
-        return NULL;
-    }
-
-    if (timeout_obj != NULL && timeout_obj != Py_None) {
+    if (timeout_obj != Py_None) {
         if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj,
                                            _PyTime_ROUND_TIMEOUT) < 0) {
             if (PyErr_ExceptionMatches(PyExc_TypeError)) {
@@ -661,18 +720,6 @@ poll_poll(pollObject *self, PyObject *args)
     return NULL;
 }
 
-static PyMethodDef poll_methods[] = {
-    {"register",        (PyCFunction)poll_register,
-     METH_VARARGS,  poll_register_doc},
-    {"modify",          (PyCFunction)poll_modify,
-     METH_VARARGS,  poll_modify_doc},
-    {"unregister",      (PyCFunction)poll_unregister,
-     METH_O,        poll_unregister_doc},
-    {"poll",            (PyCFunction)poll_poll,
-     METH_VARARGS,  poll_poll_doc},
-    {NULL,              NULL}           /* sentinel */
-};
-
 static pollObject *
 newPollObject(void)
 {
@@ -702,39 +749,6 @@ poll_dealloc(pollObject *self)
     PyObject_Del(self);
 }
 
-static PyTypeObject poll_Type = {
-    /* The ob_type field must be initialized in the module init function
-     * to be portable to Windows without using C++. */
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "select.poll",              /*tp_name*/
-    sizeof(pollObject),         /*tp_basicsize*/
-    0,                          /*tp_itemsize*/
-    /* methods */
-    (destructor)poll_dealloc, /*tp_dealloc*/
-    0,                          /*tp_print*/
-    0,                          /*tp_getattr*/
-    0,                      /*tp_setattr*/
-    0,                          /*tp_reserved*/
-    0,                          /*tp_repr*/
-    0,                          /*tp_as_number*/
-    0,                          /*tp_as_sequence*/
-    0,                          /*tp_as_mapping*/
-    0,                          /*tp_hash*/
-    0,                          /*tp_call*/
-    0,                          /*tp_str*/
-    0,                          /*tp_getattro*/
-    0,                          /*tp_setattro*/
-    0,                          /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,         /*tp_flags*/
-    0,                          /*tp_doc*/
-    0,                          /*tp_traverse*/
-    0,                          /*tp_clear*/
-    0,                          /*tp_richcompare*/
-    0,                          /*tp_weaklistoffset*/
-    0,                          /*tp_iter*/
-    0,                          /*tp_iternext*/
-    poll_methods,               /*tp_methods*/
-};
 
 #ifdef HAVE_SYS_DEVPOLL_H
 typedef struct {
@@ -785,21 +799,12 @@ static int devpoll_flush(devpollObject *self)
 }
 
 static PyObject *
-internal_devpoll_register(devpollObject *self, PyObject *args, int remove)
+internal_devpoll_register(devpollObject *self, int fd,
+                          unsigned short events, int remove)
 {
-    PyObject *o;
-    int fd;
-    unsigned short events = POLLIN | POLLPRI | POLLOUT;
-
     if (self->fd_devpoll < 0)
         return devpoll_err_closed();
 
-    if (!PyArg_ParseTuple(args, "O|O&:register", &o, ushort_converter, &events))
-        return NULL;
-
-    fd = PyObject_AsFileDescriptor(o);
-    if (fd == -1) return NULL;
-
     if (remove) {
         self->fds[self->n_fds].fd = fd;
         self->fds[self->n_fds].events = POLLREMOVE;
@@ -821,49 +826,66 @@ internal_devpoll_register(devpollObject *self, PyObject *args, int remove)
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(devpoll_register_doc,
-"register(fd [, eventmask] ) -> None\n\n\
-Register a file descriptor with the polling object.\n\
-fd -- either an integer, or an object with a fileno() method returning an\n\
-      int.\n\
-events -- an optional bitmask describing the type of events to check for");
+/*[clinic input]
+select.devpoll.register
+
+    fd: fildes
+        either an integer, or an object with a fileno() method returning
+        an int
+    eventmask: object(converter="ushort_converter", type="unsigned short", c_default="POLLIN | POLLPRI | POLLOUT") = POLLIN | POLLPRI | POLLOUT
+        an optional bitmask describing the type of events to check for
+    /
+
+Register a file descriptor with the polling object.
+[clinic start generated code]*/
 
 static PyObject *
-devpoll_register(devpollObject *self, PyObject *args)
+select_devpoll_register_impl(devpollObject *self, int fd,
+                             unsigned short eventmask)
+/*[clinic end generated code: output=6e07fe8b74abba0c input=389a0785bb8feb57]*/
 {
-    return internal_devpoll_register(self, args, 0);
+    return internal_devpoll_register(self, fd, eventmask, 0);
 }
 
-PyDoc_STRVAR(devpoll_modify_doc,
-"modify(fd[, eventmask]) -> None\n\n\
-Modify a possible already registered file descriptor.\n\
-fd -- either an integer, or an object with a fileno() method returning an\n\
-      int.\n\
-events -- an optional bitmask describing the type of events to check for");
+/*[clinic input]
+select.devpoll.modify
+
+    fd: fildes
+        either an integer, or an object with a fileno() method returning
+        an int
+    eventmask: object(converter="ushort_converter", type="unsigned short", c_default="POLLIN | POLLPRI | POLLOUT") = POLLIN | POLLPRI | POLLOUT
+        an optional bitmask describing the type of events to check for
+    /
+
+Modify a possible already registered file descriptor.
+[clinic start generated code]*/
 
+static PyObject *
+select_devpoll_modify_impl(devpollObject *self, int fd,
+                           unsigned short eventmask)
+/*[clinic end generated code: output=bc2e6d23aaff98b4 input=f0d7de3889cc55fb]*/
 static PyObject *
 devpoll_modify(devpollObject *self, PyObject *args)
 {
-    return internal_devpoll_register(self, args, 1);
+    return internal_devpoll_register(self, fd, eventmask, 1);
 }
 
+/*[clinic input]
+select.devpoll.unregister
+
+    fd: fildes
+    /
 
-PyDoc_STRVAR(devpoll_unregister_doc,
-"unregister(fd) -> None\n\n\
-Remove a file descriptor being tracked by the polling object.");
+Remove a file descriptor being tracked by the polling object.
+[clinic start generated code]*/
 
 static PyObject *
-devpoll_unregister(devpollObject *self, PyObject *o)
+select_devpoll_unregister_impl(devpollObject *self, int fd)
+/*[clinic end generated code: output=95519ffa0c7d43fe input=b4ea42a4442fd467]*/
 {
-    int fd;
-
     if (self->fd_devpoll < 0)
         return devpoll_err_closed();
 
-    fd = PyObject_AsFileDescriptor( o );
-    if (fd == -1)
-        return NULL;
-
     self->fds[self->n_fds].fd = fd;
     self->fds[self->n_fds].events = POLLREMOVE;
 
@@ -875,13 +897,20 @@ devpoll_unregister(devpollObject *self, PyObject *o)
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(devpoll_poll_doc,
-"poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\
-Polls the set of registered file descriptors, returning a list containing\n\
-any descriptors that have events or errors to report.");
+/*[clinic input]
+select.devpoll.poll
+    timeout as timeout_obj: object = None
+    /
+
+Polls the set of registered file descriptors.
+
+Returns a list containing any descriptors that have events or errors to
+report, as a list of (fd, event) 2-tuples.
+[clinic start generated code]*/
 
 static PyObject *
-devpoll_poll(devpollObject *self, PyObject *args)
+select_devpoll_poll_impl(devpollObject *self, PyObject *timeout_obj)
+/*[clinic end generated code: output=2654e5457cca0b3c input=fd0db698d84f0333]*/
 {
     struct dvpoll dvp;
     PyObject *result_list = NULL, *timeout_obj = NULL;
@@ -892,12 +921,8 @@ devpoll_poll(devpollObject *self, PyObject *args)
     if (self->fd_devpoll < 0)
         return devpoll_err_closed();
 
-    if (!PyArg_ParseTuple(args, "|O:poll", &timeout_obj)) {
-        return NULL;
-    }
-
     /* Check values for timeout */
-    if (timeout_obj == NULL || timeout_obj == Py_None) {
+    if (timeout_obj == Py_None) {
         timeout = -1;
         ms = -1;
     }
@@ -1005,8 +1030,17 @@ devpoll_internal_close(devpollObject *self)
     return save_errno;
 }
 
-static PyObject*
-devpoll_close(devpollObject *self, PyObject *Py_UNUSED(ignored))
+/*[clinic input]
+select.devpoll.close
+
+Close the devpoll file descriptor.
+
+Further operations on the devpoll object will raise an exception.
+[clinic start generated code]*/
+
+static PyObject *
+select_devpoll_close_impl(devpollObject *self)
+/*[clinic end generated code: output=26b355bd6429f21b input=6273c30f5560a99b]*/
 {
     errno = devpoll_internal_close(self);
     if (errno < 0) {
@@ -1016,12 +1050,6 @@ devpoll_close(devpollObject *self, PyObject *Py_UNUSED(ignored))
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(devpoll_close_doc,
-"close() -> None\n\
-\n\
-Close the devpoll file descriptor. Further operations on the devpoll\n\
-object will raise an exception.");
-
 static PyObject*
 devpoll_get_closed(devpollObject *self)
 {
@@ -1031,35 +1059,21 @@ devpoll_get_closed(devpollObject *self)
         Py_RETURN_FALSE;
 }
 
-static PyObject*
-devpoll_fileno(devpollObject *self, PyObject *Py_UNUSED(ignored))
+/*[clinic input]
+select.devpoll.fileno
+
+Return the file descriptor.
+[clinic start generated code]*/
+
+static PyObject *
+select_devpoll_fileno_impl(devpollObject *self)
+/*[clinic end generated code: output=26920929f8d292f4 input=ef15331ebde6c368]*/
 {
     if (self->fd_devpoll < 0)
         return devpoll_err_closed();
     return PyLong_FromLong(self->fd_devpoll);
 }
 
-PyDoc_STRVAR(devpoll_fileno_doc,
-"fileno() -> int\n\
-\n\
-Return the file descriptor.");
-
-static PyMethodDef devpoll_methods[] = {
-    {"register",        (PyCFunction)devpoll_register,
-     METH_VARARGS,  devpoll_register_doc},
-    {"modify",          (PyCFunction)devpoll_modify,
-     METH_VARARGS,  devpoll_modify_doc},
-    {"unregister",      (PyCFunction)devpoll_unregister,
-     METH_O,        devpoll_unregister_doc},
-    {"poll",            (PyCFunction)devpoll_poll,
-     METH_VARARGS,  devpoll_poll_doc},
-    {"close",           (PyCFunction)devpoll_close,    METH_NOARGS,
-     devpoll_close_doc},
-    {"fileno",          (PyCFunction)devpoll_fileno,    METH_NOARGS,
-     devpoll_fileno_doc},
-    {NULL,              NULL}           /* sentinel */
-};
-
 static PyGetSetDef devpoll_getsetlist[] = {
     {"closed", (getter)devpoll_get_closed, NULL,
      "True if the devpoll object is closed"},
@@ -1119,62 +1133,39 @@ devpoll_dealloc(devpollObject *self)
     PyObject_Del(self);
 }
 
-static PyTypeObject devpoll_Type = {
-    /* The ob_type field must be initialized in the module init function
-     * to be portable to Windows without using C++. */
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "select.devpoll",           /*tp_name*/
-    sizeof(devpollObject),      /*tp_basicsize*/
-    0,                          /*tp_itemsize*/
-    /* methods */
-    (destructor)devpoll_dealloc, /*tp_dealloc*/
-    0,                          /*tp_print*/
-    0,                          /*tp_getattr*/
-    0,                          /*tp_setattr*/
-    0,                          /*tp_reserved*/
-    0,                          /*tp_repr*/
-    0,                          /*tp_as_number*/
-    0,                          /*tp_as_sequence*/
-    0,                          /*tp_as_mapping*/
-    0,                          /*tp_hash*/
-    0,                          /*tp_call*/
-    0,                          /*tp_str*/
-    0,                          /*tp_getattro*/
-    0,                          /*tp_setattro*/
-    0,                          /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,         /*tp_flags*/
-    0,                          /*tp_doc*/
-    0,                          /*tp_traverse*/
-    0,                          /*tp_clear*/
-    0,                          /*tp_richcompare*/
-    0,                          /*tp_weaklistoffset*/
-    0,                          /*tp_iter*/
-    0,                          /*tp_iternext*/
-    devpoll_methods,            /*tp_methods*/
-    0,                          /* tp_members */
-    devpoll_getsetlist,         /* tp_getset */
-};
 #endif  /* HAVE_SYS_DEVPOLL_H */
 
 
+/*[clinic input]
+select.poll
 
-PyDoc_STRVAR(poll_doc,
-"Returns a polling object, which supports registering and\n\
-unregistering file descriptors, and then polling them for I/O events.");
+Returns a polling object.
+
+This object supports registering and unregistering file descriptors, and then
+polling them for I/O events.
+[clinic start generated code]*/
 
 static PyObject *
-select_poll(PyObject *self, PyObject *unused)
+select_poll_impl(PyObject *module)
+/*[clinic end generated code: output=16a665a4e1d228c5 input=3f877909d5696bbf]*/
 {
     return (PyObject *)newPollObject();
 }
 
 #ifdef HAVE_SYS_DEVPOLL_H
-PyDoc_STRVAR(devpoll_doc,
-"Returns a polling object, which supports registering and\n\
-unregistering file descriptors, and then polling them for I/O events.");
+
+/*[clinic input]
+select.devpoll
+
+Returns a polling object.
+
+This object supports registering and unregistering file descriptors, and then
+polling them for I/O events.
+[clinic start generated code]*/
 
 static PyObject *
-select_devpoll(PyObject *self, PyObject *unused)
+select_devpoll_impl(PyObject *module)
+/*[clinic end generated code: output=ea9213cc87fd9581 input=53a1af94564f00a3]*/
 {
     return (PyObject *)newDevPollObject();
 }
@@ -1294,20 +1285,31 @@ newPyEpoll_Object(PyTypeObject *type, int sizehint, SOCKET fd)
 }
 
 
+/*[clinic input]
+@classmethod
+select.epoll.__new__
+
+    sizehint: int = -1
+      The expected number of events to be registered.  It must be positive,
+      or -1 to use the default.  It is only used on older systems where
+      epoll_create1() is not available; otherwise it has no effect (though its
+      value is still checked).
+    flags: int = 0
+      Deprecated and completely ignored.  However, when supplied, its value
+      must be 0 or select.EPOLL_CLOEXEC, otherwise OSError is raised.
+
+Returns an epolling object.
+[clinic start generated code]*/
+
 static PyObject *
-pyepoll_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+select_epoll_impl(PyTypeObject *type, int sizehint, int flags)
+/*[clinic end generated code: output=c87404e705013bb5 input=303e3295e7975e43]*/
 {
-    int flags = 0, sizehint = -1;
-    static char *kwlist[] = {"sizehint", "flags", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:epoll", kwlist,
-                                     &sizehint, &flags))
-        return NULL;
     if (sizehint == -1) {
         sizehint = FD_SETSIZE - 1;
     }
     else if (sizehint <= 0) {
-        PyErr_SetString(PyExc_ValueError, "sizehint must be positive or -1");
+        PyErr_SetString(PyExc_ValueError, "negative sizehint");
         return NULL;
     }
 
@@ -1317,6 +1319,7 @@ pyepoll_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         return NULL;
     }
 #endif
+
     return newPyEpoll_Object(type, sizehint, -1);
 }
 
@@ -1328,8 +1331,17 @@ pyepoll_dealloc(pyEpoll_Object *self)
     Py_TYPE(self)->tp_free(self);
 }
 
-static PyObject*
-pyepoll_close(pyEpoll_Object *self, PyObject *Py_UNUSED(ignored))
+/*[clinic input]
+select.epoll.close
+
+Close the epoll control file descriptor.
+
+Further operations on the epoll object will raise an exception.
+[clinic start generated code]*/
+
+static PyObject *
+select_epoll_close_impl(pyEpoll_Object *self)
+/*[clinic end generated code: output=ee2144c446a1a435 input=ca6c66ba5a736bfd]*/
 {
     errno = pyepoll_internal_close(self);
     if (errno < 0) {
@@ -1339,11 +1351,6 @@ pyepoll_close(pyEpoll_Object *self, PyObject *Py_UNUSED(ignored))
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(pyepoll_close_doc,
-"close() -> None\n\
-\n\
-Close the epoll control file descriptor. Further operations on the epoll\n\
-object will raise an exception.");
 
 static PyObject*
 pyepoll_get_closed(pyEpoll_Object *self)
@@ -1354,50 +1361,50 @@ pyepoll_get_closed(pyEpoll_Object *self)
         Py_RETURN_FALSE;
 }
 
-static PyObject*
-pyepoll_fileno(pyEpoll_Object *self, PyObject *Py_UNUSED(ignored))
+/*[clinic input]
+select.epoll.fileno
+
+Return the epoll control file descriptor.
+[clinic start generated code]*/
+
+static PyObject *
+select_epoll_fileno_impl(pyEpoll_Object *self)
+/*[clinic end generated code: output=e171375fdc619ba3 input=c11091a6aee60b5c]*/
 {
     if (self->epfd < 0)
         return pyepoll_err_closed();
     return PyLong_FromLong(self->epfd);
 }
 
-PyDoc_STRVAR(pyepoll_fileno_doc,
-"fileno() -> int\n\
-\n\
-Return the epoll control file descriptor.");
 
-static PyObject*
-pyepoll_fromfd(PyObject *cls, PyObject *args)
-{
-    SOCKET fd;
+/*[clinic input]
+@classmethod
+select.epoll.fromfd
 
-    if (!PyArg_ParseTuple(args, "i:fromfd", &fd))
-        return NULL;
+    fd: int
+    /
+
+Create an epoll object from a given control fd.
+[clinic start generated code]*/
 
-    return newPyEpoll_Object((PyTypeObject*)cls, FD_SETSIZE - 1, fd);
+static PyObject *
+select_epoll_fromfd_impl(PyTypeObject *type, int fd)
+/*[clinic end generated code: output=c15de2a083524e8e input=faecefdb55e3046e]*/
+{
+    SOCKET s_fd = (SOCKET)fd;
+    return newPyEpoll_Object(type, FD_SETSIZE - 1, s_fd);
 }
 
-PyDoc_STRVAR(pyepoll_fromfd_doc,
-"fromfd(fd) -> epoll\n\
-\n\
-Create an epoll object from a given control fd.");
 
 static PyObject *
-pyepoll_internal_ctl(int epfd, int op, PyObject *pfd, unsigned int events)
+pyepoll_internal_ctl(int epfd, int op, int fd, unsigned int events)
 {
     struct epoll_event ev;
     int result;
-    int fd;
 
     if (epfd < 0)
         return pyepoll_err_closed();
 
-    fd = PyObject_AsFileDescriptor(pfd);
-    if (fd == -1) {
-        return NULL;
-    }
-
     switch (op) {
     case EPOLL_CTL_ADD:
     case EPOLL_CTL_MOD:
@@ -1432,77 +1439,82 @@ pyepoll_internal_ctl(int epfd, int op, PyObject *pfd, unsigned int events)
     Py_RETURN_NONE;
 }
 
+/*[clinic input]
+select.epoll.register
+
+    fd: fildes
+      the target file descriptor of the operation
+    eventmask: unsigned_int(c_default="EPOLLIN | EPOLLPRI | EPOLLOUT", bitwise=True) = EPOLLIN | EPOLLPRI | EPOLLOUT
+      a bit set composed of the various EPOLL constants
+
+Registers a new fd or raises an OSError if the fd is already registered.
+
+The epoll interface supports all file descriptors that support poll.
+[clinic start generated code]*/
+
 static PyObject *
-pyepoll_register(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
+select_epoll_register_impl(pyEpoll_Object *self, int fd,
+                           unsigned int eventmask)
+/*[clinic end generated code: output=318e5e6386520599 input=6cf699c152dd8ca9]*/
 {
-    PyObject *pfd;
-    unsigned int events = EPOLLIN | EPOLLOUT | EPOLLPRI;
-    static char *kwlist[] = {"fd", "eventmask", NULL};
+    return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_ADD, fd, eventmask);
+}
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|I:register", kwlist,
-                                     &pfd, &events)) {
-        return NULL;
-    }
+/*[clinic input]
+select.epoll.modify
 
-    return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_ADD, pfd, events);
-}
+    fd: fildes
+      the target file descriptor of the operation
+    eventmask: unsigned_int(bitwise=True)
+      a bit set composed of the various EPOLL constants
 
-PyDoc_STRVAR(pyepoll_register_doc,
-"register(fd[, eventmask]) -> None\n\
-\n\
-Registers a new fd or raises an OSError if the fd is already registered.\n\
-fd is the target file descriptor of the operation.\n\
-events is a bit set composed of the various EPOLL constants; the default\n\
-is EPOLLIN | EPOLLOUT | EPOLLPRI.\n\
-\n\
-The epoll interface supports all file descriptors that support poll.");
+Modify event mask for a registered file descriptor.
+[clinic start generated code]*/
 
 static PyObject *
-pyepoll_modify(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
+select_epoll_modify_impl(pyEpoll_Object *self, int fd,
+                         unsigned int eventmask)
+/*[clinic end generated code: output=7e3447307cff6f65 input=88a83dac53a8c3da]*/
 {
-    PyObject *pfd;
-    unsigned int events;
-    static char *kwlist[] = {"fd", "eventmask", NULL};
+    return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_MOD, fd, eventmask);
+}
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OI:modify", kwlist,
-                                     &pfd, &events)) {
-        return NULL;
-    }
+/*[clinic input]
+select.epoll.unregister
 
-    return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_MOD, pfd, events);
-}
+    fd: fildes
+      the target file descriptor of the operation
 
-PyDoc_STRVAR(pyepoll_modify_doc,
-"modify(fd, eventmask) -> None\n\
-\n\
-fd is the target file descriptor of the operation\n\
-events is a bit set composed of the various EPOLL constants");
+Remove a registered file descriptor from the epoll object.
+[clinic start generated code]*/
 
 static PyObject *
-pyepoll_unregister(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
+select_epoll_unregister_impl(pyEpoll_Object *self, int fd)
+/*[clinic end generated code: output=07c5dbd612a512d4 input=3093f68d3644743d]*/
 {
-    PyObject *pfd;
-    static char *kwlist[] = {"fd", NULL};
+    return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_DEL, fd, 0);
+}
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:unregister", kwlist,
-                                     &pfd)) {
-        return NULL;
-    }
+/*[clinic input]
+select.epoll.poll
 
-    return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_DEL, pfd, 0);
-}
+    timeout as timeout_obj: object = None
+      the maximum time to wait in seconds (as float);
+      a timeout of None or -1 makes poll wait indefinitely
+    maxevents: int = -1
+      the maximum number of events returned; -1 means no limit
 
-PyDoc_STRVAR(pyepoll_unregister_doc,
-"unregister(fd) -> None\n\
-\n\
-fd is the target file descriptor of the operation.");
+Wait for events on the epoll file descriptor.
+
+Returns a list containing any descriptors that have events to report,
+as a list of (fd, events) 2-tuples.
+[clinic start generated code]*/
 
 static PyObject *
-pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
+select_epoll_poll_impl(pyEpoll_Object *self, PyObject *timeout_obj,
+                       int maxevents)
+/*[clinic end generated code: output=e02d121a20246c6c input=33d34a5ea430fd5b]*/
 {
-    static char *kwlist[] = {"timeout", "maxevents", NULL};
-    PyObject *timeout_obj = NULL;
-    int maxevents = -1;
     int nfds, i;
     PyObject *elist = NULL, *etuple = NULL;
     struct epoll_event *evs = NULL;
@@ -1511,12 +1523,7 @@ pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
     if (self->epfd < 0)
         return pyepoll_err_closed();
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:poll", kwlist,
-                                     &timeout_obj, &maxevents)) {
-        return NULL;
-    }
-
-    if (timeout_obj == NULL || timeout_obj == Py_None) {
+    if (timeout_obj == Py_None) {
         timeout = -1;
         ms = -1;
         deadline = 0;   /* initialize to prevent gcc warning */
@@ -1606,15 +1613,15 @@ pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
     return elist;
 }
 
-PyDoc_STRVAR(pyepoll_poll_doc,
-"poll([timeout=-1[, maxevents=-1]]) -> [(fd, events), (...)]\n\
-\n\
-Wait for events on the epoll file descriptor for a maximum time of timeout\n\
-in seconds (as float). -1 makes poll wait indefinitely.\n\
-Up to maxevents are returned to the caller.");
+
+/*[clinic input]
+select.epoll.__enter__
+
+[clinic start generated code]*/
 
 static PyObject *
-pyepoll_enter(pyEpoll_Object *self, PyObject *args)
+select_epoll___enter___impl(pyEpoll_Object *self)
+/*[clinic end generated code: output=ab45d433504db2a0 input=3c22568587efeadb]*/
 {
     if (self->epfd < 0)
         return pyepoll_err_closed();
@@ -1623,94 +1630,33 @@ pyepoll_enter(pyEpoll_Object *self, PyObject *args)
     return (PyObject *)self;
 }
 
+/*[clinic input]
+select.epoll.__exit__
+
+    exc_type:  object = None
+    exc_value: object = None
+    exc_tb:    object = None
+    /
+
+[clinic start generated code]*/
+
 static PyObject *
-pyepoll_exit(PyObject *self, PyObject *args)
+select_epoll___exit___impl(pyEpoll_Object *self, PyObject *exc_type,
+                           PyObject *exc_value, PyObject *exc_tb)
+/*[clinic end generated code: output=c480f38ce361748e input=7ae81a5a4c1a98d8]*/
 {
     _Py_IDENTIFIER(close);
 
-    return _PyObject_CallMethodId(self, &PyId_close, NULL);
+    return _PyObject_CallMethodId((PyObject *)self, &PyId_close, NULL);
 }
 
-static PyMethodDef pyepoll_methods[] = {
-    {"fromfd",          (PyCFunction)pyepoll_fromfd,
-     METH_VARARGS | METH_CLASS, pyepoll_fromfd_doc},
-    {"close",           (PyCFunction)pyepoll_close,     METH_NOARGS,
-     pyepoll_close_doc},
-    {"fileno",          (PyCFunction)pyepoll_fileno,    METH_NOARGS,
-     pyepoll_fileno_doc},
-    {"modify",          (PyCFunction)pyepoll_modify,
-     METH_VARARGS | METH_KEYWORDS,      pyepoll_modify_doc},
-    {"register",        (PyCFunction)pyepoll_register,
-     METH_VARARGS | METH_KEYWORDS,      pyepoll_register_doc},
-    {"unregister",      (PyCFunction)pyepoll_unregister,
-     METH_VARARGS | METH_KEYWORDS,      pyepoll_unregister_doc},
-    {"poll",            (PyCFunction)pyepoll_poll,
-     METH_VARARGS | METH_KEYWORDS,      pyepoll_poll_doc},
-    {"__enter__",           (PyCFunction)pyepoll_enter,     METH_NOARGS,
-     NULL},
-    {"__exit__",           (PyCFunction)pyepoll_exit,     METH_VARARGS,
-     NULL},
-    {NULL,      NULL},
-};
-
 static PyGetSetDef pyepoll_getsetlist[] = {
     {"closed", (getter)pyepoll_get_closed, NULL,
      "True if the epoll handler is closed"},
     {0},
 };
 
-PyDoc_STRVAR(pyepoll_doc,
-"select.epoll(sizehint=-1, flags=0)\n\
-\n\
-Returns an epolling object\n\
-\n\
-sizehint must be a positive integer or -1 for the default size. The\n\
-sizehint is used to optimize internal data structures. It doesn't limit\n\
-the maximum number of monitored events.");
-
-static PyTypeObject pyEpoll_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "select.epoll",                                     /* tp_name */
-    sizeof(pyEpoll_Object),                             /* tp_basicsize */
-    0,                                                  /* tp_itemsize */
-    (destructor)pyepoll_dealloc,                        /* tp_dealloc */
-    0,                                                  /* tp_print */
-    0,                                                  /* tp_getattr */
-    0,                                                  /* tp_setattr */
-    0,                                                  /* tp_reserved */
-    0,                                                  /* tp_repr */
-    0,                                                  /* tp_as_number */
-    0,                                                  /* tp_as_sequence */
-    0,                                                  /* tp_as_mapping */
-    0,                                                  /* tp_hash */
-    0,                                                  /* tp_call */
-    0,                                                  /* tp_str */
-    PyObject_GenericGetAttr,                            /* tp_getattro */
-    0,                                                  /* tp_setattro */
-    0,                                                  /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                                 /* tp_flags */
-    pyepoll_doc,                                        /* tp_doc */
-    0,                                                  /* tp_traverse */
-    0,                                                  /* tp_clear */
-    0,                                                  /* tp_richcompare */
-    0,                                                  /* tp_weaklistoffset */
-    0,                                                  /* tp_iter */
-    0,                                                  /* tp_iternext */
-    pyepoll_methods,                                    /* tp_methods */
-    0,                                                  /* tp_members */
-    pyepoll_getsetlist,                                 /* tp_getset */
-    0,                                                  /* tp_base */
-    0,                                                  /* tp_dict */
-    0,                                                  /* tp_descr_get */
-    0,                                                  /* tp_descr_set */
-    0,                                                  /* tp_dictoffset */
-    0,                                                  /* tp_init */
-    0,                                                  /* tp_alloc */
-    pyepoll_new,                                        /* tp_new */
-    0,                                                  /* tp_free */
-};
-
-#endif /* HAVE_EPOLL */
+#endif /* HAVE_EPOLL */
 
 #ifdef HAVE_KQUEUE
 /* **************************************************************************
@@ -1937,48 +1883,6 @@ kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o,
     Py_RETURN_RICHCOMPARE(result, 0, op);
 }
 
-static PyTypeObject kqueue_event_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "select.kevent",                                    /* tp_name */
-    sizeof(kqueue_event_Object),                        /* tp_basicsize */
-    0,                                                  /* tp_itemsize */
-    0,                                                  /* tp_dealloc */
-    0,                                                  /* tp_print */
-    0,                                                  /* tp_getattr */
-    0,                                                  /* tp_setattr */
-    0,                                                  /* tp_reserved */
-    (reprfunc)kqueue_event_repr,                        /* tp_repr */
-    0,                                                  /* tp_as_number */
-    0,                                                  /* tp_as_sequence */
-    0,                                                  /* tp_as_mapping */
-    0,                                                  /* tp_hash */
-    0,                                                  /* tp_call */
-    0,                                                  /* tp_str */
-    0,                                                  /* tp_getattro */
-    0,                                                  /* tp_setattro */
-    0,                                                  /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                                 /* tp_flags */
-    kqueue_event_doc,                                   /* tp_doc */
-    0,                                                  /* tp_traverse */
-    0,                                                  /* tp_clear */
-    (richcmpfunc)kqueue_event_richcompare,              /* tp_richcompare */
-    0,                                                  /* tp_weaklistoffset */
-    0,                                                  /* tp_iter */
-    0,                                                  /* tp_iternext */
-    0,                                                  /* tp_methods */
-    kqueue_event_members,                               /* tp_members */
-    0,                                                  /* tp_getset */
-    0,                                                  /* tp_base */
-    0,                                                  /* tp_dict */
-    0,                                                  /* tp_descr_get */
-    0,                                                  /* tp_descr_set */
-    0,                                                  /* tp_dictoffset */
-    (initproc)kqueue_event_init,                        /* tp_init */
-    0,                                                  /* tp_alloc */
-    0,                                                  /* tp_new */
-    0,                                                  /* tp_free */
-};
-
 static PyObject *
 kqueue_queue_err_closed(void)
 {
@@ -2034,16 +1938,29 @@ newKqueue_Object(PyTypeObject *type, SOCKET fd)
     return (PyObject *)self;
 }
 
+/*[clinic input]
+@classmethod
+select.kqueue.__new__
+
+Kqueue syscall wrapper.
+
+For example, to start watching a socket for input:
+>>> kq = kqueue()
+>>> sock = socket()
+>>> sock.connect((host, port))
+>>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_ADD)], 0)
+
+To wait one second for it to become writeable:
+>>> kq.control(None, 1, 1000)
+
+To stop listening:
+>>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_DELETE)], 0)
+[clinic start generated code]*/
+
 static PyObject *
-kqueue_queue_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+select_kqueue_impl(PyTypeObject *type)
+/*[clinic end generated code: output=e0ff89f154d56236 input=cf625e49218366e8]*/
 {
-    if (PyTuple_GET_SIZE(args) ||
-                    (kwds != NULL && PyDict_GET_SIZE(kwds))) {
-        PyErr_SetString(PyExc_ValueError,
-                        "select.kqueue doesn't accept arguments");
-        return NULL;
-    }
-
     return newKqueue_Object(type, -1);
 }
 
@@ -2054,8 +1971,17 @@ kqueue_queue_dealloc(kqueue_queue_Object *self)
     Py_TYPE(self)->tp_free(self);
 }
 
-static PyObject*
-kqueue_queue_close(kqueue_queue_Object *self, PyObject *Py_UNUSED(ignored))
+/*[clinic input]
+select.kqueue.close
+
+Close the kqueue control file descriptor.
+
+Further operations on the kqueue object will raise an exception.
+[clinic start generated code]*/
+
+static PyObject *
+select_kqueue_close_impl(kqueue_queue_Object *self)
+/*[clinic end generated code: output=d1c7df0b407a4bc1 input=0b12d95430e0634c]*/
 {
     errno = kqueue_queue_internal_close(self);
     if (errno < 0) {
@@ -2065,12 +1991,6 @@ kqueue_queue_close(kqueue_queue_Object *self, PyObject *Py_UNUSED(ignored))
     Py_RETURN_NONE;
 }
 
-PyDoc_STRVAR(kqueue_queue_close_doc,
-"close() -> None\n\
-\n\
-Close the kqueue control file descriptor. Further operations on the kqueue\n\
-object will raise an exception.");
-
 static PyObject*
 kqueue_queue_get_closed(kqueue_queue_Object *self)
 {
@@ -2080,44 +2000,64 @@ kqueue_queue_get_closed(kqueue_queue_Object *self)
         Py_RETURN_FALSE;
 }
 
-static PyObject*
-kqueue_queue_fileno(kqueue_queue_Object *self, PyObject *Py_UNUSED(ignored))
+/*[clinic input]
+select.kqueue.fileno
+
+Return the kqueue control file descriptor.
+[clinic start generated code]*/
+
+static PyObject *
+select_kqueue_fileno_impl(kqueue_queue_Object *self)
+/*[clinic end generated code: output=716f46112a4f6e5c input=41911c539ca2b0ca]*/
 {
     if (self->kqfd < 0)
         return kqueue_queue_err_closed();
     return PyLong_FromLong(self->kqfd);
 }
 
-PyDoc_STRVAR(kqueue_queue_fileno_doc,
-"fileno() -> int\n\
-\n\
-Return the kqueue control file descriptor.");
+/*[clinic input]
+@classmethod
+select.kqueue.fromfd
 
-static PyObject*
-kqueue_queue_fromfd(PyObject *cls, PyObject *args)
-{
-    SOCKET fd;
+    fd: int
+    /
 
-    if (!PyArg_ParseTuple(args, "i:fromfd", &fd))
-        return NULL;
+Create a kqueue object from a given control fd.
+[clinic start generated code]*/
 
-    return newKqueue_Object((PyTypeObject*)cls, fd);
+static PyObject *
+select_kqueue_fromfd_impl(PyTypeObject *type, int fd)
+/*[clinic end generated code: output=d02c3c7dc538a653 input=f6172a48ca4ecdd0]*/
+{
+    SOCKET s_fd = (SOCKET)fd;
+
+    return newKqueue_Object(type, s_fd);
 }
 
-PyDoc_STRVAR(kqueue_queue_fromfd_doc,
-"fromfd(fd) -> kqueue\n\
-\n\
-Create a kqueue object from a given control fd.");
+/*[clinic input]
+select.kqueue.control
+
+    changelist: object
+        Must be an iterable of kevent objects describing the changes to be made
+        to the kernel's watch list or None.
+    maxevents: int
+        The maximum number of events that the kernel will return.
+    timeout as otimeout: object = None
+        The maximum time to wait in seconds, or else None to wait forever.
+        This accepts floats for smaller timeouts, too.
+    /
+
+Calls the kernel kevent function.
+[clinic start generated code]*/
 
 static PyObject *
-kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)
+select_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist,
+                           int maxevents, PyObject *otimeout)
+/*[clinic end generated code: output=81324ff5130db7ae input=59c4e30811209c47]*/
 {
-    int nevents = 0;
     int gotevents = 0;
     int nchanges = 0;
     int i = 0;
-    PyObject *otimeout = NULL;
-    PyObject *ch = NULL;
     PyObject *seq = NULL, *ei = NULL;
     PyObject *result = NULL;
     struct kevent *evl = NULL;
@@ -2129,17 +2069,14 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)
     if (self->kqfd < 0)
         return kqueue_queue_err_closed();
 
-    if (!PyArg_ParseTuple(args, "Oi|O:control", &ch, &nevents, &otimeout))
-        return NULL;
-
-    if (nevents < 0) {
+    if (maxevents < 0) {
         PyErr_Format(PyExc_ValueError,
             "Length of eventlist must be 0 or positive, got %d",
-            nevents);
+            maxevents);
         return NULL;
     }
 
-    if (otimeout == Py_None || otimeout == NULL) {
+    if (otimeout == Py_None) {
         ptimeoutspec = NULL;
     }
     else {
@@ -2163,8 +2100,8 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)
         ptimeoutspec = &timeoutspec;
     }
 
-    if (ch != NULL && ch != Py_None) {
-        seq = PySequence_Fast(ch, "changelist is not iterable");
+    if (changelist != Py_None) {
+        seq = PySequence_Fast(changelist, "changelist is not iterable");
         if (seq == NULL) {
             return NULL;
         }
@@ -2194,8 +2131,8 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)
     }
 
     /* event list */
-    if (nevents) {
-        evl = PyMem_New(struct kevent, nevents);
+    if (maxevents) {
+        evl = PyMem_New(struct kevent, maxevents);
         if (evl == NULL) {
             PyErr_NoMemory();
             goto error;
@@ -2209,7 +2146,7 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)
         Py_BEGIN_ALLOW_THREADS
         errno = 0;
         gotevents = kevent(self->kqfd, chl, nchanges,
-                           evl, nevents, ptimeoutspec);
+                           evl, maxevents, ptimeoutspec);
         Py_END_ALLOW_THREADS
 
         if (errno != EINTR)
@@ -2263,50 +2200,225 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)
     return NULL;
 }
 
-PyDoc_STRVAR(kqueue_queue_control_doc,
-"control(changelist, max_events[, timeout=None]) -> eventlist\n\
-\n\
-Calls the kernel kevent function.\n\
-- changelist must be an iterable of kevent objects describing the changes\n\
-  to be made to the kernel's watch list or None.\n\
-- max_events lets you specify the maximum number of events that the\n\
-  kernel will return.\n\
-- timeout is the maximum time to wait in seconds, or else None,\n\
-  to wait forever. timeout accepts floats for smaller timeouts, too.");
+static PyGetSetDef kqueue_queue_getsetlist[] = {
+    {"closed", (getter)kqueue_queue_get_closed, NULL,
+     "True if the kqueue handler is closed"},
+    {0},
+};
 
+#endif /* HAVE_KQUEUE */
 
-static PyMethodDef kqueue_queue_methods[] = {
-    {"fromfd",          (PyCFunction)kqueue_queue_fromfd,
-     METH_VARARGS | METH_CLASS, kqueue_queue_fromfd_doc},
-    {"close",           (PyCFunction)kqueue_queue_close,        METH_NOARGS,
-     kqueue_queue_close_doc},
-    {"fileno",          (PyCFunction)kqueue_queue_fileno,       METH_NOARGS,
-     kqueue_queue_fileno_doc},
-    {"control",         (PyCFunction)kqueue_queue_control,
-     METH_VARARGS ,     kqueue_queue_control_doc},
+
+/* ************************************************************************ */
+
+#include "clinic/selectmodule.c.h"
+
+#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
+
+static PyMethodDef poll_methods[] = {
+    SELECT_POLL_REGISTER_METHODDEF
+    SELECT_POLL_MODIFY_METHODDEF
+    SELECT_POLL_UNREGISTER_METHODDEF
+    SELECT_POLL_POLL_METHODDEF
+    {NULL, NULL}           /* sentinel */
+};
+
+static PyTypeObject poll_Type = {
+    /* The ob_type field must be initialized in the module init function
+     * to be portable to Windows without using C++. */
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "select.poll",              /*tp_name*/
+    sizeof(pollObject),         /*tp_basicsize*/
+    0,                          /*tp_itemsize*/
+    /* methods */
+    (destructor)poll_dealloc, /*tp_dealloc*/
+    0,                          /*tp_print*/
+    0,                          /*tp_getattr*/
+    0,                      /*tp_setattr*/
+    0,                          /*tp_reserved*/
+    0,                          /*tp_repr*/
+    0,                          /*tp_as_number*/
+    0,                          /*tp_as_sequence*/
+    0,                          /*tp_as_mapping*/
+    0,                          /*tp_hash*/
+    0,                          /*tp_call*/
+    0,                          /*tp_str*/
+    0,                          /*tp_getattro*/
+    0,                          /*tp_setattro*/
+    0,                          /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT,         /*tp_flags*/
+    0,                          /*tp_doc*/
+    0,                          /*tp_traverse*/
+    0,                          /*tp_clear*/
+    0,                          /*tp_richcompare*/
+    0,                          /*tp_weaklistoffset*/
+    0,                          /*tp_iter*/
+    0,                          /*tp_iternext*/
+    poll_methods,               /*tp_methods*/
+};
+
+#ifdef HAVE_SYS_DEVPOLL_H
+
+static PyMethodDef devpoll_methods[] = {
+    SELECT_DEVPOLL_REGISTER_METHODDEF
+    SELECT_DEVPOLL_MODIFY_METHODDEF
+    SELECT_DEVPOLL_UNREGISTER_METHODDEF
+    SELECT_DEVPOLL_POLL_METHODDEF
+    SELECT_DEVPOLL_CLOSE_METHODDEF
+    SELECT_DEVPOLL_FILENO_METHODDEF
+    {NULL,              NULL}           /* sentinel */
+};
+
+static PyTypeObject devpoll_Type = {
+    /* The ob_type field must be initialized in the module init function
+     * to be portable to Windows without using C++. */
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "select.devpoll",           /*tp_name*/
+    sizeof(devpollObject),      /*tp_basicsize*/
+    0,                          /*tp_itemsize*/
+    /* methods */
+    (destructor)devpoll_dealloc, /*tp_dealloc*/
+    0,                          /*tp_print*/
+    0,                          /*tp_getattr*/
+    0,                          /*tp_setattr*/
+    0,                          /*tp_reserved*/
+    0,                          /*tp_repr*/
+    0,                          /*tp_as_number*/
+    0,                          /*tp_as_sequence*/
+    0,                          /*tp_as_mapping*/
+    0,                          /*tp_hash*/
+    0,                          /*tp_call*/
+    0,                          /*tp_str*/
+    0,                          /*tp_getattro*/
+    0,                          /*tp_setattro*/
+    0,                          /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT,         /*tp_flags*/
+    0,                          /*tp_doc*/
+    0,                          /*tp_traverse*/
+    0,                          /*tp_clear*/
+    0,                          /*tp_richcompare*/
+    0,                          /*tp_weaklistoffset*/
+    0,                          /*tp_iter*/
+    0,                          /*tp_iternext*/
+    devpoll_methods,            /*tp_methods*/
+    0,                          /* tp_members */
+    devpoll_getsetlist,         /* tp_getset */
+};
+
+#endif  /* HAVE_SYS_DEVPOLL_H */
+
+#endif /* HAVE_POLL */
+
+#ifdef HAVE_EPOLL
+
+static PyMethodDef pyepoll_methods[] = {
+    SELECT_EPOLL_FROMFD_METHODDEF
+    SELECT_EPOLL_CLOSE_METHODDEF
+    SELECT_EPOLL_FILENO_METHODDEF
+    SELECT_EPOLL_MODIFY_METHODDEF
+    SELECT_EPOLL_REGISTER_METHODDEF
+    SELECT_EPOLL_UNREGISTER_METHODDEF
+    SELECT_EPOLL_POLL_METHODDEF
+    SELECT_EPOLL___ENTER___METHODDEF
+    SELECT_EPOLL___EXIT___METHODDEF
     {NULL,      NULL},
 };
 
-static PyGetSetDef kqueue_queue_getsetlist[] = {
-    {"closed", (getter)kqueue_queue_get_closed, NULL,
-     "True if the kqueue handler is closed"},
-    {0},
+static PyTypeObject pyEpoll_Type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "select.epoll",                                     /* tp_name */
+    sizeof(pyEpoll_Object),                             /* tp_basicsize */
+    0,                                                  /* tp_itemsize */
+    (destructor)pyepoll_dealloc,                        /* tp_dealloc */
+    0,                                                  /* tp_print */
+    0,                                                  /* tp_getattr */
+    0,                                                  /* tp_setattr */
+    0,                                                  /* tp_reserved */
+    0,                                                  /* tp_repr */
+    0,                                                  /* tp_as_number */
+    0,                                                  /* tp_as_sequence */
+    0,                                                  /* tp_as_mapping */
+    0,                                                  /* tp_hash */
+    0,                                                  /* tp_call */
+    0,                                                  /* tp_str */
+    PyObject_GenericGetAttr,                            /* tp_getattro */
+    0,                                                  /* tp_setattro */
+    0,                                                  /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                                 /* tp_flags */
+    select_epoll__doc__,                                /* tp_doc */
+    0,                                                  /* tp_traverse */
+    0,                                                  /* tp_clear */
+    0,                                                  /* tp_richcompare */
+    0,                                                  /* tp_weaklistoffset */
+    0,                                                  /* tp_iter */
+    0,                                                  /* tp_iternext */
+    pyepoll_methods,                                    /* tp_methods */
+    0,                                                  /* tp_members */
+    pyepoll_getsetlist,                                 /* tp_getset */
+    0,                                                  /* tp_base */
+    0,                                                  /* tp_dict */
+    0,                                                  /* tp_descr_get */
+    0,                                                  /* tp_descr_set */
+    0,                                                  /* tp_dictoffset */
+    0,                                                  /* tp_init */
+    0,                                                  /* tp_alloc */
+    select_epoll,                                       /* tp_new */
+    0,                                                  /* tp_free */
 };
 
-PyDoc_STRVAR(kqueue_queue_doc,
-"Kqueue syscall wrapper.\n\
-\n\
-For example, to start watching a socket for input:\n\
->>> kq = kqueue()\n\
->>> sock = socket()\n\
->>> sock.connect((host, port))\n\
->>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_ADD)], 0)\n\
-\n\
-To wait one second for it to become writeable:\n\
->>> kq.control(None, 1, 1000)\n\
-\n\
-To stop listening:\n\
->>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_DELETE)], 0)");
+#endif /* HAVE_EPOLL */
+
+#ifdef HAVE_KQUEUE
+
+static PyTypeObject kqueue_event_Type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "select.kevent",                                    /* tp_name */
+    sizeof(kqueue_event_Object),                        /* tp_basicsize */
+    0,                                                  /* tp_itemsize */
+    0,                                                  /* tp_dealloc */
+    0,                                                  /* tp_print */
+    0,                                                  /* tp_getattr */
+    0,                                                  /* tp_setattr */
+    0,                                                  /* tp_reserved */
+    (reprfunc)kqueue_event_repr,                        /* tp_repr */
+    0,                                                  /* tp_as_number */
+    0,                                                  /* tp_as_sequence */
+    0,                                                  /* tp_as_mapping */
+    0,                                                  /* tp_hash */
+    0,                                                  /* tp_call */
+    0,                                                  /* tp_str */
+    0,                                                  /* tp_getattro */
+    0,                                                  /* tp_setattro */
+    0,                                                  /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                                 /* tp_flags */
+    kqueue_event_doc,                                   /* tp_doc */
+    0,                                                  /* tp_traverse */
+    0,                                                  /* tp_clear */
+    (richcmpfunc)kqueue_event_richcompare,              /* tp_richcompare */
+    0,                                                  /* tp_weaklistoffset */
+    0,                                                  /* tp_iter */
+    0,                                                  /* tp_iternext */
+    0,                                                  /* tp_methods */
+    kqueue_event_members,                               /* tp_members */
+    0,                                                  /* tp_getset */
+    0,                                                  /* tp_base */
+    0,                                                  /* tp_dict */
+    0,                                                  /* tp_descr_get */
+    0,                                                  /* tp_descr_set */
+    0,                                                  /* tp_dictoffset */
+    (initproc)kqueue_event_init,                        /* tp_init */
+    0,                                                  /* tp_alloc */
+    0,                                                  /* tp_new */
+    0,                                                  /* tp_free */
+};
+
+static PyMethodDef kqueue_queue_methods[] = {
+    SELECT_KQUEUE_FROMFD_METHODDEF
+    SELECT_KQUEUE_CLOSE_METHODDEF
+    SELECT_KQUEUE_FILENO_METHODDEF
+    SELECT_KQUEUE_CONTROL_METHODDEF
+    {NULL,      NULL},
+};
 
 static PyTypeObject kqueue_queue_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
@@ -2329,7 +2441,7 @@ static PyTypeObject kqueue_queue_Type = {
     0,                                                  /* tp_setattro */
     0,                                                  /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT,                                 /* tp_flags */
-    kqueue_queue_doc,                                   /* tp_doc */
+    select_kqueue__doc__,                               /* tp_doc */
     0,                                                  /* tp_traverse */
     0,                                                  /* tp_clear */
     0,                                                  /* tp_richcompare */
@@ -2346,7 +2458,7 @@ static PyTypeObject kqueue_queue_Type = {
     0,                                                  /* tp_dictoffset */
     0,                                                  /* tp_init */
     0,                                                  /* tp_alloc */
-    kqueue_queue_new,                                   /* tp_new */
+    select_kqueue,                                      /* tp_new */
     0,                                                  /* tp_free */
 };
 
@@ -2358,38 +2470,11 @@ static PyTypeObject kqueue_queue_Type = {
 
 /* ************************************************************************ */
 
-PyDoc_STRVAR(select_doc,
-"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
-\n\
-Wait until one or more file descriptors are ready for some kind of I/O.\n\
-The first three arguments are sequences of file descriptors to be waited for:\n\
-rlist -- wait until ready for reading\n\
-wlist -- wait until ready for writing\n\
-xlist -- wait for an ``exceptional condition''\n\
-If only one kind of condition is required, pass [] for the other lists.\n\
-A file descriptor is either a socket or file object, or a small integer\n\
-gotten from a fileno() method call on one of those.\n\
-\n\
-The optional 4th argument specifies a timeout in seconds; it may be\n\
-a floating point number to specify fractions of seconds.  If it is absent\n\
-or None, the call will never time out.\n\
-\n\
-The return value is a tuple of three lists corresponding to the first three\n\
-arguments; each contains the subset of the corresponding file descriptors\n\
-that are ready.\n\
-\n\
-*** IMPORTANT NOTICE ***\n\
-On Windows, only sockets are supported; on Unix, all file\n\
-descriptors can be used.");
 
 static PyMethodDef select_methods[] = {
-    {"select",          select_select,  METH_VARARGS,   select_doc},
-#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
-    {"poll",            select_poll,    METH_NOARGS,    poll_doc},
-#endif /* HAVE_POLL */
-#ifdef HAVE_SYS_DEVPOLL_H
-    {"devpoll",         select_devpoll, METH_NOARGS,    devpoll_doc},
-#endif
+    SELECT_SELECT_METHODDEF
+    SELECT_POLL_METHODDEF
+    SELECT_DEVPOLL_METHODDEF
     {0,         0},     /* sentinel */
 };