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.
........
diff --git a/Lib/BaseHTTPServer.py b/Lib/BaseHTTPServer.py
index 8a099fe..7fbbcf2 100644
--- a/Lib/BaseHTTPServer.py
+++ b/Lib/BaseHTTPServer.py
@@ -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':
diff --git a/Lib/CGIHTTPServer.py b/Lib/CGIHTTPServer.py
index 828b092..29d701a 100644
--- a/Lib/CGIHTTPServer.py
+++ b/Lib/CGIHTTPServer.py
@@ -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(':')
diff --git a/Lib/SimpleHTTPServer.py b/Lib/SimpleHTTPServer.py
index beb0a39..36a249c 100644
--- a/Lib/SimpleHTTPServer.py
+++ b/Lib/SimpleHTTPServer.py
@@ -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
 
diff --git a/Lib/distutils/tests/test_build_ext.py b/Lib/distutils/tests/test_build_ext.py
new file mode 100644
index 0000000..96c0a23
--- /dev/null
+++ b/Lib/distutils/tests/test_build_ext.py
@@ -0,0 +1,72 @@
+import sys
+import os
+import tempfile
+import shutil
+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 support
+
+class BuildExtTestCase(unittest.TestCase):
+    def setUp(self):
+        # Create a simple test environment
+        # Note that we're making changes to sys.path
+        self.tmp_dir = tempfile.mkdtemp(prefix="pythontest_")
+        self.sys_path = sys.path[:]
+        sys.path.append(self.tmp_dir)
+
+        xx_c = os.path.join(sysconfig.project_base, 'Modules', 'xxmodule.c')
+        shutil.copy(xx_c, self.tmp_dir)
+
+    def test_build_ext(self):
+        xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
+        xx_ext = Extension('xx', [xx_c])
+        dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
+        dist.package_dir = self.tmp_dir
+        cmd = build_ext(dist)
+        cmd.build_lib = self.tmp_dir
+        cmd.build_temp = self.tmp_dir
+
+        old_stdout = sys.stdout
+        if not support.verbose:
+            # silence compiler output
+            sys.stdout = StringIO()
+        try:
+            cmd.ensure_finalized()
+            cmd.run()
+        finally:
+            sys.stdout = old_stdout
+
+        import xx
+
+        for attr in ('error', 'foo', 'new', 'roj'):
+            self.assert_(hasattr(xx, attr))
+
+        self.assertEquals(xx.foo(2, 5), 7)
+        self.assertEquals(xx.foo(13,15), 28)
+        self.assertEquals(xx.new().demo(), None)
+        doc = 'This is a template module just for instruction.'
+        self.assertEquals(xx.__doc__, doc)
+        self.assert_(isinstance(xx.Null(), xx.Null))
+        self.assert_(isinstance(xx.Str(), xx.Str))
+
+    def tearDown(self):
+        # Get everything back to normal
+        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 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__':
+    support.run_unittest(test_suite())
diff --git a/Lib/gzip.py b/Lib/gzip.py
index 45fae9f..9d8dac5 100644
--- a/Lib/gzip.py
+++ b/Lib/gzip.py
@@ -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)
diff --git a/Lib/test/pydoc_mod.py b/Lib/test/pydoc_mod.py
new file mode 100644
index 0000000..8601e3f
--- /dev/null
+++ b/Lib/test/pydoc_mod.py
@@ -0,0 +1,54 @@
+"""This is a test module for test_pydoc"""
+
+__author__ = "Benjamin Peterson"
+__credits__ = "Nobody"
+__version__ = "1.2.3.4"
+
+
+class A:
+    """Hello and goodbye"""
+    def __init__():
+        """Wow, I have no function!"""
+        pass
+
+class B(object):
+    NO_MEANING = "eggs"
+    pass
+
+def doc_func():
+    """
+    This function solves all of the world's problems:
+    hunger
+    lack of Python
+    war
+    """
+
+def nodoc_func():
+    pass
+"""This is a test module for test_pydoc"""
+
+__author__ = "Benjamin Peterson"
+__credits__ = "Nobody"
+__version__ = "1.2.3.4"
+
+
+class A:
+    """Hello and goodbye"""
+    def __init__():
+        """Wow, I have no function!"""
+        pass
+
+class B(object):
+    NO_MEANING = "eggs"
+    pass
+
+def doc_func():
+    """
+    This function solves all of the world's problems:
+    hunger
+    lack of Python
+    war
+    """
+
+def nodoc_func():
+    pass
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
index ad8c230..4ed0e24 100644
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -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)))
diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py
index c26035b..d28c024 100644
--- a/Lib/test/test_gzip.py
+++ b/Lib/test/test_gzip.py
@@ -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.
diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py
new file mode 100644
index 0000000..cc79cb8
--- /dev/null
+++ b/Lib/test/test_httpservers.py
@@ -0,0 +1,354 @@
+"""Unittests for the various HTTPServer modules.
+
+Written by Cody A.W. Somerville <cody-somerville@ubuntu.com>,
+Josip Dzolonga, and Michael Otteneder for the 2007/08 GHOP contest.
+"""
+
+from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
+from SimpleHTTPServer import SimpleHTTPRequestHandler
+from CGIHTTPServer import CGIHTTPRequestHandler
+
+import os
+import sys
+import base64
+import shutil
+import urllib
+import httplib
+import tempfile
+import threading
+
+import unittest
+from test import support
+
+
+class NoLogRequestHandler:
+    def log_message(self, *args):
+        # don't write log messages to stderr
+        pass
+
+
+class TestServerThread(threading.Thread):
+    def __init__(self, test_object, request_handler):
+        threading.Thread.__init__(self)
+        self.request_handler = request_handler
+        self.test_object = test_object
+        self.test_object.lock.acquire()
+
+    def run(self):
+        self.server = HTTPServer(('', 0), self.request_handler)
+        self.test_object.PORT = self.server.socket.getsockname()[1]
+        self.test_object.lock.release()
+        try:
+            self.server.serve_forever()
+        finally:
+            self.server.server_close()
+
+    def stop(self):
+        self.server.shutdown()
+
+
+class BaseTestCase(unittest.TestCase):
+    def setUp(self):
+        self.lock = threading.Lock()
+        self.thread = TestServerThread(self, self.request_handler)
+        self.thread.start()
+        self.lock.acquire()
+
+    def tearDown(self):
+        self.lock.release()
+        self.thread.stop()
+
+    def request(self, uri, method='GET', body=None, headers={}):
+        self.connection = httplib.HTTPConnection('localhost', self.PORT)
+        self.connection.request(method, uri, body, headers)
+        return self.connection.getresponse()
+
+
+class BaseHTTPServerTestCase(BaseTestCase):
+    class request_handler(NoLogRequestHandler, BaseHTTPRequestHandler):
+        protocol_version = 'HTTP/1.1'
+        default_request_version = 'HTTP/1.1'
+
+        def do_TEST(self):
+            self.send_response(204)
+            self.send_header('Content-Type', 'text/html')
+            self.send_header('Connection', 'close')
+            self.end_headers()
+
+        def do_KEEP(self):
+            self.send_response(204)
+            self.send_header('Content-Type', 'text/html')
+            self.send_header('Connection', 'keep-alive')
+            self.end_headers()
+
+        def do_KEYERROR(self):
+            self.send_error(999)
+
+        def do_CUSTOM(self):
+            self.send_response(999)
+            self.send_header('Content-Type', 'text/html')
+            self.send_header('Connection', 'close')
+            self.end_headers()
+
+    def setUp(self):
+        BaseTestCase.setUp(self)
+        self.con = httplib.HTTPConnection('localhost', self.PORT)
+        self.con.connect()
+
+    def test_command(self):
+        self.con.request('GET', '/')
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 501)
+
+    def test_request_line_trimming(self):
+        self.con._http_vsn_str = 'HTTP/1.1\n'
+        self.con.putrequest('GET', '/')
+        self.con.endheaders()
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 501)
+
+    def test_version_bogus(self):
+        self.con._http_vsn_str = 'FUBAR'
+        self.con.putrequest('GET', '/')
+        self.con.endheaders()
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 400)
+
+    def test_version_digits(self):
+        self.con._http_vsn_str = 'HTTP/9.9.9'
+        self.con.putrequest('GET', '/')
+        self.con.endheaders()
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 400)
+
+    def test_version_none_get(self):
+        self.con._http_vsn_str = ''
+        self.con.putrequest('GET', '/')
+        self.con.endheaders()
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 501)
+
+    def test_version_none(self):
+        self.con._http_vsn_str = ''
+        self.con.putrequest('PUT', '/')
+        self.con.endheaders()
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 400)
+
+    def test_version_invalid(self):
+        self.con._http_vsn = 99
+        self.con._http_vsn_str = 'HTTP/9.9'
+        self.con.putrequest('GET', '/')
+        self.con.endheaders()
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 505)
+
+    def test_send_blank(self):
+        self.con._http_vsn_str = ''
+        self.con.putrequest('', '')
+        self.con.endheaders()
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 400)
+
+    def test_header_close(self):
+        self.con.putrequest('GET', '/')
+        self.con.putheader('Connection', 'close')
+        self.con.endheaders()
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 501)
+
+    def test_head_keep_alive(self):
+        self.con._http_vsn_str = 'HTTP/1.1'
+        self.con.putrequest('GET', '/')
+        self.con.putheader('Connection', 'keep-alive')
+        self.con.endheaders()
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 501)
+
+    def test_handler(self):
+        self.con.request('TEST', '/')
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 204)
+
+    def test_return_header_keep_alive(self):
+        self.con.request('KEEP', '/')
+        res = self.con.getresponse()
+        self.assertEquals(res.getheader('Connection'), 'keep-alive')
+        self.con.request('TEST', '/')
+
+    def test_internal_key_error(self):
+        self.con.request('KEYERROR', '/')
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 999)
+
+    def test_return_custom_status(self):
+        self.con.request('CUSTOM', '/')
+        res = self.con.getresponse()
+        self.assertEquals(res.status, 999)
+
+
+class SimpleHTTPServerTestCase(BaseTestCase):
+    class request_handler(NoLogRequestHandler, SimpleHTTPRequestHandler):
+        pass
+
+    def setUp(self):
+        BaseTestCase.setUp(self)
+        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)
+        temp = open(os.path.join(self.tempdir, 'test'), 'wb')
+        temp.write(self.data)
+        temp.close()
+
+    def tearDown(self):
+        try:
+            os.chdir(self.cwd)
+            try:
+                shutil.rmtree(self.tempdir)
+            except:
+                pass
+        finally:
+            BaseTestCase.tearDown(self)
+
+    def check_status_and_reason(self, response, status, data=None):
+        body = response.read()
+        self.assert_(response)
+        self.assertEquals(response.status, status)
+        self.assert_(response.reason != None)
+        if data:
+            self.assertEqual(data, body)
+
+    def test_get(self):
+        #constructs the path relative to the root directory of the HTTPServer
+        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)
+        response = self.request(self.tempdir_name)
+        self.check_status_and_reason(response, 301)
+        response = self.request('/ThisDoesNotExist')
+        self.check_status_and_reason(response, 404)
+        response = self.request('/' + 'ThisDoesNotExist' + '/')
+        self.check_status_and_reason(response, 404)
+        f = open(os.path.join(self.tempdir_name, 'index.html'), 'w')
+        response = self.request('/' + self.tempdir_name + '/')
+        self.check_status_and_reason(response, 200)
+        if os.name == 'posix':
+            # chmod won't work as expected on Windows platforms
+            os.chmod(self.tempdir, 0)
+            response = self.request(self.tempdir_name + '/')
+            self.check_status_and_reason(response, 404)
+            os.chmod(self.tempdir, 0o755)
+
+    def test_head(self):
+        response = self.request(
+            self.tempdir_name + '/test', method='HEAD')
+        self.check_status_and_reason(response, 200)
+        self.assertEqual(response.getheader('content-length'),
+                         str(len(self.data)))
+        self.assertEqual(response.getheader('content-type'),
+                         'application/octet-stream')
+
+    def test_invalid_requests(self):
+        response = self.request('/', method='FOO')
+        self.check_status_and_reason(response, 501)
+        # requests must be case sensitive,so this should fail too
+        response = self.request('/', method='get')
+        self.check_status_and_reason(response, 501)
+        response = self.request('/', method='GETs')
+        self.check_status_and_reason(response, 501)
+
+
+cgi_file1 = """\
+#!%s
+
+print("Content-type: text/html")
+print()
+print("Hello World")
+"""
+
+cgi_file2 = """\
+#!%s
+import cgi
+
+print("Content-type: text/html")
+print()
+
+form = cgi.FieldStorage()
+print("%%s, %%s, %%s" %% (form.getfirst("spam"), form.getfirst("eggs"),\
+              form.getfirst("bacon")))
+"""
+
+class CGIHTTPServerTestCase(BaseTestCase):
+    class request_handler(NoLogRequestHandler, CGIHTTPRequestHandler):
+        pass
+
+    def setUp(self):
+        BaseTestCase.setUp(self)
+        self.parent_dir = tempfile.mkdtemp()
+        self.cgi_dir = os.path.join(self.parent_dir, 'cgi-bin')
+        os.mkdir(self.cgi_dir)
+
+        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, 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, 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)
+            os.rmdir(self.parent_dir)
+        finally:
+            BaseTestCase.tearDown(self)
+
+    def test_headers_and_content(self):
+        res = self.request('/cgi-bin/file1.py')
+        self.assertEquals((b'Hello World\n', 'text/html', 200), \
+             (res.read(), res.getheader('Content-type'), res.status))
+
+    def test_post(self):
+        params = urllib.urlencode({'spam' : 1, 'eggs' : 'python', 'bacon' : 123456})
+        headers = {'Content-type' : 'application/x-www-form-urlencoded'}
+        res = self.request('/cgi-bin/file2.py', 'POST', params, headers)
+
+        self.assertEquals(res.read(), b'1, python, 123456\n')
+
+    def test_invaliduri(self):
+        res = self.request('/cgi-bin/invalid')
+        res.read()
+        self.assertEquals(res.status, 404)
+
+    def test_authorization(self):
+        headers = {b'Authorization' : b'Basic ' +
+                   base64.b64encode(b'username:pass')}
+        res = self.request('/cgi-bin/file1.py', 'GET', headers=headers)
+        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()
+        support.run_unittest(#BaseHTTPServerTestCase,
+                             SimpleHTTPServerTestCase,
+                             CGIHTTPServerTestCase
+                             )
+    finally:
+        os.chdir(cwd)
+
+if __name__ == '__main__':
+    test_main()
diff --git a/Lib/test/test_json.py b/Lib/test/test_json.py
index 17e1daf..a4b6e7a 100644
--- a/Lib/test/test_json.py
+++ b/Lib/test/test_json.py
@@ -11,7 +11,6 @@
 
 def test_main():
     test.support.run_unittest(json.tests.test_suite())
-    test.support.run_doctest(json)
 
 
 if __name__ == "__main__":
diff --git a/Lib/test/test_opcodes.py b/Lib/test/test_opcodes.py
index 42ba600..8fe77ac 100644
--- a/Lib/test/test_opcodes.py
+++ b/Lib/test/test_opcodes.py
@@ -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():
diff --git a/Lib/test/test_pyclbr.py b/Lib/test/test_pyclbr.py
index bcc16df..ca0aefc 100644
--- a/Lib/test/test_pyclbr.py
+++ b/Lib/test/test_pyclbr.py
@@ -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',
diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py
index cc4a096..ab1b083 100644
--- a/Lib/test/test_pydoc.py
+++ b/Lib/test/test_pydoc.py
@@ -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()
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index 303345b..a056c23 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -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):
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index 30efeb9..4682b7d 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -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)
 
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 49ca8a5..f26fda9 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -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
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index 73b62af..fd923c8 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -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()