[Python-checkins] cpython (merge default -> default): merge heads

petri.lehtinen python-checkins at python.org
Mon Oct 24 20:33:31 CEST 2011


http://hg.python.org/cpython/rev/2358a46b621e
changeset:   73105:2358a46b621e
parent:      73104:db85b1cdcae2
parent:      73101:c2cdabc44665
user:        Petri Lehtinen <petri at digip.org>
date:        Mon Oct 24 21:22:39 2011 +0300
summary:
  merge heads

files:
  Doc/faq/extending.rst            |   30 ----
  Doc/library/2to3.rst             |    4 +-
  Doc/library/ftplib.rst           |    2 +-
  Doc/library/signal.rst           |    4 +-
  Doc/library/socketserver.rst     |   64 +++++----
  Doc/whatsnew/3.3.rst             |  129 +++++++++++-------
  Lib/_pyio.py                     |   17 +-
  Lib/asyncore.py                  |   13 +-
  Lib/decimal.py                   |   22 ---
  Lib/ftplib.py                    |   17 +-
  Lib/multiprocessing/pool.py      |    6 +-
  Lib/multiprocessing/util.py      |    9 +-
  Lib/optparse.py                  |    5 +-
  Lib/pickletools.py               |    5 +-
  Lib/socket.py                    |    8 +-
  Lib/subprocess.py                |    6 +-
  Lib/test/test_decimal.py         |   15 +-
  Lib/test/test_long.py            |   80 +++++++++++
  Lib/test/test_multiprocessing.py |   14 ++
  Lib/test/test_socket.py          |    2 +-
  Lib/xdrlib.py                    |    6 +-
  Lib/xmlrpc/client.py             |   12 +-
  Misc/NEWS                        |    9 +
  Modules/arraymodule.c            |    8 +-
  Objects/longobject.c             |   40 +++--
  25 files changed, 284 insertions(+), 243 deletions(-)


