[pypy-commit] pypy stdlib-2.7.6: merge stdlib 2.7.6 from vendor/stdlib

bdkearns noreply at buildbot.pypy.org
Sat Mar 1 22:24:10 CET 2014


Author: Brian Kearns <bdkearns at gmail.com>
Branch: stdlib-2.7.6
Changeset: r69579:cfd0f4c85cb2
Date: 2014-03-01 16:20 -0500
http://bitbucket.org/pypy/pypy/changeset/cfd0f4c85cb2/

Log:	merge stdlib 2.7.6 from vendor/stdlib

diff too long, truncating to 2000 out of 10531 lines

diff --git a/lib-python/2.7/CGIHTTPServer.py b/lib-python/2.7/CGIHTTPServer.py
--- a/lib-python/2.7/CGIHTTPServer.py
+++ b/lib-python/2.7/CGIHTTPServer.py
@@ -105,18 +105,17 @@
 
     def run_cgi(self):
         """Execute a CGI script."""
-        path = self.path
         dir, rest = self.cgi_info
 
-        i = path.find('/', len(dir) + 1)
+        i = rest.find('/')
         while i >= 0:
-            nextdir = path[:i]
-            nextrest = path[i+1:]
+            nextdir = rest[:i]
+            nextrest = rest[i+1:]
 
             scriptdir = self.translate_path(nextdir)
             if os.path.isdir(scriptdir):
                 dir, rest = nextdir, nextrest
-                i = path.find('/', len(dir) + 1)
+                i = rest.find('/')
             else:
                 break
 
diff --git a/lib-python/2.7/Cookie.py b/lib-python/2.7/Cookie.py
--- a/lib-python/2.7/Cookie.py
+++ b/lib-python/2.7/Cookie.py
@@ -238,7 +238,7 @@
 # a two-way quoting algorithm.  Any non-text character is translated
 # into a 4 character sequence: a forward-slash followed by the
 # three-digit octal equivalent of the character.  Any '\' or '"' is
-# quoted with a preceeding '\' slash.
+# quoted with a preceding '\' slash.
 #
 # These are taken from RFC2068 and RFC2109.
 #       _LegalChars       is the list of chars which don't require "'s
diff --git a/lib-python/2.7/Queue.py b/lib-python/2.7/Queue.py
--- a/lib-python/2.7/Queue.py
+++ b/lib-python/2.7/Queue.py
@@ -109,7 +109,7 @@
 
         If optional args 'block' is true and 'timeout' is None (the default),
         block if necessary until a free slot is available. If 'timeout' is
