[Python-3000-checkins] r63647 - in python/branches/py3k: Doc/library/socketserver.rst Doc/library/zipfile.rst Lib/BaseHTTPServer.py Lib/CGIHTTPServer.py Lib/SimpleHTTPServer.py Lib/distutils/tests/test_build_ext.py Lib/gzip.py Lib/test/pydoc_mod.py Lib/test/test_collections.py Lib/test/test_gzip.py Lib/test/test_httpservers.py Lib/test/test_json.py Lib/test/test_opcodes.py Lib/test/test_pyclbr.py Lib/test/test_pydoc.py Lib/test/test_weakref.py Lib/test/test_zipfile.py Lib/tkinter/__init__.py Lib/zipfile.py Makefile.pre.in Misc/ACKS Misc/build.sh Objects/weakrefobject.c

georg.brandl python-3000-checkins at python.org
Sun May 25 20:19:31 CEST 2008


Author: georg.brandl
Date: Sun May 25 20:19:30 2008
New Revision: 63647

Log:
Merged revisions 63412,63445-63447,63449-63450,63452,63454,63459,63463,63465,63470,63483-63484,63496-63497,63499-63501,63530-63531,63540,63614 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r63412 | georg.brandl | 2008-05-17 19:57:01 +0200 (Sat, 17 May 2008) | 2 lines
  
  #961805: fix Edit.text_modified().
........
  r63445 | georg.brandl | 2008-05-18 10:52:59 +0200 (Sun, 18 May 2008) | 2 lines
  
  GHOP #180 by Michael Schneider: add examples to the socketserver documentation.
........
  r63446 | georg.brandl | 2008-05-18 11:12:20 +0200 (Sun, 18 May 2008) | 2 lines
  
  GHOP #134, #171, #137: unit tests for the three HTTPServer modules.
........
  r63447 | georg.brandl | 2008-05-18 12:39:26 +0200 (Sun, 18 May 2008) | 3 lines
  
  Take namedtuple item names only from ascii_letters (this blew up on OSX),
  and make sure there are no duplicate names.
........
  r63449 | georg.brandl | 2008-05-18 13:46:51 +0200 (Sun, 18 May 2008) | 2 lines
  
  GHOP #217: add support for compiling Python with coverage checking enabled.
........
  r63450 | georg.brandl | 2008-05-18 13:52:36 +0200 (Sun, 18 May 2008) | 2 lines
  
  GHOP #257: test distutils' build_ext command, written by Josip Dzolonga.
........
  r63452 | georg.brandl | 2008-05-18 15:34:06 +0200 (Sun, 18 May 2008) | 2 lines
  
  Add GHOP students.
........
  r63454 | georg.brandl | 2008-05-18 18:32:48 +0200 (Sun, 18 May 2008) | 2 lines
  
  GHOP #121: improve test_pydoc, by Benjamin Peterson.
........
  r63459 | benjamin.peterson | 2008-05-18 22:48:07 +0200 (Sun, 18 May 2008) | 2 lines
  
  bring test_pydoc up to my high standards (now that I have them)
........
  r63463 | georg.brandl | 2008-05-18 23:10:19 +0200 (Sun, 18 May 2008) | 2 lines
  
  Fix test_pyclbr after another platform-dependent function was added to urllib.
........
  r63465 | benjamin.peterson | 2008-05-19 01:07:07 +0200 (Mon, 19 May 2008) | 2 lines
  
  change some imports in tests so they will not be skipped in 3.0
........
  r63470 | georg.brandl | 2008-05-19 18:47:25 +0200 (Mon, 19 May 2008) | 2 lines
  
  test_httpservers has unpredictable refcount behavior.
........
  r63483 | georg.brandl | 2008-05-20 08:15:36 +0200 (Tue, 20 May 2008) | 2 lines
  
  Activate two more test cases in test_httpservers.
........
  r63484 | georg.brandl | 2008-05-20 08:47:31 +0200 (Tue, 20 May 2008) | 2 lines
  
  Argh, this is the *actual* test that works under Windows.
........
  r63496 | georg.brandl | 2008-05-20 10:07:36 +0200 (Tue, 20 May 2008) | 2 lines
  
  Improve diffing logic and output for test_pydoc.
........
  r63497 | georg.brandl | 2008-05-20 10:10:03 +0200 (Tue, 20 May 2008) | 2 lines
  
  Use inspect.getabsfile() to get the documented module's filename.
........
  r63499 | georg.brandl | 2008-05-20 10:25:48 +0200 (Tue, 20 May 2008) | 3 lines
  
  Patch #1775025: allow opening zipfile members via ZipInfo instances.
  Patch by Graham Horler.
........
  r63500 | georg.brandl | 2008-05-20 10:40:43 +0200 (Tue, 20 May 2008) | 2 lines
  
  #2592: delegate nb_index and the floor/truediv slots in weakref.proxy.
........
  r63501 | georg.brandl | 2008-05-20 10:48:34 +0200 (Tue, 20 May 2008) | 2 lines
  
  #615772: raise a more explicit error from Tkinter.Misc.__contains__.
........
  r63530 | benjamin.peterson | 2008-05-22 02:57:02 +0200 (Thu, 22 May 2008) | 2 lines
  
  use more specific asserts in test_opcode
........
  r63531 | benjamin.peterson | 2008-05-22 03:02:23 +0200 (Thu, 22 May 2008) | 2 lines
  
  remove redundant invocation of json doctests
........
  r63540 | benjamin.peterson | 2008-05-23 01:09:26 +0200 (Fri, 23 May 2008) | 3 lines
  
  fix test_pydoc so it works on make installed Python installations
  Also let it pass when invoked directly
........
  r63614 | georg.brandl | 2008-05-25 10:07:37 +0200 (Sun, 25 May 2008) | 2 lines
  
  #2959: allow multiple close() calls for GzipFile.
........


Added:
   python/branches/py3k/Lib/distutils/tests/test_build_ext.py
      - copied, changed from r63454, /python/trunk/Lib/distutils/tests/test_build_ext.py
   python/branches/py3k/Lib/test/pydoc_mod.py
      - copied unchanged from r63454, /python/trunk/Lib/test/pydoc_mod.py
   python/branches/py3k/Lib/test/test_httpservers.py
      - copied, changed from r63454, /python/trunk/Lib/test/test_httpservers.py
Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Doc/library/socketserver.rst
   python/branches/py3k/Doc/library/zipfile.rst
   python/branches/py3k/Lib/BaseHTTPServer.py
   python/branches/py3k/Lib/CGIHTTPServer.py
   python/branches/py3k/Lib/SimpleHTTPServer.py
   python/branches/py3k/Lib/gzip.py
   python/branches/py3k/Lib/test/test_collections.py
   python/branches/py3k/Lib/test/test_gzip.py
   python/branches/py3k/Lib/test/test_json.py
   python/branches/py3k/Lib/test/test_opcodes.py
   python/branches/py3k/Lib/test/test_pyclbr.py
   python/branches/py3k/Lib/test/test_pydoc.py
   python/branches/py3k/Lib/test/test_weakref.py
   python/branches/py3k/Lib/test/test_zipfile.py
   python/branches/py3k/Lib/tkinter/__init__.py
   python/branches/py3k/Lib/zipfile.py
   python/branches/py3k/Makefile.pre.in
   python/branches/py3k/Misc/ACKS
   python/branches/py3k/Misc/build.sh
   python/branches/py3k/Objects/weakrefobject.c