diff --git a/Doc/faq/extending.rst b/Doc/faq/extending.rst
--- a/Doc/faq/extending.rst
+++ b/Doc/faq/extending.rst
@@ -447,34 +447,3 @@
 The Boost Python Library (BPL, http://www.boost.org/libs/python/doc/index.html)
 provides a way of doing this from C++ (i.e. you can inherit from an extension
 class written in C++ using the BPL).
-
-
-When importing module X, why do I get "undefined symbol: PyUnicodeUCS2*"?
--------------------------------------------------------------------------
-
-You are using a version of Python that uses a 4-byte representation for Unicode
-characters, but some C extension module you are importing was compiled using a
-Python that uses a 2-byte representation for Unicode characters (the default).
-
-If instead the name of the undefined symbol starts with ``PyUnicodeUCS4``, the
-problem is the reverse: Python was built using 2-byte Unicode characters, and
-the extension module was compiled using a Python with 4-byte Unicode characters.
-
-This can easily occur when using pre-built extension packages.  RedHat Linux
-7.x, in particular, provided a "python2" binary that is compiled with 4-byte
-Unicode.  This only causes the link failure if the extension uses any of the
-``PyUnicode_*()`` functions.  It is also a problem if an extension uses any of
-the Unicode-related format specifiers for :c:func:`Py_BuildValue` (or similar) or
-parameter specifications for :c:func:`PyArg_ParseTuple`.
-
-You can check the size of the Unicode character a Python interpreter is using by
-checking the value of sys.maxunicode:
-
-   >>> import sys
-   >>> if sys.maxunicode > 65535:
-   ...     print('UCS4 build')
-   ... else:
-   ...     print('UCS2 build')
-
-The only way to solve this problem is to use extension modules compiled with a
-Python binary built using the same size for Unicode characters.
diff --git a/Doc/library/2to3.rst b/Doc/library/2to3.rst
--- a/Doc/library/2to3.rst
+++ b/Doc/library/2to3.rst
@@ -123,7 +123,9 @@
 .. 2to3fixer:: callable
 
    Converts ``callable(x)`` to ``isinstance(x, collections.Callable)``, adding
-   an import to :mod:`collections` if needed.
+   an import to :mod:`collections` if needed. Note ``callable(x)`` has returned
+   in Python 3.2, so if you do not intend to support Python 3.1, you can disable
+   this fixer.
 
 .. 2to3fixer:: dict
 
diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst
--- a/Doc/library/ftplib.rst
+++ b/Doc/library/ftplib.rst
@@ -427,7 +427,7 @@
 
 .. method:: FTP_TLS.ccc()
 
-   Revert control channel back to plaintex.  This can be useful to take
+   Revert control channel back to plaintext.  This can be useful to take
    advantage of firewalls that know how to handle NAT with non-secure FTP
    without opening fixed ports.
 
diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst
--- a/Doc/library/signal.rst
+++ b/Doc/library/signal.rst
@@ -353,8 +353,8 @@
    signals in *sigset* is already pending for the calling thread, the function
    will return immediately with information about that signal. The signal
    handler is not called for the delivered signal. The function raises an
-   :exc:`OSError` with error number set to :const:`errno.EINTR` if it is
-   interrupted by a signal that is not in *sigset*.
+   :exc:`InterruptedError` if it is interrupted by a signal that is not in
+   *sigset*.
 
    The return value is an object representing the data contained in the
    :c:type:`siginfo_t` structure, namely: :attr:`si_signo`, :attr:`si_code`,
diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst
--- a/Doc/library/socketserver.rst
+++ b/Doc/library/socketserver.rst
@@ -361,7 +361,7 @@
        def handle(self):
            # self.request is the TCP socket connected to the client
            self.data = self.request.recv(1024).strip()
-           print("%s wrote:" % self.client_address[0])
+           print("{} wrote:".format(self.client_address[0]))
            print(self.data)
            # just send back the same data, but upper-cased
            self.request.send(self.data.upper())
@@ -385,7 +385,7 @@
            # self.rfile is a file-like object created by the handler;
            # we can now use e.g. readline() instead of raw recv() calls
            self.data = self.rfile.readline().strip()
-           print("%s wrote:" % self.client_address[0])
+           print("{} wrote:".format(self.client_address[0]))
            print(self.data)
            # Likewise, self.wfile is a file-like object used to write back
            # to the client
@@ -408,16 +408,18 @@
    # Create a socket (SOCK_STREAM means a TCP socket)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
-   # Connect to server and send data
-   sock.connect((HOST, PORT))
-   sock.send(bytes(data + "\n","utf8"))
+   try:
+       # Connect to server and send data
+       sock.connect((HOST, PORT))
+       sock.send(bytes(data + "\n", "utf-8"))
 
-   # Receive data from the server and shut down
-   received = sock.recv(1024)
-   sock.close()
+       # Receive data from the server and shut down
+       received = str(sock.recv(1024), "utf-8")
+   finally:
+       sock.close()
 
-   print("Sent:     %s" % data)
-   print("Received: %s" % received)
+   print("Sent:     {}".format(data))
+   print("Received: {}".format(received))
 
 
 The output of the example should look something like this:
@@ -434,10 +436,10 @@
 
    $ python TCPClient.py hello world with TCP
    Sent:     hello world with TCP
-   Received: b'HELLO WORLD WITH TCP'
+   Received: HELLO WORLD WITH TCP
    $ python TCPClient.py python is nice
    Sent:     python is nice
-   Received: b'PYTHON IS NICE'
+   Received: PYTHON IS NICE
 
 
 :class:`socketserver.UDPServer` Example
@@ -458,7 +460,7 @@
        def handle(self):
            data = self.request[0].strip()
            socket = self.request[1]
-           print("%s wrote:" % self.client_address[0])
+           print("{} wrote:".format(self.client_address[0]))
            print(data)
            socket.sendto(data.upper(), self.client_address)
 
@@ -480,11 +482,11 @@
 
    # As you can see, there is no connect() call; UDP has no connections.
    # Instead, data is directly sent to the recipient via sendto().
-   sock.sendto(bytes(data + "\n","utf8"), (HOST, PORT))
-   received = sock.recv(1024)
+   sock.sendto(bytes(data + "\n", "utf-8"), (HOST, PORT))
+   received = str(sock.recv(1024), "utf-8")
 
-   print("Sent:     %s" % data)
-   print("Received: %s" % received)
+   print("Sent:     {}".format(data))
+   print("Received: {}".format(received))
 
 The output of the example should look exactly like for the TCP server example.
 
@@ -504,9 +506,9 @@
    class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
 
        def handle(self):
-           data = self.request.recv(1024)
+           data = str(self.request.recv(1024), 'ascii')
            cur_thread = threading.current_thread()
-           response = bytes("%s: %s" % (cur_thread.getName(), data),'ascii')
+           response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
            self.request.send(response)
 
    class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
@@ -515,10 +517,12 @@
    def client(ip, port, message):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((ip, port))
-       sock.send(message)
-       response = sock.recv(1024)
-       print("Received: %s" % response)
-       sock.close()
+       try:
+           sock.send(bytes(message, 'ascii'))
+           response = str(sock.recv(1024), 'ascii')
+           print("Received: {}".format(response))
+       finally:
+           sock.close()
 
    if __name__ == "__main__":
        # Port 0 means to select an arbitrary unused port
@@ -531,13 +535,13 @@
        # more thread for each request
        server_thread = threading.Thread(target=server.serve_forever)
        # Exit the server thread when the main thread terminates
-       server_thread.setDaemon(True)
+       server_thread.daemon = True
        server_thread.start()
        print("Server loop running in thread:", server_thread.name)
 
-       client(ip, port, b"Hello World 1")
-       client(ip, port, b"Hello World 2")
-       client(ip, port, b"Hello World 3")
+       client(ip, port, "Hello World 1")
+       client(ip, port, "Hello World 2")
+       client(ip, port, "Hello World 3")
 
        server.shutdown()
 
@@ -546,9 +550,9 @@
 
    $ python ThreadedTCPServer.py
    Server loop running in thread: Thread-1
-   Received: b"Thread-2: b'Hello World 1'"
-   Received: b"Thread-3: b'Hello World 2'"
-   Received: b"Thread-4: b'Hello World 3'"
+   Received: Thread-2: Hello World 1
+   Received: Thread-3: Hello World 2
+   Received: Thread-4: Hello World 3
 
 
 The :class:`ForkingMixIn` class is used in the same way, except that the server
diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -49,28 +49,32 @@
 This article explains the new features in Python 3.3, compared to 3.2.
 
 
+.. _pep-393:
+
 PEP 393: Flexible String Representation
 =======================================
 
-[Abstract copied from the PEP: The Unicode string type is changed to support
-multiple internal representations, depending on the character with the largest
-Unicode ordinal (1, 2, or 4 bytes).  This allows a space-efficient
-representation in common cases, but gives access to full UCS-4 on all systems.
-For compatibility with existing APIs, several representations may exist in
-parallel; over time, this compatibility should be phased out.]
+The Unicode string type is changed to support multiple internal
+representations, depending on the character with the largest Unicode ordinal
+(1, 2, or 4 bytes) in the represented string.  This allows a space-efficient
+representation in common cases, but gives access to full UCS-4 on all
+systems.  For compatibility with existing APIs, several representations may
+exist in parallel; over time, this compatibility should be phased out.
 
-PEP 393 is fully backward compatible. The legacy API should remain
-available at least five years. Applications using the legacy API will not
-fully benefit of the memory reduction, or worse may use a little bit more
-memory, because Python may have to maintain two versions of each string (in
-the legacy format and in the new efficient storage).
+On the Python side, there should be no downside to this change.
 
-XXX Add list of changes introduced by :pep:`393` here:
+On the C API side, PEP 393 is fully backward compatible.  The legacy API
+should remain available at least five years.  Applications using the legacy
+API will not fully benefit of the memory reduction, or - worse - may use
+a bit more memory, because Python may have to maintain two versions of each
+string (in the legacy format and in the new efficient storage).
+
+Changes introduced by :pep:`393` are the following:
 
 * Python now always supports the full range of Unicode codepoints, including
   non-BMP ones (i.e. from ``U+0000`` to ``U+10FFFF``).  The distinction between
   narrow and wide builds no longer exists and Python now behaves like a wide
-  build.
+  build, even under Windows.
 
 * The storage of Unicode strings now depends on the highest codepoint in the string:
 
@@ -86,7 +90,8 @@
    XXX The result should be moved in the PEP and a small summary about
    performances and a link to the PEP should be added here.
 
-* Some of the problems visible on narrow builds have been fixed, for example:
+* With the death of narrow builds, the problems specific to narrow builds have
+  also been fixed, for example:
 
   * :func:`len` now always returns 1 for non-BMP characters,
     so ``len('\U0010FFFF') == 1``;
@@ -94,10 +99,11 @@
   * surrogate pairs are not recombined in string literals,
     so ``'\uDBFF\uDFFF' != '\U0010FFFF'``;
 
-  * indexing or slicing a non-BMP characters doesn't return surrogates anymore,
+  * indexing or slicing non-BMP characters returns the expected value,
     so ``'\U0010FFFF'[0]`` now returns ``'\U0010FFFF'`` and not ``'\uDBFF'``;
 
-  * several other functions in the stdlib now handle correctly non-BMP codepoints.
+  * several other functions in the standard library now handle correctly
+    non-BMP codepoints.
 
 * The value of :data:`sys.maxunicode` is now always ``1114111`` (``0x10FFFF``
   in hexadecimal).  The :c:func:`PyUnicode_GetMax` function still returns
@@ -113,40 +119,44 @@
 =====================================================
 
 :pep:`3151` - Reworking the OS and IO exception hierarchy
-PEP written and implemented by Antoine Pitrou.
+ PEP written and implemented by Antoine Pitrou.
 
-New subclasses of :exc:`OSError` exceptions:
+The hierarchy of exceptions raised by operating system errors is now both
+simplified and finer-grained.
 
- * :exc:`BlockingIOError`
- * :exc:`ChildProcessError`
- * :exc:`ConnectionError`
+You don't have to worry anymore about choosing the appropriate exception
+type between :exc:`OSError`, :exc:`IOError`, :exc:`EnvironmentError`,
+:exc:`WindowsError`, :exc:`mmap.error`, :exc:`socket.error` or
+:exc:`select.error`.  All these exception types are now only one:
+:exc:`OSError`.  The other names are kept as aliases for compatibility
+reasons.
 
-   * :exc:`BrokenPipeError`
-   * :exc:`ConnectionAbortedError`
-   * :exc:`ConnectionRefusedError`
-   * :exc:`ConnectionResetError`
+Also, it is now easier to catch a specific error condition.  Instead of
+inspecting the ``errno`` attribute (or ``args[0]``) for a particular
+constant from the :mod:`errno` module, you can catch the adequate
+:exc:`OSError` subclass.  The available subclasses are the following:
 
- * :exc:`FileExistsError`
- * :exc:`FileNotFoundError`
- * :exc:`InterruptedError`
- * :exc:`IsADirectoryError`
- * :exc:`NotADirectoryError`
- * :exc:`PermissionError`
- * :exc:`ProcessLookupError`
- * :exc:`TimeoutError`
+* :exc:`BlockingIOError`
+* :exc:`ChildProcessError`
+* :exc:`ConnectionError`
+* :exc:`FileExistsError`
+* :exc:`FileNotFoundError`
+* :exc:`InterruptedError`
+* :exc:`IsADirectoryError`
+* :exc:`NotADirectoryError`
+* :exc:`PermissionError`
+* :exc:`ProcessLookupError`
+* :exc:`TimeoutError`
 
-The following exceptions have been merged into :exc:`OSError`:
+And the :exc:`ConnectionError` itself has finer-grained subclasses:
 
- * :exc:`EnvironmentError`
- * :exc:`IOError`
- * :exc:`WindowsError`
- * :exc:`VMSError`
- * :exc:`socket.error`
- * :exc:`select.error`
- * :exc:`mmap.error`
+* :exc:`BrokenPipeError`
+* :exc:`ConnectionAbortedError`
+* :exc:`ConnectionRefusedError`
+* :exc:`ConnectionResetError`
 
 Thanks to the new exceptions, common usages of the :mod:`errno` can now be
-avoided. For example, the following code written for Python 3.2: ::
+avoided.  For example, the following code written for Python 3.2::
 
     from errno import ENOENT, EACCES, EPERM
 
@@ -161,7 +171,8 @@
         else:
             raise
 
-can now be written without the :mod:`errno` import: ::
+can now be written without the :mod:`errno` import and without manual
+inspection of exception attributes::
 
     try:
         with open("document.txt") as f:
@@ -180,7 +191,7 @@
 * Stub
 
 Added support for Unicode name aliases and named sequences.
-Both :func:`unicodedata.lookup()` and '\N{...}' now resolve name aliases,
+Both :func:`unicodedata.lookup()` and ``'\N{...}'`` now resolve name aliases,
 and :func:`unicodedata.lookup()` resolves named sequences too.
 
 (Contributed by Ezio Melotti in :issue:`12753`)
@@ -267,7 +278,7 @@
 
 The :class:`~ftplib.FTP_TLS` class now provides a new
 :func:`~ftplib.FTP_TLS.ccc` function to revert control channel back to
-plaintex.  This can be useful to take advantage of firewalls that know how to
+plaintext.  This can be useful to take advantage of firewalls that know how to
 handle NAT with non-secure FTP without opening fixed ports.
 
 (Contributed by Giampaolo Rodolà in :issue:`12139`)
@@ -531,7 +542,10 @@
 =====================
 
 This section lists previously described changes and other bugfixes
-that may require changes to your code:
+that may require changes to your code.
+
+Porting Python code
+-------------------
 
 * Issue #12326: On Linux, sys.platform doesn't contain the major version
   anymore. It is now always 'linux', instead of 'linux2' or 'linux3' depending
@@ -539,6 +553,24 @@
   with sys.platform.startswith('linux'), or directly sys.platform == 'linux' if
   you don't need to support older Python versions.
 
+Porting C code
+--------------
+
+* Due to :ref:`PEP 393 <pep-393>`, the :c:type:`Py_UNICODE` type and all
+  functions using this type are deprecated (but will stay available for
+  at least five years).  If you were using low-level Unicode APIs to
+  construct and access unicode objects and you want to benefit of the
+  memory footprint reduction provided by the PEP 393, you have to convert
+  your code to the new :doc:`Unicode API <../c-api/unicode>`.
+
+  However, if you only have been using high-level functions such as
+  :c:func:`PyUnicode_Concat()`, :c:func:`PyUnicode_Join` or
+  :c:func:`PyUnicode_FromFormat()`, your code will automatically take
+  advantage of the new unicode representations.
+
+Other issues
+------------
+
 .. Issue #11591: When :program:`python` was started with :option:`-S`,
    ``import site`` will not add site-specific paths to the module search
    paths.  In previous versions, it did.  See changeset for doc changes in
@@ -548,8 +580,3 @@
    removed.  Code checking sys.flags.division_warning will need updating.
    Contributed by Éric Araujo.
 
-* :pep:`393`: The :c:type:`Py_UNICODE` type and all functions using this type
-  are deprecated. To fully benefit of the memory footprint reduction provided
-  by the PEP 393, you have to convert your code to the new Unicode API. Read
-  the porting guide: XXX.
-
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -14,7 +14,6 @@
 
 import io
 from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END)
