[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