Modified: python/branches/py3k/Doc/library/socketserver.rst
==============================================================================
--- python/branches/py3k/Doc/library/socketserver.rst	(original)
+++ python/branches/py3k/Doc/library/socketserver.rst	Sun May 25 20:19:30 2008
@@ -236,8 +236,8 @@
 
 .. function:: handle_timeout()
 
-   This function is called when the :attr:`timeout` attribute has been set to a 
-   value other than :const:`None` and the timeout period has passed with no 
+   This function is called when the :attr:`timeout` attribute has been set to a
+   value other than :const:`None` and the timeout period has passed with no
    requests being received.  The default action for forking servers is
    to collect the status of any child processes that have exited, while
    in threading servers this method does nothing.
@@ -284,27 +284,28 @@
 
 .. function:: finish()
 
-   Called after the :meth:`handle` method to perform any clean-up actions required.
-   The default implementation does nothing.  If :meth:`setup` or :meth:`handle`
-   raise an exception, this function will not be called.
+   Called after the :meth:`handle` method to perform any clean-up actions
+   required.  The default implementation does nothing.  If :meth:`setup` or
+   :meth:`handle` raise an exception, this function will not be called.
 
 
 .. function:: handle()
 
-   This function must do all the work required to service a request. The default
-   implementation does nothing. Several instance attributes are available to it;
-   the request is available as :attr:`self.request`; the client address as
-   :attr:`self.client_address`; and the server instance as :attr:`self.server`, in
-   case it needs access to per-server information.
-
-   The type of :attr:`self.request` is different for datagram or stream services.
-   For stream services, :attr:`self.request` is a socket object; for datagram
-   services, :attr:`self.request` is a string. However, this can be hidden by using
-   the  request handler subclasses :class:`StreamRequestHandler` or
-   :class:`DatagramRequestHandler`, which override the :meth:`setup` and
-   :meth:`finish` methods, and provide :attr:`self.rfile` and :attr:`self.wfile`
-   attributes. :attr:`self.rfile` and :attr:`self.wfile` can be read or written,
-   respectively, to get the request data or return data to the client.
+   This function must do all the work required to service a request.  The
+   default implementation does nothing.  Several instance attributes are
+   available to it; the request is available as :attr:`self.request`; the client
+   address as :attr:`self.client_address`; and the server instance as
+   :attr:`self.server`, in case it needs access to per-server information.
+
+   The type of :attr:`self.request` is different for datagram or stream
+   services.  For stream services, :attr:`self.request` is a socket object; for
+   datagram services, :attr:`self.request` is a pair of string and socket.
+   However, this can be hidden by using the request handler subclasses
+   :class:`StreamRequestHandler` or :class:`DatagramRequestHandler`, which
+   override the :meth:`setup` and :meth:`finish` methods, and provide
+   :attr:`self.rfile` and :attr:`self.wfile` attributes.  :attr:`self.rfile` and
+   :attr:`self.wfile` can be read or written, respectively, to get the request
+   data or return data to the client.
 
 
 .. function:: setup()
@@ -312,3 +313,217 @@
    Called before the :meth:`handle` method to perform any initialization actions
    required.  The default implementation does nothing.
 
+
+Examples
+--------
+
+:class:`socketserver.TCPServer` Example
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the server side::
+
+   import socketserver
+
+   class MyTCPHandler(socketserver.BaseRequestHandler):
+       """
+       The RequestHandler class for our server.
+
+       It is instantiated once per connection to the server, and must
+       override the handle() method to implement communication to the
+       client.
+       """
+
+       def handle(self):
+           # self.request is the TCP socket connected to the client
+           self.data = self.request.recv(1024).strip()
+           print "%s wrote:" % self.client_address[0]
+           print self.data
+           # just send back the same data, but upper-cased
+           self.request.send(self.data.upper())
+
+   if __name__ == "__main__":
+       HOST, PORT = "localhost", 9999
+
+       # Create the server, binding to localhost on port 9999
+       server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
+
+       # Activate the server; this will keep running until you
+       # interrupt the program with Ctrl-C
+       server.serve_forever()
+
+An alternative request handler class that makes use of streams (file-like
+objects that simplify communication by providing the standard file interface)::
+
+   class MyTCPHandler(socketserver.StreamRequestHandler):
+
+       def handle(self):
+           # self.rfile is a file-like object created by the handler;
+           # we can now use e.g. readline() instead of raw recv() calls
+           self.data = self.rfile.readline().strip()
+           print "%s wrote:" % self.client_address[0]
+           print self.data
+           # Likewise, self.wfile is a file-like object used to write back
+           # to the client
+           self.wfile.write(self.data.upper())
+
+The difference is that the ``readline()`` call in the second handler will call
+``recv()`` multiple times until it encounters a newline character, while the
+single ``recv()`` call in the first handler will just return what has been sent
+from the client in one ``send()`` call.
+
+
+This is the client side::
+
+   import socket
+   import sys
+
+   HOST, PORT = "localhost", 9999
+   data = " ".join(sys.argv[1:])
+
+   # Create a socket (SOCK_STREAM means a TCP socket)
+   sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+   # Connect to server and send data
+   sock.connect((HOST, PORT))
+   sock.send(data + "\n")
+
+   # Receive data from the server and shut down
+   received = sock.recv(1024)
+   sock.close()
+
+   print "Sent:     %s" % data
+   print "Received: %s" % received
+
+
+The output of the example should look something like this:
+
+Server::
+
+   $ python TCPServer.py
+   127.0.0.1 wrote:
+   hello world with TCP
+   127.0.0.1 wrote:
+   python is nice
+
+Client::
+
+   $ python TCPClient.py hello world with TCP
+   Sent:     hello world with TCP
+   Received: HELLO WORLD WITH TCP
+   $ python TCPClient.py python is nice
+   Sent:     python is nice
+   Received: PYTHON IS NICE
+
+
+:class:`socketserver.UDPServer` Example
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the server side::
+
+   import socketserver
+
+   class MyUDPHandler(socketserver.BaseRequestHandler):
+       """
+       This class works similar to the TCP handler class, except that
+       self.request consists of a pair of data and client socket, and since
+       there is no connection the client address must be given explicitly
+       when sending data back via sendto().
+       """
+
+       def handle(self):
+           data = self.request[0].strip()
+           socket = self.request[1]
+           print "%s wrote:" % self.client_address[0]
+           print data
+           socket.sendto(data.upper(), self.client_address)
+
+   if __name__ == "__main__":
+      HOST, PORT = "localhost", 9999
+      server = socketserver.UDPServer((HOST, PORT), BaseUDPRequestHandler)
+      server.serve_forever()
+
+This is the client side::
+
+   import socket
+   import sys
+
+   HOST, PORT = "localhost"
+   data = " ".join(sys.argv[1:])
+
+   # SOCK_DGRAM is the socket type to use for UDP sockets
+   sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+   # As you can see, there is no connect() call; UDP has no connections.
+   # Instead, data is directly sent to the recipient via sendto().
+   sock.sendto(data + "\n", (HOST, PORT))
+   received = sock.recv(1024)
+
+   print "Sent:     %s" % data
+   print "Received: %s" % received
+
+The output of the example should look exactly like for the TCP server example.
+
+
+Asynchronous Mixins
+~~~~~~~~~~~~~~~~~~~
+
+To build asynchronous handlers, use the :class:`ThreadingMixIn` and
+:class:`ForkingMixIn` classes.
+
+An example for the :class:`ThreadingMixIn` class::
+
+   import socket
+   import threading
+   import socketserver
+
+   class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
+
+       def handle(self):
+           data = self.request.recv(1024)
+           cur_thread = threading.currentThread()
+           response = "%s: %s" % (cur_thread.getName(), data)
+           self.request.send(response)
+
+   class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
+       pass
+
+   def client(ip, port, message):
+       sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+       sock.connect((ip, port))
+       sock.send(message)
+       response = sock.recv(1024)
+       print "Received: %s" % response
+       sock.close()
+
+   if __name__ == "__main__":
+       # Port 0 means to select an arbitrary unused port
+       HOST, PORT = "localhost", 0
+
+       server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
+       ip, port = server.server_address
+
+       # Start a thread with the server -- that thread will then start one
+       # more thread for each request
+       server_thread = threading.Thread(target=server.serve_forever)
+       # Exit the server thread when the main thread terminates
+       server_thread.setDaemon(True)
+       server_thread.start()
+       print "Server loop running in thread:", t.getName()
+
+       client(ip, port, "Hello World 1")
+       client(ip, port, "Hello World 2")
+       client(ip, port, "Hello World 3")
+
+       server.shutdown()
+
+The output of the example should look something like this::
+
+   $ python ThreadedTCPServer.py
+   Server loop running in thread: Thread-1
+   Received: Thread-2: Hello World 1
+   Received: Thread-3: Hello World 2
+   Received: Thread-4: Hello World 3
+
+
+The :class:`ForkingMixIn` class is used in the same way, except that the server
+will spawn a new process for each request.