-from errno import EINTR
 
 # open() uses st_blksize whenever we can
 DEFAULT_BUFFER_SIZE = 8 * 1024  # bytes
@@ -948,9 +947,7 @@
                 # Read until EOF or until read() would block.
                 try:
                     chunk = self.raw.read()
-                except IOError as e:
-                    if e.errno != EINTR:
-                        raise
+                except InterruptedError:
                     continue
                 if chunk in empty_values:
                     nodata_val = chunk
@@ -972,9 +969,7 @@
         while avail < n:
             try:
                 chunk = self.raw.read(wanted)
-            except IOError as e:
-                if e.errno != EINTR:
-                    raise
+            except InterruptedError:
                 continue
             if chunk in empty_values:
                 nodata_val = chunk
@@ -1007,9 +1002,7 @@
             while True:
                 try:
                     current = self.raw.read(to_read)
-                except IOError as e:
-                    if e.errno != EINTR:
-                        raise
+                except InterruptedError:
                     continue
                 break
             if current:
@@ -1120,9 +1113,7 @@
             while self._write_buf:
                 try:
                     n = self.raw.write(self._write_buf)
-                except IOError as e:
-                    if e.errno != EINTR:
-                        raise
+                except InterruptedError:
                     continue
                 if n > len(self._write_buf) or n < 0:
                     raise IOError("write() returned incorrect number of bytes")
