Commits

Nick Coghlan committed b267e72 Merge

Merge from default

Comments (0)

Files changed (60)

Doc/includes/sqlite3/ctx_manager.py

     con.execute("insert into person(firstname) values (?)", ("Joe",))
 
 # con.rollback() is called after the with block finishes with an exception, the
-# exception is still raised and must be catched
+# exception is still raised and must be caught
 try:
     with con:
         con.execute("insert into person(firstname) values (?)", ("Joe",))

Doc/library/functions.rst

         def zip(*iterables):
             # zip('ABCD', 'xy') --> Ax By
             sentinel = object()
-            iterables = [iter(it) for it in iterables]
-            while iterables:
+            iterators = [iter(it) for it in iterables]
+            while iterators:
                 result = []
-                for it in iterables:
+                for it in iterators:
                     elem = next(it, sentinel)
                     if elem is sentinel:
                         return

Doc/library/html.parser.rst

 .. method:: HTMLParser.handle_startendtag(tag, attrs)
 
    Similar to :meth:`handle_starttag`, but called when the parser encounters an
-   XHTML-style empty tag (``<a .../>``).  This method may be overridden by
+   XHTML-style empty tag (``<img ... />``).  This method may be overridden by
    subclasses which require this particular lexical information; the default
-   implementation simple calls :meth:`handle_starttag` and :meth:`handle_endtag`.
+   implementation simply calls :meth:`handle_starttag` and :meth:`handle_endtag`.
 
 
 .. method:: HTMLParser.handle_endtag(tag)
 Example HTML Parser Application
 -------------------------------
 
-As a basic example, below is a very basic HTML parser that uses the
-:class:`HTMLParser` class to print out tags as they are encountered::
+As a basic example, below is a simple HTML parser that uses the
+:class:`HTMLParser` class to print out start tags, end tags, and data
+as they are encountered::
 
-   >>> from html.parser import HTMLParser
-   >>>
-   >>> class MyHTMLParser(HTMLParser):
-   ...     def handle_starttag(self, tag, attrs):
-   ...         print("Encountered a {} start tag".format(tag))
-   ...     def handle_endtag(self, tag):
-   ...         print("Encountered a {} end tag".format(tag))
-   ...
-   >>> page = """<html><h1>Title</h1><p>I'm a paragraph!</p></html>"""
-   >>>
-   >>> myparser = MyHTMLParser()
-   >>> myparser.feed(page)
-   Encountered a html start tag
-   Encountered a h1 start tag
-   Encountered a h1 end tag
-   Encountered a p start tag
-   Encountered a p end tag
-   Encountered a html end tag
+   from html.parser import HTMLParser
+
+   class MyHTMLParser(HTMLParser):
+       def handle_starttag(self, tag, attrs):
+           print("Encountered a start tag:", tag)
+       def handle_endtag(self, tag):
+           print("Encountered  an end tag:", tag)
+       def handle_data(self, data):
+           print("Encountered   some data:", data)
+
+   parser = MyHTMLParser()
+   parser.feed('<html><head><title>Test</title></head>'
+               '<body><h1>Parse me!</h1></body></html>')
 
 
 .. rubric:: Footnotes

Doc/library/itertools.rst

    iterables are of uneven length, missing values are filled-in with *fillvalue*.
    Iteration continues until the longest iterable is exhausted.  Equivalent to::
 
-      def zip_longest(*args, fillvalue=None):
+      class ZipExhausted(Exception):
+          pass
+
+      def zip_longest(*args, **kwds):
           # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
-          def sentinel(counter = ([fillvalue]*(len(args)-1)).pop):
-              yield counter()         # yields the fillvalue, or raises IndexError
+          fillvalue = kwds.get('fillvalue')
+          counter = len(args) - 1
+          def sentinel():
+              nonlocal counter
+              if not counter:
+                  raise ZipExhausted
+              counter -= 1
+              yield fillvalue
           fillers = repeat(fillvalue)
-          iters = [chain(it, sentinel(), fillers) for it in args]
+          iterators = [chain(it, sentinel(), fillers) for it in args]
           try:
-              for tup in zip(*iters):
-                  yield tup
-          except IndexError:
+              while iterators:
+                  yield tuple(map(next, iterators))
+          except ZipExhausted:
               pass
 
    If one of the iterables is potentially infinite, then the :func:`zip_longest`

Doc/library/sched.rst

 
 .. method:: scheduler.enter(delay, priority, action, argument)
 
-   Schedule an event for *delay* more time units. Other then the relative time, the
+   Schedule an event for *delay* more time units. Other than the relative time, the
    other arguments, the effect and the return value are the same as those for
    :meth:`enterabs`.
 

Doc/library/urllib.request.rst

      pair: HTTP; protocol
      pair: FTP; protocol
 
-* Currently, only the following protocols are supported: HTTP, (versions 0.9 and
-  1.0),  FTP, and local files.
+* Currently, only the following protocols are supported: HTTP (versions 0.9 and
+  1.0), FTP, and local files.
 
-* The caching feature of :func:`urlretrieve` has been disabled until I find the
-  time to hack proper processing of Expiration time headers.
+* The caching feature of :func:`urlretrieve` has been disabled until someone
+  finds the time to hack proper processing of Expiration time headers.
 
 * There should be a function to query whether a particular URL is in the cache.
 

Doc/tools/sphinxext/layout.html

 {% endblock %}
 {% block extrahead %}
     <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/py.png', 1) }}" />
+    <script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>
 {{ super() }}
 {% endblock %}
 {% block footer %}

Doc/tools/sphinxext/static/copybutton.js

+$(document).ready(function() {
+    /* Add a [>>>] button on the top-right corner of code samples to hide
+     * the >>> and ... prompts and the output and thus make the code
+     * copyable. */
+    var div = $('.highlight-python .highlight,' +
+                '.highlight-python3 .highlight')
+    var pre = div.find('pre');
+
+    // get the styles from the current theme
+    pre.parent().parent().css('position', 'relative');
+    var hide_text = 'Hide the prompts and ouput';
+    var show_text = 'Show the prompts and ouput';
+    var border_width = pre.css('border-top-width');
+    var border_style = pre.css('border-top-style');
+    var border_color = pre.css('border-top-color');
+    var button_styles = {
+        'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0',
+        'border-color': border_color, 'border-style': border_style,
+        'border-width': border_width, 'color': border_color, 'text-size': '75%',
+        'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em'
+    }
+
+    // create and add the button to all the code blocks that contain >>>
+    div.each(function(index) {
+        var jthis = $(this);
+        if (jthis.find('.gp').length > 0) {
+            var button = $('<span class="copybutton">&gt;&gt;&gt;</span>');
+            button.css(button_styles)
+            button.attr('title', hide_text);
+            jthis.prepend(button);
+        }
+        // tracebacks (.gt) contain bare text elements that need to be
+        // wrapped in a span to work with .nextUntil() (see later)
+        jthis.find('pre:has(.gt)').contents().filter(function() {
+            return ((this.nodeType == 3) && (this.data.trim().length > 0));
+        }).wrap('<span>');
+    });
+
+    // define the behavior of the button when it's clicked
+    $('.copybutton').toggle(
+        function() {
+            var button = $(this);
+            button.parent().find('.go, .gp, .gt').hide();
+            button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
+            button.css('text-decoration', 'line-through');
+            button.attr('title', show_text);
+        },
+        function() {
+            var button = $(this);
+            button.parent().find('.go, .gp, .gt').show();
+            button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
+            button.css('text-decoration', 'none');
+            button.attr('title', hide_text);
+        });
+});
+