Modified: python/branches/py3k/Doc/library/zipfile.rst
==============================================================================
--- python/branches/py3k/Doc/library/zipfile.rst	(original)
+++ python/branches/py3k/Doc/library/zipfile.rst	Sun May 25 20:19:30 2008
@@ -150,11 +150,11 @@
 .. method:: ZipFile.open(name[, mode[, pwd]])
 
    Extract a member from the archive as a file-like object (ZipExtFile). *name* is
-   the name of the file in the archive. The *mode* parameter, if included, must be
-   one of the following: ``'r'`` (the  default), ``'U'``, or ``'rU'``. Choosing
-   ``'U'`` or  ``'rU'`` will enable universal newline support in the read-only
-   object. *pwd* is the password used for encrypted files.  Calling  :meth:`open`
-   on a closed ZipFile will raise a  :exc:`RuntimeError`.
+   the name of the file in the archive, or a :class:`ZipInfo` object. The *mode*
+   parameter, if included, must be one of the following: ``'r'`` (the  default),
+   ``'U'``, or ``'rU'``. Choosing ``'U'`` or  ``'rU'`` will enable universal newline
+   support in the read-only object. *pwd* is the password used for encrypted files.
+   Calling  :meth:`open` on a closed ZipFile will raise a  :exc:`RuntimeError`.
 
    .. note::
 
@@ -173,14 +173,20 @@
       create a new file object that will be held by the ZipExtFile, allowing it to
       operate independently of the  ZipFile.
 
+   .. note::
+
+      The :meth:`open`, :meth:`read` and :meth:`extract` methods can take a filename
+      or a :class:`ZipInfo` object.  You will appreciate this when trying to read a
+      ZIP file that contains members with duplicate names.
+
 
 .. method:: ZipFile.extract(member[, path[, pwd]])
 
-   Extract a member from the archive to the current working directory, using its
-   full name.  Its file information is extracted as accurately as possible.
-   *path* specifies a different directory to extract to.   *member* can be a
-   filename or a :class:`ZipInfo` object.  *pwd* is the password used for
-   encrypted files.
+   Extract a member from the archive to the current working directory; *member*
+   must be its full name or a :class:`ZipInfo` object).  Its file information is
+   extracted as accurately as possible.  *path* specifies a different directory
+   to extract to.  *member* can be a filename or a :class:`ZipInfo` object.
+   *pwd* is the password used for encrypted files.
 
 
 .. method:: ZipFile.extractall([path[, members[, pwd]]])
@@ -203,9 +209,10 @@
 
 .. method:: ZipFile.read(name[, pwd])
 
-   Return the bytes of the file in the archive.  The archive must be open for read
-   or append. *pwd* is the password used for encrypted  files and, if specified, it
-   will override the default password set with :meth:`setpassword`.  Calling
+   Return the bytes of the file *name* in the archive.  *name* is the name of the
+   file in the archive, or a :class:`ZipInfo` object.  The archive must be open for
+   read or append. *pwd* is the password used for encrypted  files and, if specified,
+   it will override the default password set with :meth:`setpassword`.  Calling
    :meth:`read` on a closed ZipFile  will raise a :exc:`RuntimeError`.
 
 

Modified: python/branches/py3k/Lib/BaseHTTPServer.py
==============================================================================
--- python/branches/py3k/Lib/BaseHTTPServer.py	(original)
+++ python/branches/py3k/Lib/BaseHTTPServer.py	Sun May 25 20:19:30 2008
@@ -222,6 +222,12 @@
     error_message_format = DEFAULT_ERROR_MESSAGE
     error_content_type = DEFAULT_ERROR_CONTENT_TYPE
 
+    # The default request version.  This only affects responses up until
+    # the point where the request line is parsed, so it mainly decides what
+    # the client gets back when sending a malformed request line.
+    # Most web servers default to HTTP 0.9, i.e. don't send a status line.
+    default_request_version = "HTTP/0.9"
+
     def parse_request(self):
         """Parse a request (internal).
 
@@ -234,7 +240,7 @@
 
         """
         self.command = None  # set in case of error on the first line