diff --git a/Lib/asyncore.py b/Lib/asyncore.py
--- a/Lib/asyncore.py
+++ b/Lib/asyncore.py
@@ -54,7 +54,7 @@
 
 import os
 from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \
-     ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \
+     ENOTCONN, ESHUTDOWN, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \
      errorcode
 
 _DISCONNECTED = frozenset((ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE,
@@ -143,11 +143,8 @@
 
         try:
             r, w, e = select.select(r, w, e, timeout)
-        except select.error as err:
-            if err.args[0] != EINTR:
-                raise
-            else:
-                return
+        except InterruptedError:
+            return
 
         for fd in r:
             obj = map.get(fd)
@@ -190,9 +187,7 @@
                 pollster.register(fd, flags)
         try:
             r = pollster.poll(timeout)
-        except select.error as err:
-            if err.args[0] != EINTR:
-                raise
+        except InterruptedError:
             r = []
         for fd, flags in r:
             obj = map.get(fd)
diff --git a/Lib/decimal.py b/Lib/decimal.py
--- a/Lib/decimal.py
+++ b/Lib/decimal.py
@@ -3903,28 +3903,6 @@
         return nc
     __copy__ = copy
 
-    # _clamp is provided for backwards compatibility with third-party
-    # code.  May be removed in Python >= 3.3.
-    def _get_clamp(self):
-        "_clamp mirrors the clamp attribute.  Its use is deprecated."
-        import warnings
-        warnings.warn('Use of the _clamp attribute is deprecated. '
-                      'Please use clamp instead.',
-                      DeprecationWarning)
-        return self.clamp
-
-    def _set_clamp(self, clamp):
-        "_clamp mirrors the clamp attribute.  Its use is deprecated."
-        import warnings
-        warnings.warn('Use of the _clamp attribute is deprecated. '
-                      'Please use clamp instead.',
-                      DeprecationWarning)
-        self.clamp = clamp
-
-    # don't bother with _del_clamp;  no sane 3rd party code should
-    # be deleting the _clamp attribute
-    _clamp = property(_get_clamp, _set_clamp)
-
     def _raise_error(self, condition, explanation = None, *args):
         """Handles an error
 
diff --git a/Lib/ftplib.py b/Lib/ftplib.py
--- a/Lib/ftplib.py
+++ b/Lib/ftplib.py
@@ -175,10 +175,8 @@
 
     # Internal: "sanitize" a string for printing
     def sanitize(self, s):
-        if s[:5] == 'pass ' or s[:5] == 'PASS ':
-            i = len(s)
-            while i > 5 and s[i-1] in {'\r', '\n'}:
-                i = i-1
+        if s[:5] in {'pass ', 'PASS '}:
+            i = len(s.rstrip('\r\n'))
             s = s[:5] + '*'*(i-5) + s[i:]
         return repr(s)
 
@@ -596,10 +594,7 @@
         resp = self.sendcmd('SIZE ' + filename)
         if resp[:3] == '213':
             s = resp[3:].strip()
-            try:
-                return int(s)
-            except (OverflowError, ValueError):
-                return int(s)
+            return int(s)
 
     def mkd(self, dirname):
         '''Make a directory, return its full pathname.'''
@@ -861,11 +856,7 @@
     m = _150_re.match(resp)
     if not m:
         return None
-    s = m.group(1)
-    try:
-        return int(s)
-    except (OverflowError, ValueError):
-        return int(s)
+    return int(m.group(1))
 
 
 _227_re = None
diff --git a/Lib/multiprocessing/pool.py b/Lib/multiprocessing/pool.py
--- a/Lib/multiprocessing/pool.py
+++ b/Lib/multiprocessing/pool.py
@@ -321,7 +321,11 @@
 
     @staticmethod
     def _handle_workers(pool):
-        while pool._worker_handler._state == RUN and pool._state == RUN:
+        thread = threading.current_thread()
+
+        # Keep maintaining workers until the cache gets drained, unless the pool
+        # is terminated.
+        while thread._state == RUN or (pool._cache and thread._state != TERMINATE):
             pool._maintain_pool()
             time.sleep(0.1)
         # send sentinel to stop workers
diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py
--- a/Lib/multiprocessing/util.py
+++ b/Lib/multiprocessing/util.py
@@ -327,15 +327,12 @@
 # Automatic retry after EINTR
 #
 
-def _eintr_retry(func, _errors=(EnvironmentError, select.error)):
+def _eintr_retry(func):
     @functools.wraps(func)
     def wrapped(*args, **kwargs):
         while True:
             try:
                 return func(*args, **kwargs)
-            except _errors as e:
-                # select.error has no `errno` attribute
-                if e.args[0] == errno.EINTR:
-                    continue
-                raise
+            except InterruptedError:
+                continue
     return wrapped
diff --git a/Lib/optparse.py b/Lib/optparse.py
--- a/Lib/optparse.py
+++ b/Lib/optparse.py
@@ -417,11 +417,8 @@
 def _parse_int(val):
     return _parse_num(val, int)
 
-def _parse_long(val):
-    return _parse_num(val, int)
-
 _builtin_cvt = { "int" : (_parse_int, _("integer")),
-                 "long" : (_parse_long, _("long integer")),
+                 "long" : (_parse_int, _("integer")),
                  "float" : (float, _("floating-point")),
                  "complex" : (complex, _("complex")) }
 
diff --git a/Lib/pickletools.py b/Lib/pickletools.py
--- a/Lib/pickletools.py
+++ b/Lib/pickletools.py
@@ -510,10 +510,7 @@
     elif s == b"01":
         return True
 
-    try:
-        return int(s)
-    except OverflowError:
-        return int(s)
+    return int(s)
 
 def read_decimalnl_long(f):
     r"""
diff --git a/Lib/socket.py b/Lib/socket.py
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -53,7 +53,6 @@
 except ImportError:
     errno = None
 EBADF = getattr(errno, 'EBADF', 9)
-EINTR = getattr(errno, 'EINTR', 4)
 EAGAIN = getattr(errno, 'EAGAIN', 11)
 EWOULDBLOCK = getattr(errno, 'EWOULDBLOCK', 11)
 
@@ -280,11 +279,10 @@
             except timeout:
                 self._timeout_occurred = True
                 raise
+            except InterruptedError:
+                continue
             except error as e:
-                n = e.args[0]
-                if n == EINTR:
-                    continue
-                if n in _blocking_errnos:
+                if e.args[0] in _blocking_errnos:
                     return None
                 raise
 
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -450,10 +450,8 @@
     while True:
         try:
             return func(*args)
-        except (OSError, IOError) as e:
-            if e.errno == errno.EINTR:
-                continue
-            raise
+        except InterruptedError:
+            continue
 
 
 def call(*popenargs, timeout=None, **kwargs):
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -1834,18 +1834,9 @@
         # only, the attribute should be gettable/settable via both
         # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
         # removed.
-        c = Context(clamp = 0)
-        self.assertEqual(c.clamp, 0)
-
-        with check_warnings(("", DeprecationWarning)):
-            c._clamp = 1
-        self.assertEqual(c.clamp, 1)
-        with check_warnings(("", DeprecationWarning)):
-            self.assertEqual(c._clamp, 1)
-        c.clamp = 0
-        self.assertEqual(c.clamp, 0)
-        with check_warnings(("", DeprecationWarning)):
-            self.assertEqual(c._clamp, 0)
+        c = Context()
+        with self.assertRaises(AttributeError):
+            clamp_value = c._clamp
 
     def test_abs(self):
         c = Context()
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -43,6 +43,53 @@
 DBL_MANT_DIG = sys.float_info.mant_dig
 DBL_MIN_OVERFLOW = 2**DBL_MAX_EXP - 2**(DBL_MAX_EXP - DBL_MANT_DIG - 1)
 
+
+# Pure Python version of correctly-rounded integer-to-float conversion.
+def int_to_float(n):
+    """
+    Correctly-rounded integer-to-float conversion.
+
+    """
+    # Constants, depending only on the floating-point format in use.
+    # We use an extra 2 bits of precision for rounding purposes.
+    PRECISION = sys.float_info.mant_dig + 2
+    SHIFT_MAX = sys.float_info.max_exp - PRECISION
+    Q_MAX = 1 << PRECISION
+    ROUND_HALF_TO_EVEN_CORRECTION = [0, -1, -2, 1, 0, -1, 2, 1]
+
+    # Reduce to the case where n is positive.
+    if n == 0:
+        return 0.0
+    elif n < 0:
+        return -int_to_float(-n)
+
+    # Convert n to a 'floating-point' number q * 2**shift, where q is an
+    # integer with 'PRECISION' significant bits.  When shifting n to create q,
+    # the least significant bit of q is treated as 'sticky'.  That is, the
+    # least significant bit of q is set if either the corresponding bit of n
+    # was already set, or any one of the bits of n lost in the shift was set.
+    shift = n.bit_length() - PRECISION
+    q = n << -shift if shift < 0 else (n >> shift) | bool(n & ~(-1 << shift))
+
+    # Round half to even (actually rounds to the nearest multiple of 4,
+    # rounding ties to a multiple of 8).
+    q += ROUND_HALF_TO_EVEN_CORRECTION[q & 7]
+
+    # Detect overflow.
+    if shift + (q == Q_MAX) > SHIFT_MAX:
+        raise OverflowError("integer too large to convert to float")
+
+    # Checks: q is exactly representable, and q**2**shift doesn't overflow.
+    assert q % 4 == 0 and q // 4 <= 2**(sys.float_info.mant_dig)
+    assert q * 2**shift <= sys.float_info.max
+
+    # Some circularity here, since float(q) is doing an int-to-float
+    # conversion.  But here q is of bounded size, and is exactly representable
+    # as a float.  In a low-level C-like language, this operation would be a
+    # simple cast (e.g., from unsigned long long to double).
+    return math.ldexp(float(q), shift)
+
+
 # pure Python version of correctly-rounded true division
 def truediv(a, b):
     """Correctly-rounded true division for integers."""
@@ -367,6 +414,23 @@
                 return 1729
         self.assertEqual(int(LongTrunc()), 1729)
 
+    def check_float_conversion(self, n):
+        # Check that int -> float conversion behaviour matches
+        # that of the pure Python version above.
+        try:
+            actual = float(n)
+        except OverflowError:
+            actual = 'overflow'
+
+        try:
+            expected = int_to_float(n)
+        except OverflowError:
+            expected = 'overflow'
+
+        msg = ("Error in conversion of integer {} to float.  "
+               "Got {}, expected {}.".format(n, actual, expected))
+        self.assertEqual(actual, expected, msg)
+
     @support.requires_IEEE_754
     def test_float_conversion(self):
 
@@ -421,6 +485,22 @@
             y = 2**p * 2**53
             self.assertEqual(int(float(x)), y)
 
+        # Compare builtin float conversion with pure Python int_to_float
+        # function above.
+        test_values = [
+            int_dbl_max-1, int_dbl_max, int_dbl_max+1,
+            halfway-1, halfway, halfway + 1,
+            top_power-1, top_power, top_power+1,
+            2*top_power-1, 2*top_power, top_power*top_power,
+        ]
+        test_values.extend(exact_values)
+        for p in range(-4, 8):
+            for x in range(-128, 128):
+                test_values.append(2**(p+53) + x)
+        for value in test_values:
+            self.check_float_conversion(value)
+            self.check_float_conversion(-value)
+
     def test_float_overflow(self):
         for x in -2.0, -1.0, 0.0, 1.0, 2.0:
             self.assertEqual(float(int(x)), x)
diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py
--- a/Lib/test/test_multiprocessing.py
+++ b/Lib/test/test_multiprocessing.py
@@ -1266,6 +1266,20 @@
         p.close()
         p.join()
 
+    def test_pool_worker_lifetime_early_close(self):
+        # Issue #10332: closing a pool whose workers have limited lifetimes
+        # before all the tasks completed would make join() hang.
+        p = multiprocessing.Pool(3, maxtasksperchild=1)
+        results = []
+        for i in range(6):
+            results.append(p.apply_async(sqr, (i, 0.3)))
+        p.close()
+        p.join()
+        # check the results
+        for (j, res) in enumerate(results):
+            self.assertEqual(res.get(), sqr(j))
+
+
 #
 # Test that manager has expected number of shared objects left
 #
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -3584,7 +3584,7 @@
 
     @staticmethod
     def _raise_eintr():
-        raise socket.error(errno.EINTR)
+        raise socket.error(errno.EINTR, "interrupted")
 
     def _textiowrap_mock_socket(self, mock, buffering=-1):
         raw = socket.SocketIO(mock, "r")
diff --git a/Lib/xdrlib.py b/Lib/xdrlib.py
--- a/Lib/xdrlib.py
+++ b/Lib/xdrlib.py
@@ -141,11 +141,7 @@
         data = self.__buf[i:j]
         if len(data) < 4:
             raise EOFError
-        x = struct.unpack('>L', data)[0]
-        try:
-            return int(x)
-        except OverflowError:
-            return x
+        return struct.unpack('>L', data)[0]
 
     def unpack_int(self):
         i = self.__pos
diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py
--- a/Lib/xmlrpc/client.py
+++ b/Lib/xmlrpc/client.py
@@ -535,15 +535,6 @@
         write("<value><nil/></value>")
     dispatch[type(None)] = dump_nil
 
-    def dump_int(self, value, write):
-        # in case ints are > 32 bits
-        if value > MAXINT or value < MININT:
-            raise OverflowError("int exceeds XML-RPC limits")
-        write("<value><int>")
-        write(str(value))
-        write("</int></value>\n")
-    #dispatch[int] = dump_int
-
     def dump_bool(self, value, write):
         write("<value><boolean>")
         write(value and "1" or "0")
@@ -558,6 +549,9 @@
         write("</int></value>\n")
     dispatch[int] = dump_long
 
+    # backward compatible
+    dump_int = dump_long
+
     def dump_double(self, value, write):
         write("<value><double>")
         write(repr(value))
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -341,6 +341,13 @@
 Library
 -------
 
+- Issue #10332: multiprocessing: fix a race condition when a Pool is closed
+  before all tasks have completed.
+
+- Issue #13255: wrong docstrings in array module.
+
+- Issue #8540: Remove deprecated Context._clamp attribute in Decimal module.
+
 - Issue #13235: Added PendingDeprecationWarning to warn() method and function.
 
 - Issue #9168: now smtpd is able to bind privileged port.
@@ -1681,6 +1688,8 @@
 Documentation
 -------------
 
+- Issue #13141: Demonstrate recommended style for socketserver examples.
+
 - Issue #11818: Fix tempfile examples for Python 3.
 
 
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -1550,7 +1550,7 @@
 \n\
 Extends this array with data from the unicode string ustr.\n\
 The array must be a unicode type array; otherwise a ValueError\n\
-is raised.  Use array.frombytes(ustr.decode(...)) to\n\
+is raised.  Use array.frombytes(ustr.encode(...)) to\n\
 append Unicode data to an array of some other type.");
 
 
@@ -1572,7 +1572,7 @@
 \n\
 Convert the array to a unicode string.  The array must be\n\
 a unicode type array; otherwise a ValueError is raised.  Use\n\
-array.tostring().decode() to obtain a unicode string from\n\
+array.tobytes().decode() to obtain a unicode string from\n\
 an array of some other type.");
 
 
@@ -2636,7 +2636,7 @@
 extend() -- extend array by appending multiple elements from an iterable\n\
 fromfile() -- read items from a file object\n\
 fromlist() -- append items from the list\n\
-fromstring() -- append items from the string\n\
+frombytes() -- append items from the string\n\
 index() -- return index of first occurrence of an object\n\
 insert() -- insert a new item into the array at a provided position\n\
 pop() -- remove and return item (default last)\n\
@@ -2644,7 +2644,7 @@
 reverse() -- reverse the order of the items in the array\n\
 tofile() -- write all items to a file object\n\
 tolist() -- return the array converted to an ordinary list\n\
-tostring() -- return the array converted to a string\n\
+tobytes() -- return the array converted to a string\n\
 \n\
 Attributes:\n\
 \n\
diff --git a/Objects/longobject.c b/Objects/longobject.c
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -322,8 +322,15 @@
 #define PY_ABS_LONG_MIN         (0-(unsigned long)LONG_MIN)
 #define PY_ABS_SSIZE_T_MIN      (0-(size_t)PY_SSIZE_T_MIN)
 
-/* Get a C long int from a long int object.
-   Returns -1 and sets an error condition if overflow occurs. */
+/* Get a C long int from a long int object or any object that has an __int__
+   method.
+
+   On overflow, return -1 and set *overflow to 1 or -1 depending on the sign of
+   the result.  Otherwise *overflow is 0.
+
+   For other errors (e.g., TypeError), return -1 and set an error condition.
+   In this case *overflow will be 0.
+*/
 
 long
 PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
@@ -412,6 +419,9 @@
     return res;
 }
 
+/* Get a C long int from a long int object or any object that has an __int__
+   method.  Return -1 and set an error if overflow occurs. */
+
 long
 PyLong_AsLong(PyObject *obj)
 {
@@ -923,7 +933,7 @@
 
 }
 
-/* Create a new long (or int) object from a C pointer */
+/* Create a new long int object from a C pointer */
 
 PyObject *
 PyLong_FromVoidPtr(void *p)
@@ -941,15 +951,11 @@
 
 }
 