Include/unicodeobject.h

 #ifndef Py_LIMITED_API
 /* Externally visible for str.strip(unicode) */
 PyAPI_FUNC(PyObject *) _PyUnicode_XStrip(
-    PyUnicodeObject *self,
+    PyObject *self,
     int striptype,
     PyObject *sepobj
     );
     Py_UNICODE c
     );
 
-PyAPI_FUNC(size_t) Py_UCS4_strlen(
-    const Py_UCS4 *u
-    );
-
-PyAPI_FUNC(Py_UCS4*) Py_UCS4_strcpy(
-    Py_UCS4 *s1,
-    const Py_UCS4 *s2);
-
-PyAPI_FUNC(Py_UCS4*) Py_UCS4_strcat(
-    Py_UCS4 *s1, const Py_UCS4 *s2);
-
-PyAPI_FUNC(Py_UCS4*) Py_UCS4_strncpy(
-    Py_UCS4 *s1,
-    const Py_UCS4 *s2,
-    size_t n);
-
-PyAPI_FUNC(int) Py_UCS4_strcmp(
-    const Py_UCS4 *s1,
-    const Py_UCS4 *s2
-    );
-
-PyAPI_FUNC(int) Py_UCS4_strncmp(
-    const Py_UCS4 *s1,
-    const Py_UCS4 *s2,
-    size_t n
-    );
-
-PyAPI_FUNC(Py_UCS4*) Py_UCS4_strchr(
-    const Py_UCS4 *s,
-    Py_UCS4 c
-    );
-
-PyAPI_FUNC(Py_UCS4*) Py_UCS4_strrchr(
-    const Py_UCS4 *s,
-    Py_UCS4 c
-    );
-
 /* Create a copy of a unicode string ending with a nul character. Return NULL
    and raise a MemoryError exception on memory allocation failure, otherwise
    return a new allocated buffer (use PyMem_Free() to free the buffer). */
 from gettext import gettext as _, ngettext
 
 
-def _callable(obj):
-    return hasattr(obj, '__call__') or hasattr(obj, '__bases__')
-
-
 SUPPRESS = '==SUPPRESS=='
 
 OPTIONAL = '?'
 
         # create the action object, and add it to the parser
         action_class = self._pop_action_class(kwargs)
-        if not _callable(action_class):
+        if not callable(action_class):
             raise ValueError('unknown action "%s"' % (action_class,))
         action = action_class(**kwargs)
 
         # raise an error if the action type is not callable
         type_func = self._registry_get('type', action.type, action.type)
-        if not _callable(type_func):
+        if not callable(type_func):
             raise ValueError('%r is not callable' % (type_func,))
 
         # raise an error if the metavar does not match the type
 
     def _get_value(self, action, arg_string):
         type_func = self._registry_get('type', action.type, action.type)
-        if not _callable(type_func):
+        if not callable(type_func):
             msg = _('%r is not callable')
             raise ArgumentError(action, msg % type_func)
 
 dispatch_table = {}
 
 def pickle(ob_type, pickle_function, constructor_ob=None):
-    if not hasattr(pickle_function, '__call__'):
+    if not callable(pickle_function):
         raise TypeError("reduction functions must be callable")
     dispatch_table[ob_type] = pickle_function
 
         constructor(constructor_ob)
 
 def constructor(object):
-    if not hasattr(object, '__call__'):
+    if not callable(object):
         raise TypeError("constructors must be callable")
 
 # Example: provide pickling support for complex numbers.

Lib/distutils/dist.py

             for (help_option, short, desc, func) in cmd_class.help_options:
                 if hasattr(opts, parser.get_attr_name(help_option)):
                     help_option_found=1