-        self.request_version = version = "HTTP/0.9" # Default
+        self.request_version = version = self.default_request_version
         self.close_connection = 1
         requestline = str(self.raw_requestline, 'iso-8859-1')
         if requestline[-2:] == '\r\n':

Modified: python/branches/py3k/Lib/CGIHTTPServer.py
==============================================================================
--- python/branches/py3k/Lib/CGIHTTPServer.py	(original)
+++ python/branches/py3k/Lib/CGIHTTPServer.py	Sun May 25 20:19:30 2008
@@ -182,8 +182,10 @@
                 env['AUTH_TYPE'] = authorization[0]
                 if authorization[0].lower() == "basic":
                     try:
-                        authorization = base64.decodestring(authorization[1])
-                    except binascii.Error:
+                        authorization = authorization[1].encode('ascii')
+                        authorization = base64.decodestring(authorization).\
+                                        decode('ascii')
+                    except (binascii.Error, UnicodeError):
                         pass
                     else:
                         authorization = authorization.split(':')

Modified: python/branches/py3k/Lib/SimpleHTTPServer.py
==============================================================================
--- python/branches/py3k/Lib/SimpleHTTPServer.py	(original)
+++ python/branches/py3k/Lib/SimpleHTTPServer.py	Sun May 25 20:19:30 2008
@@ -11,13 +11,14 @@
 __all__ = ["SimpleHTTPRequestHandler"]
 
 import os
+import sys
 import posixpath
 import BaseHTTPServer
 import urllib
 import cgi
 import shutil
 import mimetypes
-from io import StringIO
+from io import BytesIO
 
 
 class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
@@ -76,12 +77,8 @@
             else:
                 return self.list_directory(path)
         ctype = self.guess_type(path)
-        if ctype.startswith('text/'):
-            mode = 'r'
-        else:
-            mode = 'rb'
         try:
-            f = open(path, mode)
+            f = open(path, 'rb')
         except IOError:
             self.send_error(404, "File not found")
             return None
@@ -107,12 +104,12 @@
             self.send_error(404, "No permission to list directory")
             return None
         list.sort(key=lambda a: a.lower())
-        f = StringIO()
+        r = []
         displaypath = cgi.escape(urllib.unquote(self.path))
