[Python-3000-checkins] r61728 - in python/branches/py3k: Doc/ACKS.txt Doc/c-api/import.rst Doc/library/__future__.rst Doc/library/future_builtins.rst Doc/library/python.rst Doc/library/select.rst Doc/license.rst Doc/reference/datamodel.rst Doc/tutorial/datastructures.rst Doc/whatsnew/2.6.rst Lib/csv.py Lib/test/regrtest.py Lib/test/test_epoll.py Lib/test/test_kqueue.py Lib/test/test_poll.py Lib/test/test_signal.py Lib/test/test_threading.py Lib/test/test_urllib2.py Lib/urllib2.py Modules/selectmodule.c configure configure.in pyconfig.h.in

christian.heimes python-3000-checkins at python.org
Sat Mar 22 01:47:36 CET 2008


Author: christian.heimes
Date: Sat Mar 22 01:47:35 2008
New Revision: 61728

Added:
   python/branches/py3k/Doc/library/future_builtins.rst
      - copied unchanged from r61722, python/trunk/Doc/library/future_builtins.rst
   python/branches/py3k/Lib/test/test_epoll.py
      - copied, changed from r61722, python/trunk/Lib/test/test_epoll.py
   python/branches/py3k/Lib/test/test_kqueue.py
      - copied, changed from r61722, python/trunk/Lib/test/test_kqueue.py
Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Doc/ACKS.txt
   python/branches/py3k/Doc/c-api/import.rst
   python/branches/py3k/Doc/library/__future__.rst
   python/branches/py3k/Doc/library/python.rst
   python/branches/py3k/Doc/library/select.rst
   python/branches/py3k/Doc/license.rst
   python/branches/py3k/Doc/reference/datamodel.rst
   python/branches/py3k/Doc/tutorial/datastructures.rst
   python/branches/py3k/Doc/whatsnew/2.6.rst
   python/branches/py3k/Lib/csv.py
   python/branches/py3k/Lib/test/regrtest.py
   python/branches/py3k/Lib/test/test_poll.py
   python/branches/py3k/Lib/test/test_signal.py
   python/branches/py3k/Lib/test/test_threading.py
   python/branches/py3k/Lib/test/test_urllib2.py
   python/branches/py3k/Lib/urllib2.py
   python/branches/py3k/Modules/selectmodule.c
   python/branches/py3k/configure
   python/branches/py3k/configure.in
   python/branches/py3k/pyconfig.h.in
Log:
Merged revisions 61687-61688,61696,61700,61704-61705,61707-61709,61711-61712,61714-61716,61718-61722 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r61687 | jeffrey.yasskin | 2008-03-21 06:02:44 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  Speed up test_signal from ~24s to 4s by avoiding nearly all of the sleep calls.
........
  r61688 | jeffrey.yasskin | 2008-03-21 06:51:37 +0100 (Fri, 21 Mar 2008) | 5 lines
  
  Try to fix test_signal breakages on Linux due to r61687. It appears that at
  least two of the linux build bots aren't leaving zombie processes around for
  os.waitpid to wait for, causing ECHILD errors. This would be a symptom of a bug
  somewhere, but probably not in signal itself.
........
  r61696 | georg.brandl | 2008-03-21 15:32:33 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  Mark the descitems in the tutorial as "noindex" so that :meth: cross-refs don't link to them.
........
  r61700 | georg.brandl | 2008-03-21 18:19:29 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  Fix markup.
........
  r61704 | jeffrey.yasskin | 2008-03-21 19:25:06 +0100 (Fri, 21 Mar 2008) | 3 lines
  
  Try to fix test_signal on FreeBSD. I'm assuming that os.kill is failing to
  raise a signal, but switching to subprocess makes the code cleaner anyway.
........
  r61705 | jeffrey.yasskin | 2008-03-21 19:48:04 +0100 (Fri, 21 Mar 2008) | 7 lines
  
  Speed test_threading up from 14s to .5s, and avoid a deadlock on certain
  failures. The test for enumerate-after-join is now a little less rigorous, but
  the bug it references says the error happened in the first couple iterations,
  so 100 iterations should still be enough.
  
  cProfile was useful for identifying the slow tests here.
........
  r61707 | georg.brandl | 2008-03-21 20:14:38 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  Fix a code block in __future__ docs.
........
  r61708 | georg.brandl | 2008-03-21 20:20:21 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  Add docs for __func__ and __self__ on methods.
........
  r61709 | georg.brandl | 2008-03-21 20:37:57 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  Add docs for print_function and future_builtins. Fixes #2442.
........
  r61711 | georg.brandl | 2008-03-21 20:54:00 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  #2136: allow single quotes in realm spec.
........
  r61712 | georg.brandl | 2008-03-21 21:01:51 +0100 (Fri, 21 Mar 2008) | 3 lines
  
  Issue #2432: give DictReader the dialect and line_num attributes
  advertised in the docs.
........
  r61714 | georg.brandl | 2008-03-21 21:11:46 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  #2358: add py3k warning to sys.exc_clear().
........
  r61715 | georg.brandl | 2008-03-21 21:21:46 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  #2346/#2347: add py3k warning for __methods__ and __members__. Patch by Jack Diederich.
........
  r61716 | georg.brandl | 2008-03-21 21:38:24 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  #2348: add py3k warning for file.softspace.
........
  r61718 | georg.brandl | 2008-03-21 21:55:20 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  #2160: document PyImport_GetImporter.
........
  r61719 | georg.brandl | 2008-03-21 21:55:51 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  Update doc ACKS.
........
  r61720 | steven.bethard | 2008-03-21 22:01:18 +0100 (Fri, 21 Mar 2008) | 1 line
  
  Replace hack in regrtest.py with use of sys.py3kwarning.
........
  r61721 | georg.brandl | 2008-03-21 22:05:03 +0100 (Fri, 21 Mar 2008) | 2 lines
  
  Add missing versionadded tag.
........
  r61722 | christian.heimes | 2008-03-22 00:49:44 +0100 (Sat, 22 Mar 2008) | 3 lines
  
  Applied patch #1657 epoll and kqueue wrappers for the select module
  The patch adds wrappers for the Linux epoll syscalls and the BSD kqueue syscalls. Thanks to Thomas Herve and the Twisted people for their support and help.
  TODO: Finish documentation documentation
........


Modified: python/branches/py3k/Doc/ACKS.txt
==============================================================================
--- python/branches/py3k/Doc/ACKS.txt	(original)
+++ python/branches/py3k/Doc/ACKS.txt	Sat Mar 22 01:47:35 2008
@@ -21,6 +21,7 @@
    * Chris Barker
    * Don Bashford
    * Anthony Baxter
+   * Alexander Belopolsky
    * Bennett Benson
    * Jonathan Black
    * Robin Boerdijk

Modified: python/branches/py3k/Doc/c-api/import.rst
==============================================================================
--- python/branches/py3k/Doc/c-api/import.rst	(original)
+++ python/branches/py3k/Doc/c-api/import.rst	Sat Mar 22 01:47:35 2008
@@ -134,6 +134,19 @@
    ``sys.modules``).  Note that this is a per-interpreter variable.
 
 
+.. cfunction:: PyObject* PyImport_GetImporter(PyObject *path)
+
+   Return an importer object for a :data:`sys.path`/:attr:`pkg.__path__` item
+   *path*, possibly by fetching it from the :data:`sys.path_importer_cache`
+   dict.  If it wasn't yet cached, traverse :data:`sys.path_hooks` until a hook
+   is found that can handle the path item.  Return ``None`` if no hook could;
+   this tells our caller it should fall back to the builtin import mechanism.
+   Cache the result in :data:`sys.path_importer_cache`.  Return a new reference
+   to the importer object.
+
+   .. versionadded:: 2.6
+
+
 .. cfunction:: void _PyImport_Init()
 
    Initialize the import mechanism.  For internal use only.

Modified: python/branches/py3k/Doc/library/__future__.rst
==============================================================================
--- python/branches/py3k/Doc/library/__future__.rst	(original)
+++ python/branches/py3k/Doc/library/__future__.rst	Sat Mar 22 01:47:35 2008
@@ -1,4 +1,3 @@
-
 :mod:`__future__` --- Future statement definitions
 ==================================================
 
@@ -22,8 +21,8 @@
 
 Each statement in :file:`__future__.py` is of the form::
 
-   FeatureName = "_Feature(" OptionalRelease "," MandatoryRelease ","
-                           CompilerFlag ")"
+   FeatureName = _Feature(OptionalRelease, MandatoryRelease,
+                          CompilerFlag)
 
 
 where, normally, *OptionalRelease* is less than *MandatoryRelease*, and both are

Modified: python/branches/py3k/Doc/library/python.rst
==============================================================================
--- python/branches/py3k/Doc/library/python.rst	(original)
+++ python/branches/py3k/Doc/library/python.rst	Sat Mar 22 01:47:35 2008
@@ -14,6 +14,7 @@
 
    sys.rst
    builtins.rst
+   future_builtins.rst
    __main__.rst
    warnings.rst
    contextlib.rst

Modified: python/branches/py3k/Doc/library/select.rst
==============================================================================
--- python/branches/py3k/Doc/library/select.rst	(original)
+++ python/branches/py3k/Doc/library/select.rst	Sat Mar 22 01:47:35 2008
@@ -7,10 +7,12 @@
 
 
 This module provides access to the :cfunc:`select` and :cfunc:`poll` functions
-available in most operating systems.  Note that on Windows, it only works for
-sockets; on other operating systems, it also works for other file types (in
-particular, on Unix, it works on pipes).  It cannot be used on regular files to
-determine whether a file has grown since it was last read.
+available in most operating systems, :cfunc:`epoll` available on Linux 2.5+ and
+:cfunc:`kqueue` available on most BSD.
+Note that on Windows, it only works for sockets; on other operating systems,
+it also works for other file types (in particular, on Unix, it works on pipes).
+It cannot be used on regular files to determine whether a file has grown since
+it was last read.
 
 The module defines the following:
 
@@ -22,6 +24,16 @@
    string, as would be printed by the C function :cfunc:`perror`.
 
 
+.. type:: epoll([sizehint=-1])
+
+   (Only supported on Linux 2.5.44 and newer.)  Returns an edge polling
+   object, which can be used as Edge or Level Triggered interface for I/O
+   events; see section :ref:`epoll-objects` below for the methods supported
+   by epolling objects.
+
+   .. versionadded:: 2.6
+
+
 .. function:: poll()
 
    (Not supported by all operating systems.)  Returns a polling object, which
@@ -30,6 +42,24 @@
    by polling objects.
 
 