-                    if hasattr(func, '__call__'):
+                    if callable(func):
                         func()
                     else:
                         raise DistutilsClassError(

Lib/encodings/__init__.py

         if not 4 <= len(entry) <= 7:
             raise CodecRegistryError('module "%s" (%s) failed to register'
                                      % (mod.__name__, mod.__file__))
-        if not hasattr(entry[0], '__call__') or \
-           not hasattr(entry[1], '__call__') or \
-           (entry[2] is not None and not hasattr(entry[2], '__call__')) or \
-           (entry[3] is not None and not hasattr(entry[3], '__call__')) or \
-           (len(entry) > 4 and entry[4] is not None and not hasattr(entry[4], '__call__')) or \
-           (len(entry) > 5 and entry[5] is not None and not hasattr(entry[5], '__call__')):
+        if not callable(entry[0]) or not callable(entry[1]) or \
+           (entry[2] is not None and not callable(entry[2])) or \
+           (entry[3] is not None and not callable(entry[3])) or \
+           (len(entry) > 4 and entry[4] is not None and not callable(entry[4])) or \
+           (len(entry) > 5 and entry[5] is not None and not callable(entry[5])):
             raise CodecRegistryError('incompatible codecs in module "%s" (%s)'
                                      % (mod.__name__, mod.__file__))
         if len(entry)<7 or entry[6] is None:
             raise ValueError("FileInput opening mode must be one of "
                              "'r', 'rU', 'U' and 'rb'")
         self._mode = mode
-        if inplace and openhook:
-            raise ValueError("FileInput cannot use an opening hook in inplace mode")
-        elif openhook and not hasattr(openhook, '__call__'):
-            raise ValueError("FileInput openhook must be callable")
+        if openhook:
+            if inplace:
+                raise ValueError("FileInput cannot use an opening hook in inplace mode")
+            if not callable(openhook):
+                raise ValueError("FileInput openhook must be callable")
         self._openhook = openhook
 
     def __del__(self):
 
     Equivalent to:  sorted(iterable, reverse=True)[:n]
     """
+    if n < 0:
+        return []
     it = iter(iterable)
     result = list(islice(it, n))
     if not result:
 
     Equivalent to:  sorted(iterable)[:n]
     """
+    if n < 0:
+        return []
     if hasattr(iterable, '__len__') and n * 10 <= len(iterable):
         # For smaller values of n, the bisect method is faster than a minheap.
         # It is also memory efficient, consuming only n elements of space.
             import hashlib
             digestmod = hashlib.md5
 
-        if hasattr(digestmod, '__call__'):
+        if callable(digestmod):
             self.digest_cons = digestmod
         else:
             self.digest_cons = lambda d=b'': digestmod.new(d)

Lib/html/parser.py

     r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*'
     r'(\'[^\']*\'|"[^"]*"|[^\s"\'=<>`]*))?')
 attrfind_tolerant = re.compile(
-    r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*'
+    r',?\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*'
     r'(\'[^\']*\'|"[^"]*"|[^>\s]*))?')
 locatestarttagend = re.compile(r"""
   <[a-zA-Z][-.a-zA-Z0-9:_]*          # tag name
         assert match, 'unexpected call to parse_starttag()'
         k = match.end()
         self.lasttag = tag = rawdata[i+1:k].lower()
-
         while k < endpos:
             if self.strict:
                 m = attrfind.match(rawdata, k)
             else:
-                m = attrfind_tolerant.search(rawdata, k)
+                m = attrfind_tolerant.match(rawdata, k)
             if not m:
                 break
             attrname, rest, attrvalue = m.group(1, 2, 3)

Lib/idlelib/PyShell.py

         self.restarting = False
         self.subprocess_arglist = None
         self.port = PORT
+        self.original_compiler_flags = self.compile.compiler.flags
 
     rpcclt = None
     rpcsubproc = None
             gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
             # reload remote debugger breakpoints for all PyShellEditWindows
             debug.load_breakpoints()
+        self.compile.compiler.flags = self.original_compiler_flags
         self.restarting = False
         return self.rpcclt
 

Lib/idlelib/rpc.py

     # Adds names to dictionary argument 'methods'
     for name in dir(obj):
         attr = getattr(obj, name)
-        if hasattr(attr, '__call__'):
+        if callable(attr):
             methods[name] = 1
     if isinstance(obj, type):
         for super in obj.__bases__:
 def _getattributes(obj, attributes):
     for name in dir(obj):
         attr = getattr(obj, name)
-        if not hasattr(attr, '__call__'):
+        if not callable(attr):
             attributes[name] = 1
 
 class MethodProxy(object):

Lib/importlib/__init__.py

         except ImportError:
             raise ImportError('posix, nt, or os2 module required for importlib')
 _bootstrap._os = _os
-import imp, sys, marshal, errno, _io
+import imp, sys, marshal, _io
 _bootstrap.imp = imp
 _bootstrap.sys = sys
 _bootstrap.marshal = marshal
-_bootstrap.errno = errno
 _bootstrap._io = _io
 import _warnings
 _bootstrap._warnings = _warnings

Lib/importlib/_bootstrap.py

 
 """
 
-# Injected modules are '_warnings', 'imp', 'sys', 'marshal', 'errno', '_io',
+# Injected modules are '_warnings', 'imp', 'sys', 'marshal', '_io',
 # and '_os' (a.k.a. 'posix', 'nt' or 'os2').
 # Injected attribute is path_sep.
 #
             parent = _path_join(parent, part)
             try:
                 _os.mkdir(parent)
-            except OSError as exc:
+            except FileExistsError:
                 # Probably another Python process already created the dir.
-                if exc.errno == errno.EEXIST:
-                    continue
-                else:
-                    raise
-            except IOError as exc:
+                continue
+            except PermissionError:
                 # If can't get proper access, then just forget about writing
                 # the data.
-                if exc.errno == errno.EACCES:
-                    return
-                else:
-                    raise
+                return
         try:
             _write_atomic(path, data)
         except (PermissionError, FileExistsError):

Lib/logging/config.py

     def configure_custom(self, config):
         """Configure an object with a user-supplied factory."""
         c = config.pop('()')
-        if not hasattr(c, '__call__'):
+        if not callable(c):
             c = self.resolve(c)
         props = config.pop('.', None)
         # Check for valid identifiers
         filters = config.pop('filters', None)
         if '()' in config:
             c = config.pop('()')
-            if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType:
+            if not callable(c):
                 c = self.resolve(c)
             factory = c
         else:

Lib/multiprocessing/managers.py

     temp = []
     for name in dir(obj):
         func = getattr(obj, name)
-        if hasattr(func, '__call__'):
+        if callable(func):
             temp.append(name)
     return temp
 
         '''
         assert self._state.value == State.INITIAL
 
-        if initializer is not None and not hasattr(initializer, '__call__'):
+        if initializer is not None and not callable(initializer):
             raise TypeError('initializer must be a callable')
 
         # pipe over which we will retrieve address of server

Lib/multiprocessing/pool.py

         if processes < 1:
             raise ValueError("Number of processes must be at least 1")
 
-        if initializer is not None and not hasattr(initializer, '__call__'):
+        if initializer is not None and not callable(initializer):
             raise TypeError('initializer must be a callable')
 
         self._processes = processes
 
     def _check_callback(self):
         if self.action == "callback":
-            if not hasattr(self.callback, '__call__'):
+            if not callable(self.callback):
                 raise OptionError(
                     "callback not callable: %r" % self.callback, self)
             if (self.callback_args is not None and

Lib/packaging/dist.py

             for help_option, short, desc, func in cmd_class.help_options:
                 if hasattr(opts, help_option.replace('-', '_')):
                     help_option_found = True
-                    if hasattr(func, '__call__'):
+                    if callable(func):
                         func()
                     else:
                         raise PackagingClassError(
             else:
                 hook_obj = hook
 
-            if not hasattr(hook_obj, '__call__'):
+            if not callable(hook_obj):
                 raise PackagingOptionError('hook %r is not callable' % hook)
 
             logger.info('running %s %s for command %s',

Lib/packaging/run.py

             for help_option, short, desc, func in cmd_class.help_options:
                 if hasattr(opts, help_option.replace('-', '_')):
                     help_option_found = True
-                    if hasattr(func, '__call__'):
+                    if callable(func):
                         func()
                     else:
                         raise PackagingClassError(
             raise PicklingError("args from save_reduce() should be a tuple")
 
         # Assert that func is callable
-        if not hasattr(func, '__call__'):
+        if not callable(func):
             raise PicklingError("func from save_reduce() should be callable")
 
         save = self.save
                 push(msg)
                 for name, kind, homecls, value in ok:
                     base = self.docother(getattr(object, name), name, mod)
-                    if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
+                    if callable(value) or inspect.isdatadescriptor(value):
                         doc = getattr(value, "__doc__", None)
                     else:
                         doc = None
                 hr.maybe()
                 push(msg)
                 for name, kind, homecls, value in ok:
-                    if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
+                    if callable(value) or inspect.isdatadescriptor(value):
                         doc = getdoc(value)
                     else:
                         doc = None
             if i == j:
                 break
             action = self.lexicon[m.lastindex-1][1]
-            if hasattr(action, "__call__"):
+            if callable(action):
                 self.match = m
                 action = action(self, m.group())
             if action is not None:

Lib/rlcompleter.py

             return None
 
     def _callable_postfix(self, val, word):
-        if hasattr(val, '__call__'):
+        if callable(val):
             word = word + "("
         return word
 
     """
     if extra_args is None:
         extra_args = []
-    if not isinstance(function, collections.Callable):
+    if not callable(function):
         raise TypeError('The %s object is not callable' % function)
     if not isinstance(extra_args, (tuple, list)):
         raise TypeError('extra_args needs to be a sequence')
             raise RegistryError(msg % (extension,
                                        existing_extensions[extension]))
 
-    if not isinstance(function, collections.Callable):
+    if not callable(function):
         raise TypeError('The registered function must be a callable')
 
 

Lib/socketserver.py

 data is stored externally (e.g. in the file system), a synchronous
 class will essentially render the service "deaf" while one request is
 being handled -- which may be for a very long time if a client is slow
-to recv all the data it has requested.  Here a threading or forking
+to read all the data it has requested.  Here a threading or forking
 server is appropriate.
 
 In some cases, it may be appropriate to process part of a request
 import os
 import shutil
 import stat
-import errno
 import time
 import struct
 import copy
             # Use a safe mode for the directory, the real mode is set
             # later in _extract_member().
             os.mkdir(targetpath, 0o700)
-        except EnvironmentError as e:
-            if e.errno != errno.EEXIST:
-                raise
+        except FileExistsError:
+            pass
 
     def makefile(self, tarinfo, targetpath):
         """Make a file called targetpath.
 import sys as _sys
 import io as _io
 import os as _os
-import errno as _errno
 from random import Random as _Random
 
 try:
     def _set_cloexec(fd):
         try:
             flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
-        except IOError:
+        except OSError:
             pass
         else:
             # flags read successfully, modify
 elif hasattr(_os, "stat"):
     _stat = _os.stat
 else:
-    # Fallback.  All we need is something that raises os.error if the
+    # Fallback.  All we need is something that raises OSError if the
     # file doesn't exist.
     def _stat(fn):
-        try:
-            f = open(fn)
-        except IOError:
-            raise _os.error
+        f = open(fn)
         f.close()
 
 def _exists(fn):
     try:
         _stat(fn)
-    except _os.error:
+    except OSError:
         return False
     else:
         return True
     # As a last resort, the current directory.
     try:
         dirlist.append(_os.getcwd())
-    except (AttributeError, _os.error):
+    except (AttributeError, OSError):
         dirlist.append(_os.curdir)
 
     return dirlist
                 _os.unlink(filename)
                 del fp, fd
                 return dir
-            except (OSError, IOError) as e:
-                if e.args[0] != _errno.EEXIST:
-                    break # no point trying more names in this directory
+            except FileExistsError:
                 pass
-    raise IOError(_errno.ENOENT,
-                  "No usable temporary directory found in %s" % dirlist)
+            except OSError:
+                break   # no point trying more names in this directory
+    raise FileNotFoundError("No usable temporary directory found in %s" % dirlist)
 
 _name_sequence = None
 
             fd = _os.open(file, flags, 0o600)
             _set_cloexec(fd)
             return (fd, _os.path.abspath(file))
-        except OSError as e:
-            if e.errno == _errno.EEXIST:
-                continue # try again
-            raise
+        except FileExistsError:
+            continue    # try again
 
-    raise IOError(_errno.EEXIST, "No usable temporary file name found")
+    raise FileExistsError("No usable temporary file name found")
 
 
 # User visible interfaces.
         try:
             _os.mkdir(file, 0o700)
             return file
-        except OSError as e:
-            if e.errno == _errno.EEXIST:
-                continue # try again
-            raise
+        except FileExistsError:
+            continue    # try again
 
-    raise IOError(_errno.EEXIST, "No usable temporary directory name found")
+    raise FileExistsError("No usable temporary directory name found")
 
 def mktemp(suffix="", prefix=template, dir=None):
     """User-callable function to return a unique temporary file name.  The
         if not _exists(file):
             return file
 
-    raise IOError(_errno.EEXIST, "No usable temporary filename found")
+    raise FileExistsError("No usable temporary filename found")
 
 
 class _TemporaryFileWrapper:
     _islink = staticmethod(_os.path.islink)
     _remove = staticmethod(_os.remove)
     _rmdir = staticmethod(_os.rmdir)
-    _os_error = _os.error
+    _os_error = OSError
     _warn = _warnings.warn
 
     def _rmtree(self, path):

Lib/test/regrtest.py

 """
 
 import builtins
-import errno
 import faulthandler
 import getopt
 import io
         TEMPDIR = os.path.abspath(TEMPDIR)
         try:
             os.mkdir(TEMPDIR)
-        except OSError as e:
-            if e.errno != errno.EEXIST:
-                raise
+        except FileExistsError:
+            pass
 
     # Define a writable temp dir that will be used as cwd while running
     # the tests. The name of the dir includes the pid to allow parallel

Lib/test/test_asyncore.py

         client = TestClient(self.family, server.address)
         self.loop_waiting_for_flag(client)
 
+    def test_handle_close_after_conn_broken(self):
+        # Check that ECONNRESET/EPIPE is correctly handled (issues #5661 and
+        # #11265).
+
+        data = b'\0' * 128
+
+        class TestClient(BaseClient):
+
+            def handle_write(self):
+                self.send(data)
+
+            def handle_close(self):
+                self.flag = True
+                self.close()
+
+            def handle_expt(self):
+                self.flag = True
+                self.close()
+
+        class TestHandler(BaseTestHandler):
+
+            def handle_read(self):
+                self.recv(len(data))
+                self.close()
+
+            def writable(self):
+                return False
+
+        server = BaseServer(self.family, self.addr, TestHandler)
+        client = TestClient(self.family, server.address)
+        self.loop_waiting_for_flag(client)
+
     @unittest.skipIf(sys.platform.startswith("sunos"),
                      "OOB support is broken on Solaris")
     def test_handle_expt(self):

Lib/test/test_float.py

         self.assertRaises(TypeError, float, Foo4(42))
         self.assertAlmostEqual(float(FooStr('8')), 9.)
 
+    def test_is_integer(self):
+        self.assertFalse((1.1).is_integer())
+        self.assertTrue((1.).is_integer())
+        self.assertFalse(float("nan").is_integer())
+        self.assertFalse(float("inf").is_integer())
+
     def test_floatasratio(self):
         for f, ratio in [
                 (0.875, (7, 8)),

Lib/test/test_htmlparser.py

                                 [('action', 'bogus|&#()value')])],
                         collector = self.collector)
 
+    def test_issue13273(self):
+        html = ('<div style=""    ><b>The <a href="some_url">rain</a> '
+                '<br /> in <span>Spain</span></b></div>')
+        expected = [
+            ('starttag', 'div', [('style', '')]),
+            ('starttag', 'b', []),
+            ('data', 'The '),
+            ('starttag', 'a', [('href', 'some_url')]),
+            ('data', 'rain'),
+            ('endtag', 'a'),
+            ('data', ' '),
+            ('startendtag', 'br', []),
+            ('data', ' in '),
+            ('starttag', 'span', []),
+            ('data', 'Spain'),
+            ('endtag', 'span'),
+            ('endtag', 'b'),
+            ('endtag', 'div')
+        ]
+        self._run_check(html, expected, collector=self.collector)
+
+    def test_issue13273_2(self):
+        html = '<div style="", foo = "bar" ><b>The <a href="some_url">rain</a>'
+        expected = [
+            ('starttag', 'div', [('style', ''), ('foo', 'bar')]),
+            ('starttag', 'b', []),
+            ('data', 'The '),
+            ('starttag', 'a', [('href', 'some_url')]),
+            ('data', 'rain'),
+            ('endtag', 'a'),
+        ]
+        self._run_check(html, expected, collector=self.collector)
+
     def test_unescape_function(self):
         p = html.parser.HTMLParser()
         self.assertEqual(p.unescape('&#bad;'),'&#bad;')

Lib/test/test_nntplib.py

 import unittest
 import functools
 import contextlib
-import collections.abc
 from test import support
 from nntplib import NNTP, GroupInfo, _have_ssl
 import nntplib
             if not name.startswith('test_'):
                 continue
             meth = getattr(cls, name)
-            if not isinstance(meth, collections.abc.Callable):
+            if not callable(meth):
                 continue
             # Need to use a closure so that meth remains bound to its current
             # value

Lib/test/test_ssl.py

             try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)
             if hasattr(ssl, 'PROTOCOL_SSLv2'):
                 try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
-            try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False)
+            try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,
+                               client_options=ssl.OP_NO_SSLv3)
             try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False)
             if no_sslv2_implies_sslv3_hello():
                 # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs
             if hasattr(ssl, 'PROTOCOL_SSLv2'):
                 try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
             try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
-            try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False)
+            try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
+                               client_options=ssl.OP_NO_TLSv1)
 
         def test_starttls(self):
             """Switching from clear text to encrypted and back again."""

Lib/test/test_xmlrpc.py

         (newdt,), m = xmlrpclib.loads(s, use_datetime=0)
         self.assertEqual(newdt, xmlrpclib.DateTime('00010210T11:41:23'))
 
-    def test_cmp_datetime_DateTime(self):
-        now = datetime.datetime.now()
-        dt = xmlrpclib.DateTime(now.timetuple())
-        self.assertTrue(dt == now)
-        self.assertTrue(now == dt)
-        then = now + datetime.timedelta(seconds=4)
-        self.assertTrue(then >= dt)
-        self.assertTrue(dt < then)
-
     def test_bug_1164912 (self):
         d = xmlrpclib.DateTime()
         ((new_d,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((d,),
                           ('host.tld',
                            [('Authorization', 'Basic dXNlcg==')], {}))
 
+    def test_dump_bytes(self):
+        self.assertRaises(TypeError, xmlrpclib.dumps, (b"my dog has fleas",))
+
     def test_ssl_presence(self):
         try:
             import ssl
         self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, s)
 
     def test_dotted_attribute(self):
-        # this will raise AttirebuteError because code don't want us to use
+        # this will raise AttributeError because code don't want us to use
         # private methods
         self.assertRaises(AttributeError,
                           xmlrpc.server.resolve_dotted_attribute, str, '__add')
         t2 = xmlrpclib._datetime(d)
         self.assertEqual(t1, tref)
 
+    def test_comparison(self):
+        now = datetime.datetime.now()
+        dtime = xmlrpclib.DateTime(now.timetuple())
+
+        # datetime vs. DateTime
+        self.assertTrue(dtime == now)
+        self.assertTrue(now == dtime)
+        then = now + datetime.timedelta(seconds=4)
+        self.assertTrue(then >= dtime)
+        self.assertTrue(dtime < then)
+
+        # str vs. DateTime
+        dstr = now.strftime("%Y%m%dT%H:%M:%S")
+        self.assertTrue(dtime == dstr)
+        self.assertTrue(dstr == dtime)
+        dtime_then = xmlrpclib.DateTime(then.timetuple())
+        self.assertTrue(dtime_then >= dstr)
+        self.assertTrue(dstr < dtime_then)
+
+        # some other types
+        dbytes = dstr.encode('ascii')
+        dtuple = now.timetuple()
+        with self.assertRaises(TypeError):
+            dtime == 1970
+        with self.assertRaises(TypeError):
+            dtime != dbytes
+        with self.assertRaises(TypeError):
+            dtime == bytearray(dbytes)
+        with self.assertRaises(TypeError):
+            dtime != dtuple
+        with self.assertRaises(TypeError):
+            dtime < float(1970)
+        with self.assertRaises(TypeError):
+            dtime > dbytes
+        with self.assertRaises(TypeError):
+            dtime <= bytearray(dbytes)
+        with self.assertRaises(TypeError):
+            dtime >= dtuple
+
 class BinaryTestCase(unittest.TestCase):
 
     # XXX What should str(Binary(b"\xff")) return?  I'm chosing "\xff"
     class MyRequestHandler(requestHandler):
         rpc_paths = []
 
+    class BrokenDispatcher:
+        def _marshaled_dispatch(self, data, dispatch_method=None, path=None):
+            raise RuntimeError("broken dispatcher")
+
     serv = MyXMLRPCServer(("localhost", 0), MyRequestHandler,
                           logRequests=False, bind_and_activate=False)
     serv.socket.settimeout(3)
             d.register_multicall_functions()
         serv.get_dispatcher(paths[0]).register_function(pow)
         serv.get_dispatcher(paths[1]).register_function(lambda x,y: x+y, 'add')
+        serv.add_dispatcher("/is/broken", BrokenDispatcher())
         evt.set()
 
         # handle up to 'numrequests' requests
         p = xmlrpclib.ServerProxy(URL+"/foo")
         self.assertEqual(p.pow(6,8), 6**8)
         self.assertRaises(xmlrpclib.Fault, p.add, 6, 8)
+
     def test_path2(self):
         p = xmlrpclib.ServerProxy(URL+"/foo/bar")
         self.assertEqual(p.add(6,8), 6+8)
         self.assertRaises(xmlrpclib.Fault, p.pow, 6, 8)
 
+    def test_path3(self):
+        p = xmlrpclib.ServerProxy(URL+"/is/broken")
+        self.assertRaises(xmlrpclib.Fault, p.add, 6, 8)
+
 #A test case that verifies that a server using the HTTP/1.1 keep-alive mechanism
 #does indeed serve subsequent requests on the same connection
 class BaseKeepaliveServerTestCase(BaseServerTestCase):
             if isinstance(setup, str):
                 setup = reindent(setup, 4)
                 src = template.format(stmt=stmt, setup=setup)
-            elif hasattr(setup, '__call__'):
+            elif callable(setup):
                 src = template.format(stmt=stmt, setup='_setup()')
                 ns['_setup'] = setup
             else:
             code = compile(src, dummy_src_name, "exec")
             exec(code, globals(), ns)
             self.inner = ns["inner"]
-        elif hasattr(stmt, '__call__'):
+        elif callable(stmt):
             self.src = None
             if isinstance(setup, str):
                 _setup = setup
                 def setup():
                     exec(_setup, globals(), ns)
-            elif not hasattr(setup, '__call__'):
+            elif not callable(setup):
                 raise ValueError("setup is neither a string nor callable")
             self.inner = _template_func(setup, stmt)
         else:

Lib/tkinter/__init__.py

         for k, v in cnf.items():
             if v is not None:
                 if k[-1] == '_': k = k[:-1]
-                if hasattr(v, '__call__'):
+                if callable(v):
                     v = self._register(v)
                 elif isinstance(v, (tuple, list)):
                     nv = []
         """Bind function FUNC to command NAME for this widget.
         Return the function bound to NAME if None is given. NAME could be
         e.g. "WM_SAVE_YOURSELF" or "WM_DELETE_WINDOW"."""
-        if hasattr(func, '__call__'):
+        if callable(func):
             command = self._register(func)
         else:
             command = func
         elif kw: cnf = kw
         options = ()
         for k, v in cnf.items():
-            if hasattr(v, '__call__'):
+            if callable(v):
                 v = self._register(v)
             options = options + ('-'+k, v)
         self.tk.call(('image', 'create', imgtype, name,) + options)
         for k, v in _cnfmerge(kw).items():
             if v is not None:
                 if k[-1] == '_': k = k[:-1]
-                if hasattr(v, '__call__'):
+                if callable(v):
                     v = self._register(v)
                 res = res + ('-'+k, v)
         self.tk.call((self.name, 'config') + res)

Lib/tkinter/tix.py

         elif kw: cnf = kw
         options = ()
         for k, v in cnf.items():
-            if hasattr(v, '__call__'):
+            if callable(v):
                 v = self._register(v)
             options = options + ('-'+k, v)
         return master.tk.call(('image', 'create', imgtype,) + options)

Lib/unittest/loader.py

                 return self.suiteClass([inst])
         elif isinstance(obj, suite.TestSuite):
             return obj
-        if hasattr(obj, '__call__'):
+        if callable(obj):
             test = obj()
             if isinstance(test, suite.TestSuite):
                 return test
         def isTestMethod(attrname, testCaseClass=testCaseClass,
                          prefix=self.testMethodPrefix):
             return attrname.startswith(prefix) and \
-                hasattr(getattr(testCaseClass, attrname), '__call__')
+                callable(getattr(testCaseClass, attrname))
         testFnNames = testFnNames = list(filter(isTestMethod,
                                                 dir(testCaseClass)))
         if self.sortTestMethodsUsing:

Lib/unittest/suite.py

 
     def addTest(self, test):
         # sanity checks
-        if not hasattr(test, '__call__'):
+        if not callable(test):
             raise TypeError("{} is not callable".format(repr(test)))
         if isinstance(test, type) and issubclass(test,
                                                  (case.TestCase, TestSuite)):
         raise RuntimeError(
               "Unrecognized action (%r) in warnings.filters:\n %s" %
               (action, item))
-    if not hasattr(showwarning, "__call__"):
+    if not callable(showwarning):
         raise TypeError("warnings.showwarning() must be set to a "
                         "function or method")
     # Print message and context

Lib/xmlrpc/client.py

 # OF THIS SOFTWARE.
 # --------------------------------------------------------------------
 
-#
-# things to look into some day:
-
-# TODO: sort out True/False/boolean issues for Python 2.3
-
 """
 An XML-RPC client interface for Python.
 
 
 Exported constants:
 
-  True
-  False
+  (none)
 
 Exported functions:
 
                  name (None if not present).
 """
 
-import re, time, operator
+import base64
+import sys
+import time
+from datetime import datetime
 import http.client
 from xml.parsers import expat
 import socket
 # --------------------------------------------------------------------
 # Internal stuff
 
-try:
-    import datetime
-except ImportError:
-    datetime = None
-
 def escape(s):
     s = s.replace("&", "&amp;")
     s = s.replace("<", "&lt;")
     return s.replace(">", "&gt;",)
 
-__version__ = "1.0.1"
+# used in User-Agent header sent
+__version__ = sys.version[:3]
 
 # xmlrpc integer limits
 MAXINT =  2**31-1
 ##
 # Indicates an XML-RPC fault response package.  This exception is
 # raised by the unmarshalling layer, if the XML-RPC response contains
-# a fault string.  This exception can also used as a class, to
+# a fault string.  This exception can also be used as a class, to
 # generate a fault XML-RPC message.
 #
 # @param faultCode The XML-RPC fault code.
         self.faultCode = faultCode
         self.faultString = faultString
     def __repr__(self):
-        return (
-            "<Fault %s: %s>" %
-            (self.faultCode, repr(self.faultString))
-            )
+        return "<Fault %s: %r>" % (self.faultCode, self.faultString)
 
 # --------------------------------------------------------------------
 # Special values
 #              tuple, or a integer time value.
 
 def _strftime(value):
-    if datetime:
-        if isinstance(value, datetime.datetime):
-            return "%04d%02d%02dT%02d:%02d:%02d" % (
-                value.year, value.month, value.day,
-                value.hour, value.minute, value.second)
+    if isinstance(value, datetime):
+        return value.strftime("%Y%m%dT%H:%M:%S")
 
     if not isinstance(value, (tuple, time.struct_time)):
         if value == 0:
         if isinstance(other, DateTime):
             s = self.value
             o = other.value
-        elif datetime and isinstance(other, datetime.datetime):
+        elif isinstance(other, datetime):
             s = self.value
             o = other.strftime("%Y%m%dT%H:%M:%S")
-        elif isinstance(other, (str, unicode)):
+        elif isinstance(other, str):
             s = self.value
             o = other
         elif hasattr(other, "timetuple"):
         return self.value
 
     def __repr__(self):
-        return "<DateTime %s at %x>" % (repr(self.value), id(self))
+        return "<DateTime %r at %x>" % (self.value, id(self))
 
     def decode(self, data):
         self.value = str(data).strip()
     return value
 
 def _datetime_type(data):
-    t = time.strptime(data, "%Y%m%dT%H:%M:%S")
-    return datetime.datetime(*tuple(t)[:6])
+    return datetime.strptime(data, "%Y%m%dT%H:%M:%S")
 
 ##
 # Wrapper for binary data.  This can be used to transport any kind
 #
 # @param data An 8-bit string containing arbitrary data.
 
-import base64
-import io
-
 class Binary:
     """Wrapper for binary data."""
 
         out.write("<value><base64>\n")
         encoded = base64.encodebytes(self.data)
         out.write(encoded.decode('ascii'))
-        out.write('\n')
         out.write("</base64></value>\n")
 
 def _binary(data):
             f = self.dispatch[type(value)]
         except KeyError:
             # check if this object can be marshalled as a structure
-            try:
-                value.__dict__
-            except:
+            if not hasattr(value, '__dict__'):
                 raise TypeError("cannot marshal %s objects" % type(value))
             # check if this class is a sub-class of a basic type,
             # because we don't know how to marshal these types
         write("</double></value>\n")
     dispatch[float] = dump_double
 
-    def dump_string(self, value, write, escape=escape):
-        write("<value><string>")
-        write(escape(value))
-        write("</string></value>\n")
-    dispatch[bytes] = dump_string
-
     def dump_unicode(self, value, write, escape=escape):
         write("<value><string>")
         write(escape(value))
         del self.memo[i]
     dispatch[dict] = dump_struct
 
-    if datetime:
-        def dump_datetime(self, value, write):
-            write("<value><dateTime.iso8601>")
-            write(_strftime(value))
-            write("</dateTime.iso8601></value>\n")
-        dispatch[datetime.datetime] = dump_datetime
+    def dump_datetime(self, value, write):
+        write("<value><dateTime.iso8601>")
+        write(_strftime(value))
+        write("</dateTime.iso8601></value>\n")
+    dispatch[datetime] = dump_datetime
 
     def dump_instance(self, value, write):
         # check for special wrappers
         self._encoding = "utf-8"
         self.append = self._stack.append
         self._use_datetime = use_datetime
-        if use_datetime and not datetime:
-            raise ValueError("the datetime module is not available")
 
     def close(self):
         # return response tuple and target method
     Create an instance of the fastest available parser, and attach it
     to an unmarshalling object.  Return both objects.
     """
-    if use_datetime and not datetime:
-        raise ValueError("the datetime module is not available")
     if FastParser and FastUnmarshaller:
         if use_datetime:
             mkdatetime = _datetime_type
     """Handles an HTTP transaction to an XML-RPC server."""
 
     # client identifier (may be overridden)
-    user_agent = "xmlrpclib.py/%s (by www.pythonware.com)" % __version__
+    user_agent = "Python-xmlrpc/%s" % __version__
 
     #if true, we'll request gzip encoding
     accept_gzip_encoding = True
         auth, host = urllib.parse.splituser(host)
 
         if auth:
-            import base64
             auth = urllib.parse.unquote_to_bytes(auth)
             auth = base64.encodebytes(auth).decode("utf-8")
             auth = "".join(auth.split()) # get rid of whitespace

Lib/xmlrpc/server.py

 
     return [member for member in dir(obj)
                 if not member.startswith('_') and
-                    hasattr(getattr(obj, member), '__call__')]
+                    callable(getattr(obj, member))]
 
 class SimpleXMLRPCDispatcher:
     """Mix-in class that dispatches XML-RPC requests.
         if method is None:
             return ""
         else:
-            import pydoc
             return pydoc.getdoc(method)
 
     def system_multicall(self, call_list):
     Simple XML-RPC server that allows functions and a single instance
     to be installed to handle requests. The default implementation
     attempts to dispatch XML-RPC calls to the functions or instance
-    installed in the server. Override the _dispatch method inhereted
+    installed in the server. Override the _dispatch method inherited
     from SimpleXMLRPCDispatcher to change this behavior.
     """
 
                                     encoding, bind_and_activate)
         self.dispatchers = {}
         self.allow_none = allow_none
-        self.encoding = encoding
+        self.encoding = encoding or 'utf-8'
 
     def add_dispatcher(self, path, dispatcher):
         self.dispatchers[path] = dispatcher
             # (each dispatcher should have handled their own
             # exceptions)
             exc_type, exc_value = sys.exc_info()[:2]
-            response = xmlrpclib.dumps(
-                xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)),
+            response = dumps(
+                Fault(1, "%s:%s" % (exc_type, exc_value)),
                 encoding=self.encoding, allow_none=self.allow_none)
+            response = response.encode(self.encoding)
         return response
 
 class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):
 
 
 if __name__ == '__main__':
-    print('Running XML-RPC server on port 8000')
     server = SimpleXMLRPCServer(("localhost", 8000))
     server.register_function(pow)
     server.register_function(lambda x,y: x+y, 'add')
-    server.serve_forever()
+    print('Serving XML-RPC on localhost port 8000')
+    try:
+        server.serve_forever()
+    except KeyboardInterrupt:
+        print("\nKeyboard interrupt received, exiting.")
+        server.server_close()
+        sys.exit(0)
 Scott David Daniels
 Ben Darnell
 Jonathan Dasteel
+Xavier de Gaye
 John DeGood
 Ned Deily
 Vincent Delft
 Core and Builtins
 -----------------
 
+- Issue #10519: Avoid unnecessary recursive function calls in
+  setobject.c.
+
+- Issue #10363: Deallocate global locks in Py_Finalize().
+
 - Issue #13018: Fix reference leaks in error paths in dictobject.c.
   Patch by Suman Saha.
 
 - Issue #12380: The rjust, ljust and center methods of bytes and bytearray
   now accept a bytearray argument.
 
+
 Library
 -------
 
+- Issue 13296: Fix IDLE to clear compile __future__ flags on shell restart.
+  (Patch by Roger Serwy)
+
+- Fix the xmlrpc.client user agent to return something similar to
+  urllib.request user agent: "Python-xmlrpc/3.3".
+
+- Issue #13293: Better error message when trying to marshal bytes using
+  xmlrpc.client.
+
+- Issue #13291: NameError in xmlrpc package.
+
+- Issue #13258: Use callable() built-in in the standard library.
+
+- Issue #13273: fix a bug that prevented HTMLParser to properly detect some
+  tags when strict=False.
+
 - Issue #11183: Add finer-grained exceptions to the ssl module, so that
   you don't have to inspect the exception's attributes in the common case.
 
 Tests
 -----
 
+- Issue #5661: Add a test for ECONNRESET/EPIPE handling to test_asyncore. Patch
+  by Xavier de Gaye.
+
+- Issue #13218: Fix test_ssl failures on Debian/Ubuntu.
+
 - Re-enable lib2to3's test_parser.py tests, though with an expected failure
   (see issue 13125).
 

Modules/zipimport.c

 static int
 zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds)
 {
-    PyObject *pathobj, *files;
-    Py_UCS4 *path, *p, *prefix, buf[MAXPATHLEN+2];
-    Py_ssize_t len;
+    PyObject *path, *files, *tmp;
+    PyObject *filename = NULL;
+    Py_ssize_t len, flen;
+#ifdef ALTSEP
+    _Py_IDENTIFIER(replace);
+#endif
 
     if (!_PyArg_NoKeywords("zipimporter()", kwds))
         return -1;
 
     if (!PyArg_ParseTuple(args, "O&:zipimporter",
-                          PyUnicode_FSDecoder, &pathobj))
+                          PyUnicode_FSDecoder, &path))
         return -1;
 
-    if (PyUnicode_READY(pathobj) == -1)
+    if (PyUnicode_READY(path) == -1)
         return -1;
 
-    /* copy path to buf */
-    len = PyUnicode_GET_LENGTH(pathobj);
+    len = PyUnicode_GET_LENGTH(path);
     if (len == 0) {
         PyErr_SetString(ZipImportError, "archive path is empty");
         goto error;
     }
-    if (len >= MAXPATHLEN) {
-        PyErr_SetString(ZipImportError,
-                        "archive path too long");
-        goto error;
-    }
-    if (!PyUnicode_AsUCS4(pathobj, buf, Py_ARRAY_LENGTH(buf), 1))
-        goto error;
 
 #ifdef ALTSEP
-    for (p = buf; *p; p++) {
-        if (*p == ALTSEP)
-            *p = SEP;
-    }
+    tmp = _PyObject_CallMethodId(path, &PyId_replace, "CC", ALTSEP, SEP);
+    if (!tmp)
+        goto error;
+    Py_DECREF(path);
+    path = tmp;
 #endif
 
-    path = NULL;
-    prefix = NULL;
+    filename = path;
+    Py_INCREF(filename);
+    flen = len;
     for (;;) {
         struct stat statbuf;
         int rv;
 
-        if (pathobj == NULL) {
-            pathobj = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
-                                                buf, len);
-            if (pathobj == NULL)
-                goto error;
-        }
-        rv = _Py_stat(pathobj, &statbuf);
+        rv = _Py_stat(filename, &statbuf);
         if (rv == 0) {
             /* it exists */
-            if (S_ISREG(statbuf.st_mode))
-                /* it's a file */
-                path = buf;
+            if (!S_ISREG(statbuf.st_mode))
+                /* it's a not file */
+                Py_CLEAR(filename);
             break;
         }
         else if (PyErr_Occurred())
             goto error;
+        Py_CLEAR(filename);
         /* back up one path element */
-        p = Py_UCS4_strrchr(buf, SEP);
-        if (prefix != NULL)
-            *prefix = SEP;
-        if (p == NULL)
+        flen = PyUnicode_FindChar(path, SEP, 0, flen, -1);
+        if (flen == -1)
             break;
-        *p = '\0';
-        len = p - buf;
-        prefix = p;
-        Py_CLEAR(pathobj);
+        filename = PyUnicode_Substring(path, 0, flen);
     }
-    if (path == NULL) {
+    if (filename == NULL) {
         PyErr_SetString(ZipImportError, "not a Zip file");
         goto error;
     }
 
-    files = PyDict_GetItem(zip_directory_cache, pathobj);
+    if (PyUnicode_READY(filename) < 0)
+        goto error;
+
+    files = PyDict_GetItem(zip_directory_cache, filename);
     if (files == NULL) {
-        files = read_directory(pathobj);
+        files = read_directory(filename);
         if (files == NULL)
             goto error;
-        if (PyDict_SetItem(zip_directory_cache, pathobj, files) != 0)
+        if (PyDict_SetItem(zip_directory_cache, filename, files) != 0)
             goto error;
     }
     else
         Py_INCREF(files);
     self->files = files;
 
-    self->archive = pathobj;
-    pathobj = NULL;
+    /* Transfer reference */
+    self->archive = filename;
+    filename = NULL;
 
-    if (prefix != NULL) {
-        prefix++;
-        len = Py_UCS4_strlen(prefix);
-        if (prefix[len-1] != SEP) {
+    /* Check if there is a prefix directory following the filename. */
+    if (flen != len) {
+        tmp = PyUnicode_Substring(path, flen+1,
+                                  PyUnicode_GET_LENGTH(path));
+        if (tmp == NULL)
+            goto error;
+        self->prefix = tmp;
+        if (PyUnicode_READ_CHAR(path, len-1) != SEP) {
             /* add trailing SEP */
-            prefix[len] = SEP;
-            prefix[len + 1] = '\0';
-            len++;
+            tmp = PyUnicode_FromFormat("%U%c", self->prefix, SEP);
+            if (tmp == NULL)
+                goto error;
+            Py_DECREF(self->prefix);
+            self->prefix = tmp;
         }
     }
     else
-        len = 0;
-    self->prefix = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
-                                               prefix, len);
-    if (self->prefix == NULL)
-        goto error;
-
+        self->prefix = PyUnicode_New(0, 0);
+    Py_DECREF(path);
     return 0;
 
 error:
-    Py_XDECREF(pathobj);
+    Py_DECREF(path);
+    Py_XDECREF(filename);
     return -1;
 }
 
 static PyObject *
 get_subname(PyObject *fullname)
 {
-    Py_ssize_t len;
-    Py_UCS4 *subname, *fullname_ucs4;
-    fullname_ucs4 = PyUnicode_AsUCS4Copy(fullname);
-    if (!fullname_ucs4)
+    Py_ssize_t len, dot;
+    if (PyUnicode_READY(fullname) < 0)
         return NULL;
-    subname = Py_UCS4_strrchr(fullname_ucs4, '.');
-    if (subname == NULL) {
-        PyMem_Free(fullname_ucs4);
+    len = PyUnicode_GET_LENGTH(fullname);
+    dot = PyUnicode_FindChar(fullname, '.', 0, len, -1);
+    if (dot == -1) {
         Py_INCREF(fullname);
         return fullname;
-    } else {
-        PyObject *result;
-        subname++;
-        len = PyUnicode_GET_LENGTH(fullname);
-        len -= subname - fullname_ucs4;
-        result = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
-                                           subname, len);
-        PyMem_Free(fullname_ucs4);
-        return result;
-    }
+    } else
+        return PyUnicode_Substring(fullname, dot+1, len);
 }
 
 /* Given a (sub)modulename, write the potential file path in the
 zipimporter_get_data(PyObject *obj, PyObject *args)
 {
     ZipImporter *self = (ZipImporter *)obj;
-    PyObject *pathobj, *key;
-    const Py_UCS4 *path;
+    PyObject *path, *key;
 #ifdef ALTSEP
-    Py_UCS4 *p;
+    _Py_IDENTIFIER(replace);
 #endif
     PyObject *toc_entry;
-    Py_ssize_t path_len, len;
-    Py_UCS4 buf[MAXPATHLEN + 1], archive[MAXPATHLEN + 1];
+    Py_ssize_t path_start, path_len, len;
 
-    if (!PyArg_ParseTuple(args, "U:zipimporter.get_data", &pathobj))
+    if (!PyArg_ParseTuple(args, "U:zipimporter.get_data", &path))
         return NULL;
 
-    if (PyUnicode_READY(pathobj) == -1)
+#ifdef ALTSEP
+    path = _PyObject_CallMethodId(path, &PyId_replace, "CC", ALTSEP, SEP);
+    if (!path)
         return NULL;
+#else
+    Py_INCREF(path);
+#endif
+    if (PyUnicode_READY(path) == -1)
+        goto error;
 
-    path_len = PyUnicode_GET_LENGTH(pathobj);
-    if (path_len >= MAXPATHLEN) {
-        PyErr_SetString(ZipImportError, "path too long");
-        return NULL;
-    }
-    if (!PyUnicode_AsUCS4(pathobj, buf, Py_ARRAY_LENGTH(buf), 1))
-        return NULL;
-    path = buf;
-#ifdef ALTSEP
-    for (p = buf; *p; p++) {
-        if (*p == ALTSEP)
-            *p = SEP;
-    }
-#endif
+    path_len = PyUnicode_GET_LENGTH(path);
+
     len = PyUnicode_GET_LENGTH(self->archive);
-    if ((size_t)len < Py_UCS4_strlen(path)) {
-        if (!PyUnicode_AsUCS4(self->archive, archive, Py_ARRAY_LENGTH(archive), 1))
-            return NULL;
-        if (Py_UCS4_strncmp(path, archive, len) == 0 &&
-            path[len] == SEP) {
-            path += len + 1;
-            path_len -= len + 1;
-        }
+    path_start = 0;
+    if (PyUnicode_Tailmatch(path, self->archive, 0, len, -1)
+        && PyUnicode_READ_CHAR(path, len) == SEP) {
+        path_start = len + 1;
     }
 
-    key = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
-                                    path, path_len);
+    key = PyUnicode_Substring(path, path_start, path_len);
     if (key == NULL)
-        return NULL;
+        goto error;
     toc_entry = PyDict_GetItem(self->files, key);
     if (toc_entry == NULL) {
         PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, key);
         Py_DECREF(key);
-        return NULL;
+        goto error;
     }
     Py_DECREF(key);
+    Py_DECREF(path);
     return get_data(self->archive, toc_entry);
+  error:
+    Py_DECREF(path);
+    return NULL;
 }
 
 static PyObject *
     long header_offset, name_size, header_size, header_position;
     long l, count;
     Py_ssize_t i;
-    size_t length;
-    Py_UCS4 path[MAXPATHLEN + 5];
     char name[MAXPATHLEN + 5];
     PyObject *nameobj = NULL;
     char *p, endof_central_dir[22];
     long arc_offset; /* offset from beginning of file to start of zip-archive */
-    PyObject *pathobj;
+    PyObject *path;
     const char *charset;
     int bootstrap;
 
-    if (PyUnicode_GET_LENGTH(archive) > MAXPATHLEN) {
-        PyErr_SetString(PyExc_OverflowError,
-                        "Zip path name is too long");
-        return NULL;
-    }
-    if (!PyUnicode_AsUCS4(archive, path, Py_ARRAY_LENGTH(path), 1))
-        return NULL;
-
     fp = _Py_fopen(archive, "rb");
     if (fp == NULL) {
         PyErr_Format(ZipImportError, "can't open Zip file: %R", archive);
     if (files == NULL)
         goto error;
 
-    length = Py_UCS4_strlen(path);
-    path[length] = SEP;
-
     /* Start of Central Directory */
     count = 0;
     for (;;) {
                     PY_MAJOR_VERSION, PY_MINOR_VERSION);
             goto error;
         }
-        for (i = 0; (i < (MAXPATHLEN - (Py_ssize_t)length - 1)) &&
-                 (i < PyUnicode_GET_LENGTH(nameobj)); i++)
-            path[length + 1 + i] = PyUnicode_READ_CHAR(nameobj, i);
-        path[length + 1 + i] = 0;
-        pathobj = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
-                                            path, Py_UCS4_strlen(path));
-        if (pathobj == NULL)
+        path = PyUnicode_FromFormat("%U%c%U", archive, SEP, nameobj);
+        if (path == NULL)
             goto error;
-        t = Py_BuildValue("Niiiiiii", pathobj, compress, data_size,
+        t = Py_BuildValue("Niiiiiii", path, compress, data_size,
                           file_size, file_offset, time, date, crc);
         if (t == NULL)
             goto error;

Objects/setobject.c

         tmpkey = make_new_set(&PyFrozenSet_Type, key);
         if (tmpkey == NULL)
             return -1;
-        rv = set_contains(so, tmpkey);
+        rv = set_contains_key(so, tmpkey);
         Py_DECREF(tmpkey);
     }
     return rv;
 static PyObject *
 set_discard(PySetObject *so, PyObject *key)
 {
-    PyObject *tmpkey, *result;
+    PyObject *tmpkey;
     int rv;
 
     rv = set_discard_key(so, key);
         tmpkey = make_new_set(&PyFrozenSet_Type, key);
         if (tmpkey == NULL)
             return NULL;
-        result = set_discard(so, tmpkey);
+        rv = set_discard_key(so, tmpkey);
         Py_DECREF(tmpkey);
-        return result;
+        if (rv == -1)
+            return NULL;
     }
     Py_RETURN_NONE;
 }