-        f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
-        f.write("<html>\n<title>Directory listing for %s</title>\n" % displaypath)
-        f.write("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
-        f.write("<hr>\n<ul>\n")
+        r.append('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
+        r.append("<html>\n<title>Directory listing for %s</title>\n" % displaypath)
+        r.append("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
+        r.append("<hr>\n<ul>\n")
         for name in list:
             fullname = os.path.join(path, name)
             displayname = linkname = name
@@ -123,14 +120,17 @@
             if os.path.islink(fullname):
                 displayname = name + "@"
                 # Note: a link to a directory displays with @ and links with /
-            f.write('<li><a href="%s">%s</a>\n'
+            r.append('<li><a href="%s">%s</a>\n'
                     % (urllib.quote(linkname), cgi.escape(displayname)))
-        f.write("</ul>\n<hr>\n</body>\n</html>\n")
-        length = f.tell()
+        r.append("</ul>\n<hr>\n</body>\n</html>\n")
+        enc = sys.getfilesystemencoding()
+        encoded = ''.join(r).encode(enc)
+        f = BytesIO()
+        f.write(encoded)
         f.seek(0)
         self.send_response(200)
-        self.send_header("Content-type", "text/html")
-        self.send_header("Content-Length", str(length))
+        self.send_header("Content-type", "text/html; charset=%s" % enc)
+        self.send_header("Content-Length", str(len(encoded)))
         self.end_headers()
         return f
 

Copied: python/branches/py3k/Lib/distutils/tests/test_build_ext.py (from r63454, /python/trunk/Lib/distutils/tests/test_build_ext.py)
==============================================================================
--- /python/trunk/Lib/distutils/tests/test_build_ext.py	(original)
+++ python/branches/py3k/Lib/distutils/tests/test_build_ext.py	Sun May 25 20:19:30 2008
@@ -2,14 +2,14 @@
 import os
 import tempfile
 import shutil
-from StringIO import StringIO
+from io import StringIO
 
 from distutils.core import Extension, Distribution
 from distutils.command.build_ext import build_ext
 from distutils import sysconfig
 
 import unittest
-from test import test_support
+from test import support
 
 class BuildExtTestCase(unittest.TestCase):
     def setUp(self):
@@ -32,7 +32,7 @@
         cmd.build_temp = self.tmp_dir
 
         old_stdout = sys.stdout
-        if not test_support.verbose:
+        if not support.verbose:
             # silence compiler output
             sys.stdout = StringIO()
         try:
@@ -56,17 +56,17 @@
 
     def tearDown(self):
         # Get everything back to normal
-        test_support.unload('xx')
+        support.unload('xx')
         sys.path = self.sys_path
         # XXX on Windows the test leaves a directory with xx.pyd in TEMP
         shutil.rmtree(self.tmp_dir, False if os.name != "nt" else True)
 
 def test_suite():
     if not sysconfig.python_build:
-        if test_support.verbose:
-            print 'test_build_ext: The test must be run in a python build dir'
+        if support.verbose:
+            print('test_build_ext: The test must be run in a python build dir')
         return unittest.TestSuite()
     else: return unittest.makeSuite(BuildExtTestCase)
 
 if __name__ == '__main__':
-    test_support.run_unittest(test_suite())
+    support.run_unittest(test_suite())

Modified: python/branches/py3k/Lib/gzip.py
==============================================================================
--- python/branches/py3k/Lib/gzip.py	(original)
+++ python/branches/py3k/Lib/gzip.py	Sun May 25 20:19:30 2008
@@ -323,6 +323,8 @@
             raise IOError("Incorrect length of data produced")
 
     def close(self):
+        if self.fileobj is None:
+            return
         if self.mode == WRITE:
             self.fileobj.write(self.compress.flush())
             write32u(self.fileobj, self.crc)

Modified: python/branches/py3k/Lib/test/test_collections.py
==============================================================================
--- python/branches/py3k/Lib/test/test_collections.py	(original)
+++ python/branches/py3k/Lib/test/test_collections.py	Sun May 25 20:19:30 2008
@@ -114,7 +114,9 @@
         # n = 10000
         n = 254 # SyntaxError: more than 255 arguments:
         import string, random
-        names = [''.join([random.choice(string.ascii_letters) for j in range(10)]) for i in range(n)]
+        names = list(set(''.join([random.choice(string.ascii_letters)
+                                  for j in range(10)]) for i in range(n)))
+        n = len(names)
         Big = namedtuple('Big', names)
         b = Big(*range(n))
         self.assertEqual(b, tuple(range(n)))

Modified: python/branches/py3k/Lib/test/test_gzip.py
==============================================================================
--- python/branches/py3k/Lib/test/test_gzip.py	(original)
+++ python/branches/py3k/Lib/test/test_gzip.py	Sun May 25 20:19:30 2008
@@ -24,14 +24,14 @@
 class TestGzip(unittest.TestCase):
     filename = support.TESTFN
 
-    def setUp (self):
+    def setUp(self):
         support.unlink(self.filename)
 
-    def tearDown (self):
+    def tearDown(self):
         support.unlink(self.filename)
 
 
-    def test_write (self):
+    def test_write(self):
         f = gzip.GzipFile(self.filename, 'wb') ; f.write(data1 * 50)
 
         # Try flush and fileno.
@@ -41,6 +41,9 @@
             os.fsync(f.fileno())
         f.close()
 
+        # Test multiple close() calls.
+        f.close()
+
     def test_read(self):
         self.test_write()
         # Try reading.

Copied: python/branches/py3k/Lib/test/test_httpservers.py (from r63454, /python/trunk/Lib/test/test_httpservers.py)
==============================================================================
--- /python/trunk/Lib/test/test_httpservers.py	(original)
+++ python/branches/py3k/Lib/test/test_httpservers.py	Sun May 25 20:19:30 2008
@@ -18,7 +18,7 @@
 import threading
 
 import unittest
-from test import test_support
+from test import support
 
 
 class NoLogRequestHandler:
@@ -193,18 +193,19 @@
 
     def setUp(self):
         BaseTestCase.setUp(self)
-        os.chdir(tempfile.gettempdir())
-        self.data = 'We are the knights who say Ni!'
-        self.tempdir = tempfile.mkdtemp(dir=tempfile.gettempdir())
+        self.cwd = os.getcwd()
+        basetempdir = tempfile.gettempdir()
+        os.chdir(basetempdir)
+        self.data = b'We are the knights who say Ni!'
+        self.tempdir = tempfile.mkdtemp(dir=basetempdir)
         self.tempdir_name = os.path.basename(self.tempdir)
-        self.tempfile = tempfile.NamedTemporaryFile(dir=self.tempdir)
-        self.tempfile.file.write(self.data)
-        self.tempfile.file.flush()
-        self.tempfile_name = os.path.basename(self.tempfile.name)
+        temp = open(os.path.join(self.tempdir, 'test'), 'wb')
+        temp.write(self.data)
+        temp.close()
 
     def tearDown(self):
         try:
-            self.tempfile.close()
+            os.chdir(self.cwd)
             try:
                 shutil.rmtree(self.tempdir)
             except:
@@ -222,7 +223,7 @@
 
     def test_get(self):
         #constructs the path relative to the root directory of the HTTPServer
-        response = self.request(self.tempdir_name + '/' + self.tempfile_name)
+        response = self.request(self.tempdir_name + '/test')
         self.check_status_and_reason(response, 200, data=self.data)
         response = self.request(self.tempdir_name + '/')
         self.check_status_and_reason(response, 200)
@@ -240,11 +241,11 @@
             os.chmod(self.tempdir, 0)
             response = self.request(self.tempdir_name + '/')
             self.check_status_and_reason(response, 404)
-            os.chmod(self.tempdir, 0755)
+            os.chmod(self.tempdir, 0o755)
 
     def test_head(self):
         response = self.request(
-            self.tempdir_name + '/'+ self.tempfile_name, method='HEAD')
+            self.tempdir_name + '/test', method='HEAD')
         self.check_status_and_reason(response, 200)
         self.assertEqual(response.getheader('content-length'),
                          str(len(self.data)))
@@ -264,21 +265,21 @@
 cgi_file1 = """\
 #!%s
 
-print "Content-type: text/html"
-print
-print "Hello World"
+print("Content-type: text/html")
+print()
+print("Hello World")
 """
 
 cgi_file2 = """\
 #!%s
 import cgi
 
-print "Content-type: text/html"
-print
+print("Content-type: text/html")
+print()
 
 form = cgi.FieldStorage()
-print "%%s, %%s, %%s" % (form.getfirst("spam"), form.getfirst("eggs"),\
-              form.getfirst("bacon"))
+print("%%s, %%s, %%s" %% (form.getfirst("spam"), form.getfirst("eggs"),\
+              form.getfirst("bacon")))
 """
 
 class CGIHTTPServerTestCase(BaseTestCase):
@@ -294,17 +295,19 @@
         self.file1_path = os.path.join(self.cgi_dir, 'file1.py')
         with open(self.file1_path, 'w') as file1:
             file1.write(cgi_file1 % sys.executable)
-        os.chmod(self.file1_path, 0777)
+        os.chmod(self.file1_path, 0o777)
 
         self.file2_path = os.path.join(self.cgi_dir, 'file2.py')
         with open(self.file2_path, 'w') as file2:
             file2.write(cgi_file2 % sys.executable)
-        os.chmod(self.file2_path, 0777)
+        os.chmod(self.file2_path, 0o777)
 
+        self.cwd = os.getcwd()
         os.chdir(self.parent_dir)
 
     def tearDown(self):
         try:
+            os.chdir(self.cwd)
             os.remove(self.file1_path)
             os.remove(self.file2_path)
             os.rmdir(self.cgi_dir)
@@ -314,7 +317,7 @@
 
     def test_headers_and_content(self):
         res = self.request('/cgi-bin/file1.py')
-        self.assertEquals(('Hello World\n', 'text/html', 200), \
+        self.assertEquals((b'Hello World\n', 'text/html', 200), \
              (res.read(), res.getheader('Content-type'), res.status))
 
     def test_post(self):
@@ -322,7 +325,7 @@
         headers = {'Content-type' : 'application/x-www-form-urlencoded'}
         res = self.request('/cgi-bin/file2.py', 'POST', params, headers)
 
-        self.assertEquals(res.read(), '1, python, 123456\n')
+        self.assertEquals(res.read(), b'1, python, 123456\n')
 
     def test_invaliduri(self):
         res = self.request('/cgi-bin/invalid')
@@ -330,20 +333,20 @@
         self.assertEquals(res.status, 404)
 
     def test_authorization(self):
-        headers = {'Authorization' : 'Basic %s' % \
-                base64.b64encode('username:pass')}
+        headers = {b'Authorization' : b'Basic ' +
+                   base64.b64encode(b'username:pass')}
         res = self.request('/cgi-bin/file1.py', 'GET', headers=headers)
-        self.assertEquals(('Hello World\n', 'text/html', 200), \
+        self.assertEquals((b'Hello World\n', 'text/html', 200), \
              (res.read(), res.getheader('Content-type'), res.status))
 
 
 def test_main(verbose=None):
     try:
         cwd = os.getcwd()
-        test_support.run_unittest(BaseHTTPServerTestCase,
-                                  #SimpleHTTPServerTestCase,
-                                  #CGIHTTPServerTestCase
-                                  )
+        support.run_unittest(#BaseHTTPServerTestCase,
+                             SimpleHTTPServerTestCase,
+                             CGIHTTPServerTestCase
+                             )
     finally:
         os.chdir(cwd)
 

Modified: python/branches/py3k/Lib/test/test_json.py
==============================================================================
--- python/branches/py3k/Lib/test/test_json.py	(original)
+++ python/branches/py3k/Lib/test/test_json.py	Sun May 25 20:19:30 2008
@@ -11,7 +11,6 @@
 
 def test_main():
     test.support.run_unittest(json.tests.test_suite())
-    test.support.run_doctest(json)
 
 
 if __name__ == "__main__":

Modified: python/branches/py3k/Lib/test/test_opcodes.py
==============================================================================
--- python/branches/py3k/Lib/test/test_opcodes.py	(original)
+++ python/branches/py3k/Lib/test/test_opcodes.py	Sun May 25 20:19:30 2008
@@ -68,35 +68,35 @@
 
         f = eval('lambda: None')
         g = eval('lambda: None')
-        self.failIf(f == g)
+        self.assertNotEquals(f, g)
 
         f = eval('lambda a: a')
         g = eval('lambda a: a')
-        self.failIf(f == g)
+        self.assertNotEquals(f, g)
 
         f = eval('lambda a=1: a')
         g = eval('lambda a=1: a')
-        self.failIf(f == g)
+        self.assertNotEquals(f, g)
 
         f = eval('lambda: 0')
         g = eval('lambda: 1')
-        self.failIf(f == g)
+        self.assertNotEquals(f, g)
 
         f = eval('lambda: None')
         g = eval('lambda a: None')
-        self.failIf(f == g)
+        self.assertNotEquals(f, g)
 
         f = eval('lambda a: None')
         g = eval('lambda b: None')
-        self.failIf(f == g)
+        self.assertNotEquals(f, g)
 
         f = eval('lambda a: None')
         g = eval('lambda a=None: None')
-        self.failIf(f == g)
+        self.assertNotEquals(f, g)
 
         f = eval('lambda a=0: None')
         g = eval('lambda a=1: None')
-        self.failIf(f == g)
+        self.assertNotEquals(f, g)
 
 
 def test_main():

Modified: python/branches/py3k/Lib/test/test_pyclbr.py
==============================================================================
--- python/branches/py3k/Lib/test/test_pyclbr.py	(original)
+++ python/branches/py3k/Lib/test/test_pyclbr.py	Sun May 25 20:19:30 2008
@@ -158,6 +158,7 @@
         cm('cgi', ignore=('log',))      # set with = in module
         cm('urllib', ignore=('_CFNumberToInt32',
                              '_CStringFromCFString',
+                             '_CFSetup',
                              'getproxies_registry',
                              'proxy_bypass_registry',
                              'proxy_bypass_macosx_sysconf',

Modified: python/branches/py3k/Lib/test/test_pydoc.py
==============================================================================
--- python/branches/py3k/Lib/test/test_pydoc.py	(original)
+++ python/branches/py3k/Lib/test/test_pydoc.py	Sun May 25 20:19:30 2008
@@ -1,25 +1,285 @@
-from test import support
-import unittest
-import pydoc
-
-class TestDescriptions(unittest.TestCase):
-    def test_module(self):
-        # Check that pydocfodder module can be described
-        from test import pydocfodder
-        doc = pydoc.render_doc(pydocfodder)
-        assert "pydocfodder" in doc
-
-    def test_class(self):
-        class C(object): "New-style class"
-        c = C()
-
-        self.failUnlessEqual(pydoc.describe(C), 'class C')
-        self.failUnlessEqual(pydoc.describe(c), 'C')
-        self.failUnless('C in module test.test_pydoc object'
-                        in pydoc.render_doc(c))
-
-def test_main():
-    support.run_unittest(TestDescriptions)
-
-if __name__ == "__main__":
-    unittest.main()
+import sys
+import os
+import difflib
+import subprocess
+import re
+import pydoc
+import inspect
+import unittest
+import test.support
+
+from test import pydoc_mod
+
+expected_text_pattern = \
+"""
+NAME
+    test.pydoc_mod - This is a test module for test_pydoc
+
+FILE
+    %s
+%s
+CLASSES
+    builtins.object
+        A
+        B
+\x20\x20\x20\x20
+    class A(builtins.object)
+     |  Hello and goodbye
+     |\x20\x20
+     |  Methods defined here:
+     |\x20\x20
+     |  __init__()
+     |      Wow, I have no function!
+     |\x20\x20
+     |  ----------------------------------------------------------------------
+     |  Data descriptors defined here:
+     |\x20\x20
+     |  __dict__
+     |      dictionary for instance variables (if defined)
+     |\x20\x20
+     |  __weakref__
+     |      list of weak references to the object (if defined)
+\x20\x20\x20\x20
+    class B(builtins.object)
+     |  Data descriptors defined here:
+     |\x20\x20
+     |  __dict__
+     |      dictionary for instance variables (if defined)
+     |\x20\x20
+     |  __weakref__
+     |      list of weak references to the object (if defined)
+     |\x20\x20
+     |  ----------------------------------------------------------------------
+     |  Data and other attributes defined here:
+     |\x20\x20
+     |  NO_MEANING = 'eggs'
+
+FUNCTIONS
+    doc_func()
+        This function solves all of the world's problems:
+        hunger
+        lack of Python
+        war
+\x20\x20\x20\x20
+    nodoc_func()
+
+DATA
+    __author__ = 'Benjamin Peterson'
+    __credits__ = 'Nobody'
+    __package__ = None
+    __version__ = '1.2.3.4'
+
+VERSION
+    1.2.3.4
+
+AUTHOR
+    Benjamin Peterson
+
+CREDITS
+    Nobody
+""".strip()
+
+expected_html_pattern = \
+"""
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="test.html"><font color="#ffffff">test</font></a>.pydoc_mod</strong></big></big> (version 1.2.3.4)</font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:%s">%s</a>%s</font></td></tr></table>
+    <p><tt>This&nbsp;is&nbsp;a&nbsp;test&nbsp;module&nbsp;for&nbsp;test_pydoc</tt></p>
+<p>
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+\x20\x20\x20\x20
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%%"><dl>
+<dt><font face="helvetica, arial"><a href="builtins.html#object">builtins.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="test.pydoc_mod.html#A">A</a>
+</font></dt><dt><font face="helvetica, arial"><a href="test.pydoc_mod.html#B">B</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="A">class <strong>A</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
+\x20\x20\x20\x20
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Hello&nbsp;and&nbsp;goodbye<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%%">Methods defined here:<br>
+<dl><dt><a name="A-__init__"><strong>__init__</strong></a>()</dt><dd><tt>Wow,&nbsp;I&nbsp;have&nbsp;no&nbsp;function!</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="B">class <strong>B</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
+\x20\x20\x20\x20
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%%">Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>NO_MEANING</strong> = 'eggs'</dl>
+
+</td></tr></table></td></tr></table><p>
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+\x20\x20\x20\x20
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%%"><dl><dt><a name="-doc_func"><strong>doc_func</strong></a>()</dt><dd><tt>This&nbsp;function&nbsp;solves&nbsp;all&nbsp;of&nbsp;the&nbsp;world's&nbsp;problems:<br>
+hunger<br>
+lack&nbsp;of&nbsp;Python<br>
+war</tt></dd></dl>
+ <dl><dt><a name="-nodoc_func"><strong>nodoc_func</strong></a>()</dt></dl>
+</td></tr></table><p>
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+\x20\x20\x20\x20
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%%"><strong>__author__</strong> = 'Benjamin Peterson'<br>
+<strong>__credits__</strong> = 'Nobody'<br>
+<strong>__package__</strong> = None<br>
+<strong>__version__</strong> = '1.2.3.4'</td></tr></table><p>
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#7799ee">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Author</strong></big></font></td></tr>
+\x20\x20\x20\x20
+<tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%%">Benjamin&nbsp;Peterson</td></tr></table><p>
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#7799ee">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Credits</strong></big></font></td></tr>
+\x20\x20\x20\x20
+<tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%%">Nobody</td></tr></table>
+""".strip()
+
+
+# output pattern for missing module
+missing_pattern = "no Python documentation found for '%s'"
+
+def run_pydoc(module_name, *args):
+    """
+    Runs pydoc on the specified module. Returns the stripped
+    output of pydoc.
+    """
+    cmd = [sys.executable, pydoc.__file__, " ".join(args), module_name]
+    output = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout.read()
+    return output.strip()
+
+def get_pydoc_html(module):
+    "Returns pydoc generated output as html"
+    doc = pydoc.HTMLDoc()
+    output = doc.docmodule(module)
+    loc = doc.getdocloc(pydoc_mod) or ""
+    if loc:
+        loc = "<br><a href=\"" + loc + "\">Module Docs</a>"
+    return output.strip(), loc
+
+def get_pydoc_text(module):
+    "Returns pydoc generated output as text"
+    doc = pydoc.TextDoc()
+    loc = doc.getdocloc(pydoc_mod) or ""
+    if loc:
+        loc = "\nMODULE DOCS\n    " + loc + "\n"
+
+    output = doc.docmodule(module)
+
+    # cleanup the extra text formatting that pydoc preforms
+    patt = re.compile('\b.')
+    output = patt.sub('', output)
+    return output.strip(), loc
+
+def print_diffs(text1, text2):
+    "Prints unified diffs for two texts"
+    lines1 = text1.splitlines(True)
+    lines2 = text2.splitlines(True)
+    diffs = difflib.unified_diff(lines1, lines2, n=0, fromfile='expected',
+                                 tofile='got')
+    print('\n' + ''.join(diffs))
+
+
+class PyDocDocTest(unittest.TestCase):
+
+    def test_html_doc(self):
+        result, doc_loc = get_pydoc_html(pydoc_mod)
+        mod_file = inspect.getabsfile(pydoc_mod)
+        expected_html = expected_html_pattern % (mod_file, mod_file, doc_loc)
+        if result != expected_html:
+            print_diffs(expected_html, result)
+            self.fail("outputs are not equal, see diff above")
+
+    def test_text_doc(self):
+        result, doc_loc = get_pydoc_text(pydoc_mod)
+        expected_text = expected_text_pattern % \
+                        (inspect.getabsfile(pydoc_mod), doc_loc)
+        if result != expected_text:
+            print_diffs(expected_text, result)
+            self.fail("outputs are not equal, see diff above")
+
+    def test_not_here(self):
+        missing_module = "test.i_am_not_here"
+        result = str(run_pydoc(missing_module), 'ascii')
+        expected = missing_pattern % missing_module
+        self.assertEqual(expected, result,
+            "documentation for missing module found")
+
+
+class TestDescriptions(unittest.TestCase):
+
+    def test_module(self):
+        # Check that pydocfodder module can be described
+        from test import pydocfodder
+        doc = pydoc.render_doc(pydocfodder)
+        self.assert_("pydocfodder" in doc)
+
+    def test_classic_class(self):
+        class C: "Classic class"
+        c = C()
+        self.assertEqual(pydoc.describe(C), 'class C')
+        self.assertEqual(pydoc.describe(c), 'C')
+        expected = 'C in module %s' % __name__
+        self.assert_(expected in pydoc.render_doc(c))
+
+    def test_class(self):
+        class C(object): "New-style class"
+        c = C()
+
+        self.assertEqual(pydoc.describe(C), 'class C')
+        self.assertEqual(pydoc.describe(c), 'C')
+        expected = 'C in module %s object' % __name__
+        self.assert_(expected in pydoc.render_doc(c))
+
+
+def test_main():
+    test.support.run_unittest(PyDocDocTest, TestDescriptions)
+
+if __name__ == "__main__":
+    test_main()

Modified: python/branches/py3k/Lib/test/test_weakref.py
==============================================================================
--- python/branches/py3k/Lib/test/test_weakref.py	(original)
+++ python/branches/py3k/Lib/test/test_weakref.py	Sun May 25 20:19:30 2008
@@ -3,6 +3,7 @@
 import unittest
 import collections
 import weakref
+import operator
 
 from test import support
 
@@ -182,6 +183,26 @@
         self.assertEqual(L3[:5], p3[:5])
         self.assertEqual(L3[2:5], p3[2:5])
 
+    def test_proxy_index(self):
+        class C:
+            def __index__(self):
+                return 10
+        o = C()
+        p = weakref.proxy(o)
+        self.assertEqual(operator.index(p), 10)
+
+    def test_proxy_div(self):
+        class C:
+            def __floordiv__(self, other):
+                return 42
+            def __ifloordiv__(self, other):
+                return 21
+        o = C()
+        p = weakref.proxy(o)
+        self.assertEqual(p // 5, 42)
+        p //= 5
+        self.assertEqual(p, 21)
+
     # The PyWeakref_* C API is documented as allowing either NULL or
     # None as the value for the callback, where either means "no
     # callback".  The "no callback" ref and proxy objects are supposed
@@ -1059,7 +1080,7 @@
     def _reference(self):
         return self.__ref.copy()
 
-libreftest = """ Doctest for examples in the library reference: libweakref.tex
+libreftest = """ Doctest for examples in the library reference: weakref.rst
 
 >>> import weakref
 >>> class Dict(dict):

Modified: python/branches/py3k/Lib/test/test_zipfile.py
==============================================================================
--- python/branches/py3k/Lib/test/test_zipfile.py	(original)
+++ python/branches/py3k/Lib/test/test_zipfile.py	Sun May 25 20:19:30 2008
@@ -125,6 +125,25 @@
         for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
             self.zipOpenTest(f, zipfile.ZIP_STORED)
 
+    def testOpenViaZipInfo(self):
+        # Create the ZIP archive
+        zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
+        zipfp.writestr("name", "foo")
+        zipfp.writestr("name", "bar")
+        zipfp.close()
+
+        zipfp = zipfile.ZipFile(TESTFN2, "r")
+        infos = zipfp.infolist()
+        data = b""
+        for info in infos:
+            data += zipfp.open(info).read()
+        self.assert_(data == b"foobar" or data == b"barfoo")
+        data = b""
+        for info in infos:
+            data += zipfp.read(info)
+        self.assert_(data == b"foobar" or data == b"barfoo")
+        zipfp.close()
+
     def zipRandomOpenTest(self, f, compression):
         self.makeTestArchive(f, compression)
 

Modified: python/branches/py3k/Lib/tkinter/__init__.py
==============================================================================
--- python/branches/py3k/Lib/tkinter/__init__.py	(original)
+++ python/branches/py3k/Lib/tkinter/__init__.py	Sun May 25 20:19:30 2008
@@ -2903,8 +2903,7 @@
         and edit_undo
 
         """
-        return self._getints(
-            self.tk.call((self._w, 'edit') + args)) or ()
+        return self.tk.call(self._w, 'edit', *args)
 
     def edit_modified(self, arg=None):
         """Get or Set the modified flag

Modified: python/branches/py3k/Lib/zipfile.py
==============================================================================
--- python/branches/py3k/Lib/zipfile.py	(original)
+++ python/branches/py3k/Lib/zipfile.py	Sun May 25 20:19:30 2008
@@ -783,10 +783,13 @@
         else:
             zef_file = io.open(self.filename, 'rb')
 
-        # Get info object for name
-        zinfo = self.getinfo(name)
-
-        filepos = zef_file.tell()
+        # Make sure we have an info object
+        if isinstance(name, ZipInfo):
+            # 'name' is already an info object
+            zinfo = name
+        else:
+            # Get info object for name
+            zinfo = self.getinfo(name)
 
         zef_file.seek(zinfo.header_offset, 0)
 
@@ -891,7 +894,7 @@
         if upperdirs and not os.path.exists(upperdirs):
             os.makedirs(upperdirs)
 
-        source = self.open(member.filename, pwd=pwd)
+        source = self.open(member, pwd=pwd)
         target = open(targetpath, "wb")
         shutil.copyfileobj(source, target)
         source.close()

Modified: python/branches/py3k/Makefile.pre.in
==============================================================================
--- python/branches/py3k/Makefile.pre.in	(original)
+++ python/branches/py3k/Makefile.pre.in	Sun May 25 20:19:30 2008
@@ -373,6 +373,12 @@
 build_all_use_profile:
 	$(MAKE) all CFLAGS="$(CFLAGS) -fprofile-use"
 
+coverage:
+	@echo "Building with support for coverage checking:"
+	$(MAKE) clean
+	$(MAKE) all CFLAGS="$(CFLAGS) -O0 -pg -fprofile-arcs -ftest-coverage" LIBS="$(LIBS) -lgcov"
+
+
 # Build the interpreter
 $(BUILDPYTHON):	Modules/python.o $(LIBRARY) $(LDLIBRARY)
 		$(LINKCC) $(LDFLAGS) $(LINKFORSHARED) -o $@ \

Modified: python/branches/py3k/Misc/ACKS
==============================================================================
--- python/branches/py3k/Misc/ACKS	(original)
+++ python/branches/py3k/Misc/ACKS	Sun May 25 20:19:30 2008
@@ -375,6 +375,7 @@
 Joseph Koshy
 Bob Kras
 Holger Krekel
+Michael Kremer
 Fabian Kreutz
 Hannu Krosing
 Andrew Kuchling
@@ -496,6 +497,7 @@
 Jason Orendorff
 Douglas Orr
 Denis S. Otkidach
+Michael Otteneder
 Russel Owen
 Ondrej Palkovsky
 Mike Pall
@@ -634,6 +636,7 @@
 Rafal Smotrzyk
 Dirk Soede
 Paul Sokolovsky
+Cody Somerville
 Clay Spence
 Per Spilling
 Joshua Spoerri

Modified: python/branches/py3k/Misc/build.sh
==============================================================================
--- python/branches/py3k/Misc/build.sh	(original)
+++ python/branches/py3k/Misc/build.sh	Sun May 25 20:19:30 2008
@@ -67,7 +67,7 @@
 # Note: test_XXX (none currently) really leak, but are disabled
 # so we don't send spam.  Any test which really leaks should only 
 # be listed here if there are also test cases under Lib/test/leakers.
-LEAKY_TESTS="test_(asynchat|cmd_line|popen2|socket|smtplib|sys|threadsignals|urllib2_localnet)"
+LEAKY_TESTS="test_(asynchat|cmd_line|popen2|socket|smtplib|sys|threadsignals|urllib2_localnet|httpservers)"
 
 # These tests always fail, so skip them so we don't get false positives.
 _ALWAYS_SKIP=""

Modified: python/branches/py3k/Objects/weakrefobject.c
==============================================================================
--- python/branches/py3k/Objects/weakrefobject.c	(original)
+++ python/branches/py3k/Objects/weakrefobject.c	Sun May 25 20:19:30 2008
@@ -474,6 +474,8 @@
 WRAP_BINARY(proxy_add, PyNumber_Add)
 WRAP_BINARY(proxy_sub, PyNumber_Subtract)
 WRAP_BINARY(proxy_mul, PyNumber_Multiply)
+WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
+WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
 WRAP_BINARY(proxy_mod, PyNumber_Remainder)
 WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
 WRAP_TERNARY(proxy_pow, PyNumber_Power)
@@ -492,6 +494,8 @@
 WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
 WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
 WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
+WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
+WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
 WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
 WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
 WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
@@ -499,6 +503,7 @@
 WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
 WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
 WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
+WRAP_UNARY(proxy_index, PyNumber_Index)
 
 static int
 proxy_bool(PyWeakReference *proxy)
@@ -605,6 +610,11 @@
     proxy_iand,             /*nb_inplace_and*/
     proxy_ixor,             /*nb_inplace_xor*/
     proxy_ior,              /*nb_inplace_or*/
+    proxy_floor_div,        /*nb_floor_divide*/
+    proxy_true_div,         /*nb_true_divide*/
+    proxy_ifloor_div,       /*nb_inplace_floor_divide*/
+    proxy_itrue_div,        /*nb_inplace_true_divide*/
+    proxy_index,            /*nb_index*/
 };
 
 static PySequenceMethods proxy_as_sequence = {


More information about the Python-3000-checkins mailing list