-/* Get a C pointer from a long object (or an int object in some cases) */
+/* Get a C pointer from a long int object. */
 
 void *
 PyLong_AsVoidPtr(PyObject *vv)
 {
-    /* This function will allow int or long objects. If vv is neither,
-       then the PyLong_AsLong*() functions will raise the exception:
-       PyExc_SystemError, "bad argument to internal function"
-    */
 #if SIZEOF_VOID_P <= SIZEOF_LONG
     long x;
 
@@ -1130,8 +1136,8 @@
     return (PyObject *)v;
 }
 
-/* Get a C PY_LONG_LONG int from a long int object.
-   Return -1 and set an error if overflow occurs. */
+/* Get a C long long int from a long int object or any object that has an
+   __int__ method.  Return -1 and set an error if overflow occurs. */
 
 PY_LONG_LONG
 PyLong_AsLongLong(PyObject *vv)
@@ -1287,12 +1293,14 @@
 }
 #undef IS_LITTLE_ENDIAN
 
-/* Get a C long long int from a Python long or Python int object.
-   On overflow, returns -1 and sets *overflow to 1 or -1 depending
-   on the sign of the result.  Otherwise *overflow is 0.
-
-   For other errors (e.g., type error), returns -1 and sets an error
-   condition.
+/* Get a C long long int from a long int object or any object that has an
+   __int__ method.
+
+   On overflow, return -1 and set *overflow to 1 or -1 depending on the sign of
+   the result.  Otherwise *overflow is 0.
+
+   For other errors (e.g., TypeError), return -1 and set an error condition.
+   In this case *overflow will be 0.
 */
 
 PY_LONG_LONG

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list