+.. type:: kqueue()
+
+   (Only supported on BSD.)  Returns a kernel queue object
+   object; see section :ref:`kqueue-objects` below for the methods supported
+   by kqueue objects.
+
+   .. versionadded:: 2.6
+
+
+.. type:: kqueue(ident, filter=KQ_FILTER_READ, flags=KQ_ADD, fflags=0, data=0, udata=0)
+
+   (Only supported on BSD.)  Returns a kernel event object
+   object; see section :ref:`kevent-objects` below for the methods supported
+   by kqueue objects.
+
+   .. versionadded:: 2.6
+
+
 .. function:: select(iwtd, owtd, ewtd[, timeout])
 
    This is a straightforward interface to the Unix :cfunc:`select` system call.
@@ -67,6 +97,81 @@
       not handle file descriptors that don't originate from WinSock.
 
 
+.. _epoll-objects:
+
+Edge and Level Trigger Polling (epoll) Objects
+----------------------------------------------
+
+   http://linux.die.net/man/4/epoll
+
+   *eventmask*
+
+   +-----------------------+-----------------------------------------------+
+   | Constant              | Meaning                                       |
+   +=======================+===============================================+
+   | :const:`EPOLLIN`      | Available for read                            |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLOUT`     | Available for write                           |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLPRI`     | Urgent data for read                          |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLERR`     | Error condition happend on the assoc. fd      |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLHUP`     | Hang up happend on the assoc. fd              |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLET`      | Set Edge Trigger behavior, the default is     |
+   |                       | Level Trigger behavior                        |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLONESHOT` | Set one-shot behavior. After one event is     |
+   |                       | pulled out, the fd is internally disabled     |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLRDNORM`  | ???                                           |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLRDBAND`  | ???                                           |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLWRNORM`  | ???                                           |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLWRBAND`  | ???                                           |
+   +-----------------------+-----------------------------------------------+
+   | :const:`EPOLLMSG`     | ???                                           |
+   +-----------------------+-----------------------------------------------+
+
+
+.. method:: epoll.close()
+
+   Close the control file descriptor of the epoll object.
+
+
+.. method:: epoll.fileno()
+
+   Return the file descriptor number of the control fd.
+
+
+.. method:: epoll.fromfd(fd)
+
+   Create an epoll object from a given file descriptor.
+
+
+.. method:: epoll.register(fd[, eventmask])
+
+   Register a fd descriptor with the epoll object.
+
+
+.. method:: epoll.modify(fd, eventmask)
+
+   Modify a register file descriptor.
+
+
+.. method:: epoll.unregister(fd)
+
+   Remove a registered file descriptor from the epoll object.
+
+
+.. method:: epoll.poll([timeout=-1[, maxevents=-1]])
+
+   Wait for events. timeout in seconds (float)
+
+
 .. _poll-objects:
 
 Polling Objects
@@ -114,6 +219,16 @@
    the same effect as registering the descriptor exactly once.
 
 
+.. method:: poll.modify(fd, eventmask)
+
+   Modifies an already registered fd. This has the same effect as
+   :meth:`register(fd, eventmask)`.  Attempting to modify a file descriptor
+   that was never registered causes an :exc:`IOError` exception with errno
+   :const:`ENOENT` to be raised.
+
+   .. versionadded:: 2.6
+
+
 .. method:: poll.unregister(fd)
 
    Remove a file descriptor being tracked by a polling object.  Just like the
@@ -137,3 +252,184 @@
    returning. If *timeout* is omitted, negative, or :const:`None`, the call will
    block until there is an event for this poll object.
 