-        a positive number, it blocks at most 'timeout' seconds and raises
+        a non-negative number, it blocks at most 'timeout' seconds and raises
         the Full exception if no free slot was available within that time.
         Otherwise ('block' is false), put an item on the queue if a free slot
         is immediately available, else raise the Full exception ('timeout'
@@ -125,7 +125,7 @@
                     while self._qsize() == self.maxsize:
                         self.not_full.wait()
                 elif timeout < 0:
-                    raise ValueError("'timeout' must be a positive number")
+                    raise ValueError("'timeout' must be a non-negative number")
                 else:
                     endtime = _time() + timeout
                     while self._qsize() == self.maxsize:
@@ -152,7 +152,7 @@
 
         If optional args 'block' is true and 'timeout' is None (the default),
         block if necessary until an item is available. If 'timeout' is
-        a positive number, it blocks at most 'timeout' seconds and raises
+        a non-negative number, it blocks at most 'timeout' seconds and raises
         the Empty exception if no item was available within that time.
         Otherwise ('block' is false), return an item if one is immediately
         available, else raise the Empty exception ('timeout' is ignored
@@ -167,7 +167,7 @@
                 while not self._qsize():
                     self.not_empty.wait()
             elif timeout < 0:
-                raise ValueError("'timeout' must be a positive number")
+                raise ValueError("'timeout' must be a non-negative number")
             else:
                 endtime = _time() + timeout
                 while not self._qsize():
diff --git a/lib-python/2.7/SimpleHTTPServer.py b/lib-python/2.7/SimpleHTTPServer.py
--- a/lib-python/2.7/SimpleHTTPServer.py
+++ b/lib-python/2.7/SimpleHTTPServer.py
@@ -149,6 +149,8 @@
         # abandon query parameters
         path = path.split('?',1)[0]
         path = path.split('#',1)[0]
+        # Don't forget explicit trailing slash when normalizing. Issue17324
+        trailing_slash = path.rstrip().endswith('/')
         path = posixpath.normpath(urllib.unquote(path))
         words = path.split('/')
         words = filter(None, words)
@@ -158,6 +160,8 @@
             head, word = os.path.split(word)
             if word in (os.curdir, os.pardir): continue
             path = os.path.join(path, word)
+        if trailing_slash:
+            path += '/'
         return path
 
     def copyfile(self, source, outputfile):
diff --git a/lib-python/2.7/_osx_support.py b/lib-python/2.7/_osx_support.py
--- a/lib-python/2.7/_osx_support.py
+++ b/lib-python/2.7/_osx_support.py
@@ -53,7 +53,7 @@
 
 
 def _read_output(commandstring):
-    """Output from succesful command execution or None"""
+    """Output from successful command execution or None"""
     # Similar to os.popen(commandstring, "r").read(),
     # but without actually using os.popen because that
     # function is not usable during python bootstrap.
@@ -68,7 +68,7 @@
 
     with contextlib.closing(fp) as fp:
         cmd = "%s 2>/dev/null >'%s'" % (commandstring, fp.name)
-        return fp.read().decode('utf-8').strip() if not os.system(cmd) else None
+        return fp.read().strip() if not os.system(cmd) else None
 
 
 def _find_build_tool(toolname):
@@ -152,7 +152,7 @@
     #    are not installed.
     #
     #    Futhermore, the compiler that can be used varies between
-    #    Xcode releases. Upto Xcode 4 it was possible to use 'gcc-4.2'
+    #    Xcode releases. Up to Xcode 4 it was possible to use 'gcc-4.2'
     #    as the compiler, after that 'clang' should be used because
     #    gcc-4.2 is either not present, or a copy of 'llvm-gcc' that
     #    miscompiles Python.
@@ -192,7 +192,7 @@
 
     if cc != oldcc:
         # Found a replacement compiler.
-        # Modify config vars using new compiler, if not already explictly
+        # Modify config vars using new compiler, if not already explicitly
         # overriden by an env variable, preserving additional arguments.
         for cv in _COMPILER_CONFIG_VARS:
             if cv in _config_vars and cv not in os.environ:
@@ -235,13 +235,19 @@
     if re.search('-arch\s+ppc', _config_vars['CFLAGS']) is not None:
         # NOTE: Cannot use subprocess here because of bootstrap
         # issues when building Python itself
-        status = os.system("'%s' -arch ppc -x c /dev/null 2>/dev/null"%(
-            _config_vars['CC'].replace("'", "'\"'\"'"),))
-        # The Apple compiler drivers return status 255 if no PPC
-        if (status >> 8) == 255:
-            # Compiler doesn't support PPC, remove the related
-            # '-arch' flags if not explicitly overridden by an
-            # environment variable
+        status = os.system(
+            """echo 'int main{};' | """
+            """'%s' -c -arch ppc -x c -o /dev/null /dev/null 2>/dev/null"""
+            %(_config_vars['CC'].replace("'", "'\"'\"'"),))
+        if status:
+            # The compile failed for some reason.  Because of differences
+            # across Xcode and compiler versions, there is no reliable way
+            # to be sure why it failed.  Assume here it was due to lack of
+            # PPC support and remove the related '-arch' flags from each
+            # config variables not explicitly overriden by an environment
+            # variable.  If the error was for some other reason, we hope the
+            # failure will show up again when trying to compile an extension
+            # module.
             for cv in _UNIVERSAL_CONFIG_VARS:
                 if cv in _config_vars and cv not in os.environ:
                     flags = _config_vars[cv]
@@ -274,7 +280,7 @@
     # compile an extension using an SDK that is not present
     # on the current machine it is better to not use an SDK
     # than to fail.  This is particularly important with
-    # the standalong Command Line Tools alternative to a
+    # the standalone Command Line Tools alternative to a
     # full-blown Xcode install since the CLT packages do not
     # provide SDKs.  If the SDK is not present, it is assumed
     # that the header files and dev libs have been installed
@@ -378,7 +384,7 @@
     compilers are present, i.e. when installing pure
     Python dists.  Customization of compiler paths
     and detection of unavailable archs is deferred
-    until the first extention module build is
+    until the first extension module build is
     requested (in distutils.sysconfig.customize_compiler).
 
     Currently called from distutils.sysconfig
diff --git a/lib-python/2.7/_strptime.py b/lib-python/2.7/_strptime.py
--- a/lib-python/2.7/_strptime.py
+++ b/lib-python/2.7/_strptime.py
@@ -222,7 +222,7 @@
         """Convert a list to a regex string for matching a directive.
 
         Want possible matching values to be from longest to shortest.  This
-        prevents the possibility of a match occuring for a value that also
+        prevents the possibility of a match occurring for a value that also
         a substring of a larger value that should have matched (e.g., 'abc'
         matching when 'abcdef' should have been the match).
 
diff --git a/lib-python/2.7/_weakrefset.py b/lib-python/2.7/_weakrefset.py
--- a/lib-python/2.7/_weakrefset.py
+++ b/lib-python/2.7/_weakrefset.py
@@ -171,6 +171,12 @@
             return NotImplemented
         return self.data == set(ref(item) for item in other)
 
+    def __ne__(self, other):
+        opposite = self.__eq__(other)
+        if opposite is NotImplemented:
+            return NotImplemented
+        return not opposite
+
     def symmetric_difference(self, other):
         newset = self.copy()
         newset.symmetric_difference_update(other)
diff --git a/lib-python/2.7/aifc.py b/lib-python/2.7/aifc.py
--- a/lib-python/2.7/aifc.py
+++ b/lib-python/2.7/aifc.py
@@ -123,7 +123,7 @@
 compression type, and then write audio frames using writeframesraw.
 When all frames have been written, either call writeframes('') or
 close() to patch up the sizes in the header.
-Marks can be added anytime.  If there are any marks, ypu must call
+Marks can be added anytime.  If there are any marks, you must call
 close() after all frames have been written.
 The close() method is called automatically when the class instance
 is destroyed.
@@ -480,31 +480,30 @@
                         pass
                     else:
                         self._convert = self._adpcm2lin
-                        self._framesize = self._framesize // 4
+                        self._sampwidth = 2
                         return
                 # for ULAW and ALAW try Compression Library
                 try:
                     import cl
                 except ImportError:
-                    if self._comptype == 'ULAW':
+                    if self._comptype in ('ULAW', 'ulaw'):
                         try:
                             import audioop
                             self._convert = self._ulaw2lin
-                            self._framesize = self._framesize // 2
+                            self._sampwidth = 2
                             return
                         except ImportError:
                             pass
                     raise Error, 'cannot read compressed AIFF-C files'
-                if self._comptype == 'ULAW':
+                if self._comptype in ('ULAW', 'ulaw'):
                     scheme = cl.G711_ULAW
-                    self._framesize = self._framesize // 2
-                elif self._comptype == 'ALAW':
+                elif self._comptype in ('ALAW', 'alaw'):
                     scheme = cl.G711_ALAW
-                    self._framesize = self._framesize // 2
                 else:
                     raise Error, 'unsupported compression type'
                 self._decomp = cl.OpenDecompressor(scheme)
                 self._convert = self._decomp_data
+                self._sampwidth = 2
         else:
             self._comptype = 'NONE'
             self._compname = 'not compressed'
@@ -655,7 +654,7 @@
     def setcomptype(self, comptype, compname):
         if self._nframeswritten:
             raise Error, 'cannot change parameters after starting to write'
-        if comptype not in ('NONE', 'ULAW', 'ALAW', 'G722'):
+        if comptype not in ('NONE', 'ULAW', 'ulaw', 'ALAW', 'alaw', 'G722'):
             raise Error, 'unsupported compression type'
         self._comptype = comptype
         self._compname = compname
@@ -675,7 +674,7 @@
         nchannels, sampwidth, framerate, nframes, comptype, compname = info
         if self._nframeswritten:
             raise Error, 'cannot change parameters after starting to write'
-        if comptype not in ('NONE', 'ULAW', 'ALAW', 'G722'):
+        if comptype not in ('NONE', 'ULAW', 'ulaw', 'ALAW', 'alaw', 'G722'):
             raise Error, 'unsupported compression type'
         self.setnchannels(nchannels)
         self.setsampwidth(sampwidth)
@@ -804,7 +803,7 @@
         try:
             import cl
         except ImportError:
-            if self._comptype == 'ULAW':
+            if self._comptype in ('ULAW', 'ulaw'):
                 try:
                     import audioop
                     self._convert = self._lin2ulaw
@@ -812,9 +811,9 @@
                 except ImportError:
                     pass
             raise Error, 'cannot write compressed AIFF-C files'
-        if self._comptype == 'ULAW':
+        if self._comptype in ('ULAW', 'ulaw'):
             scheme = cl.G711_ULAW
-        elif self._comptype == 'ALAW':
+        elif self._comptype in ('ALAW', 'alaw'):
             scheme = cl.G711_ALAW
         else:
             raise Error, 'unsupported compression type'
@@ -867,7 +866,10 @@
         _write_short(self._file, self._nchannels)
         self._nframes_pos = self._file.tell()
         _write_ulong(self._file, self._nframes)
-        _write_short(self._file, self._sampwidth * 8)
+        if self._comptype in ('ULAW', 'ulaw', 'ALAW', 'alaw', 'G722'):
+            _write_short(self._file, 8)
+        else:
+            _write_short(self._file, self._sampwidth * 8)
         _write_float(self._file, self._framerate)
         if self._aifc:
             self._file.write(self._comptype)
@@ -953,23 +955,27 @@
         sys.argv.append('/usr/demos/data/audio/bach.aiff')
     fn = sys.argv[1]
     f = open(fn, 'r')
-    print "Reading", fn
-    print "nchannels =", f.getnchannels()
-    print "nframes   =", f.getnframes()
-    print "sampwidth =", f.getsampwidth()
-    print "framerate =", f.getframerate()
-    print "comptype  =", f.getcomptype()
-    print "compname  =", f.getcompname()
-    if sys.argv[2:]:
-        gn = sys.argv[2]
-        print "Writing", gn
-        g = open(gn, 'w')
-        g.setparams(f.getparams())
-        while 1:
-            data = f.readframes(1024)
-            if not data:
-                break
-            g.writeframes(data)
-        g.close()
+    try:
+        print "Reading", fn
+        print "nchannels =", f.getnchannels()
+        print "nframes   =", f.getnframes()
+        print "sampwidth =", f.getsampwidth()
+        print "framerate =", f.getframerate()
+        print "comptype  =", f.getcomptype()
+        print "compname  =", f.getcompname()
+        if sys.argv[2:]:
+            gn = sys.argv[2]
+            print "Writing", gn
+            g = open(gn, 'w')
+            try:
+                g.setparams(f.getparams())
+                while 1:
+                    data = f.readframes(1024)
+                    if not data:
+                        break
+                    g.writeframes(data)
+            finally:
+                g.close()
+            print "Done."
+    finally:
         f.close()
-        print "Done."
diff --git a/lib-python/2.7/calendar.py b/lib-python/2.7/calendar.py
--- a/lib-python/2.7/calendar.py
+++ b/lib-python/2.7/calendar.py
@@ -220,7 +220,7 @@
     def yeardatescalendar(self, year, width=3):
         """
         Return the data for the specified year ready for formatting. The return
-        value is a list of month rows. Each month row contains upto width months.
+        value is a list of month rows. Each month row contains up to width months.
         Each month contains between 4 and 6 weeks and each week contains 1-7
         days. Days are datetime.date objects.
         """
diff --git a/lib-python/2.7/cgi.py b/lib-python/2.7/cgi.py
--- a/lib-python/2.7/cgi.py
+++ b/lib-python/2.7/cgi.py
@@ -697,6 +697,9 @@
             if not line:
                 self.done = -1
                 break
+            if delim == "\r":
+                line = delim + line
+                delim = ""
             if line[:2] == "--" and last_line_lfend:
                 strippedline = line.strip()
                 if strippedline == next:
@@ -713,6 +716,12 @@
                 delim = "\n"
                 line = line[:-1]
                 last_line_lfend = True
+            elif line[-1] == "\r":
+                # We may interrupt \r\n sequences if they span the 2**16
+                # byte boundary
+                delim = "\r"
+                line = line[:-1]
+                last_line_lfend = False
             else:
                 delim = ""
                 last_line_lfend = False
diff --git a/lib-python/2.7/collections.py b/lib-python/2.7/collections.py
--- a/lib-python/2.7/collections.py
+++ b/lib-python/2.7/collections.py
@@ -275,6 +275,12 @@
         'Return self as a plain tuple.  Used by copy and pickle.'
         return tuple(self)
 
+    __dict__ = _property(_asdict)
+
+    def __getstate__(self):
+        'Exclude the OrderedDict from pickling'
+        pass
+
 {field_defs}
 '''
 
@@ -371,7 +377,7 @@
     result = namespace[typename]
 
     # For pickling to work, the __module__ variable needs to be set to the frame
-    # where the named tuple is created.  Bypass this step in enviroments where
+    # where the named tuple is created.  Bypass this step in environments where
     # sys._getframe is not defined (Jython for example) or sys._getframe is not
     # defined for arguments greater than 0 (IronPython).
     try:
diff --git a/lib-python/2.7/compiler/pyassem.py b/lib-python/2.7/compiler/pyassem.py
--- a/lib-python/2.7/compiler/pyassem.py
+++ b/lib-python/2.7/compiler/pyassem.py
@@ -125,7 +125,7 @@
         # Make sure every block appears in dominators, even if no
         # other block must precede it.
         dominators.setdefault(b, set())
-        # preceeding blocks dominate following blocks
+        # preceding blocks dominate following blocks
         for c in b.get_followers():
             while 1:
                 dominators.setdefault(c, set()).add(b)
diff --git a/lib-python/2.7/csv.py b/lib-python/2.7/csv.py
--- a/lib-python/2.7/csv.py
+++ b/lib-python/2.7/csv.py
@@ -261,8 +261,9 @@
 
         # if we see an extra quote between delimiters, we've got a
         # double quoted format
-        dq_regexp = re.compile(r"((%(delim)s)|^)\W*%(quote)s[^%(delim)s\n]*%(quote)s[^%(delim)s\n]*%(quote)s\W*((%(delim)s)|$)" % \
-                               {'delim':delim, 'quote':quotechar}, re.MULTILINE)
+        dq_regexp = re.compile(
+                               r"((%(delim)s)|^)\W*%(quote)s[^%(delim)s\n]*%(quote)s[^%(delim)s\n]*%(quote)s\W*((%(delim)s)|$)" % \
+                               {'delim':re.escape(delim), 'quote':quotechar}, re.MULTILINE)
 
 
 
diff --git a/lib-python/2.7/ctypes/test/runtests.py b/lib-python/2.7/ctypes/test/runtests.py
--- a/lib-python/2.7/ctypes/test/runtests.py
+++ b/lib-python/2.7/ctypes/test/runtests.py
@@ -2,7 +2,7 @@
 
 Run all tests found in this directory, and print a summary of the results.
 Command line flags:
-  -q     quiet mode: don't prnt anything while the tests are running
+  -q     quiet mode: don't print anything while the tests are running
   -r     run tests repeatedly, look for refcount leaks
   -u<resources>
          Add resources to the lits of allowed resources. '*' allows all
diff --git a/lib-python/2.7/ctypes/test/test_cfuncs.py b/lib-python/2.7/ctypes/test/test_cfuncs.py
--- a/lib-python/2.7/ctypes/test/test_cfuncs.py
+++ b/lib-python/2.7/ctypes/test/test_cfuncs.py
@@ -191,7 +191,7 @@
         self.assertEqual(self._dll.tv_i(-42), None)
         self.assertEqual(self.S(), -42)
 
-# The following repeates the above tests with stdcall functions (where
+# The following repeats the above tests with stdcall functions (where
 # they are available)
 try:
     WinDLL
diff --git a/lib-python/2.7/ctypes/test/test_integers.py b/lib-python/2.7/ctypes/test/test_integers.py
--- a/lib-python/2.7/ctypes/test/test_integers.py
+++ b/lib-python/2.7/ctypes/test/test_integers.py
@@ -1,4 +1,4 @@
-# superseeded by test_numbers.py
+# superseded by test_numbers.py
 import unittest
 
 if __name__ == '__main__':
diff --git a/lib-python/2.7/ctypes/test/test_numbers.py b/lib-python/2.7/ctypes/test/test_numbers.py
--- a/lib-python/2.7/ctypes/test/test_numbers.py
+++ b/lib-python/2.7/ctypes/test/test_numbers.py
@@ -216,7 +216,7 @@
 
     def test_init(self):
         # c_int() can be initialized from Python's int, and c_int.
-        # Not from c_long or so, which seems strange, abd should
+        # Not from c_long or so, which seems strange, abc should
         # probably be changed:
         self.assertRaises(TypeError, c_int, c_long(42))
 
diff --git a/lib-python/2.7/ctypes/test/test_refcounts.py b/lib-python/2.7/ctypes/test/test_refcounts.py
--- a/lib-python/2.7/ctypes/test/test_refcounts.py
+++ b/lib-python/2.7/ctypes/test/test_refcounts.py
@@ -47,7 +47,7 @@
         # this is the standard refcount for func
         self.assertEqual(grc(func), 2)
 
-        # the CFuncPtr instance holds atr least one refcount on func:
+        # the CFuncPtr instance holds at least one refcount on func:
         f = OtherCallback(func)
         self.assertTrue(grc(func) > 2)
 
@@ -64,7 +64,7 @@
         x = X()
         x.a = OtherCallback(func)
 
-        # the CFuncPtr instance holds atr least one refcount on func:
+        # the CFuncPtr instance holds at least one refcount on func:
         self.assertTrue(grc(func) > 2)
 
         # and may release it again
@@ -77,7 +77,7 @@
 
         f = OtherCallback(func)
 
-        # the CFuncPtr instance holds atr least one refcount on func:
+        # the CFuncPtr instance holds at least one refcount on func:
         self.assertTrue(grc(func) > 2)
 
         # create a cycle
diff --git a/lib-python/2.7/ctypes/test/test_structures.py b/lib-python/2.7/ctypes/test/test_structures.py
--- a/lib-python/2.7/ctypes/test/test_structures.py
+++ b/lib-python/2.7/ctypes/test/test_structures.py
@@ -108,7 +108,7 @@
     def test_emtpy(self):
         # I had problems with these
         #
-        # Although these are patological cases: Empty Structures!
+        # Although these are pathological cases: Empty Structures!
         class X(Structure):
             _fields_ = []
 
diff --git a/lib-python/2.7/ctypes/util.py b/lib-python/2.7/ctypes/util.py
--- a/lib-python/2.7/ctypes/util.py
+++ b/lib-python/2.7/ctypes/util.py
@@ -93,7 +93,7 @@
         fdout, ccout = tempfile.mkstemp()
         os.close(fdout)
         cmd = 'if type gcc >/dev/null 2>&1; then CC=gcc; elif type cc >/dev/null 2>&1; then CC=cc;else exit 10; fi;' \
-              '$CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name
+              'LANG=C LC_ALL=C $CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name
         try:
             f = os.popen(cmd)
             try:
diff --git a/lib-python/2.7/decimal.py b/lib-python/2.7/decimal.py
--- a/lib-python/2.7/decimal.py
+++ b/lib-python/2.7/decimal.py
@@ -25,7 +25,7 @@
 
 and IEEE standard 854-1987:
 
-    www.cs.berkeley.edu/~ejr/projects/754/private/drafts/854-1987/dir.html
+    http://en.wikipedia.org/wiki/IEEE_854-1987
 
 Decimal floating point has finite precision with arbitrarily large bounds.
 
diff --git a/lib-python/2.7/difflib.py b/lib-python/2.7/difflib.py
--- a/lib-python/2.7/difflib.py
+++ b/lib-python/2.7/difflib.py
@@ -586,7 +586,7 @@
     def get_grouped_opcodes(self, n=3):
         """ Isolate change clusters by eliminating ranges with no changes.
 
-        Return a generator of groups with upto n lines of context.
+        Return a generator of groups with up to n lines of context.
         Each group is in the same format as returned by get_opcodes().
 
         >>> from pprint import pprint
@@ -1361,7 +1361,7 @@
     linejunk -- passed on to ndiff (see ndiff documentation)
     charjunk -- passed on to ndiff (see ndiff documentation)
 
-    This function returns an interator which returns a tuple:
+    This function returns an iterator which returns a tuple:
     (from line tuple, to line tuple, boolean flag)
 
     from/to line tuple -- (line num, line text)
@@ -1963,7 +1963,7 @@
         self._make_prefix()
 
         # change tabs to spaces before it gets more difficult after we insert
-        # markkup
+        # markup
         fromlines,tolines = self._tab_newline_replace(fromlines,tolines)
 
         # create diffs iterator which generates side by side from/to data
diff --git a/lib-python/2.7/distutils/__init__.py b/lib-python/2.7/distutils/__init__.py
--- a/lib-python/2.7/distutils/__init__.py
+++ b/lib-python/2.7/distutils/__init__.py
@@ -15,5 +15,5 @@
 # Updated automatically by the Python release process.
 #
 #--start constants--
-__version__ = "2.7.5"
+__version__ = "2.7.6"
 #--end constants--
diff --git a/lib-python/2.7/distutils/command/build_ext.py b/lib-python/2.7/distutils/command/build_ext.py
--- a/lib-python/2.7/distutils/command/build_ext.py
+++ b/lib-python/2.7/distutils/command/build_ext.py
@@ -241,12 +241,10 @@
                 # building python standard extensions
                 self.library_dirs.append('.')
 
-        # for extensions under Linux or Solaris with a shared Python library,
+        # For building extensions with a shared Python library,
         # Python's library directory must be appended to library_dirs
-        sysconfig.get_config_var('Py_ENABLE_SHARED')
-        if ((sys.platform.startswith('linux') or sys.platform.startswith('gnu')
-             or sys.platform.startswith('sunos'))
-            and sysconfig.get_config_var('Py_ENABLE_SHARED')):
+        # See Issues: #1600860, #4366
+        if (sysconfig.get_config_var('Py_ENABLE_SHARED')):
             if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
                 # building third party extensions
                 self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
diff --git a/lib-python/2.7/distutils/command/sdist.py b/lib-python/2.7/distutils/command/sdist.py
--- a/lib-python/2.7/distutils/command/sdist.py
+++ b/lib-python/2.7/distutils/command/sdist.py
@@ -183,7 +183,7 @@
         depends on the user's options.
         """
         # new behavior when using a template:
-        # the file list is recalculated everytime because
+        # the file list is recalculated every time because
         # even if MANIFEST.in or setup.py are not changed
         # the user might have added some files in the tree that
         # need to be included.
diff --git a/lib-python/2.7/distutils/cygwinccompiler.py b/lib-python/2.7/distutils/cygwinccompiler.py
--- a/lib-python/2.7/distutils/cygwinccompiler.py
+++ b/lib-python/2.7/distutils/cygwinccompiler.py
@@ -322,13 +322,18 @@
         else:
             entry_point = ''
 
-        self.set_executables(compiler='gcc -mno-cygwin -O -Wall',
-                             compiler_so='gcc -mno-cygwin -mdll -O -Wall',
-                             compiler_cxx='g++ -mno-cygwin -O -Wall',
-                             linker_exe='gcc -mno-cygwin',
-                             linker_so='%s -mno-cygwin %s %s'
-                                        % (self.linker_dll, shared_option,
-                                           entry_point))
+        if self.gcc_version < '4' or is_cygwingcc():
+            no_cygwin = ' -mno-cygwin'
+        else:
+            no_cygwin = ''
+
+        self.set_executables(compiler='gcc%s -O -Wall' % no_cygwin,
+                             compiler_so='gcc%s -mdll -O -Wall' % no_cygwin,
+                             compiler_cxx='g++%s -O -Wall' % no_cygwin,
+                             linker_exe='gcc%s' % no_cygwin,
+                             linker_so='%s%s %s %s'
+                                    % (self.linker_dll, no_cygwin,
+                                       shared_option, entry_point))
         # Maybe we should also append -mthreads, but then the finished
         # dlls need another dll (mingwm10.dll see Mingw32 docs)
         # (-mthreads: Support thread-safe exception handling on `Mingw32')
@@ -450,3 +455,12 @@
     else:
         dllwrap_version = None
     return (gcc_version, ld_version, dllwrap_version)
+
+def is_cygwingcc():
+    '''Try to determine if the gcc that would be used is from cygwin.'''
+    out = os.popen('gcc -dumpmachine', 'r')
+    out_string = out.read()
+    out.close()
+    # out_string is the target triplet cpu-vendor-os
+    # Cygwin's gcc sets the os to 'cygwin'
+    return out_string.strip().endswith('cygwin')
diff --git a/lib-python/2.7/distutils/sysconfig.py b/lib-python/2.7/distutils/sysconfig.py
--- a/lib-python/2.7/distutils/sysconfig.py
+++ b/lib-python/2.7/distutils/sysconfig.py
@@ -1,4 +1,3 @@
-
 # The content of this file is redirected from
 # sysconfig_cpython or sysconfig_pypy.
 # All underscore names are imported too, because
@@ -11,5 +10,3 @@
 else:
     from distutils import sysconfig_cpython as _sysconfig_module
 globals().update(_sysconfig_module.__dict__)
-
-_USE_CLANG = None
diff --git a/lib-python/2.7/distutils/sysconfig_cpython.py b/lib-python/2.7/distutils/sysconfig_cpython.py
--- a/lib-python/2.7/distutils/sysconfig_cpython.py
+++ b/lib-python/2.7/distutils/sysconfig_cpython.py
@@ -175,9 +175,15 @@
                             'CCSHARED', 'LDSHARED', 'SO', 'AR',
                             'ARFLAGS')
 
-        newcc = None
         if 'CC' in os.environ:
-            cc = os.environ['CC']
+            newcc = os.environ['CC']
+            if (sys.platform == 'darwin'
+                    and 'LDSHARED' not in os.environ
+                    and ldshared.startswith(cc)):
+                # On OS X, if CC is overridden, use that as the default
+                #       command for LDSHARED as well
+                ldshared = newcc + ldshared[len(cc):]
+            cc = newcc
         if 'CXX' in os.environ:
             cxx = os.environ['CXX']
         if 'LDSHARED' in os.environ:
diff --git a/lib-python/2.7/distutils/tests/test_build_clib.py b/lib-python/2.7/distutils/tests/test_build_clib.py
--- a/lib-python/2.7/distutils/tests/test_build_clib.py
+++ b/lib-python/2.7/distutils/tests/test_build_clib.py
@@ -77,7 +77,7 @@
 
         cmd.compiler = FakeCompiler()
 
-        # build_libraries is also doing a bit of typoe checking
+        # build_libraries is also doing a bit of typo checking
         lib = [('name', {'sources': 'notvalid'})]
         self.assertRaises(DistutilsSetupError, cmd.build_libraries, lib)
 
diff --git a/lib-python/2.7/distutils/tests/test_cmd.py b/lib-python/2.7/distutils/tests/test_cmd.py
--- a/lib-python/2.7/distutils/tests/test_cmd.py
+++ b/lib-python/2.7/distutils/tests/test_cmd.py
@@ -34,6 +34,18 @@
         self.assertRaises(DistutilsOptionError,
                           cmd.ensure_string_list, 'not_string_list2')
 
+        cmd.option1 = 'ok,dok'
+        cmd.ensure_string_list('option1')
+        self.assertEqual(cmd.option1, ['ok', 'dok'])
+
+        cmd.option2 = ['xxx', 'www']
+        cmd.ensure_string_list('option2')
+
+        cmd.option3 = ['ok', 2]
+        self.assertRaises(DistutilsOptionError, cmd.ensure_string_list,
+                          'option3')
+
+
     def test_make_file(self):
 
         cmd = self.cmd
@@ -77,19 +89,6 @@
         cmd.option3 = 1
         self.assertRaises(DistutilsOptionError, cmd.ensure_string, 'option3')
 
-    def test_ensure_string_list(self):
-        cmd = self.cmd
-        cmd.option1 = 'ok,dok'
-        cmd.ensure_string_list('option1')
-        self.assertEqual(cmd.option1, ['ok', 'dok'])
-
-        cmd.option2 = ['xxx', 'www']
-        cmd.ensure_string_list('option2')
-
-        cmd.option3 = ['ok', 2]
-        self.assertRaises(DistutilsOptionError, cmd.ensure_string_list,
-                          'option3')
-
     def test_ensure_filename(self):
         cmd = self.cmd
         cmd.option1 = __file__
diff --git a/lib-python/2.7/distutils/tests/test_unixccompiler.py b/lib-python/2.7/distutils/tests/test_unixccompiler.py
--- a/lib-python/2.7/distutils/tests/test_unixccompiler.py
+++ b/lib-python/2.7/distutils/tests/test_unixccompiler.py
@@ -1,7 +1,8 @@
 """Tests for distutils.unixccompiler."""
+import os
 import sys
 import unittest
-from test.test_support import run_unittest
+from test.test_support import EnvironmentVarGuard, run_unittest
 
 from distutils import sysconfig
 from distutils.unixccompiler import UnixCCompiler
@@ -122,6 +123,37 @@
         sysconfig.get_config_var = gcv
         self.assertEqual(self.cc.rpath_foo(), '-R/foo')
 
+    @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for OS X')
+    def test_osx_cc_overrides_ldshared(self):
+        # Issue #18080:
+        # ensure that setting CC env variable also changes default linker
+        def gcv(v):
+            if v == 'LDSHARED':
+                return 'gcc-4.2 -bundle -undefined dynamic_lookup '
+            return 'gcc-4.2'
+        sysconfig.get_config_var = gcv
+        with EnvironmentVarGuard() as env:
+            env['CC'] = 'my_cc'
+            del env['LDSHARED']
+            sysconfig.customize_compiler(self.cc)
+        self.assertEqual(self.cc.linker_so[0], 'my_cc')
+
+    @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for OS X')
+    def test_osx_explict_ldshared(self):
+        # Issue #18080:
+        # ensure that setting CC env variable does not change
+        #   explicit LDSHARED setting for linker
+        def gcv(v):
+            if v == 'LDSHARED':
+                return 'gcc-4.2 -bundle -undefined dynamic_lookup '
+            return 'gcc-4.2'
+        sysconfig.get_config_var = gcv
+        with EnvironmentVarGuard() as env:
+            env['CC'] = 'my_cc'
+            env['LDSHARED'] = 'my_ld -bundle -dynamic'
+            sysconfig.customize_compiler(self.cc)
+        self.assertEqual(self.cc.linker_so[0], 'my_ld')
+
 
 def test_suite():
     return unittest.makeSuite(UnixCCompilerTestCase)
diff --git a/lib-python/2.7/doctest.py b/lib-python/2.7/doctest.py
--- a/lib-python/2.7/doctest.py
+++ b/lib-python/2.7/doctest.py
@@ -424,7 +424,7 @@
         zero-based, with respect to the beginning of the DocTest.
 
       - indent: The example's indentation in the DocTest string.
-        I.e., the number of space characters that preceed the
+        I.e., the number of space characters that precede the
         example's first prompt.
 
       - options: A dictionary mapping from option flags to True or
@@ -564,7 +564,7 @@
         # Want consists of any non-blank lines that do not start with PS1.
         (?P<want> (?:(?![ ]*$)    # Not a blank line
                      (?![ ]*>>>)  # Not a line starting with PS1
-                     .*$\n?       # But any other line
+                     .+$\n?       # But any other line
                   )*)
         ''', re.MULTILINE | re.VERBOSE)
 
@@ -895,7 +895,7 @@
         if '__name__' not in globs:
             globs['__name__'] = '__main__'  # provide a default module name
 
-        # Recursively expore `obj`, extracting DocTests.
+        # Recursively explore `obj`, extracting DocTests.
         tests = []
         self._find(tests, obj, name, module, source_lines, globs, {})
         # Sort the tests by alpha order of names, for consistency in
diff --git a/lib-python/2.7/email/charset.py b/lib-python/2.7/email/charset.py
--- a/lib-python/2.7/email/charset.py
+++ b/lib-python/2.7/email/charset.py
@@ -183,7 +183,7 @@
                    header encoding.  Charset.SHORTEST is not allowed for
                    body_encoding.
 
-    output_charset: Some character sets must be converted before the can be
+    output_charset: Some character sets must be converted before they can be
                     used in email headers or bodies.  If the input_charset is
                     one of them, this attribute will contain the name of the
                     charset output will be converted to.  Otherwise, it will
diff --git a/lib-python/2.7/fileinput.py b/lib-python/2.7/fileinput.py
--- a/lib-python/2.7/fileinput.py
+++ b/lib-python/2.7/fileinput.py
@@ -90,12 +90,11 @@
 
 def input(files=None, inplace=0, backup="", bufsize=0,
           mode="r", openhook=None):
-    """input([files[, inplace[, backup[, mode[, openhook]]]]])
+    """Return an instance of the FileInput class, which can be iterated.
 
-    Create an instance of the FileInput class. The instance will be used
-    as global state for the functions of this module, and is also returned
-    to use during iteration. The parameters to this function will be passed
-    along to the constructor of the FileInput class.
+    The parameters are passed to the constructor of the FileInput class.
+    The returned instance, in addition to being an iterator,
+    keeps global state for the functions of this module,.
     """
     global _state
     if _state and _state._file:
@@ -182,7 +181,7 @@
     return _state.isstdin()
 
 class FileInput:
-    """class FileInput([files[, inplace[, backup[, mode[, openhook]]]]])
+    """FileInput([files[, inplace[, backup[, bufsize[, mode[, openhook]]]]]])
 
     Class FileInput is the implementation of the module; its methods
     filename(), lineno(), fileline(), isfirstline(), isstdin(), fileno(),
diff --git a/lib-python/2.7/ftplib.py b/lib-python/2.7/ftplib.py
--- a/lib-python/2.7/ftplib.py
+++ b/lib-python/2.7/ftplib.py
@@ -55,6 +55,8 @@
 
 # The standard FTP server control port
 FTP_PORT = 21
+# The sizehint parameter passed to readline() calls
+MAXLINE = 8192
 
 
 # Exception raised when an error or invalid response is received
@@ -101,6 +103,7 @@
     debugging = 0
     host = ''
     port = FTP_PORT
+    maxline = MAXLINE
     sock = None
     file = None
     welcome = None
@@ -180,7 +183,9 @@
     # Internal: return one line from the server, stripping CRLF.
     # Raise EOFError if the connection is closed
     def getline(self):
-        line = self.file.readline()
+        line = self.file.readline(self.maxline + 1)
+        if len(line) > self.maxline:
+            raise Error("got more than %d bytes" % self.maxline)
         if self.debugging > 1:
             print '*get*', self.sanitize(line)
         if not line: raise EOFError
@@ -432,7 +437,9 @@
         conn = self.transfercmd(cmd)
         fp = conn.makefile('rb')
         while 1:
-            line = fp.readline()
+            line = fp.readline(self.maxline + 1)
+            if len(line) > self.maxline:
+                raise Error("got more than %d bytes" % self.maxline)
             if self.debugging > 2: print '*retr*', repr(line)
             if not line:
                 break
@@ -485,7 +492,9 @@
         self.voidcmd('TYPE A')
         conn = self.transfercmd(cmd)
         while 1:
-            buf = fp.readline()
+            buf = fp.readline(self.maxline + 1)
+            if len(buf) > self.maxline:
+                raise Error("got more than %d bytes" % self.maxline)
             if not buf: break
             if buf[-2:] != CRLF:
                 if buf[-1] in CRLF: buf = buf[:-1]
@@ -710,7 +719,9 @@
             fp = conn.makefile('rb')
             try:
                 while 1:
-                    line = fp.readline()
+                    line = fp.readline(self.maxline + 1)
+                    if len(line) > self.maxline:
+                        raise Error("got more than %d bytes" % self.maxline)
                     if self.debugging > 2: print '*retr*', repr(line)
                     if not line:
                         break
@@ -748,7 +759,9 @@
             conn = self.transfercmd(cmd)
             try:
                 while 1:
-                    buf = fp.readline()
+                    buf = fp.readline(self.maxline + 1)
+                    if len(buf) > self.maxline:
+                        raise Error("got more than %d bytes" % self.maxline)
                     if not buf: break
                     if buf[-2:] != CRLF:
                         if buf[-1] in CRLF: buf = buf[:-1]
@@ -905,7 +918,9 @@
         fp = open(filename, "r")
         in_macro = 0
         while 1:
-            line = fp.readline()
+            line = fp.readline(self.maxline + 1)
+            if len(line) > self.maxline:
+                raise Error("got more than %d bytes" % self.maxline)
             if not line: break
             if in_macro and line.strip():
                 macro_lines.append(line)
diff --git a/lib-python/2.7/genericpath.py b/lib-python/2.7/genericpath.py
--- a/lib-python/2.7/genericpath.py
+++ b/lib-python/2.7/genericpath.py
@@ -22,7 +22,7 @@
 
 
 # This follows symbolic links, so both islink() and isdir() can be true
-# for the same path ono systems that support symlinks
+# for the same path on systems that support symlinks
 def isfile(path):
     """Test whether a path is a regular file"""
     try:
diff --git a/lib-python/2.7/heapq.py b/lib-python/2.7/heapq.py
--- a/lib-python/2.7/heapq.py
+++ b/lib-python/2.7/heapq.py
@@ -366,6 +366,7 @@
 
     '''
     _heappop, _heapreplace, _StopIteration = heappop, heapreplace, StopIteration
+    _len = len
 
     h = []
     h_append = h.append
@@ -377,17 +378,21 @@
             pass
     heapify(h)
 
-    while 1:
+    while _len(h) > 1:
         try:
             while 1:
-                v, itnum, next = s = h[0]   # raises IndexError when h is empty
+                v, itnum, next = s = h[0]
                 yield v
                 s[0] = next()               # raises StopIteration when exhausted
                 _heapreplace(h, s)          # restore heap condition
         except _StopIteration:
             _heappop(h)                     # remove empty iterator
-        except IndexError:
-            return
+    if h:
+        # fast case when only a single iterator remains
+        v, itnum, next = h[0]
+        yield v
+        for v in next.__self__:
+            yield v
 
 # Extend the implementations of nsmallest and nlargest to use a key= argument
 _nsmallest = nsmallest
diff --git a/lib-python/2.7/idlelib/AutoComplete.py b/lib-python/2.7/idlelib/AutoComplete.py
--- a/lib-python/2.7/idlelib/AutoComplete.py
+++ b/lib-python/2.7/idlelib/AutoComplete.py
@@ -156,12 +156,9 @@
         if not comp_lists[0]:
             return
         self.autocompletewindow = self._make_autocomplete_window()
-        self.autocompletewindow.show_window(comp_lists,
-                                            "insert-%dc" % len(comp_start),
-                                            complete,
-                                            mode,
-                                            userWantsWin)
-        return True
+        return not self.autocompletewindow.show_window(
+                comp_lists, "insert-%dc" % len(comp_start),
+                complete, mode, userWantsWin)
 
     def fetch_completions(self, what, mode):
         """Return a pair of lists of completions for something. The first list
diff --git a/lib-python/2.7/idlelib/AutoCompleteWindow.py b/lib-python/2.7/idlelib/AutoCompleteWindow.py
--- a/lib-python/2.7/idlelib/AutoCompleteWindow.py
+++ b/lib-python/2.7/idlelib/AutoCompleteWindow.py
@@ -157,13 +157,14 @@
         self.start = self.widget.get(self.startindex, "insert")
         if complete:
             completed = self._complete_string(self.start)
+            start = self.start
             self._change_start(completed)
             i = self._binary_search(completed)
             if self.completions[i] == completed and \
                (i == len(self.completions)-1 or
                 self.completions[i+1][:len(completed)] != completed):
                 # There is exactly one matching completion
-                return
+                return completed == start
         self.userwantswindow = userWantsWin
         self.lasttypedstart = self.start
 
diff --git a/lib-python/2.7/idlelib/Bindings.py b/lib-python/2.7/idlelib/Bindings.py
--- a/lib-python/2.7/idlelib/Bindings.py
+++ b/lib-python/2.7/idlelib/Bindings.py
@@ -15,7 +15,7 @@
 menudefs = [
  # underscore prefixes character to underscore
  ('file', [
-   ('_New Window', '<<open-new-window>>'),
+   ('_New File', '<<open-new-window>>'),
    ('_Open...', '<<open-window-from-file>>'),
    ('Open _Module...', '<<open-module>>'),
    ('Class _Browser', '<<open-class-browser>>'),
@@ -98,6 +98,10 @@
     # menu
     del menudefs[-1][1][0:2]
 
+    # Remove the 'Configure' entry from the options menu, it is in the
+    # application menu as 'Preferences'
+    del menudefs[-2][1][0:2]
+
 default_keydefs = idleConf.GetCurrentKeySet()
 
 del sys
diff --git a/lib-python/2.7/idlelib/CallTips.py b/lib-python/2.7/idlelib/CallTips.py
--- a/lib-python/2.7/idlelib/CallTips.py
+++ b/lib-python/2.7/idlelib/CallTips.py
@@ -163,7 +163,7 @@
             if fob.func_code.co_flags & 0x8:
                 items.append("***")
             arg_text = ", ".join(items)
-            arg_text = "(%s)" % re.sub("\.\d+", "<tuple>", arg_text)
+            arg_text = "(%s)" % re.sub("(?<!\d)\.\d+", "<tuple>", arg_text)
         # See if we can use the docstring
         doc = getattr(ob, "__doc__", "")
         if doc:
@@ -223,4 +223,6 @@
     tests = (t1, t2, t3, t4, t5, t6, t7,
              TC, tc.t1, tc.t2, tc.t3, tc.t4, tc.t5, tc.t6, tc.t7)
 
-    test(tests)
+    # test(tests)
+    from unittest import main
+    main('idlelib.idle_test.test_calltips', verbosity=2, exit=False)
diff --git a/lib-python/2.7/idlelib/Delegator.py b/lib-python/2.7/idlelib/Delegator.py
--- a/lib-python/2.7/idlelib/Delegator.py
+++ b/lib-python/2.7/idlelib/Delegator.py
@@ -4,12 +4,12 @@
 
     def __init__(self, delegate=None):
         self.delegate = delegate
-        self.__cache = {}
+        self.__cache = set()
 
     def __getattr__(self, name):
         attr = getattr(self.delegate, name) # May raise AttributeError
         setattr(self, name, attr)
-        self.__cache[name] = attr
+        self.__cache.add(name)
         return attr
 
     def __nonzero__(self):
@@ -21,21 +21,13 @@
         return True
 
     def resetcache(self):
-        for key in self.__cache.keys():
+        for key in self.__cache:
             try:
                 delattr(self, key)
             except AttributeError:
                 pass
         self.__cache.clear()
 
-    def cachereport(self):
-        keys = self.__cache.keys()
-        keys.sort()
-        print keys
-
     def setdelegate(self, delegate):
         self.resetcache()
         self.delegate = delegate
-
-    def getdelegate(self):
-        return self.delegate
diff --git a/lib-python/2.7/idlelib/EditorWindow.py b/lib-python/2.7/idlelib/EditorWindow.py
--- a/lib-python/2.7/idlelib/EditorWindow.py
+++ b/lib-python/2.7/idlelib/EditorWindow.py
@@ -346,6 +346,36 @@
         self.askinteger = tkSimpleDialog.askinteger
         self.showerror = tkMessageBox.showerror
 
+        self._highlight_workaround()  # Fix selection tags on Windows
+
+    def _highlight_workaround(self):
+        # On Windows, Tk removes painting of the selection
+        # tags which is different behavior than on Linux and Mac.
+        # See issue14146 for more information.
+        if not sys.platform.startswith('win'):
+            return
+
+        text = self.text
+        text.event_add("<<Highlight-FocusOut>>", "<FocusOut>")
+        text.event_add("<<Highlight-FocusIn>>", "<FocusIn>")
+        def highlight_fix(focus):
+            sel_range = text.tag_ranges("sel")
+            if sel_range:
+                if focus == 'out':
+                    HILITE_CONFIG = idleConf.GetHighlight(
+                            idleConf.CurrentTheme(), 'hilite')
+                    text.tag_config("sel_fix", HILITE_CONFIG)
+                    text.tag_raise("sel_fix")
+                    text.tag_add("sel_fix", *sel_range)
+                elif focus == 'in':
+                    text.tag_remove("sel_fix", "1.0", "end")
+
+        text.bind("<<Highlight-FocusOut>>",
+                lambda ev: highlight_fix("out"))
+        text.bind("<<Highlight-FocusIn>>",
+                lambda ev: highlight_fix("in"))
+
+
     def _filename_to_unicode(self, filename):
         """convert filename to unicode in order to display it in Tk"""
         if isinstance(filename, unicode) or not filename:
@@ -437,7 +467,6 @@
     ]
 
     if macosxSupport.runningAsOSXApp():
-        del menu_specs[-3]
         menu_specs[-2] = ("windows", "_Window")
 
 
@@ -660,7 +689,7 @@
         # XXX Ought to insert current file's directory in front of path
         try:
             (f, file, (suffix, mode, type)) = _find_module(name)
-        except (NameError, ImportError), msg:
+        except (NameError, ImportError) as msg:
             tkMessageBox.showerror("Import error", str(msg), parent=self.text)
             return
         if type != imp.PY_SOURCE:
@@ -804,7 +833,11 @@
                     menuEventDict[menu[0]][prepstr(item[0])[1]] = item[1]
         for menubarItem in self.menudict.keys():
             menu = self.menudict[menubarItem]
-            end = menu.index(END) + 1
+            end = menu.index(END)
+            if end is None:
+                # Skip empty menus
+                continue
+            end += 1
             for index in range(0, end):
                 if menu.type(index) == 'command':
                     accel = menu.entrycget(index, 'accelerator')
@@ -861,11 +894,8 @@
         "Load and update the recent files list and menus"
         rf_list = []
         if os.path.exists(self.recent_files_path):
-            rf_list_file = open(self.recent_files_path,'r')
-            try:
+            with  open(self.recent_files_path, 'r') as rf_list_file:
                 rf_list = rf_list_file.readlines()
-            finally:
-                rf_list_file.close()
         if new_file:
             new_file = os.path.abspath(new_file) + '\n'
             if new_file in rf_list:
diff --git a/lib-python/2.7/idlelib/FormatParagraph.py b/lib-python/2.7/idlelib/FormatParagraph.py
--- a/lib-python/2.7/idlelib/FormatParagraph.py
+++ b/lib-python/2.7/idlelib/FormatParagraph.py
@@ -1,18 +1,19 @@
-# Extension to format a paragraph
+"""Extension to format a paragraph or selection to a max width.
 
-# Does basic, standard text formatting, and also understands Python
-# comment blocks.  Thus, for editing Python source code, this
-# extension is really only suitable for reformatting these comment
-# blocks or triple-quoted strings.
+Does basic, standard text formatting, and also understands Python
+comment blocks. Thus, for editing Python source code, this
+extension is really only suitable for reformatting these comment
+blocks or triple-quoted strings.
 
-# Known problems with comment reformatting:
-# * If there is a selection marked, and the first line of the
-#   selection is not complete, the block will probably not be detected
-#   as comments, and will have the normal "text formatting" rules
-#   applied.
-# * If a comment block has leading whitespace that mixes tabs and
-#   spaces, they will not be considered part of the same block.
-# * Fancy comments, like this bulleted list, arent handled :-)
+Known problems with comment reformatting:
+* If there is a selection marked, and the first line of the
+  selection is not complete, the block will probably not be detected
+  as comments, and will have the normal "text formatting" rules
+  applied.
+* If a comment block has leading whitespace that mixes tabs and
+  spaces, they will not be considered part of the same block.
+* Fancy comments, like this bulleted list, aren't handled :-)
+"""
 
 import re
 from idlelib.configHandler import idleConf
@@ -32,41 +33,31 @@
         self.editwin = None
 
     def format_paragraph_event(self, event):
-        maxformatwidth = int(idleConf.GetOption('main','FormatParagraph',
-                                                'paragraph', type='int'))
+        """Formats paragraph to a max width specified in idleConf.
+
+        If text is selected, format_paragraph_event will start breaking lines
+        at the max width, starting from the beginning selection.
+
+        If no text is selected, format_paragraph_event uses the current
+        cursor location to determine the paragraph (lines of text surrounded
+        by blank lines) and formats it.
+        """
+        maxformatwidth = idleConf.GetOption(
+                'main', 'FormatParagraph', 'paragraph', type='int')
         text = self.editwin.text
         first, last = self.editwin.get_selection_indices()
         if first and last:
             data = text.get(first, last)
-            comment_header = ''
+            comment_header = get_comment_header(data)
         else:
             first, last, comment_header, data = \
                     find_paragraph(text, text.index("insert"))
         if comment_header:
-            # Reformat the comment lines - convert to text sans header.
-            lines = data.split("\n")
-            lines = map(lambda st, l=len(comment_header): st[l:], lines)
-            data = "\n".join(lines)
-            # Reformat to maxformatwidth chars or a 20 char width, whichever is greater.
-            format_width = max(maxformatwidth - len(comment_header), 20)
-            newdata = reformat_paragraph(data, format_width)
-            # re-split and re-insert the comment header.
-            newdata = newdata.split("\n")
-            # If the block ends in a \n, we dont want the comment
-            # prefix inserted after it. (Im not sure it makes sense to
-            # reformat a comment block that isnt made of complete
-            # lines, but whatever!)  Can't think of a clean solution,
-            # so we hack away
-            block_suffix = ""
-            if not newdata[-1]:
-                block_suffix = "\n"
-                newdata = newdata[:-1]
-            builder = lambda item, prefix=comment_header: prefix+item
-            newdata = '\n'.join(map(builder, newdata)) + block_suffix
+            newdata = reformat_comment(data, maxformatwidth, comment_header)
         else:
-            # Just a normal text format
             newdata = reformat_paragraph(data, maxformatwidth)
         text.tag_remove("sel", "1.0", "end")
+
         if newdata != data:
             text.mark_set("insert", first)
             text.undo_block_start()
@@ -79,31 +70,44 @@
         return "break"
 
 def find_paragraph(text, mark):
+    """Returns the start/stop indices enclosing the paragraph that mark is in.
+
+    Also returns the comment format string, if any, and paragraph of text
+    between the start/stop indices.
+    """
     lineno, col = map(int, mark.split("."))
-    line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
+    line = text.get("%d.0" % lineno, "%d.end" % lineno)
+
+    # Look for start of next paragraph if the index passed in is a blank line
     while text.compare("%d.0" % lineno, "<", "end") and is_all_white(line):
         lineno = lineno + 1
-        line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
+        line = text.get("%d.0" % lineno, "%d.end" % lineno)
     first_lineno = lineno
     comment_header = get_comment_header(line)
     comment_header_len = len(comment_header)
+
+    # Once start line found, search for end of paragraph (a blank line)
     while get_comment_header(line)==comment_header and \
               not is_all_white(line[comment_header_len:]):
         lineno = lineno + 1
-        line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
+        line = text.get("%d.0" % lineno, "%d.end" % lineno)
     last = "%d.0" % lineno
-    # Search back to beginning of paragraph
+
+    # Search back to beginning of paragraph (first blank line before)
     lineno = first_lineno - 1
-    line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
+    line = text.get("%d.0" % lineno, "%d.end" % lineno)
     while lineno > 0 and \
               get_comment_header(line)==comment_header and \
               not is_all_white(line[comment_header_len:]):
         lineno = lineno - 1
-        line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
+        line = text.get("%d.0" % lineno, "%d.end" % lineno)
     first = "%d.0" % (lineno+1)
+
     return first, last, comment_header, text.get(first, last)
 
+# This should perhaps be replaced with textwrap.wrap
 def reformat_paragraph(data, limit):
+    """Return data reformatted to specified width (limit)."""
     lines = data.split("\n")
     i = 0
     n = len(lines)
@@ -126,7 +130,7 @@
             if not word:
                 continue # Can happen when line ends in whitespace
             if len((partial + word).expandtabs()) > limit and \
-               partial != indent1:
+                   partial != indent1:
                 new.append(partial.rstrip())
                 partial = indent2
             partial = partial + word + " "
@@ -138,13 +142,50 @@
     new.extend(lines[i:])
     return "\n".join(new)
 
+def reformat_comment(data, limit, comment_header):
+    """Return data reformatted to specified width with comment header."""
+
+    # Remove header from the comment lines
+    lc = len(comment_header)
+    data = "\n".join(line[lc:] for line in data.split("\n"))
+    # Reformat to maxformatwidth chars or a 20 char width,
+    # whichever is greater.
+    format_width = max(limit - len(comment_header), 20)
+    newdata = reformat_paragraph(data, format_width)
+    # re-split and re-insert the comment header.
+    newdata = newdata.split("\n")
+    # If the block ends in a \n, we dont want the comment prefix
+    # inserted after it. (Im not sure it makes sense to reformat a
+    # comment block that is not made of complete lines, but whatever!)
+    # Can't think of a clean solution, so we hack away
+    block_suffix = ""
+    if not newdata[-1]:
+        block_suffix = "\n"
+        newdata = newdata[:-1]
+    return '\n'.join(comment_header+line for line in newdata) + block_suffix
+
 def is_all_white(line):
+    """Return True if line is empty or all whitespace."""
+
     return re.match(r"^\s*$", line) is not None
 
 def get_indent(line):
-    return re.match(r"^(\s*)", line).group()
+    """Return the initial space or tab indent of line."""
+    return re.match(r"^([ \t]*)", line).group()
 
 def get_comment_header(line):
-    m = re.match(r"^(\s*#*)", line)
+    """Return string with leading whitespace and '#' from line or ''.
+
+    A null return indicates that the line is not a comment line. A non-
+    null return, such as '    #', will be used to find the other lines of
+    a comment block with the same  indent.
+    """
+    m = re.match(r"^([ \t]*#*)", line)
     if m is None: return ""
     return m.group(1)
+
+if __name__ == "__main__":
+    from test import support; support.use_resources = ['gui']
+    import unittest
+    unittest.main('idlelib.idle_test.test_formatparagraph',
+            verbosity=2, exit=False)
diff --git a/lib-python/2.7/idlelib/GrepDialog.py b/lib-python/2.7/idlelib/GrepDialog.py
--- a/lib-python/2.7/idlelib/GrepDialog.py
+++ b/lib-python/2.7/idlelib/GrepDialog.py
@@ -81,36 +81,24 @@
         hits = 0
         for fn in list:
             try:
-                f = open(fn)
-            except IOError, msg:
+                with open(fn) as f:
+                    for lineno, line in enumerate(f, 1):
+                        if line[-1:] == '\n':
+                            line = line[:-1]
+                        if prog.search(line):
+                            sys.stdout.write("%s: %s: %s\n" %
+                                             (fn, lineno, line))
+                            hits += 1
+            except IOError as msg:
                 print msg
-                continue
-            lineno = 0
-            while 1:
-                block = f.readlines(100000)
-                if not block:
-                    break
-                for line in block:
-                    lineno = lineno + 1
-                    if line[-1:] == '\n':
-                        line = line[:-1]
-                    if prog.search(line):
-                        sys.stdout.write("%s: %s: %s\n" % (fn, lineno, line))
-                        hits = hits + 1
-        if hits:
-            if hits == 1:
-                s = ""
-            else:
-                s = "s"
-            print "Found", hits, "hit%s." % s
-            print "(Hint: right-click to open locations.)"
-        else:
-            print "No hits."
+        print(("Hits found: %s\n"
+              "(Hint: right-click to open locations.)"
+              % hits) if hits else "No hits.")
 
     def findfiles(self, dir, base, rec):
         try:
             names = os.listdir(dir or os.curdir)
-        except os.error, msg:
+        except os.error as msg:
             print msg
             return []
         list = []
@@ -131,3 +119,9 @@
         if self.top:
             self.top.grab_release()
             self.top.withdraw()
+
+if __name__ == "__main__":
+    # A human test is a bit tricky since EditorWindow() imports this module.
+    # Hence Idle must be restarted after editing this file for a live test.
+    import unittest
+    unittest.main('idlelib.idle_test.test_grep', verbosity=2, exit=False)
diff --git a/lib-python/2.7/idlelib/IOBinding.py b/lib-python/2.7/idlelib/IOBinding.py
--- a/lib-python/2.7/idlelib/IOBinding.py
+++ b/lib-python/2.7/idlelib/IOBinding.py
@@ -71,7 +71,7 @@
 
 encoding = encoding.lower()
 
-coding_re = re.compile("coding[:=]\s*([-\w_.]+)")
+coding_re = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)')
 
 class EncodingMessage(SimpleDialog):
     "Inform user that an encoding declaration is needed."
@@ -125,11 +125,12 @@
     Raise LookupError if the encoding is declared but unknown.
     """
     # Only consider the first two lines
-    str = str.split("\n")[:2]
-    str = "\n".join(str)
-
-    match = coding_re.search(str)
-    if not match:
+    lst = str.split("\n", 2)[:2]
+    for line in lst:
+        match = coding_re.match(line)
+        if match is not None:
+            break
+    else:
         return None
     name = match.group(1)
     # Check whether the encoding is known
@@ -248,10 +249,9 @@
         try:
             # open the file in binary mode so that we can handle
             #   end-of-line convention ourselves.
-            f = open(filename,'rb')
-            chars = f.read()
-            f.close()
-        except IOError, msg:
+            with open(filename, 'rb') as f:
+                chars = f.read()
+        except IOError as msg:
             tkMessageBox.showerror("I/O Error", str(msg), master=self.text)
             return False
 
@@ -294,7 +294,7 @@
         # Next look for coding specification
         try:
             enc = coding_spec(chars)
-        except LookupError, name:
+        except LookupError as name:
             tkMessageBox.showerror(
                 title="Error loading the file",
                 message="The encoding '%s' is not known to this Python "\
@@ -383,12 +383,10 @@
         if self.eol_convention != "\n":
             chars = chars.replace("\n", self.eol_convention)
         try:
-            f = open(filename, "wb")
-            f.write(chars)
-            f.flush()
-            f.close()
+            with open(filename, "wb") as f:
+                f.write(chars)
             return True
-        except IOError, msg:
+        except IOError as msg:
             tkMessageBox.showerror("I/O Error", str(msg),
                                    master=self.text)
             return False
@@ -408,7 +406,7 @@
         try:
             enc = coding_spec(chars)
             failed = None
-        except LookupError, msg:
+        except LookupError as msg:
             failed = msg
             enc = None
         if enc:
diff --git a/lib-python/2.7/idlelib/IdleHistory.py b/lib-python/2.7/idlelib/IdleHistory.py
--- a/lib-python/2.7/idlelib/IdleHistory.py
+++ b/lib-python/2.7/idlelib/IdleHistory.py
@@ -1,81 +1,93 @@
+"Implement Idle Shell history mechanism with History class"
+
 from idlelib.configHandler import idleConf
 
 class History:
+    ''' Implement Idle Shell history mechanism.
 
-    def __init__(self, text, output_sep = "\n"):
+    store - Store source statement (called from PyShell.resetoutput).
+    fetch - Fetch stored statement matching prefix already entered.
+    history_next - Bound to <<history-next>> event (default Alt-N).
+    history_prev - Bound to <<history-prev>> event (default Alt-P).
+    '''
+    def __init__(self, text):
+        '''Initialize data attributes and bind event methods.
+
+        .text - Idle wrapper of tk Text widget, with .bell().
+        .history - source statements, possibly with multiple lines.
+        .prefix - source already entered at prompt; filters history list.
+        .pointer - index into history.
+        .cyclic - wrap around history list (or not).
+        '''
         self.text = text
         self.history = []
-        self.history_prefix = None
-        self.history_pointer = None
-        self.output_sep = output_sep
+        self.prefix = None
+        self.pointer = None
         self.cyclic = idleConf.GetOption("main", "History", "cyclic", 1, "bool")
         text.bind("<<history-previous>>", self.history_prev)
         text.bind("<<history-next>>", self.history_next)
 
     def history_next(self, event):
-        self.history_do(0)
+        "Fetch later statement; start with ealiest if cyclic."
+        self.fetch(reverse=False)
         return "break"
 
     def history_prev(self, event):
-        self.history_do(1)
+        "Fetch earlier statement; start with most recent."
+        self.fetch(reverse=True)
         return "break"
 
-    def _get_source(self, start, end):
-        # Get source code from start index to end index.  Lines in the
-        # text control may be separated by sys.ps2 .
-        lines = self.text.get(start, end).split(self.output_sep)
-        return "\n".join(lines)
+    def fetch(self, reverse):
+        '''Fetch statememt and replace current line in text widget.
 
-    def _put_source(self, where, source):
-        output = self.output_sep.join(source.split("\n"))
-        self.text.insert(where, output)
-
-    def history_do(self, reverse):
+        Set prefix and pointer as needed for successive fetches.
+        Reset them to None, None when returning to the start line.
+        Sound bell when return to start line or cannot leave a line
+        because cyclic is False.
+        '''
         nhist = len(self.history)
-        pointer = self.history_pointer
-        prefix = self.history_prefix
+        pointer = self.pointer
+        prefix = self.prefix
         if pointer is not None and prefix is not None:
             if self.text.compare("insert", "!=", "end-1c") or \
-               self._get_source("iomark", "end-1c") != self.history[pointer]:
+                    self.text.get("iomark", "end-1c") != self.history[pointer]:
                 pointer = prefix = None
+                self.text.mark_set("insert", "end-1c")  # != after cursor move
         if pointer is None or prefix is None:
-            prefix = self._get_source("iomark", "end-1c")
+            prefix = self.text.get("iomark", "end-1c")
             if reverse:
-                pointer = nhist
+                pointer = nhist  # will be decremented
             else:
                 if self.cyclic:
-                    pointer = -1
-                else:
+                    pointer = -1  # will be incremented
+                else:  # abort history_next
                     self.text.bell()
                     return
         nprefix = len(prefix)
         while 1:
-            if reverse:
-                pointer = pointer - 1
-            else:
-                pointer = pointer + 1
+            pointer += -1 if reverse else 1
             if pointer < 0 or pointer >= nhist:
                 self.text.bell()
-                if not self.cyclic and pointer < 0:
+                if not self.cyclic and pointer < 0:  # abort history_prev
                     return
                 else:
-                    if self._get_source("iomark", "end-1c") != prefix:
+                    if self.text.get("iomark", "end-1c") != prefix:
                         self.text.delete("iomark", "end-1c")
-                        self._put_source("iomark", prefix)
+                        self.text.insert("iomark", prefix)
                     pointer = prefix = None
                 break
             item = self.history[pointer]
             if item[:nprefix] == prefix and len(item) > nprefix:
                 self.text.delete("iomark", "end-1c")
-                self._put_source("iomark", item)
+                self.text.insert("iomark", item)
                 break
-        self.text.mark_set("insert", "end-1c")
         self.text.see("insert")
         self.text.tag_remove("sel", "1.0", "end")
-        self.history_pointer = pointer
-        self.history_prefix = prefix
+        self.pointer = pointer
+        self.prefix = prefix
 
-    def history_store(self, source):
+    def store(self, source):
+        "Store Shell input statement into history list."
         source = source.strip()
         if len(source) > 2:
             # avoid duplicates
@@ -84,5 +96,11 @@
             except ValueError:
                 pass
             self.history.append(source)
-        self.history_pointer = None
-        self.history_prefix = None
+        self.pointer = None
+        self.prefix = None
+
+if __name__ == "__main__":
+    from test import test_support as support
+    support.use_resources = ['gui']
+    from unittest import main
+    main('idlelib.idle_test.test_idlehistory', verbosity=2, exit=False)
diff --git a/lib-python/2.7/idlelib/PathBrowser.py b/lib-python/2.7/idlelib/PathBrowser.py
--- a/lib-python/2.7/idlelib/PathBrowser.py
+++ b/lib-python/2.7/idlelib/PathBrowser.py
@@ -92,4 +92,5 @@
         mainloop()
 
 if __name__ == "__main__":
-    main()
+    from unittest import main
+    main('idlelib.idle_test.test_pathbrowser', verbosity=2, exit=False)
diff --git a/lib-python/2.7/idlelib/PyShell.py b/lib-python/2.7/idlelib/PyShell.py
--- a/lib-python/2.7/idlelib/PyShell.py
+++ b/lib-python/2.7/idlelib/PyShell.py
@@ -50,35 +50,55 @@
 # internal warnings to the console.  ScriptBinding.check_syntax() will
 # temporarily redirect the stream to the shell window to display warnings when
 # checking user's code.
-global warning_stream
-warning_stream = sys.__stderr__
-try:
-    import warnings
-except ImportError:
-    pass
-else:
-    def idle_showwarning(message, category, filename, lineno,
-                         file=None, line=None):
-        if file is None:
-            file = warning_stream
-        try:
-            file.write(warnings.formatwarning(message, category, filename,
-                                              lineno, line=line))
-        except IOError:
-            pass  ## file (probably __stderr__) is invalid, warning dropped.
-    warnings.showwarning = idle_showwarning
-    def idle_formatwarning(message, category, filename, lineno, line=None):
-        """Format warnings the IDLE way"""
-        s = "\nWarning (from warnings module):\n"
-        s += '  File \"%s\", line %s\n' % (filename, lineno)
-        if line is None:
-            line = linecache.getline(filename, lineno)
-        line = line.strip()
-        if line:
-            s += "    %s\n" % line
-        s += "%s: %s\n>>> " % (category.__name__, message)
-        return s
-    warnings.formatwarning = idle_formatwarning
+warning_stream = sys.__stderr__  # None, at least on Windows, if no console.
+import warnings
+
+def idle_formatwarning(message, category, filename, lineno, line=None):
+    """Format warnings the IDLE way."""
+
+    s = "\nWarning (from warnings module):\n"
+    s += '  File \"%s\", line %s\n' % (filename, lineno)
+    if line is None:
+        line = linecache.getline(filename, lineno)
+    line = line.strip()
+    if line:
+        s += "    %s\n" % line
+    s += "%s: %s\n" % (category.__name__, message)
+    return s
+
+def idle_showwarning(
+        message, category, filename, lineno, file=None, line=None):
+    """Show Idle-format warning (after replacing warnings.showwarning).
+
+    The differences are the formatter called, the file=None replacement,
+    which can be None, the capture of the consequence AttributeError,
+    and the output of a hard-coded prompt.
+    """
+    if file is None:
+        file = warning_stream
+    try:
+        file.write(idle_formatwarning(
+                message, category, filename, lineno, line=line))
+        file.write(">>> ")
+    except (AttributeError, IOError):
+        pass  # if file (probably __stderr__) is invalid, skip warning.
+
+_warnings_showwarning = None
+
+def capture_warnings(capture):
+    "Replace warning.showwarning with idle_showwarning, or reverse."
+
+    global _warnings_showwarning
+    if capture:
+        if _warnings_showwarning is None:
+            _warnings_showwarning = warnings.showwarning
+            warnings.showwarning = idle_showwarning
+    else:
+        if _warnings_showwarning is not None:
+            warnings.showwarning = _warnings_showwarning
+            _warnings_showwarning = None
+
+capture_warnings(True)
 
 def extended_linecache_checkcache(filename=None,
                                   orig_checkcache=linecache.checkcache):
@@ -370,6 +390,7 @@
         self.port = PORT
         self.original_compiler_flags = self.compile.compiler.flags
 
+    _afterid = None
     rpcclt = None
     rpcpid = None
 
@@ -409,7 +430,7 @@
             try:
                 self.rpcclt = MyRPCClient(addr)
                 break
-            except socket.error, err:
+            except socket.error as err:
                 pass
         else:
             self.display_port_binding_error()
@@ -430,7 +451,7 @@
         self.rpcclt.listening_sock.settimeout(10)
         try:
             self.rpcclt.accept()
-        except socket.timeout, err:
+        except socket.timeout as err:
             self.display_no_subprocess_error()
             return None
         self.rpcclt.register("console", self.tkconsole)
@@ -465,7 +486,7 @@
         self.spawn_subprocess()
         try:
             self.rpcclt.accept()
-        except socket.timeout, err:
+        except socket.timeout as err:
             self.display_no_subprocess_error()
             return None
         self.transfer_path(with_cwd=with_cwd)
@@ -497,6 +518,8 @@
         threading.Thread(target=self.__request_interrupt).start()
 
     def kill_subprocess(self):
+        if self._afterid is not None:
+            self.tkconsole.text.after_cancel(self._afterid)
         try:
             self.rpcclt.close()
         except AttributeError:  # no socket
@@ -569,8 +592,8 @@
                 pass
         # Reschedule myself
         if not self.tkconsole.closing:
-            self.tkconsole.text.after(self.tkconsole.pollinterval,
-                                      self.poll_subprocess)
+            self._afterid = self.tkconsole.text.after(
+                self.tkconsole.pollinterval, self.poll_subprocess)
 
     debugger = None
 
@@ -844,7 +867,6 @@
     ]
 
     if macosxSupport.runningAsOSXApp():
-        del menu_specs[-3]
         menu_specs[-2] = ("windows", "_Window")
 
 
@@ -988,10 +1010,6 @@
         self.stop_readline()
         self.canceled = True
         self.closing = True
-        # Wait for poll_subprocess() rescheduling to stop
-        self.text.after(2 * self.pollinterval, self.close2)
-
-    def close2(self):
         return EditorWindow.close(self)
 
     def _close(self):
@@ -1260,7 +1278,7 @@
     def resetoutput(self):
         source = self.text.get("iomark", "end-1c")
         if self.history:
-            self.history.history_store(source)
+            self.history.store(source)
         if self.text.get("end-2c") != "\n":
             self.text.insert("end-1c", "\n")
         self.text.mark_set("iomark", "end-1c")
@@ -1430,6 +1448,7 @@
 def main():
     global flist, root, use_subprocess
 
+    capture_warnings(True)
     use_subprocess = True
     enable_shell = False
     enable_edit = False
@@ -1439,7 +1458,7 @@
     startup = False
     try:
         opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
-    except getopt.error, msg:
+    except getopt.error as msg:
         sys.stderr.write("Error: %s\n" % str(msg))
         sys.stderr.write(usage_msg)
         sys.exit(2)
@@ -1562,7 +1581,10 @@
     while flist.inversedict:  # keep IDLE running while files are open.
         root.mainloop()
     root.destroy()
+    capture_warnings(False)
 
 if __name__ == "__main__":
     sys.modules['PyShell'] = sys.modules['__main__']
     main()
+
+capture_warnings(False)  # Make sure turned off; see issue 18081
diff --git a/lib-python/2.7/idlelib/RstripExtension.py b/lib-python/2.7/idlelib/RstripExtension.py
--- a/lib-python/2.7/idlelib/RstripExtension.py
+++ b/lib-python/2.7/idlelib/RstripExtension.py
@@ -1,13 +1,9 @@
 'Provides "Strip trailing whitespace" under the "Format" menu.'
 
-__author__ = "Roger D. Serwy <roger.serwy at gmail.com>"
-
 class RstripExtension:
 
     menudefs = [
-        ('format', [None,
-               ('Strip trailing whitespace', '<<do-rstrip>>'),
-       ]),]
+        ('format', [None, ('Strip trailing whitespace', '<<do-rstrip>>'), ] ), ]
 
     def __init__(self, editwin):
         self.editwin = editwin
@@ -20,10 +16,18 @@
 
         undo.undo_block_start()
 
-        end_line = int(float(text.index('end'))) + 1
+        end_line = int(float(text.index('end')))
         for cur in range(1, end_line):
-            txt = text.get('%i.0' % cur, '%i.0 lineend' % cur)
+            txt = text.get('%i.0' % cur, '%i.end' % cur)
+            raw = len(txt)
             cut = len(txt.rstrip())
-            text.delete('%i.%i' % (cur, cut), '%i.0 lineend' % cur)
+            # Since text.delete() marks file as changed, even if not,
+            # only call it when needed to actually delete something.
+            if cut < raw:
+                text.delete('%i.%i' % (cur, cut), '%i.end' % cur)
 
         undo.undo_block_stop()
+
+if __name__ == "__main__":
+    import unittest
+    unittest.main('idlelib.idle_test.test_rstrip', verbosity=2, exit=False)
diff --git a/lib-python/2.7/idlelib/ScriptBinding.py b/lib-python/2.7/idlelib/ScriptBinding.py
--- a/lib-python/2.7/idlelib/ScriptBinding.py
+++ b/lib-python/2.7/idlelib/ScriptBinding.py
@@ -70,13 +70,13 @@
         f = open(filename, 'r')
         try:
             tabnanny.process_tokens(tokenize.generate_tokens(f.readline))
-        except tokenize.TokenError, msg:
+        except tokenize.TokenError as msg:
             msgtxt, (lineno, start) = msg
             self.editwin.gotoline(lineno)
             self.errorbox("Tabnanny Tokenizing Error",
                           "Token Error: %s" % msgtxt)
             return False
-        except tabnanny.NannyNag, nag:
+        except tabnanny.NannyNag as nag:
             # The error messages from tabnanny are too confusing...
             self.editwin.gotoline(nag.get_lineno())
             self.errorbox("Tab/space error", indent_message)
@@ -87,9 +87,8 @@
         self.shell = shell = self.flist.open_shell()
         saved_stream = shell.get_warning_stream()
         shell.set_warning_stream(shell.stderr)
-        f = open(filename, 'r')
-        source = f.read()
-        f.close()
+        with open(filename, 'r') as f:
+            source = f.read()
         if '\r' in source:
             source = re.sub(r"\r\n", "\n", source)
             source = re.sub(r"\r", "\n", source)
@@ -101,7 +100,7 @@
             try:
                 # If successful, return the compiled code
                 return compile(source, filename, "exec")
-            except (SyntaxError, OverflowError, ValueError), err:


More information about the pypy-commit mailing list