+
+.. _kqueue-objects:
+
+Kqueue Objects
+--------------
+
+.. method:: kqueue.close()
+
+   Close the control file descriptor of the kqueue object.
+
+
+.. method:: kqueue.fileno()
+
+   Return the file descriptor number of the control fd.
+
+
+.. method:: epoll.fromfd(fd)
+
+   Create a kqueue object from a given file descriptor.
+
+
+.. method:: control(changelist, max_events=0[, timeout=None]) -> eventlist
+
+   Low level interface to kevent
+
+   - changelist must be an iterable of kevent object or None
+   - max_events must be 0 or a positive integer
+   - timeout in seconds (floats possible)
+
+
+.. _kevent-objects:
+
+Kevent Objects
+--------------
+
+   http://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
+
+   .. attribute:: ident
+
+   Value used to identify the event. The interpretation depends on the filter
+   but it's usually the file descriptor. In the constructor ident can either
+   be an int or an object with a fileno() function. kevent stores the integer
+   internally.
+
+   .. attribute:: filter
+
+   Name of the kernel filter
+
+   +---------------------------+---------------------------------------------+
+   | Constant                  | Meaning                                     |
+   +===========================+=============================================+
+   | :const:`KQ_FILTER_READ`   | Takes a descriptor and returns whenever     |
+   |                           | there is data available to read             |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_FILTER_WRITE`  | Takes a descriptor and returns whenever     |
+   |                           | there is data available to read             |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_FILTER_AIO`    | AIO requests                                |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_FILTER_VNODE`  | Returns when one or more of the requested   |
+   |                           | events watched in *fflag* occurs            |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_FILTER_PROC`   | Watch for events on a process id            |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_FILTER_NETDEV` | Watch for events on a network device        |
+   |                           | [not available on Mac OS X]                 |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_FILTER_SIGNAL` | Returns whenever the watched signal is      |
+   |                           | delivered to the process                    |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_FILTER_TIMER`  | Establishes an arbitrary timer              |
+   +---------------------------+---------------------------------------------+
+
+   .. attribute:: flags
+
+   Filter action
+
+   +---------------------------+---------------------------------------------+
+   | Constant                  | Meaning                                     |
+   +===========================+=============================================+
+   | :const:`KQ_EV_ADD`        | Adds or modifies an event                   |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_EV_DELETE`     | Removes an event from the queue             |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_EV_ENABLE`     | Permitscontrol() to returns the event       |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_EV_DISABLE`    | Disablesevent                               |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_EV_ONESHOT`    | Removes event after first occurence         |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_EV_CLEAR`      | Reset the state after an event is retrieved |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_EV_SYSFLAGS`   | internal event                              |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_EV_FLAG1`      | internal event                              |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_EV_EOF`        | Filter specific EOF condition               |
+   +---------------------------+---------------------------------------------+
+   | :const:`KQ_EV_ERROR`      | See return values                           |
+   +---------------------------+---------------------------------------------+
+
+
+   .. attribute:: fflags
+
+   Filter specific flags
+
+
+   *:const:`KQ_FILTER_READ` and  :const:`KQ_FILTER_WRITE` filter flags
+
+   +----------------------------+--------------------------------------------+
+   | Constant                   | Meaning                                    |
+   +============================+============================================+
+   | :const:`KQ_NOTE_LOWAT`     | low water mark of a socket buffer          |
+   +----------------------------+--------------------------------------------+
+
+
+   *:const:`KQ_FILTER_VNODE` filter flags*
+
+   +----------------------------+--------------------------------------------+
+   | Constant                   | Meaning                                    |
+   +============================+============================================+
+   | :const:`KQ_NOTE_DELETE`    | *unlink()* was called                      |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_WRITE`     | a write occured                            |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_EXTEND`    | the file was extended                      |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_ATTRIB`    | an attribute was changed                   |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_LINK`      | the link count has changed                 |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_RENAME`    | the file was renamed                       |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_REVOKE`    | access to the file was revoked             |
+   +----------------------------+--------------------------------------------+
+
+
+   *:const:`KQ_FILTER_PROC` filter flags*
+
+   +----------------------------+--------------------------------------------+
+   | Constant                   | Meaning                                    |
+   +============================+============================================+
+   | :const:`KQ_NOTE_EXIT`      | the process has exited                     |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_FORK`      | the process has called *fork()*            |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_EXEC`      | the process has executed a new process     |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_PCTRLMASK` | internal filter flag                       |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_PDATAMASK` | internal filter flag                       |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_TRACK`     | follow a process across *fork()*           |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_CHILD`     | returned on the child process for          |
+   |                            | *NOTE_TRACK*                               |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_TRACKERR`  | unable to attach to a child                |
+   +----------------------------+--------------------------------------------+
+
+   *:const:`KQ_FILTER_NETDEV` filter flags* [not available on Mac OS X]
+
+   +----------------------------+--------------------------------------------+
+   | Constant                   | Meaning                                    |
+   +============================+============================================+
+   | :const:`KQ_NOTE_LINKUP`    | link is up                                 |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_LINKDOWN`  | link is down                               |
+   +----------------------------+--------------------------------------------+
+   | :const:`KQ_NOTE_LINKINV`   | link state is invalid                      |
+   +----------------------------+--------------------------------------------+
+
+
+   .. attribute:: data
+
+   Filter specific data
+
+
+   .. attribute:: udata
+
+   User defined value

Modified: python/branches/py3k/Doc/license.rst
==============================================================================
--- python/branches/py3k/Doc/license.rst	(original)
+++ python/branches/py3k/Doc/license.rst	Sat Mar 22 01:47:35 2008
@@ -599,3 +599,58 @@
    ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
    OF THIS SOFTWARE.
 
+
+test_epoll
+----------
+
+The :mod:`test_epoll` contains the following notice::
+
+  Copyright (c) 2001-2006 Twisted Matrix Laboratories.
+
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Select kqueue
+-------------
+
+The :mod:`select` and contains the following notice for the kqueue interface::
+
+  Copyright (c) 2000 Doug White, 2006 James Knight, 2007 Christian Heimes
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  SUCH DAMAGE.

Modified: python/branches/py3k/Doc/reference/datamodel.rst
==============================================================================
--- python/branches/py3k/Doc/reference/datamodel.rst	(original)
+++ python/branches/py3k/Doc/reference/datamodel.rst	Sat Mar 22 01:47:35 2008
@@ -510,6 +510,10 @@
       An instance method object combines a class, a class instance and any
       callable object (normally a user-defined function).
 
+      .. versionchanged:: 2.6
+         For 3.0 forward-compatibility, :attr:`im_func` is also available as
+         :attr:`__func__`, and :attr:`im_self` as :attr:`__self__`.
+
       .. index::
          single: __func__ (method attribute)
          single: __self__ (method attribute)

Modified: python/branches/py3k/Doc/tutorial/datastructures.rst
==============================================================================
--- python/branches/py3k/Doc/tutorial/datastructures.rst	(original)
+++ python/branches/py3k/Doc/tutorial/datastructures.rst	Sat Mar 22 01:47:35 2008
@@ -83,17 +83,20 @@
 
 
 .. method:: list.append(x)
+   :noindex:
 
    Add an item to the end of the list; equivalent to ``a[len(a):] = [x]``.
 
 
 .. method:: list.extend(L)
+   :noindex:
 
    Extend the list by appending all the items in the given list; equivalent to
    ``a[len(a):] = L``.
 
 
 .. method:: list.insert(i, x)
+   :noindex:
 
    Insert an item at a given position.  The first argument is the index of the
    element before which to insert, so ``a.insert(0, x)`` inserts at the front of
@@ -101,12 +104,14 @@
 
 
 .. method:: list.remove(x)
+   :noindex:
 
    Remove the first item from the list whose value is *x*. It is an error if there
    is no such item.
 
 
 .. method:: list.pop([i])
+   :noindex:
 
    Remove the item at the given position in the list, and return it.  If no index
    is specified, ``a.pop()`` removes and returns the last item in the list.  (The
@@ -116,22 +121,26 @@
 
 
 .. method:: list.index(x)
+   :noindex:
 
    Return the index in the list of the first item whose value is *x*. It is an
    error if there is no such item.
 
 
 .. method:: list.count(x)
+   :noindex:
 
    Return the number of times *x* appears in the list.
 
 
 .. method:: list.sort()
+   :noindex:
 
    Sort the items of the list, in place.
 
 
 .. method:: list.reverse()
+   :noindex:
 
    Reverse the elements of the list, in place.
 

Modified: python/branches/py3k/Doc/whatsnew/2.6.rst
==============================================================================
--- python/branches/py3k/Doc/whatsnew/2.6.rst	(original)
+++ python/branches/py3k/Doc/whatsnew/2.6.rst	Sat Mar 22 01:47:35 2008
@@ -540,7 +540,7 @@
 
 So far we've shown how to specify which field to substitute into the
 resulting string.  The precise formatting used is also controllable by
-adding a colon followed by a format specifier.  For example:
+adding a colon followed by a format specifier.  For example::
 
      # Field 0: left justify, pad to 15 characters
      # Field 1: right justify, pad to 6 characters
@@ -552,7 +552,7 @@
      fmt.format('Banquet', 125) ->
        'Banquet         $   125'
 
-Format specifiers can reference other fields through nesting:
+Format specifiers can reference other fields through nesting::
 
     fmt = '{0:{1}}'
     fmt.format('Invoice #1234', width) ->

Modified: python/branches/py3k/Lib/csv.py
==============================================================================
--- python/branches/py3k/Lib/csv.py	(original)
+++ python/branches/py3k/Lib/csv.py	Sat Mar 22 01:47:35 2008
@@ -72,6 +72,8 @@
         self.restkey = restkey          # key to catch long rows
         self.restval = restval          # default value for short rows
         self.reader = reader(f, dialect, *args, **kwds)
+        self.dialect = dialect
+        self.line_num = 0
 
     def __iter__(self):
         return self
@@ -81,6 +83,7 @@
         if self.fieldnames is None:
             self.fieldnames = row
             row = next(self.reader)
+        self.line_num = self.reader.line_num
 
         # unlike the basic reader, we prefer not to return blanks,
         # because we will typically wind up with a dict full of None

Modified: python/branches/py3k/Lib/test/regrtest.py
==============================================================================
--- python/branches/py3k/Lib/test/regrtest.py	(original)
+++ python/branches/py3k/Lib/test/regrtest.py	Sat Mar 22 01:47:35 2008
@@ -873,10 +873,12 @@
         test_dl
         test_fcntl
         test_fork1
+        test_epoll
         test_gdbm
         test_grp
         test_ioctl
         test_largefile
+        test_kqueue
         test_mhlib
         test_openpty
         test_ossaudiodev
@@ -897,6 +899,7 @@
         test_curses
         test_dl
         test_largefile
+        test_kqueue
         test_ossaudiodev
         """,
    'mac':
@@ -912,10 +915,12 @@
         test_dl
         test_fcntl
         test_fork1
+        test_epoll
         test_grp
         test_ioctl
         test_largefile
         test_locale
+        test_kqueue
         test_mmap
         test_openpty
         test_ossaudiodev
@@ -933,7 +938,9 @@
         """
         test_bsddb
         test_dl
+        test_epoll
         test_largefile
+        test_kqueue
         test_minidom
         test_openpty
         test_pyexpat
@@ -944,7 +951,9 @@
         """
         test_bsddb
         test_dl
+        test_epoll
         test_largefile
+        test_kqueue
         test_minidom
         test_openpty
         test_pyexpat
@@ -957,9 +966,11 @@
         test_bsddb
         test_dl
         test_fork1
+        test_epoll
         test_gettext
         test_largefile
         test_locale
+        test_kqueue
         test_minidom
         test_openpty
         test_pyexpat
@@ -977,9 +988,11 @@
         test_bsddb
         test_bsddb3
         test_curses
+        test_epoll
         test_gdbm
         test_largefile
         test_locale
+        test_minidom
         test_ossaudiodev
         test_poll
         """,
@@ -988,6 +1001,8 @@
         test_bsddb
         test_curses
         test_dbm
+        test_epoll
+        test_kqueue
         test_gdbm
         test_gzip
         test_openpty
@@ -999,10 +1014,12 @@
         test_bsddb
         test_curses
         test_dl
+        test_epoll
         test_gdbm
         test_gzip
         test_largefile
         test_locale
+        test_kqueue
         test_minidom
         test_openpty
         test_pyexpat
@@ -1015,8 +1032,10 @@
         test_curses
         test_dl
         test_gdbm
+        test_epoll
         test_largefile
         test_locale
+        test_kqueue
         test_mhlib
         test_mmap
         test_poll
@@ -1027,7 +1046,9 @@
         test_bsddb3
         test_curses
         test_dbm
+        test_epoll
         test_ioctl
+        test_kqueue
         test_largefile
         test_locale
         test_ossaudiodev
@@ -1040,6 +1061,8 @@
         test_commands
         test_curses
         test_dl
+        test_epoll
+        test_kqueue
         test_largefile
         test_mhlib
         test_mmap
@@ -1053,6 +1076,7 @@
         """
         test_bsddb
         test_bsddb3
+        test_epoll
         test_gdbm
         test_locale
         test_ossaudiodev
@@ -1069,8 +1093,10 @@
         test_bsddb3
         test_bz2
         test_dl
+        test_epoll
         test_gdbm
         test_gzip
+        test_kqueue
         test_ossaudiodev
         test_tcl
         test_zipimport
@@ -1082,6 +1108,7 @@
         test_bsddb3
         test_ctypes
         test_dl
+        test_epoll
         test_gdbm
         test_locale
         test_normalization
@@ -1096,6 +1123,7 @@
         test_ctypes
         test_curses
         test_dl
+        test_epoll
         test_gdbm
         test_locale
         test_ossaudiodev

Copied: python/branches/py3k/Lib/test/test_epoll.py (from r61722, python/trunk/Lib/test/test_epoll.py)
==============================================================================
--- python/trunk/Lib/test/test_epoll.py	(original)
+++ python/branches/py3k/Lib/test/test_epoll.py	Sat Mar 22 01:47:35 2008
@@ -51,7 +51,7 @@
         client.setblocking(False)
         try:
             client.connect(('127.0.0.1', self.serverSocket.getsockname()[1]))
-        except socket.error, e:
+        except socket.error as e:
             self.assertEquals(e.args[0], errno.EINPROGRESS)
         else:
             raise AssertionError("Connect should have raised EINPROGRESS")
@@ -63,7 +63,7 @@
     def test_create(self):
         try:
             ep = select.epoll(16)
-        except OSError, e:
+        except OSError as e:
             raise AssertionError(str(e))
         self.assert_(ep.fileno() > 0, ep.fileno())
         self.assert_(not ep.closed)
@@ -106,7 +106,7 @@
         ep.close()
         try:
             ep2.poll(1, 4)
-        except IOError, e:
+        except IOError as e:
             self.failUnlessEqual(e.args[0], errno.EBADF, e)
         else:
             self.fail("epoll on closed fd didn't raise EBADF")
@@ -138,8 +138,8 @@
         then = time.time()
         self.failIf(events)
 
-        client.send("Hello!")
-        server.send("world!!!")
+        client.send(b"Hello!")
+        server.send(b"world!!!")
 
         now = time.time()
         events = ep.poll(1, 4)

Copied: python/branches/py3k/Lib/test/test_kqueue.py (from r61722, python/trunk/Lib/test/test_kqueue.py)
==============================================================================
--- python/trunk/Lib/test/test_kqueue.py	(original)
+++ python/branches/py3k/Lib/test/test_kqueue.py	Sat Mar 22 01:47:35 2008
@@ -78,7 +78,7 @@
         client.setblocking(False)
         try:
             client.connect(('127.0.0.1', serverSocket.getsockname()[1]))
-        except socket.error, e:
+        except socket.error as e:
             self.assertEquals(e.args[0], errno.EINPROGRESS)
         else:
             #raise AssertionError("Connect should have raised EINPROGRESS")
@@ -117,8 +117,8 @@
             (client.fileno(), select.KQ_FILTER_WRITE, flags),
             (server.fileno(), select.KQ_FILTER_WRITE, flags)])
 
-        client.send("Hello!")
-        server.send("world!!!")
+        client.send(b"Hello!")
+        server.send(b"world!!!")
 
         events = kq.control(None, 4, 1)
         # We may need to call it several times

Modified: python/branches/py3k/Lib/test/test_poll.py
==============================================================================
--- python/branches/py3k/Lib/test/test_poll.py	(original)
+++ python/branches/py3k/Lib/test/test_poll.py	Sat Mar 22 01:47:35 2008
@@ -34,7 +34,8 @@
 
         for i in range(NUM_PIPES):
             rd, wr = os.pipe()
-            p.register(rd, select.POLLIN)
+            p.register(rd)
+            p.modify(rd, select.POLLIN)
             p.register(wr, select.POLLOUT)
             readers.append(rd)
             writers.append(wr)

Modified: python/branches/py3k/Lib/test/test_signal.py
==============================================================================
--- python/branches/py3k/Lib/test/test_signal.py	(original)
+++ python/branches/py3k/Lib/test/test_signal.py	Sat Mar 22 01:47:35 2008
@@ -1,6 +1,11 @@
 import unittest
 from test import test_support
+from contextlib import closing, nested
+import pickle
+import select
 import signal
+import subprocess
+import traceback
 import sys, os, time, errno
 
 if sys.platform[:3] in ('win', 'os2') or sys.platform == 'riscos':
@@ -11,39 +16,19 @@
 class HandlerBCalled(Exception):
     pass
 
-class InterProcessSignalTests(unittest.TestCase):
-    MAX_DURATION = 20   # Entire test should last at most 20 sec.
 
-    # Set up a child to send signals to us (the parent) after waiting
-    # long enough to receive the alarm.  It seems we miss the alarm
-    # for some reason.  This will hopefully stop the hangs on
-    # Tru64/Alpha.  Alas, it doesn't.  Tru64 appears to miss all the
-    # signals at times, or seemingly random subsets of them, and
-    # nothing done in force_test_exit so far has actually helped.
-    def spawn_force_test_exit_process(self, parent_pid):
-        # Sigh, both imports seem necessary to avoid errors.
-        import os
-        fork_pid = os.fork()
-        if fork_pid:
-            # In parent.
-            return fork_pid
+def exit_subprocess():
+    """Use os._exit(0) to exit the current subprocess.
+
+    Otherwise, the test catches the SystemExit and continues executing
+    in parallel with the original test, so you wind up with an
+    exponential number of tests running concurrently.
+    """
+    os._exit(0)
 
-        # In child.
-        import os, time
-        try:
-            # Wait 5 seconds longer than the expected alarm to give enough
-            # time for the normal sequence of events to occur.  This is
-            # just a stop-gap to try to prevent the test from hanging.
-            time.sleep(self.MAX_DURATION + 5)
-            print("  child should not have to kill parent",
-                  file=sys.__stdout__)
-            for signame in "SIGHUP", "SIGUSR1", "SIGUSR2", "SIGALRM":
-                os.kill(parent_pid, getattr(signal, signame))
-                print("    child sent", signame, "to",
-                      parent_pid, file=sys.__stdout__)
-                time.sleep(1)
-        finally:
-            os._exit(0)
+
+class InterProcessSignalTests(unittest.TestCase):
+    MAX_DURATION = 20   # Entire test should last at most 20 sec.
 
     def handlerA(self, *args):
         self.a_called = True
@@ -56,121 +41,133 @@
             print("handlerB invoked", args)
         raise HandlerBCalled(*args)
 
-    def test_main(self):
-        self.assertEquals(signal.getsignal(signal.SIGHUP), self.handlerA)
-        self.assertEquals(signal.getsignal(signal.SIGUSR1), self.handlerB)
-        self.assertEquals(signal.getsignal(signal.SIGUSR2), signal.SIG_IGN)
-        self.assertEquals(signal.getsignal(signal.SIGALRM),
-                          signal.default_int_handler)
-
-        # Launch an external script to send us signals.
-        # We expect the external script to:
-        #    send HUP, which invokes handlerA to set a_called
-        #    send USR1, which invokes handlerB to set b_called and raise
-        #               HandlerBCalled
-        #    send USR2, which is ignored
-        #
-        # Then we expect the alarm to go off, and its handler raises
-        # KeyboardInterrupt, finally getting us out of the loop.
+    def wait(self, child):
+        """Wait for child to finish, ignoring EINTR."""
+        while True:
+            try:
+                child.wait()
+                return
+            except OSError as e:
+                if e.errno != errno.EINTR:
+                    raise
 
-        if test_support.verbose:
-            verboseflag = '-x'
-        else:
-            verboseflag = '+x'
+    def run_test(self):
+        # Install handlers. This function runs in a sub-process, so we
+        # don't worry about re-setting the default handlers.
+        signal.signal(signal.SIGHUP, self.handlerA)
+        signal.signal(signal.SIGUSR1, self.handlerB)
+        signal.signal(signal.SIGUSR2, signal.SIG_IGN)
+        signal.signal(signal.SIGALRM, signal.default_int_handler)
+
+        # Variables the signals will modify:
+        self.a_called = False
+        self.b_called = False
 
-        pid = self.pid
+        # Let the sub-processes know who to send signals to.
+        pid = os.getpid()
         if test_support.verbose:
             print("test runner's pid is", pid)
 
-        # Shell script that will send us asynchronous signals
-        script = """
-         (
-                set %(verboseflag)s
-                sleep 2
-                kill -HUP %(pid)d
-                sleep 2
-                kill -USR1 %(pid)d
-                sleep 2
-                kill -USR2 %(pid)d
-         ) &
-        """ % vars()
-
-        signal.alarm(self.MAX_DURATION)
-
-        handler_b_exception_raised = False
+        child = subprocess.Popen(['kill', '-HUP', str(pid)])
+        self.wait(child)
+        self.assertTrue(self.a_called)
+        self.assertFalse(self.b_called)
+        self.a_called = False
 
-        os.system(script)
         try:
+            child = subprocess.Popen(['kill', '-USR1', str(pid)])
+            # This wait should be interrupted by the signal's exception.
+            self.wait(child)
+            self.fail('HandlerBCalled exception not thrown')
+        except HandlerBCalled:
+            self.assertTrue(self.b_called)
+            self.assertFalse(self.a_called)
             if test_support.verbose:
-                print("starting pause() loop...")
-            while 1:
-                try:
-                    if test_support.verbose:
-                        print("call pause()...")
-                    signal.pause()
-                    if test_support.verbose:
-                        print("pause() returned")
-                except HandlerBCalled:
-                    handler_b_exception_raised = True
-                    if test_support.verbose:
-                        print("HandlerBCalled exception caught")
+                print("HandlerBCalled exception caught")
 
+        child = subprocess.Popen(['kill', '-USR2', str(pid)])
+        self.wait(child)  # Nothing should happen.
+
+        try:
+            signal.alarm(1)
+            # The race condition in pause doesn't matter in this case,
+            # since alarm is going to raise a KeyboardException, which
+            # will skip the call.
+            signal.pause()
         except KeyboardInterrupt:
             if test_support.verbose:
                 print("KeyboardInterrupt (the alarm() went off)")
-
-        self.assert_(self.a_called)
-        self.assert_(self.b_called)
-        self.assert_(handler_b_exception_raised)
-
-    def setUp(self):
-        # Install handlers.
-        self.hup = signal.signal(signal.SIGHUP, self.handlerA)
-        self.usr1 = signal.signal(signal.SIGUSR1, self.handlerB)
-        self.usr2 = signal.signal(signal.SIGUSR2, signal.SIG_IGN)
-        self.alrm = signal.signal(signal.SIGALRM,
-                                  signal.default_int_handler)
-        self.a_called = False
-        self.b_called = False
-        self.pid = os.getpid()
-        self.fork_pid = self.spawn_force_test_exit_process(self.pid)
-
-    def tearDown(self):
-        # Forcibly kill the child we created to ping us if there was a
-        # test error.
-        try:
-            # Make sure we don't kill ourself if there was a fork
-            # error.
-            if self.fork_pid > 0:
-                os.kill(self.fork_pid, signal.SIGKILL)
         except:
-            # If the child killed us, it has probably exited.  Killing
-            # a non-existent process will raise an error which we
-            # don't care about.
-            pass
-
-        # Restore handlers.
-        signal.alarm(0) # cancel alarm in case we died early
-        signal.signal(signal.SIGHUP, self.hup)
-        signal.signal(signal.SIGUSR1, self.usr1)
-        signal.signal(signal.SIGUSR2, self.usr2)
-        signal.signal(signal.SIGALRM, self.alrm)
+            self.fail('Some other exception woke us from pause: %s' %
+                      traceback.format_exc())
+        else:
+            self.fail('pause returned of its own accord')
+
+    def test_main(self):
+        # This function spawns a child process to insulate the main
+        # test-running process from all the signals. It then
+        # communicates with that child process over a pipe and
+        # re-raises information about any exceptions the child
+        # throws. The real work happens in self.run_test().
+        os_done_r, os_done_w = os.pipe()
+        with nested(closing(os.fdopen(os_done_r, 'rb')),
+                    closing(os.fdopen(os_done_w, 'wb'))) as (done_r, done_w):
+            child = os.fork()
+            if child == 0:
+                # In the child process; run the test and report results
+                # through the pipe.
+                try:
+                    done_r.close()
+                    # Have to close done_w again here because
+                    # exit_subprocess() will skip the enclosing with block.
+                    with closing(done_w):
+                        try:
+                            self.run_test()
+                        except:
+                            pickle.dump(traceback.format_exc(), done_w)
+                        else:
+                            pickle.dump(None, done_w)
+                except:
+                    print('Uh oh, raised from pickle.')
+                    traceback.print_exc()
+                finally:
+                    exit_subprocess()
+
+            done_w.close()
+            # Block for up to MAX_DURATION seconds for the test to finish.
+            r, w, x = select.select([done_r], [], [], self.MAX_DURATION)
+            if done_r in r:
+                tb = pickle.load(done_r)
+                if tb:
+                    self.fail(tb)
+            else:
+                os.kill(child, signal.SIGKILL)
+                self.fail('Test deadlocked after %d seconds.' %
+                          self.MAX_DURATION)
 
 
 class BasicSignalTests(unittest.TestCase):
+    def trivial_signal_handler(self, *args):
+        pass
+
     def test_out_of_range_signal_number_raises_error(self):
         self.assertRaises(ValueError, signal.getsignal, 4242)
 
-        def trivial_signal_handler(*args):
-            pass
-
         self.assertRaises(ValueError, signal.signal, 4242,
-                          trivial_signal_handler)
+                          self.trivial_signal_handler)
 
     def test_setting_signal_handler_to_none_raises_error(self):
         self.assertRaises(TypeError, signal.signal,
                           signal.SIGUSR1, None)
 
+    def test_getsignal(self):
+        hup = signal.signal(signal.SIGHUP, self.trivial_signal_handler)
+        self.assertEquals(signal.getsignal(signal.SIGHUP),
+                          self.trivial_signal_handler)
+        signal.signal(signal.SIGHUP, hup)
+        self.assertEquals(signal.getsignal(signal.SIGHUP), hup)
+
+
 class WakeupSignalTests(unittest.TestCase):
     TIMEOUT_FULL = 10
     TIMEOUT_HALF = 5
@@ -233,7 +230,7 @@
                 os.kill(ppid, self.signum)
                 time.sleep(0.2)
             finally:
-                os._exit(0)
+                exit_subprocess()
 
         try:
             os.close(w)

Modified: python/branches/py3k/Lib/test/test_threading.py
==============================================================================
--- python/branches/py3k/Lib/test/test_threading.py	(original)
+++ python/branches/py3k/Lib/test/test_threading.py	Sat Mar 22 01:47:35 2008
@@ -30,32 +30,26 @@
         self.nrunning = nrunning
 
     def run(self):
-        delay = random.random() * 2
+        delay = random.random() / 10000.0
         if verbose:
             print('task', self.getName(), 'will run for', delay, 'sec')
 
-        self.sema.acquire()
+        with self.sema:
+            with self.mutex:
+                self.nrunning.inc()
+                if verbose:
+                    print(self.nrunning.get(), 'tasks are running')
+                self.testcase.assert_(self.nrunning.get() <= 3)
 
-        self.mutex.acquire()
-        self.nrunning.inc()
-        if verbose:
-            print(self.nrunning.get(), 'tasks are running')
-        self.testcase.assert_(self.nrunning.get() <= 3)
-        self.mutex.release()
-
-        time.sleep(delay)
-        if verbose:
-            print('task', self.getName(), 'done')
-
-        self.mutex.acquire()
-        self.nrunning.dec()
-        self.testcase.assert_(self.nrunning.get() >= 0)
-        if verbose:
-            print(self.getName(), 'is finished.', self.nrunning.get(), \
-                  'tasks are running')
-        self.mutex.release()
-
-        self.sema.release()
+            time.sleep(delay)
+            if verbose:
+                print('task', self.getName(), 'done')
+            with self.mutex:
+                self.nrunning.dec()
+                self.testcase.assert_(self.nrunning.get() >= 0)
+                if verbose:
+                    print('%s is finished. %d tasks are running' %
+                        self.getName(), self.nrunning.get())
 
 class ThreadTests(unittest.TestCase):
 
@@ -218,6 +212,10 @@
         rc = subprocess.call([sys.executable, "-c", """if 1:
             import ctypes, sys, time, thread
 
+            # This lock is used as a simple event variable.
+            ready = thread.allocate_lock()
+            ready.acquire()
+
             # Module globals are cleared before __del__ is run
             # So we save the functions in class dict
             class C:
@@ -229,10 +227,11 @@
 
             def waitingThread():
                 x = C()
+                ready.release()
                 time.sleep(100)
 
             thread.start_new_thread(waitingThread, ())
-            time.sleep(1) # be sure the other thread is waiting
+            ready.acquire()  # Be sure the other thread is waiting.
             sys.exit(42)
             """])
         self.assertEqual(rc, 42)
@@ -242,7 +241,6 @@
         # threading.enumerate() after it has been join()ed.
         enum = threading.enumerate
         old_interval = sys.getcheckinterval()
-        sys.setcheckinterval(1)
         try:
             for i in range(1, 1000):
                 t = threading.Thread(target=lambda: None)

Modified: python/branches/py3k/Lib/test/test_urllib2.py
==============================================================================
--- python/branches/py3k/Lib/test/test_urllib2.py	(original)
+++ python/branches/py3k/Lib/test/test_urllib2.py	Sat Mar 22 01:47:35 2008
@@ -906,13 +906,14 @@
         self.assertEqual([(handlers[0], "http_open")],
                          [tup[0:2] for tup in o.calls])
 
-    def test_basic_auth(self):
+    def test_basic_auth(self, quote_char='"'):
         opener = OpenerDirector()
         password_manager = MockPasswordManager()
         auth_handler = urllib2.HTTPBasicAuthHandler(password_manager)
         realm = "ACME Widget Store"
         http_handler = MockHTTPHandler(
-            401, 'WWW-Authenticate: Basic realm="%s"\r\n\r\n' % realm)
+            401, 'WWW-Authenticate: Basic realm=%s%s%s\r\n\r\n' %
+            (quote_char, realm, quote_char) )
         opener.add_handler(auth_handler)
         opener.add_handler(http_handler)
         self._test_basic_auth(opener, auth_handler, "Authorization",
@@ -921,6 +922,9 @@
                               "http://acme.example.com/protected",
                               )
 
+    def test_basic_auth_with_single_quoted_realm(self):
+        self.test_basic_auth(quote_char="'")
+
     def test_proxy_basic_auth(self):
         opener = OpenerDirector()
         ph = urllib2.ProxyHandler(dict(http="proxy.example.com:3128"))

Modified: python/branches/py3k/Lib/urllib2.py
==============================================================================
--- python/branches/py3k/Lib/urllib2.py	(original)
+++ python/branches/py3k/Lib/urllib2.py	Sat Mar 22 01:47:35 2008
@@ -777,7 +777,10 @@
     # XXX this allows for multiple auth-schemes, but will stupidly pick
     # the last one with a realm specified.
 
-    rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', re.I)
+    # allow for double- and single-quoted realm values
+    # (single quotes are a violation of the RFC, but appear in the wild)
+    rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+'
+                    'realm=(["\'])(.*?)\\2', re.I)
 
     # XXX could pre-emptively send auth info already accepted (RFC 2617,
     # end of section 2, and section 1.2 immediately after "credentials"
@@ -797,7 +800,7 @@
         if authreq:
             mo = AbstractBasicAuthHandler.rx.search(authreq)
             if mo:
-                scheme, realm = mo.groups()
+                scheme, quote, realm = mo.groups()
                 if scheme.lower() == 'basic':
                     return self.retry_http_basic_auth(host, req, realm)
 

Modified: python/branches/py3k/Modules/selectmodule.c
==============================================================================
--- python/branches/py3k/Modules/selectmodule.c	(original)
+++ python/branches/py3k/Modules/selectmodule.c	Sat Mar 22 01:47:35 2008
@@ -5,6 +5,7 @@
 */
 
 #include "Python.h"
+#include <structmember.h>
 
 #ifdef __APPLE__
     /* Perform runtime testing for a broken poll on OSX to make it easier
@@ -53,7 +54,6 @@
 #  endif
 #endif
 
-
 static PyObject *SelectError;
 
 /* list of Python objects and their file descriptor */
@@ -238,7 +238,7 @@
 		seconds = (long)timeout;
 		timeout = timeout - (double)seconds;
 		tv.tv_sec = seconds;
-		tv.tv_usec = (long)(timeout*1000000.0);
+		tv.tv_usec = (long)(timeout * 1E6);
 		tvp = &tv;
 	}
 
@@ -402,11 +402,59 @@
 		return NULL;
 
 	self->ufd_uptodate = 0;
-		       
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
 
+PyDoc_STRVAR(poll_modify_doc,
+"modify(fd, eventmask) -> None\n\n\
+Modify an already register 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");
+
+static PyObject *
+poll_modify(pollObject *self, PyObject *args)
+{
+	PyObject *o, *key, *value;
+	int fd, events;
+	int err;
+
+	if (!PyArg_ParseTuple(args, "Oi:modify", &o, &events)) {
+		return NULL;
+	}
+  
+	fd = PyObject_AsFileDescriptor(o);
+	if (fd == -1) return NULL;
+
+	/* Modify registered fd */
+	key = PyLong_FromLong(fd);
+	if (key == NULL)
+		return NULL;
+	if (PyDict_GetItem(self->dict, key) == NULL) {
+		errno = ENOENT;
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+	value = PyLong_FromLong(events);
+	if (value == NULL) {
+		Py_DECREF(key);
+		return NULL;
+	}
+	err = PyDict_SetItem(self->dict, key, value);
+	Py_DECREF(key);
+	Py_DECREF(value);
+	if (err < 0)
+		return NULL;
+
+	self->ufd_uptodate = 0;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
 PyDoc_STRVAR(poll_unregister_doc,
 "unregister(fd) -> None\n\n\
 Remove a file descriptor being tracked by the polling object.");
@@ -480,9 +528,9 @@
 			return NULL;
 
 	/* call poll() */
-	Py_BEGIN_ALLOW_THREADS;
+	Py_BEGIN_ALLOW_THREADS
 	poll_result = poll(self->ufds, self->ufd_len, timeout);
-	Py_END_ALLOW_THREADS;
+	Py_END_ALLOW_THREADS
  
 	if (poll_result < 0) {
 		PyErr_SetFromErrno(SelectError);
@@ -540,7 +588,9 @@
 static PyMethodDef poll_methods[] = {
 	{"register",	(PyCFunction)poll_register,	
 	 METH_VARARGS,  poll_register_doc},
-	{"unregister",	(PyCFunction)poll_unregister,	
+	{"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},
@@ -643,6 +693,1007 @@
 
 #endif /* HAVE_POLL */
 
+#ifdef HAVE_EPOLL
+/* **************************************************************************
+ *                      epoll interface for Linux 2.6
+ *
+ * Written by Christian Heimes
+ * Inspired by Twisted's _epoll.pyx and select.poll()
+ */
+
+#ifdef HAVE_SYS_EPOLL_H
+#include <sys/epoll.h>
+#endif
+
+typedef struct {
+	PyObject_HEAD
+	SOCKET epfd;			/* epoll control file descriptor */
+} pyEpoll_Object;
+
+static PyTypeObject pyEpoll_Type;
+#define pyepoll_CHECK(op) (PyObject_TypeCheck((op), &pyEpoll_Type))
+
+static PyObject *
+pyepoll_err_closed(void)
+{
+	PyErr_SetString(PyExc_ValueError, "I/O operation on closed epoll fd");
+	return NULL;
+}
+
+static int
+pyepoll_internal_close(pyEpoll_Object *self)
+{
+	int save_errno = 0;
+	if (self->epfd >= 0) {
+		int epfd = self->epfd;
+		self->epfd = -1;
+		Py_BEGIN_ALLOW_THREADS
+		if (close(epfd) < 0)
+			save_errno = errno;
+		Py_END_ALLOW_THREADS
+	}
+	return save_errno;
+}
+
+static PyObject *
+newPyEpoll_Object(PyTypeObject *type, int sizehint, SOCKET fd)
+{
+	pyEpoll_Object *self;
+	
+	if (sizehint == -1) {
+		sizehint = FD_SETSIZE-1;
+	}
+	else if (sizehint < 1) {
+		PyErr_Format(PyExc_ValueError,
+			     "sizehint must be greater zero, got %d",
+			     sizehint);
+		return NULL;
+	}
+
+	assert(type != NULL && type->tp_alloc != NULL);
+	self = (pyEpoll_Object *) type->tp_alloc(type, 0);
+	if (self == NULL)
+		return NULL;
+
+	if (fd == -1) {
+		Py_BEGIN_ALLOW_THREADS
+		self->epfd = epoll_create(sizehint);
+		Py_END_ALLOW_THREADS
+	}
+	else {
+		self->epfd = fd;
+	}
+	if (self->epfd < 0) {
+		Py_DECREF(self);
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+	return (PyObject *)self;
+}
+
+
+static PyObject *
+pyepoll_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	int sizehint = -1;
+	static char *kwlist[] = {"sizehint", NULL};
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:epoll", kwlist,
+					 &sizehint))
+		return NULL;
+
+	return newPyEpoll_Object(type, sizehint, -1);
+}
+
+
+static void
+pyepoll_dealloc(pyEpoll_Object *self)
+{
+	(void)pyepoll_internal_close(self);
+	Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject*
+pyepoll_close(pyEpoll_Object *self)
+{
+	errno = pyepoll_internal_close(self);
+	if (errno < 0) {
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+	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)
+{
+	if (self->epfd < 0)
+		Py_RETURN_TRUE;
+	else
+		Py_RETURN_FALSE;
+}
+
+static PyObject*
+pyepoll_fileno(pyEpoll_Object *self)
+{
+	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;
+
+	if (!PyArg_ParseTuple(args, "i:fromfd", &fd))
+		return NULL;
+
+	return newPyEpoll_Object((PyTypeObject*)cls, -1, 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)
+{
+	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:
+		ev.events = events;
+		ev.data.fd = fd;
+		Py_BEGIN_ALLOW_THREADS
+		result = epoll_ctl(epfd, op, fd, &ev);
+		Py_END_ALLOW_THREADS
+		break;
+	    case EPOLL_CTL_DEL:
+		/* In kernel versions before 2.6.9, the EPOLL_CTL_DEL
+		 * operation required a non-NULL pointer in event, even
+		 * though this argument is ignored. */
+		Py_BEGIN_ALLOW_THREADS
+		result = epoll_ctl(epfd, op, fd, &ev);
+		if (errno == EBADF) {
+			/* fd already closed */
+			result = 0;
+			errno = 0;
+		}
+		Py_END_ALLOW_THREADS
+		break;
+	    default:
+		result = -1;
+		errno = EINVAL;
+	}
+
+	if (result < 0) {
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+	Py_RETURN_NONE;
+}
+
+static PyObject *
+pyepoll_register(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
+{
+	PyObject *pfd;
+	unsigned int events = EPOLLIN | EPOLLOUT | EPOLLPRI;
+	static char *kwlist[] = {"fd", "eventmask", NULL};
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|I:register", kwlist,
+					 &pfd, &events)) {
+		return NULL;
+	}
+
+	return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_ADD, pfd, events);
+}
+
+PyDoc_STRVAR(pyepoll_register_doc,
+"register(fd[, eventmask]) -> bool\n\
+\n\
+Registers a new fd or modifies an already registered fd. register returns\n\
+True if a new fd was registered or False if the event mask for fd was modified.\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 EPOLL_IN | EPOLL_OUT | EPOLL_PRI.\n\
+\n\
+The epoll interface supports all file descriptors that support poll.");
+
+static PyObject *
+pyepoll_modify(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
+{
+	PyObject *pfd;
+	unsigned int events;
+	static char *kwlist[] = {"fd", "eventmask", NULL};
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "OI:modify", kwlist,
+					 &pfd, &events)) {
+		return NULL;
+	}
+
+	return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_MOD, pfd, events);
+}
+
+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");
+
+static PyObject *
+pyepoll_unregister(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
+{
+	PyObject *pfd;
+	static char *kwlist[] = {"fd", NULL};
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:unregister", kwlist,
+					 &pfd)) {
+		return NULL;
+	}
+
+	return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_DEL, pfd, 0);
+}
+
+PyDoc_STRVAR(pyepoll_unregister_doc,
+"unregister(fd) -> None\n\
+\n\
+fd is the target file descriptor of the operation.");
+
+static PyObject *
+pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
+{
+	double dtimeout = -1.;
+	int timeout;
+	int maxevents = -1;
+	int nfds, i;
+	PyObject *elist = NULL, *etuple = NULL;
+	struct epoll_event *evs = NULL;
+	static char *kwlist[] = {"timeout", "maxevents", NULL};
+
+	if (self->epfd < 0)
+		return pyepoll_err_closed();
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|di:poll", kwlist,
+					 &dtimeout, &maxevents)) {
+		return NULL;
+	}
+
+	if (dtimeout < 0) {
+		timeout = -1;
+	}
+	else if (dtimeout * 1000.0 > INT_MAX) {
+		PyErr_SetString(PyExc_OverflowError,
+				"timeout is too large");
+	}
+	else {
+		timeout = (int)(dtimeout * 1000.0);
+	}
+
+	if (maxevents == -1) {
+		maxevents = FD_SETSIZE-1;
+	}
+	else if (maxevents < 1) {
+		PyErr_Format(PyExc_ValueError,
+			     "maxevents must be greater than 0, got %d",
+			     maxevents);
+		return NULL;
+	}
+
+	evs = PyMem_New(struct epoll_event, maxevents);
+	if (evs == NULL) {
+		Py_DECREF(self);
+		PyErr_NoMemory();
+		return NULL;
+	}
+
+	Py_BEGIN_ALLOW_THREADS
+	nfds = epoll_wait(self->epfd, evs, maxevents, timeout);
+	Py_END_ALLOW_THREADS
+	if (nfds < 0) {
+		PyErr_SetFromErrno(PyExc_IOError);
+		goto error;
+	}
+
+	elist = PyList_New(nfds);
+	if (elist == NULL) {
+		goto error;
+	}
+
+	for (i = 0; i < nfds; i++) {
+		etuple = Py_BuildValue("iI", evs[i].data.fd,
+				       evs[i].events);
+		if (etuple == NULL) {
+			goto error;
+		}
+		PyList_SET_ITEM(elist, i, etuple);
+	}
+
+	if (0) {
+	    error:
+		Py_CLEAR(elist);
+		Py_XDECREF(etuple);
+	}
+	PyMem_Free(evs);
+	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.");
+
+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},
+	{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])\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_compare */
+	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 */
+
+#ifdef HAVE_KQUEUE
+/* **************************************************************************
+ *                      kqueue interface for BSD
+ *
+ * Copyright (c) 2000 Doug White, 2006 James Knight, 2007 Christian Heimes
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_SYS_EVENT_H
+#include <sys/event.h>
+#endif
+
+PyDoc_STRVAR(kqueue_event_doc,
+"kevent(ident, filter=KQ_FILTER_READ, flags=KQ_ADD, fflags=0, data=0, udata=0)\n\
+\n\
+This object is the equivalent of the struct kevent for the C API.\n\
+\n\
+See the kqueue manpage for more detailed information about the meaning\n\
+of the arguments.\n\
+\n\
+One minor note: while you might hope that udata could store a\n\
+reference to a python object, it cannot, because it is impossible to\n\
+keep a proper reference count of the object once it's passed into the\n\
+kernel. Therefore, I have restricted it to only storing an integer.  I\n\
+recommend ignoring it and simply using the 'ident' field to key off\n\
+of. You could also set up a dictionary on the python side to store a\n\
+udata->object mapping.");
+
+typedef struct {
+	PyObject_HEAD
+	struct kevent e;
+} kqueue_event_Object;
+
+static PyTypeObject kqueue_event_Type;
+
+#define kqueue_event_Check(op) (PyObject_TypeCheck((op), &kqueue_event_Type))
+
+typedef struct {
+	PyObject_HEAD
+	SOCKET kqfd;		/* kqueue control fd */
+} kqueue_queue_Object;
+
+static PyTypeObject kqueue_queue_Type;
+
+#define kqueue_queue_Check(op) (PyObject_TypeCheck((op), &kqueue_queue_Type))
+
+/* Unfortunately, we can't store python objects in udata, because
+ * kevents in the kernel can be removed without warning, which would
+ * forever lose the refcount on the object stored with it.
+ */
+
+#define KQ_OFF(x) offsetof(kqueue_event_Object, x)
+static struct PyMemberDef kqueue_event_members[] = {
+	{"ident",	T_UINT,		KQ_OFF(e.ident)},
+	{"filter",	T_SHORT,	KQ_OFF(e.filter)},
+	{"flags",	T_USHORT,	KQ_OFF(e.flags)},
+	{"fflags",	T_UINT,		KQ_OFF(e.fflags)},
+	{"data",	T_INT,		KQ_OFF(e.data)},
+	{"udata",	T_INT,		KQ_OFF(e.udata)},
+	{NULL} /* Sentinel */
+};
+#undef KQ_OFF
+
+static PyObject *
+kqueue_event_repr(kqueue_event_Object *s)
+{
+	char buf[1024];
+	PyOS_snprintf(
+		buf, sizeof(buf),
+		"<select.kevent ident=%lu filter=%d flags=0x%x fflags=0x%x "
+		"data=0x%lx udata=%p>",
+		(unsigned long)(s->e.ident), s->e.filter, s->e.flags,
+		s->e.fflags, (long)(s->e.data), s->e.udata);
+	return PyString_FromString(buf);
+}
+
+static int
+kqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds)
+{
+	PyObject *pfd;
+	static char *kwlist[] = {"ident", "filter", "flags", "fflags",
+				 "data", "udata", NULL};
+
+	EV_SET(&(self->e), 0, EVFILT_READ, EV_ADD, 0, 0, 0); /* defaults */
+	
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|hhiii:kevent", kwlist,
+		&pfd, &(self->e.filter), &(self->e.flags),
+		&(self->e.fflags), &(self->e.data), &(self->e.udata))) {
+		return -1;
+	}
+
+	self->e.ident = PyObject_AsFileDescriptor(pfd);
+	if (self->e.ident == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+static PyObject *
+kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o,
+			 int op)
+{
+	int result = 0;
+
+	if (!kqueue_event_Check(o)) {
+		if (op == Py_EQ || op == Py_NE) {
+                	PyObject *res = op == Py_EQ ? Py_False : Py_True;
+			Py_INCREF(res);
+			return res;
+		}
+		PyErr_Format(PyExc_TypeError,
+			"can't compare %.200s to %.200s",
+			Py_TYPE(s)->tp_name, Py_TYPE(o)->tp_name);
+		return NULL;
+	}
+	if (((result = s->e.ident - o->e.ident) == 0) &&
+	    ((result = s->e.filter - o->e.filter) == 0) &&
+	    ((result = s->e.flags - o->e.flags) == 0) &&
+	    ((result = s->e.fflags - o->e.fflags) == 0) &&
+	    ((result = s->e.data - o->e.data) == 0) &&
+	    ((result = s->e.udata - o->e.udata) == 0)
+	   ) {
+		result = 0;
+	}
+
+	switch (op) {
+	    case Py_EQ:
+		result = (result == 0);
+		break;
+	    case Py_NE:
+		result = (result != 0);
+		break;
+	    case Py_LE:
+		result = (result <= 0);
+		break;
+	    case Py_GE:
+		result = (result >= 0);
+		break;
+	    case Py_LT:
+		result = (result < 0);
+		break;
+	    case Py_GT:
+		result = (result > 0);
+		break;
+	}
+	return PyBool_FromLong(result);
+}
+
+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_compare */
+	(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)
+{
+	PyErr_SetString(PyExc_ValueError, "I/O operation on closed kqueue fd");
+	return NULL;
+}
+
+static int
+kqueue_queue_internal_close(kqueue_queue_Object *self)
+{
+	int save_errno = 0;
+	if (self->kqfd >= 0) {
+		int kqfd = self->kqfd;
+		self->kqfd = -1;
+		Py_BEGIN_ALLOW_THREADS
+		if (close(kqfd) < 0)
+			save_errno = errno;
+		Py_END_ALLOW_THREADS
+	}
+	return save_errno;
+}
+
+static PyObject *
+newKqueue_Object(PyTypeObject *type, SOCKET fd)
+{
+	kqueue_queue_Object *self;
+	assert(type != NULL && type->tp_alloc != NULL);
+	self = (kqueue_queue_Object *) type->tp_alloc(type, 0);
+	if (self == NULL) {
+		return NULL;
+	}
+	
+	if (fd == -1) {
+		Py_BEGIN_ALLOW_THREADS
+		self->kqfd = kqueue();
+		Py_END_ALLOW_THREADS
+	}
+	else {
+		self->kqfd = fd;
+	}
+	if (self->kqfd < 0) {
+		Py_DECREF(self);
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+	return (PyObject *)self;
+}
+
+static PyObject *
+kqueue_queue_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+
+	if ((args != NULL && PyObject_Size(args)) ||
+			(kwds != NULL && PyObject_Size(kwds))) {
+		PyErr_SetString(PyExc_ValueError,
+				"select.kqueue doesn't accept arguments");
+		return NULL;
+	}
+
+	return newKqueue_Object(type, -1);
+}
+
+static void
+kqueue_queue_dealloc(kqueue_queue_Object *self)
+{
+	kqueue_queue_internal_close(self);
+	Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject*
+kqueue_queue_close(kqueue_queue_Object *self)
+{
+	errno = kqueue_queue_internal_close(self);
+	if (errno < 0) {
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+	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)
+{
+	if (self->kqfd < 0)
+		Py_RETURN_TRUE;
+	else
+		Py_RETURN_FALSE;
+}
+
+static PyObject*
+kqueue_queue_fileno(kqueue_queue_Object *self)
+{
+	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.");
+
+static PyObject*
+kqueue_queue_fromfd(PyObject *cls, PyObject *args)
+{
+	SOCKET fd;
+
+	if (!PyArg_ParseTuple(args, "i:fromfd", &fd))
+		return NULL;
+
+	return newKqueue_Object((PyTypeObject*)cls, fd);
+}
+
+PyDoc_STRVAR(kqueue_queue_fromfd_doc,
+"fromfd(fd) -> kqueue\n\
+\n\
+Create a kqueue object from a given control fd.");
+
+static PyObject *
+kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)
+{
+	int nevents = 0;
+	int gotevents = 0;
+	int nchanges = 0;
+	int i = 0;
+	PyObject *otimeout = NULL;
+	PyObject *ch = NULL;
+	PyObject *it = NULL, *ei = NULL;
+	PyObject *result = NULL;
+	struct kevent *evl = NULL;
+	struct kevent *chl = NULL;
+	struct timespec timeoutspec;
+	struct timespec *ptimeoutspec;
+
+	if (self->kqfd < 0)
+		return kqueue_queue_err_closed();
+
+	if (!PyArg_ParseTuple(args, "Oi|O:control", &ch, &nevents, &otimeout))
+		return NULL;
+
+	if (nevents < 0) {
+		PyErr_Format(PyExc_ValueError,
+			"Length of eventlist must be 0 or positive, got %d",
+			nchanges);
+		return NULL;
+	}
+
+	if (ch != NULL && ch != Py_None) {
+		it = PyObject_GetIter(ch);
+		if (it == NULL) {
+			PyErr_SetString(PyExc_TypeError,
+					"changelist is not iterable");
+			return NULL;
+		}
+		nchanges = PyObject_Size(ch);
+		if (nchanges < 0) {
+			return NULL;
+		}
+	}
+
+	if (otimeout == Py_None || otimeout == NULL) {
+		ptimeoutspec = NULL;
+	}
+	else if (PyNumber_Check(otimeout)) {
+		double timeout;
+		long seconds;
+
+		timeout = PyFloat_AsDouble(otimeout);
+		if (timeout == -1 && PyErr_Occurred())
+			return NULL;
+		if (timeout > (double)LONG_MAX) {
+			PyErr_SetString(PyExc_OverflowError,
+					"timeout period too long");
+			return NULL;
+		}
+		if (timeout < 0) {
+			PyErr_SetString(PyExc_ValueError,
+					"timeout must be positive or None");
+			return NULL;
+		}
+
+		seconds = (long)timeout;
+		timeout = timeout - (double)seconds;
+		timeoutspec.tv_sec = seconds;
+		timeoutspec.tv_nsec = (long)(timeout * 1E9);
+		ptimeoutspec = &timeoutspec;
+	}
+	else {
+		PyErr_Format(PyExc_TypeError,
+			"timeout argument must be an number "
+			"or None, got %.200s",
+			Py_TYPE(otimeout)->tp_name);
+		return NULL;
+	}
+
+	if (nchanges) {
+		chl = PyMem_New(struct kevent, nchanges);
+		if (chl == NULL) {
+			PyErr_NoMemory();
+			return NULL;
+		}
+		while ((ei = PyIter_Next(it)) != NULL) {
+			if (!kqueue_event_Check(ei)) {
+				Py_DECREF(ei);
+				PyErr_SetString(PyExc_TypeError,
+					"changelist must be an iterable of "
+				 	"select.kevent objects");
+				goto error;
+			} else {
+				chl[i] = ((kqueue_event_Object *)ei)->e;
+			}
+			Py_DECREF(ei);
+		}
+	}
+	Py_CLEAR(it);
+
+	/* event list */
+	if (nevents) {
+		evl = PyMem_New(struct kevent, nevents);
+		if (evl == NULL) {
+			PyErr_NoMemory();
+			return NULL;
+		}
+	}
+
+	Py_BEGIN_ALLOW_THREADS
+	gotevents = kevent(self->kqfd, chl, nchanges,
+			   evl, nevents, ptimeoutspec);
+	Py_END_ALLOW_THREADS
+
+	if (gotevents == -1) {
+		PyErr_SetFromErrno(PyExc_OSError);
+		goto error;
+	}
+
+	result = PyList_New(gotevents);
+	if (result == NULL) {
+		goto error;
+	}
+
+	for (i=0; i < gotevents; i++) {
+		kqueue_event_Object *ch;
+
+		ch = PyObject_New(kqueue_event_Object, &kqueue_event_Type);
+		if (ch == NULL) {
+			goto error;
+		}
+		ch->e = evl[i];
+		PyList_SET_ITEM(result, i, (PyObject *)ch);
+	}
+	PyMem_Free(chl);
+	PyMem_Free(evl);
+	return result;
+
+    error:
+	PyMem_Free(chl);
+	PyMem_Free(evl);
+	Py_XDECREF(result);
+	Py_XDECREF(it);
+	return NULL;
+}
+
+PyDoc_STRVAR(kqueue_queue_control_doc,
+"control(changelist, max_events=0[, timeout=None]) -> eventlist\n\
+\n\
+Calls the kernel kevent function.\n\
+- changelist must be a list 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 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},
+	{NULL,	NULL},
+};
+
+static PyGetSetDef kqueue_queue_getsetlist[] = {
+	{"closed", (getter)kqueue_queue_get_closed, NULL,
+	 "True if the kqueue handler is closed"},
+	{0},
+};
+
+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)");
+
+static PyTypeObject kqueue_queue_Type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	"select.kqueue",				/* tp_name */
+	sizeof(kqueue_queue_Object),			/* tp_basicsize */
+	0,						/* tp_itemsize */
+	(destructor)kqueue_queue_dealloc,		/* tp_dealloc */
+	0,						/* tp_print */
+	0,						/* tp_getattr */
+	0,						/* tp_setattr */
+	0,						/* tp_compare */
+	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 */
+	kqueue_queue_doc,				/* tp_doc */
+	0,						/* tp_traverse */
+	0,						/* tp_clear */
+	0,						/* tp_richcompare */
+	0,						/* tp_weaklistoffset */
+	0,						/* tp_iter */
+	0,						/* tp_iternext */
+	kqueue_queue_methods,				/* tp_methods */
+	0,						/* tp_members */
+	kqueue_queue_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 */
+	kqueue_queue_new,				/* tp_new */
+	0,						/* tp_free */
+};
+
+#endif /* HAVE_KQUEUE */
+/* ************************************************************************ */
+
 PyDoc_STRVAR(select_doc,
 "select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
 \n\
@@ -664,14 +1715,15 @@
 that are ready.\n\
 \n\
 *** IMPORTANT NOTICE ***\n\
-On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors.");
+On Windows and OpenVMS, only sockets are supported; on Unix, all file\n\
+descriptors.");
 
 static PyMethodDef select_methods[] = {
-    {"select",	select_select, METH_VARARGS, select_doc},
-#if defined(HAVE_POLL) 
-    {"poll",    select_poll,   METH_NOARGS, poll_doc},
+	{"select",	select_select,	METH_VARARGS,	select_doc},
+#ifdef HAVE_POLL
+	{"poll",	select_poll,	METH_NOARGS,	poll_doc},
 #endif /* HAVE_POLL */
-    {0,  	0},			     /* sentinel */
+	{0,  	0},	/* sentinel */
 };
 
 PyDoc_STRVAR(module_doc,
@@ -691,8 +1743,8 @@
 	SelectError = PyErr_NewException("select.error", NULL, NULL);
 	Py_INCREF(SelectError);
 	PyModule_AddObject(m, "error", SelectError);
-#if defined(HAVE_POLL) 
 
+#if defined(HAVE_POLL)
 #ifdef __APPLE__
 	if (select_have_broken_poll()) {
 		if (PyObject_DelAttrString(m, "poll") == -1) {
@@ -727,4 +1779,103 @@
 #endif
 	}
 #endif /* HAVE_POLL */
+
+#ifdef HAVE_EPOLL
+	Py_TYPE(&pyEpoll_Type) = &PyType_Type;
+	if (PyType_Ready(&pyEpoll_Type) < 0)
+		return;
+
+	Py_INCREF(&pyEpoll_Type);
+	PyModule_AddObject(m, "epoll", (PyObject *) &pyEpoll_Type);
+
+	PyModule_AddIntConstant(m, "EPOLLIN", EPOLLIN);
+	PyModule_AddIntConstant(m, "EPOLLOUT", EPOLLOUT);
+	PyModule_AddIntConstant(m, "EPOLLPRI", EPOLLPRI);
+	PyModule_AddIntConstant(m, "EPOLLERR", EPOLLERR);
+	PyModule_AddIntConstant(m, "EPOLLHUP", EPOLLHUP);
+	PyModule_AddIntConstant(m, "EPOLLET", EPOLLET);
+#ifdef EPOLLONESHOT
+	/* Kernel 2.6.2+ */
+	PyModule_AddIntConstant(m, "EPOLLONESHOT", EPOLLONESHOT);
+#endif
+	/* PyModule_AddIntConstant(m, "EPOLL_RDHUP", EPOLLRDHUP); */
+	PyModule_AddIntConstant(m, "EPOLLRDNORM", EPOLLRDNORM);
+	PyModule_AddIntConstant(m, "EPOLLRDBAND", EPOLLRDBAND);
+	PyModule_AddIntConstant(m, "EPOLLWRNORM", EPOLLWRNORM);
+	PyModule_AddIntConstant(m, "EPOLLWRBAND", EPOLLWRBAND);
+	PyModule_AddIntConstant(m, "EPOLLMSG", EPOLLMSG);
+#endif /* HAVE_EPOLL */
+
+#ifdef HAVE_KQUEUE
+	kqueue_event_Type.tp_new = PyType_GenericNew;
+	Py_TYPE(&kqueue_event_Type) = &PyType_Type;
+	if(PyType_Ready(&kqueue_event_Type) < 0)
+		return;
+
+	Py_INCREF(&kqueue_event_Type);
+	PyModule_AddObject(m, "kevent", (PyObject *)&kqueue_event_Type);
+
+	Py_TYPE(&kqueue_queue_Type) = &PyType_Type;
+	if(PyType_Ready(&kqueue_queue_Type) < 0)
+		return;
+	Py_INCREF(&kqueue_queue_Type);
+	PyModule_AddObject(m, "kqueue", (PyObject *)&kqueue_queue_Type);
+	
+	/* event filters */
+	PyModule_AddIntConstant(m, "KQ_FILTER_READ", EVFILT_READ);
+	PyModule_AddIntConstant(m, "KQ_FILTER_WRITE", EVFILT_WRITE);
+	PyModule_AddIntConstant(m, "KQ_FILTER_AIO", EVFILT_AIO);
+	PyModule_AddIntConstant(m, "KQ_FILTER_VNODE", EVFILT_VNODE);
+	PyModule_AddIntConstant(m, "KQ_FILTER_PROC", EVFILT_PROC);
+#ifdef EVFILT_NETDEV
+	PyModule_AddIntConstant(m, "KQ_FILTER_NETDEV", EVFILT_NETDEV);
+#endif
+	PyModule_AddIntConstant(m, "KQ_FILTER_SIGNAL", EVFILT_SIGNAL);
+	PyModule_AddIntConstant(m, "KQ_FILTER_TIMER", EVFILT_TIMER);
+
+	/* event flags */
+	PyModule_AddIntConstant(m, "KQ_EV_ADD", EV_ADD);
+	PyModule_AddIntConstant(m, "KQ_EV_DELETE", EV_DELETE);
+	PyModule_AddIntConstant(m, "KQ_EV_ENABLE", EV_ENABLE);
+	PyModule_AddIntConstant(m, "KQ_EV_DISABLE", EV_DISABLE);
+	PyModule_AddIntConstant(m, "KQ_EV_ONESHOT", EV_ONESHOT);
+	PyModule_AddIntConstant(m, "KQ_EV_CLEAR", EV_CLEAR);
+
+	PyModule_AddIntConstant(m, "KQ_EV_SYSFLAGS", EV_SYSFLAGS);
+	PyModule_AddIntConstant(m, "KQ_EV_FLAG1", EV_FLAG1);
+
+	PyModule_AddIntConstant(m, "KQ_EV_EOF", EV_EOF);
+	PyModule_AddIntConstant(m, "KQ_EV_ERROR", EV_ERROR);
+
+	/* READ WRITE filter flag */
+	PyModule_AddIntConstant(m, "KQ_NOTE_LOWAT", NOTE_LOWAT);
+	
+	/* VNODE filter flags  */
+	PyModule_AddIntConstant(m, "KQ_NOTE_DELETE", NOTE_DELETE);
+	PyModule_AddIntConstant(m, "KQ_NOTE_WRITE", NOTE_WRITE);
+	PyModule_AddIntConstant(m, "KQ_NOTE_EXTEND", NOTE_EXTEND);
+	PyModule_AddIntConstant(m, "KQ_NOTE_ATTRIB", NOTE_ATTRIB);
+	PyModule_AddIntConstant(m, "KQ_NOTE_LINK", NOTE_LINK);
+	PyModule_AddIntConstant(m, "KQ_NOTE_RENAME", NOTE_RENAME);
+	PyModule_AddIntConstant(m, "KQ_NOTE_REVOKE", NOTE_REVOKE);
+
+	/* PROC filter flags  */
+	PyModule_AddIntConstant(m, "KQ_NOTE_EXIT", NOTE_EXIT);
+	PyModule_AddIntConstant(m, "KQ_NOTE_FORK", NOTE_FORK);
+	PyModule_AddIntConstant(m, "KQ_NOTE_EXEC", NOTE_EXEC);
+	PyModule_AddIntConstant(m, "KQ_NOTE_PCTRLMASK", NOTE_PCTRLMASK);
+	PyModule_AddIntConstant(m, "KQ_NOTE_PDATAMASK", NOTE_PDATAMASK);
+
+	PyModule_AddIntConstant(m, "KQ_NOTE_TRACK", NOTE_TRACK);
+	PyModule_AddIntConstant(m, "KQ_NOTE_CHILD", NOTE_CHILD);
+	PyModule_AddIntConstant(m, "KQ_NOTE_TRACKERR", NOTE_TRACKERR);
+
+	/* NETDEV filter flags */
+#ifdef EVFILT_NETDEV
+	PyModule_AddIntConstant(m, "KQ_NOTE_LINKUP", NOTE_LINKUP);
+	PyModule_AddIntConstant(m, "KQ_NOTE_LINKDOWN", NOTE_LINKDOWN);
+	PyModule_AddIntConstant(m, "KQ_NOTE_LINKINV", NOTE_LINKINV);
+#endif
+
+#endif /* HAVE_KQUEUE */
 }

Modified: python/branches/py3k/configure
==============================================================================
--- python/branches/py3k/configure	(original)
+++ python/branches/py3k/configure	Sat Mar 22 01:47:35 2008
@@ -5390,13 +5390,15 @@
 
 
 
+
+
 for ac_header in asm/types.h conio.h curses.h direct.h dlfcn.h errno.h \
 fcntl.h grp.h \
 io.h langinfo.h libintl.h ncurses.h poll.h process.h pthread.h \
 shadow.h signal.h stdint.h stropts.h termios.h thread.h \
 unistd.h utime.h \
-sys/audioio.h sys/bsdtty.h sys/file.h sys/loadavg.h sys/lock.h sys/mkdev.h \
-sys/modem.h \
+sys/audioio.h sys/bsdtty.h sys/epoll.h sys/event.h sys/file.h sys/loadavg.h \
+sys/lock.h sys/mkdev.h sys/modem.h \
 sys/param.h sys/poll.h sys/select.h sys/socket.h sys/statvfs.h sys/stat.h \
 sys/time.h \
 sys/times.h sys/types.h sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h \
@@ -16130,7 +16132,111 @@
 fi
 
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking for epoll" >&5
+echo $ECHO_N "checking for epoll... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/epoll.h>
+int
+main ()
+{
+void *x=epoll_create
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_EPOLL 1
+_ACEOF
+
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	{ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking for kqueue" >&5
+echo $ECHO_N "checking for kqueue... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/event.h>
+
+int
+main ()
+{
+int x=kqueue()
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_KQUEUE 1
+_ACEOF
 
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	{ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 # On some systems (eg. FreeBSD 5), we would find a definition of the
 # functions ctermid_r, setgroups in the library, but no prototype
 # (e.g. because we use _XOPEN_SOURCE). See whether we can take their

Modified: python/branches/py3k/configure.in
==============================================================================
--- python/branches/py3k/configure.in	(original)
+++ python/branches/py3k/configure.in	Sat Mar 22 01:47:35 2008
@@ -1077,8 +1077,8 @@
 io.h langinfo.h libintl.h ncurses.h poll.h process.h pthread.h \
 shadow.h signal.h stdint.h stropts.h termios.h thread.h \
 unistd.h utime.h \
-sys/audioio.h sys/bsdtty.h sys/file.h sys/loadavg.h sys/lock.h sys/mkdev.h \
-sys/modem.h \
+sys/audioio.h sys/bsdtty.h sys/epoll.h sys/event.h sys/file.h sys/loadavg.h \
+sys/lock.h sys/mkdev.h sys/modem.h \
 sys/param.h sys/poll.h sys/select.h sys/socket.h sys/statvfs.h sys/stat.h \
 sys/time.h \
 sys/times.h sys/types.h sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h \
@@ -2325,7 +2325,21 @@
   AC_MSG_RESULT(yes),
   AC_MSG_RESULT(no)
 )
-
+AC_MSG_CHECKING(for epoll)
+AC_TRY_COMPILE([#include <sys/epoll.h>], void *x=epoll_create,
+  AC_DEFINE(HAVE_EPOLL, 1, Define if you have the 'epoll' functions.)
+  AC_MSG_RESULT(yes),
+  AC_MSG_RESULT(no)
+)
+AC_MSG_CHECKING(for kqueue)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/event.h>
+    ], int x=kqueue(),
+  AC_DEFINE(HAVE_KQUEUE, 1, Define if you have the 'kqueue' functions.)
+  AC_MSG_RESULT(yes),
+  AC_MSG_RESULT(no)
+)
 # On some systems (eg. FreeBSD 5), we would find a definition of the
 # functions ctermid_r, setgroups in the library, but no prototype
 # (e.g. because we use _XOPEN_SOURCE). See whether we can take their

Modified: python/branches/py3k/pyconfig.h.in
==============================================================================
--- python/branches/py3k/pyconfig.h.in	(original)
+++ python/branches/py3k/pyconfig.h.in	Sat Mar 22 01:47:35 2008
@@ -144,6 +144,9 @@
 /* Defined when any dynamic module loading is enabled. */
 #undef HAVE_DYNAMIC_LOADING
 
+/* Define if you have the 'epoll' functions. */
+#undef HAVE_EPOLL
+
 /* Define to 1 if you have the <errno.h> header file. */
 #undef HAVE_ERRNO_H
 
@@ -315,6 +318,9 @@
 /* Define to 1 if you have the `killpg' function. */
 #undef HAVE_KILLPG
 
+/* Define if you have the 'kqueue' functions. */
+#undef HAVE_KQUEUE
+
 /* Define to 1 if you have the <langinfo.h> header file. */
 #undef HAVE_LANGINFO_H
 
@@ -630,6 +636,12 @@
    */
 #undef HAVE_SYS_DIR_H
 
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+#undef HAVE_SYS_EPOLL_H
+
+/* Define to 1 if you have the <sys/event.h> header file. */
+#undef HAVE_SYS_EVENT_H
+
 /* Define to 1 if you have the <sys/file.h> header file. */
 #undef HAVE_SYS_FILE_H
 


More information about the Python-3000-checkins mailing list