merge heads
This commit is contained in:
commit
08a95cabe3
|
@ -447,34 +447,3 @@ In Python 2.2, you can inherit from built-in classes such as :class:`int`,
|
||||||
The Boost Python Library (BPL, http://www.boost.org/libs/python/doc/index.html)
|
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
|
provides a way of doing this from C++ (i.e. you can inherit from an extension
|
||||||
class written in C++ using the BPL).
|
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.
|
|
||||||
|
|
|
@ -123,7 +123,9 @@ and off individually. They are described here in more detail.
|
||||||
.. 2to3fixer:: callable
|
.. 2to3fixer:: callable
|
||||||
|
|
||||||
Converts ``callable(x)`` to ``isinstance(x, collections.Callable)``, adding
|
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
|
.. 2to3fixer:: dict
|
||||||
|
|
||||||
|
|
|
@ -427,7 +427,7 @@ FTP_TLS Objects
|
||||||
|
|
||||||
.. method:: FTP_TLS.ccc()
|
.. 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
|
advantage of firewalls that know how to handle NAT with non-secure FTP
|
||||||
without opening fixed ports.
|
without opening fixed ports.
|
||||||
|
|
||||||
|
|
|
@ -353,8 +353,8 @@ The :mod:`signal` module defines the following functions:
|
||||||
signals in *sigset* is already pending for the calling thread, the function
|
signals in *sigset* is already pending for the calling thread, the function
|
||||||
will return immediately with information about that signal. The signal
|
will return immediately with information about that signal. The signal
|
||||||
handler is not called for the delivered signal. The function raises an
|
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
|
:exc:`InterruptedError` if it is interrupted by a signal that is not in
|
||||||
interrupted by a signal that is not in *sigset*.
|
*sigset*.
|
||||||
|
|
||||||
The return value is an object representing the data contained in the
|
The return value is an object representing the data contained in the
|
||||||
:c:type:`siginfo_t` structure, namely: :attr:`si_signo`, :attr:`si_code`,
|
:c:type:`siginfo_t` structure, namely: :attr:`si_signo`, :attr:`si_code`,
|
||||||
|
|
|
@ -361,7 +361,7 @@ This is the server side::
|
||||||
def handle(self):
|
def handle(self):
|
||||||
# self.request is the TCP socket connected to the client
|
# self.request is the TCP socket connected to the client
|
||||||
self.data = self.request.recv(1024).strip()
|
self.data = self.request.recv(1024).strip()
|
||||||
print("%s wrote:" % self.client_address[0])
|
print("{} wrote:".format(self.client_address[0]))
|
||||||
print(self.data)
|
print(self.data)
|
||||||
# just send back the same data, but upper-cased
|
# just send back the same data, but upper-cased
|
||||||
self.request.send(self.data.upper())
|
self.request.send(self.data.upper())
|
||||||
|
@ -385,7 +385,7 @@ objects that simplify communication by providing the standard file interface)::
|
||||||
# self.rfile is a file-like object created by the handler;
|
# self.rfile is a file-like object created by the handler;
|
||||||
# we can now use e.g. readline() instead of raw recv() calls
|
# we can now use e.g. readline() instead of raw recv() calls
|
||||||
self.data = self.rfile.readline().strip()
|
self.data = self.rfile.readline().strip()
|
||||||
print("%s wrote:" % self.client_address[0])
|
print("{} wrote:".format(self.client_address[0]))
|
||||||
print(self.data)
|
print(self.data)
|
||||||
# Likewise, self.wfile is a file-like object used to write back
|
# Likewise, self.wfile is a file-like object used to write back
|
||||||
# to the client
|
# to the client
|
||||||
|
@ -408,16 +408,18 @@ This is the client side::
|
||||||
# Create a socket (SOCK_STREAM means a TCP socket)
|
# Create a socket (SOCK_STREAM means a TCP socket)
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
|
||||||
|
try:
|
||||||
# Connect to server and send data
|
# Connect to server and send data
|
||||||
sock.connect((HOST, PORT))
|
sock.connect((HOST, PORT))
|
||||||
sock.send(bytes(data + "\n","utf8"))
|
sock.send(bytes(data + "\n", "utf-8"))
|
||||||
|
|
||||||
# Receive data from the server and shut down
|
# Receive data from the server and shut down
|
||||||
received = sock.recv(1024)
|
received = str(sock.recv(1024), "utf-8")
|
||||||
|
finally:
|
||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
print("Sent: %s" % data)
|
print("Sent: {}".format(data))
|
||||||
print("Received: %s" % received)
|
print("Received: {}".format(received))
|
||||||
|
|
||||||
|
|
||||||
The output of the example should look something like this:
|
The output of the example should look something like this:
|
||||||
|
@ -434,10 +436,10 @@ Client::
|
||||||
|
|
||||||
$ python TCPClient.py hello world with TCP
|
$ python TCPClient.py hello world with TCP
|
||||||
Sent: 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
|
$ python TCPClient.py python is nice
|
||||||
Sent: python is nice
|
Sent: python is nice
|
||||||
Received: b'PYTHON IS NICE'
|
Received: PYTHON IS NICE
|
||||||
|
|
||||||
|
|
||||||
:class:`socketserver.UDPServer` Example
|
:class:`socketserver.UDPServer` Example
|
||||||
|
@ -458,7 +460,7 @@ This is the server side::
|
||||||
def handle(self):
|
def handle(self):
|
||||||
data = self.request[0].strip()
|
data = self.request[0].strip()
|
||||||
socket = self.request[1]
|
socket = self.request[1]
|
||||||
print("%s wrote:" % self.client_address[0])
|
print("{} wrote:".format(self.client_address[0]))
|
||||||
print(data)
|
print(data)
|
||||||
socket.sendto(data.upper(), self.client_address)
|
socket.sendto(data.upper(), self.client_address)
|
||||||
|
|
||||||
|
@ -480,11 +482,11 @@ This is the client side::
|
||||||
|
|
||||||
# As you can see, there is no connect() call; UDP has no connections.
|
# As you can see, there is no connect() call; UDP has no connections.
|
||||||
# Instead, data is directly sent to the recipient via sendto().
|
# Instead, data is directly sent to the recipient via sendto().
|
||||||
sock.sendto(bytes(data + "\n","utf8"), (HOST, PORT))
|
sock.sendto(bytes(data + "\n", "utf-8"), (HOST, PORT))
|
||||||
received = sock.recv(1024)
|
received = str(sock.recv(1024), "utf-8")
|
||||||
|
|
||||||
print("Sent: %s" % data)
|
print("Sent: {}".format(data))
|
||||||
print("Received: %s" % received)
|
print("Received: {}".format(received))
|
||||||
|
|
||||||
The output of the example should look exactly like for the TCP server example.
|
The output of the example should look exactly like for the TCP server example.
|
||||||
|
|
||||||
|
@ -504,9 +506,9 @@ An example for the :class:`ThreadingMixIn` class::
|
||||||
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
|
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
data = self.request.recv(1024)
|
data = str(self.request.recv(1024), 'ascii')
|
||||||
cur_thread = threading.current_thread()
|
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)
|
self.request.send(response)
|
||||||
|
|
||||||
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
||||||
|
@ -515,9 +517,11 @@ An example for the :class:`ThreadingMixIn` class::
|
||||||
def client(ip, port, message):
|
def client(ip, port, message):
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
sock.connect((ip, port))
|
sock.connect((ip, port))
|
||||||
sock.send(message)
|
try:
|
||||||
response = sock.recv(1024)
|
sock.send(bytes(message, 'ascii'))
|
||||||
print("Received: %s" % response)
|
response = str(sock.recv(1024), 'ascii')
|
||||||
|
print("Received: {}".format(response))
|
||||||
|
finally:
|
||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -531,13 +535,13 @@ An example for the :class:`ThreadingMixIn` class::
|
||||||
# more thread for each request
|
# more thread for each request
|
||||||
server_thread = threading.Thread(target=server.serve_forever)
|
server_thread = threading.Thread(target=server.serve_forever)
|
||||||
# Exit the server thread when the main thread terminates
|
# Exit the server thread when the main thread terminates
|
||||||
server_thread.setDaemon(True)
|
server_thread.daemon = True
|
||||||
server_thread.start()
|
server_thread.start()
|
||||||
print("Server loop running in thread:", server_thread.name)
|
print("Server loop running in thread:", server_thread.name)
|
||||||
|
|
||||||
client(ip, port, b"Hello World 1")
|
client(ip, port, "Hello World 1")
|
||||||
client(ip, port, b"Hello World 2")
|
client(ip, port, "Hello World 2")
|
||||||
client(ip, port, b"Hello World 3")
|
client(ip, port, "Hello World 3")
|
||||||
|
|
||||||
server.shutdown()
|
server.shutdown()
|
||||||
|
|
||||||
|
@ -546,9 +550,9 @@ The output of the example should look something like this::
|
||||||
|
|
||||||
$ python ThreadedTCPServer.py
|
$ python ThreadedTCPServer.py
|
||||||
Server loop running in thread: Thread-1
|
Server loop running in thread: Thread-1
|
||||||
Received: b"Thread-2: b'Hello World 1'"
|
Received: Thread-2: Hello World 1
|
||||||
Received: b"Thread-3: b'Hello World 2'"
|
Received: Thread-3: Hello World 2
|
||||||
Received: b"Thread-4: b'Hello World 3'"
|
Received: Thread-4: Hello World 3
|
||||||
|
|
||||||
|
|
||||||
The :class:`ForkingMixIn` class is used in the same way, except that the server
|
The :class:`ForkingMixIn` class is used in the same way, except that the server
|
||||||
|
|
|
@ -49,28 +49,32 @@
|
||||||
This article explains the new features in Python 3.3, compared to 3.2.
|
This article explains the new features in Python 3.3, compared to 3.2.
|
||||||
|
|
||||||
|
|
||||||
|
.. _pep-393:
|
||||||
|
|
||||||
PEP 393: Flexible String Representation
|
PEP 393: Flexible String Representation
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
[Abstract copied from the PEP: The Unicode string type is changed to support
|
The Unicode string type is changed to support multiple internal
|
||||||
multiple internal representations, depending on the character with the largest
|
representations, depending on the character with the largest Unicode ordinal
|
||||||
Unicode ordinal (1, 2, or 4 bytes). This allows a space-efficient
|
(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.
|
representation in common cases, but gives access to full UCS-4 on all
|
||||||
For compatibility with existing APIs, several representations may exist in
|
systems. For compatibility with existing APIs, several representations may
|
||||||
parallel; over time, this compatibility should be phased out.]
|
exist in parallel; over time, this compatibility should be phased out.
|
||||||
|
|
||||||
PEP 393 is fully backward compatible. The legacy API should remain
|
On the Python side, there should be no downside to this change.
|
||||||
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).
|
|
||||||
|
|
||||||
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
|
* 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
|
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
|
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:
|
* The storage of Unicode strings now depends on the highest codepoint in the string:
|
||||||
|
|
||||||
|
@ -86,7 +90,8 @@ XXX Add list of changes introduced by :pep:`393` here:
|
||||||
XXX The result should be moved in the PEP and a small summary about
|
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.
|
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,
|
* :func:`len` now always returns 1 for non-BMP characters,
|
||||||
so ``len('\U0010FFFF') == 1``;
|
so ``len('\U0010FFFF') == 1``;
|
||||||
|
@ -94,10 +99,11 @@ XXX Add list of changes introduced by :pep:`393` here:
|
||||||
* surrogate pairs are not recombined in string literals,
|
* surrogate pairs are not recombined in string literals,
|
||||||
so ``'\uDBFF\uDFFF' != '\U0010FFFF'``;
|
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'``;
|
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``
|
* The value of :data:`sys.maxunicode` is now always ``1114111`` (``0x10FFFF``
|
||||||
in hexadecimal). The :c:func:`PyUnicode_GetMax` function still returns
|
in hexadecimal). The :c:func:`PyUnicode_GetMax` function still returns
|
||||||
|
@ -113,40 +119,44 @@ PEP 3151: Reworking the OS and IO exception hierarchy
|
||||||
=====================================================
|
=====================================================
|
||||||
|
|
||||||
:pep:`3151` - Reworking the OS and IO exception hierarchy
|
: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`
|
You don't have to worry anymore about choosing the appropriate exception
|
||||||
* :exc:`ChildProcessError`
|
type between :exc:`OSError`, :exc:`IOError`, :exc:`EnvironmentError`,
|
||||||
* :exc:`ConnectionError`
|
: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`
|
Also, it is now easier to catch a specific error condition. Instead of
|
||||||
* :exc:`ConnectionAbortedError`
|
inspecting the ``errno`` attribute (or ``args[0]``) for a particular
|
||||||
* :exc:`ConnectionRefusedError`
|
constant from the :mod:`errno` module, you can catch the adequate
|
||||||
* :exc:`ConnectionResetError`
|
:exc:`OSError` subclass. The available subclasses are the following:
|
||||||
|
|
||||||
* :exc:`FileExistsError`
|
* :exc:`BlockingIOError`
|
||||||
* :exc:`FileNotFoundError`
|
* :exc:`ChildProcessError`
|
||||||
* :exc:`InterruptedError`
|
* :exc:`ConnectionError`
|
||||||
* :exc:`IsADirectoryError`
|
* :exc:`FileExistsError`
|
||||||
* :exc:`NotADirectoryError`
|
* :exc:`FileNotFoundError`
|
||||||
* :exc:`PermissionError`
|
* :exc:`InterruptedError`
|
||||||
* :exc:`ProcessLookupError`
|
* :exc:`IsADirectoryError`
|
||||||
* :exc:`TimeoutError`
|
* :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:`BrokenPipeError`
|
||||||
* :exc:`IOError`
|
* :exc:`ConnectionAbortedError`
|
||||||
* :exc:`WindowsError`
|
* :exc:`ConnectionRefusedError`
|
||||||
* :exc:`VMSError`
|
* :exc:`ConnectionResetError`
|
||||||
* :exc:`socket.error`
|
|
||||||
* :exc:`select.error`
|
|
||||||
* :exc:`mmap.error`
|
|
||||||
|
|
||||||
Thanks to the new exceptions, common usages of the :mod:`errno` can now be
|
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
|
from errno import ENOENT, EACCES, EPERM
|
||||||
|
|
||||||
|
@ -161,7 +171,8 @@ avoided. For example, the following code written for Python 3.2: ::
|
||||||
else:
|
else:
|
||||||
raise
|
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:
|
try:
|
||||||
with open("document.txt") as f:
|
with open("document.txt") as f:
|
||||||
|
@ -180,7 +191,7 @@ Some smaller changes made to the core Python language are:
|
||||||
* Stub
|
* Stub
|
||||||
|
|
||||||
Added support for Unicode name aliases and named sequences.
|
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.
|
and :func:`unicodedata.lookup()` resolves named sequences too.
|
||||||
|
|
||||||
(Contributed by Ezio Melotti in :issue:`12753`)
|
(Contributed by Ezio Melotti in :issue:`12753`)
|
||||||
|
@ -267,7 +278,7 @@ ftplib
|
||||||
|
|
||||||
The :class:`~ftplib.FTP_TLS` class now provides a new
|
The :class:`~ftplib.FTP_TLS` class now provides a new
|
||||||
:func:`~ftplib.FTP_TLS.ccc` function to revert control channel back to
|
: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.
|
handle NAT with non-secure FTP without opening fixed ports.
|
||||||
|
|
||||||
(Contributed by Giampaolo Rodolà in :issue:`12139`)
|
(Contributed by Giampaolo Rodolà in :issue:`12139`)
|
||||||
|
@ -531,7 +542,10 @@ Porting to Python 3.3
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
This section lists previously described changes and other bugfixes
|
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
|
* Issue #12326: On Linux, sys.platform doesn't contain the major version
|
||||||
anymore. It is now always 'linux', instead of 'linux2' or 'linux3' depending
|
anymore. It is now always 'linux', instead of 'linux2' or 'linux3' depending
|
||||||
|
@ -539,6 +553,24 @@ that may require changes to your code:
|
||||||
with sys.platform.startswith('linux'), or directly sys.platform == 'linux' if
|
with sys.platform.startswith('linux'), or directly sys.platform == 'linux' if
|
||||||
you don't need to support older Python versions.
|
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`,
|
.. Issue #11591: When :program:`python` was started with :option:`-S`,
|
||||||
``import site`` will not add site-specific paths to the module search
|
``import site`` will not add site-specific paths to the module search
|
||||||
paths. In previous versions, it did. See changeset for doc changes in
|
paths. In previous versions, it did. See changeset for doc changes in
|
||||||
|
@ -548,8 +580,3 @@ that may require changes to your code:
|
||||||
removed. Code checking sys.flags.division_warning will need updating.
|
removed. Code checking sys.flags.division_warning will need updating.
|
||||||
Contributed by Éric Araujo.
|
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.
|
|
||||||
|
|
||||||
|
|
17
Lib/_pyio.py
17
Lib/_pyio.py
|
@ -14,7 +14,6 @@ except ImportError:
|
||||||
|
|
||||||
import io
|
import io
|
||||||
from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END)
|
from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END)
|
||||||
from errno import EINTR
|
|
||||||
|
|
||||||
# open() uses st_blksize whenever we can
|
# open() uses st_blksize whenever we can
|
||||||
DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes
|
DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes
|
||||||
|
@ -948,9 +947,7 @@ class BufferedReader(_BufferedIOMixin):
|
||||||
# Read until EOF or until read() would block.
|
# Read until EOF or until read() would block.
|
||||||
try:
|
try:
|
||||||
chunk = self.raw.read()
|
chunk = self.raw.read()
|
||||||
except IOError as e:
|
except InterruptedError:
|
||||||
if e.errno != EINTR:
|
|
||||||
raise
|
|
||||||
continue
|
continue
|
||||||
if chunk in empty_values:
|
if chunk in empty_values:
|
||||||
nodata_val = chunk
|
nodata_val = chunk
|
||||||
|
@ -972,9 +969,7 @@ class BufferedReader(_BufferedIOMixin):
|
||||||
while avail < n:
|
while avail < n:
|
||||||
try:
|
try:
|
||||||
chunk = self.raw.read(wanted)
|
chunk = self.raw.read(wanted)
|
||||||
except IOError as e:
|
except InterruptedError:
|
||||||
if e.errno != EINTR:
|
|
||||||
raise
|
|
||||||
continue
|
continue
|
||||||
if chunk in empty_values:
|
if chunk in empty_values:
|
||||||
nodata_val = chunk
|
nodata_val = chunk
|
||||||
|
@ -1007,9 +1002,7 @@ class BufferedReader(_BufferedIOMixin):
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
current = self.raw.read(to_read)
|
current = self.raw.read(to_read)
|
||||||
except IOError as e:
|
except InterruptedError:
|
||||||
if e.errno != EINTR:
|
|
||||||
raise
|
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
if current:
|
if current:
|
||||||
|
@ -1120,9 +1113,7 @@ class BufferedWriter(_BufferedIOMixin):
|
||||||
while self._write_buf:
|
while self._write_buf:
|
||||||
try:
|
try:
|
||||||
n = self.raw.write(self._write_buf)
|
n = self.raw.write(self._write_buf)
|
||||||
except IOError as e:
|
except InterruptedError:
|
||||||
if e.errno != EINTR:
|
|
||||||
raise
|
|
||||||
continue
|
continue
|
||||||
if n > len(self._write_buf) or n < 0:
|
if n > len(self._write_buf) or n < 0:
|
||||||
raise IOError("write() returned incorrect number of bytes")
|
raise IOError("write() returned incorrect number of bytes")
|
||||||
|
|
|
@ -54,7 +54,7 @@ import warnings
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \
|
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \
|
||||||
ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \
|
ENOTCONN, ESHUTDOWN, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \
|
||||||
errorcode
|
errorcode
|
||||||
|
|
||||||
_DISCONNECTED = frozenset((ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE,
|
_DISCONNECTED = frozenset((ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE,
|
||||||
|
@ -143,10 +143,7 @@ def poll(timeout=0.0, map=None):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r, w, e = select.select(r, w, e, timeout)
|
r, w, e = select.select(r, w, e, timeout)
|
||||||
except select.error as err:
|
except InterruptedError:
|
||||||
if err.args[0] != EINTR:
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
for fd in r:
|
for fd in r:
|
||||||
|
@ -190,9 +187,7 @@ def poll2(timeout=0.0, map=None):
|
||||||
pollster.register(fd, flags)
|
pollster.register(fd, flags)
|
||||||
try:
|
try:
|
||||||
r = pollster.poll(timeout)
|
r = pollster.poll(timeout)
|
||||||
except select.error as err:
|
except InterruptedError:
|
||||||
if err.args[0] != EINTR:
|
|
||||||
raise
|
|
||||||
r = []
|
r = []
|
||||||
for fd, flags in r:
|
for fd, flags in r:
|
||||||
obj = map.get(fd)
|
obj = map.get(fd)
|
||||||
|
|
|
@ -3903,28 +3903,6 @@ class Context(object):
|
||||||
return nc
|
return nc
|
||||||
__copy__ = copy
|
__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):
|
def _raise_error(self, condition, explanation = None, *args):
|
||||||
"""Handles an error
|
"""Handles an error
|
||||||
|
|
||||||
|
|
|
@ -175,10 +175,8 @@ class FTP:
|
||||||
|
|
||||||
# Internal: "sanitize" a string for printing
|
# Internal: "sanitize" a string for printing
|
||||||
def sanitize(self, s):
|
def sanitize(self, s):
|
||||||
if s[:5] == 'pass ' or s[:5] == 'PASS ':
|
if s[:5] in {'pass ', 'PASS '}:
|
||||||
i = len(s)
|
i = len(s.rstrip('\r\n'))
|
||||||
while i > 5 and s[i-1] in {'\r', '\n'}:
|
|
||||||
i = i-1
|
|
||||||
s = s[:5] + '*'*(i-5) + s[i:]
|
s = s[:5] + '*'*(i-5) + s[i:]
|
||||||
return repr(s)
|
return repr(s)
|
||||||
|
|
||||||
|
@ -596,9 +594,6 @@ class FTP:
|
||||||
resp = self.sendcmd('SIZE ' + filename)
|
resp = self.sendcmd('SIZE ' + filename)
|
||||||
if resp[:3] == '213':
|
if resp[:3] == '213':
|
||||||
s = resp[3:].strip()
|
s = resp[3:].strip()
|
||||||
try:
|
|
||||||
return int(s)
|
|
||||||
except (OverflowError, ValueError):
|
|
||||||
return int(s)
|
return int(s)
|
||||||
|
|
||||||
def mkd(self, dirname):
|
def mkd(self, dirname):
|
||||||
|
@ -861,11 +856,7 @@ def parse150(resp):
|
||||||
m = _150_re.match(resp)
|
m = _150_re.match(resp)
|
||||||
if not m:
|
if not m:
|
||||||
return None
|
return None
|
||||||
s = m.group(1)
|
return int(m.group(1))
|
||||||
try:
|
|
||||||
return int(s)
|
|
||||||
except (OverflowError, ValueError):
|
|
||||||
return int(s)
|
|
||||||
|
|
||||||
|
|
||||||
_227_re = None
|
_227_re = None
|
||||||
|
|
|
@ -321,7 +321,11 @@ class Pool(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _handle_workers(pool):
|
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()
|
pool._maintain_pool()
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
# send sentinel to stop workers
|
# send sentinel to stop workers
|
||||||
|
|
|
@ -327,15 +327,12 @@ class ForkAwareLocal(threading.local):
|
||||||
# Automatic retry after EINTR
|
# Automatic retry after EINTR
|
||||||
#
|
#
|
||||||
|
|
||||||
def _eintr_retry(func, _errors=(EnvironmentError, select.error)):
|
def _eintr_retry(func):
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def wrapped(*args, **kwargs):
|
def wrapped(*args, **kwargs):
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
except _errors as e:
|
except InterruptedError:
|
||||||
# select.error has no `errno` attribute
|
|
||||||
if e.args[0] == errno.EINTR:
|
|
||||||
continue
|
continue
|
||||||
raise
|
|
||||||
return wrapped
|
return wrapped
|
||||||
|
|
|
@ -417,11 +417,8 @@ def _parse_num(val, type):
|
||||||
def _parse_int(val):
|
def _parse_int(val):
|
||||||
return _parse_num(val, int)
|
return _parse_num(val, int)
|
||||||
|
|
||||||
def _parse_long(val):
|
|
||||||
return _parse_num(val, int)
|
|
||||||
|
|
||||||
_builtin_cvt = { "int" : (_parse_int, _("integer")),
|
_builtin_cvt = { "int" : (_parse_int, _("integer")),
|
||||||
"long" : (_parse_long, _("long integer")),
|
"long" : (_parse_int, _("integer")),
|
||||||
"float" : (float, _("floating-point")),
|
"float" : (float, _("floating-point")),
|
||||||
"complex" : (complex, _("complex")) }
|
"complex" : (complex, _("complex")) }
|
||||||
|
|
||||||
|
|
|
@ -510,9 +510,6 @@ def read_decimalnl_short(f):
|
||||||
elif s == b"01":
|
elif s == b"01":
|
||||||
return True
|
return True
|
||||||
|
|
||||||
try:
|
|
||||||
return int(s)
|
|
||||||
except OverflowError:
|
|
||||||
return int(s)
|
return int(s)
|
||||||
|
|
||||||
def read_decimalnl_long(f):
|
def read_decimalnl_long(f):
|
||||||
|
|
|
@ -53,7 +53,6 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
errno = None
|
errno = None
|
||||||
EBADF = getattr(errno, 'EBADF', 9)
|
EBADF = getattr(errno, 'EBADF', 9)
|
||||||
EINTR = getattr(errno, 'EINTR', 4)
|
|
||||||
EAGAIN = getattr(errno, 'EAGAIN', 11)
|
EAGAIN = getattr(errno, 'EAGAIN', 11)
|
||||||
EWOULDBLOCK = getattr(errno, 'EWOULDBLOCK', 11)
|
EWOULDBLOCK = getattr(errno, 'EWOULDBLOCK', 11)
|
||||||
|
|
||||||
|
@ -280,11 +279,10 @@ class SocketIO(io.RawIOBase):
|
||||||
except timeout:
|
except timeout:
|
||||||
self._timeout_occurred = True
|
self._timeout_occurred = True
|
||||||
raise
|
raise
|
||||||
except error as e:
|
except InterruptedError:
|
||||||
n = e.args[0]
|
|
||||||
if n == EINTR:
|
|
||||||
continue
|
continue
|
||||||
if n in _blocking_errnos:
|
except error as e:
|
||||||
|
if e.args[0] in _blocking_errnos:
|
||||||
return None
|
return None
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
|
@ -450,10 +450,8 @@ def _eintr_retry_call(func, *args):
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
return func(*args)
|
return func(*args)
|
||||||
except (OSError, IOError) as e:
|
except InterruptedError:
|
||||||
if e.errno == errno.EINTR:
|
|
||||||
continue
|
continue
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def call(*popenargs, timeout=None, **kwargs):
|
def call(*popenargs, timeout=None, **kwargs):
|
||||||
|
|
|
@ -1834,18 +1834,9 @@ class ContextAPItests(unittest.TestCase):
|
||||||
# only, the attribute should be gettable/settable via both
|
# only, the attribute should be gettable/settable via both
|
||||||
# `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
|
# `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
|
||||||
# removed.
|
# removed.
|
||||||
c = Context(clamp = 0)
|
c = Context()
|
||||||
self.assertEqual(c.clamp, 0)
|
with self.assertRaises(AttributeError):
|
||||||
|
clamp_value = c._clamp
|
||||||
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)
|
|
||||||
|
|
||||||
def test_abs(self):
|
def test_abs(self):
|
||||||
c = Context()
|
c = Context()
|
||||||
|
|
|
@ -43,6 +43,53 @@ DBL_MIN_EXP = sys.float_info.min_exp
|
||||||
DBL_MANT_DIG = sys.float_info.mant_dig
|
DBL_MANT_DIG = sys.float_info.mant_dig
|
||||||
DBL_MIN_OVERFLOW = 2**DBL_MAX_EXP - 2**(DBL_MAX_EXP - DBL_MANT_DIG - 1)
|
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
|
# pure Python version of correctly-rounded true division
|
||||||
def truediv(a, b):
|
def truediv(a, b):
|
||||||
"""Correctly-rounded true division for integers."""
|
"""Correctly-rounded true division for integers."""
|
||||||
|
@ -367,6 +414,23 @@ class LongTest(unittest.TestCase):
|
||||||
return 1729
|
return 1729
|
||||||
self.assertEqual(int(LongTrunc()), 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
|
@support.requires_IEEE_754
|
||||||
def test_float_conversion(self):
|
def test_float_conversion(self):
|
||||||
|
|
||||||
|
@ -421,6 +485,22 @@ class LongTest(unittest.TestCase):
|
||||||
y = 2**p * 2**53
|
y = 2**p * 2**53
|
||||||
self.assertEqual(int(float(x)), y)
|
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):
|
def test_float_overflow(self):
|
||||||
for x in -2.0, -1.0, 0.0, 1.0, 2.0:
|
for x in -2.0, -1.0, 0.0, 1.0, 2.0:
|
||||||
self.assertEqual(float(int(x)), x)
|
self.assertEqual(float(int(x)), x)
|
||||||
|
|
|
@ -1266,6 +1266,20 @@ class _TestPoolWorkerLifetime(BaseTestCase):
|
||||||
p.close()
|
p.close()
|
||||||
p.join()
|
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
|
# Test that manager has expected number of shared objects left
|
||||||
#
|
#
|
||||||
|
|
|
@ -3584,7 +3584,7 @@ class FileObjectInterruptedTestCase(unittest.TestCase):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _raise_eintr():
|
def _raise_eintr():
|
||||||
raise socket.error(errno.EINTR)
|
raise socket.error(errno.EINTR, "interrupted")
|
||||||
|
|
||||||
def _textiowrap_mock_socket(self, mock, buffering=-1):
|
def _textiowrap_mock_socket(self, mock, buffering=-1):
|
||||||
raw = socket.SocketIO(mock, "r")
|
raw = socket.SocketIO(mock, "r")
|
||||||
|
|
|
@ -141,11 +141,7 @@ class Unpacker:
|
||||||
data = self.__buf[i:j]
|
data = self.__buf[i:j]
|
||||||
if len(data) < 4:
|
if len(data) < 4:
|
||||||
raise EOFError
|
raise EOFError
|
||||||
x = struct.unpack('>L', data)[0]
|
return struct.unpack('>L', data)[0]
|
||||||
try:
|
|
||||||
return int(x)
|
|
||||||
except OverflowError:
|
|
||||||
return x
|
|
||||||
|
|
||||||
def unpack_int(self):
|
def unpack_int(self):
|
||||||
i = self.__pos
|
i = self.__pos
|
||||||
|
|
|
@ -535,15 +535,6 @@ class Marshaller:
|
||||||
write("<value><nil/></value>")
|
write("<value><nil/></value>")
|
||||||
dispatch[type(None)] = dump_nil
|
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):
|
def dump_bool(self, value, write):
|
||||||
write("<value><boolean>")
|
write("<value><boolean>")
|
||||||
write(value and "1" or "0")
|
write(value and "1" or "0")
|
||||||
|
@ -558,6 +549,9 @@ class Marshaller:
|
||||||
write("</int></value>\n")
|
write("</int></value>\n")
|
||||||
dispatch[int] = dump_long
|
dispatch[int] = dump_long
|
||||||
|
|
||||||
|
# backward compatible
|
||||||
|
dump_int = dump_long
|
||||||
|
|
||||||
def dump_double(self, value, write):
|
def dump_double(self, value, write):
|
||||||
write("<value><double>")
|
write("<value><double>")
|
||||||
write(repr(value))
|
write(repr(value))
|
||||||
|
|
|
@ -341,6 +341,13 @@ Core and Builtins
|
||||||
Library
|
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 #13235: Added PendingDeprecationWarning to warn() method and function.
|
||||||
|
|
||||||
- Issue #9168: now smtpd is able to bind privileged port.
|
- Issue #9168: now smtpd is able to bind privileged port.
|
||||||
|
@ -1681,6 +1688,8 @@ C-API
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
- Issue #13141: Demonstrate recommended style for socketserver examples.
|
||||||
|
|
||||||
- Issue #11818: Fix tempfile examples for Python 3.
|
- Issue #11818: Fix tempfile examples for Python 3.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1550,7 +1550,7 @@ PyDoc_STRVAR(fromunicode_doc,
|
||||||
\n\
|
\n\
|
||||||
Extends this array with data from the unicode string ustr.\n\
|
Extends this array with data from the unicode string ustr.\n\
|
||||||
The array must be a unicode type array; otherwise a ValueError\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.");
|
append Unicode data to an array of some other type.");
|
||||||
|
|
||||||
|
|
||||||
|
@ -1572,7 +1572,7 @@ PyDoc_STRVAR(tounicode_doc,
|
||||||
\n\
|
\n\
|
||||||
Convert the array to a unicode string. The array must be\n\
|
Convert the array to a unicode string. The array must be\n\
|
||||||
a unicode type array; otherwise a ValueError is raised. Use\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.");
|
an array of some other type.");
|
||||||
|
|
||||||
|
|
||||||
|
@ -2636,7 +2636,7 @@ count() -- return number of occurrences of an object\n\
|
||||||
extend() -- extend array by appending multiple elements from an iterable\n\
|
extend() -- extend array by appending multiple elements from an iterable\n\
|
||||||
fromfile() -- read items from a file object\n\
|
fromfile() -- read items from a file object\n\
|
||||||
fromlist() -- append items from the list\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\
|
index() -- return index of first occurrence of an object\n\
|
||||||
insert() -- insert a new item into the array at a provided position\n\
|
insert() -- insert a new item into the array at a provided position\n\
|
||||||
pop() -- remove and return item (default last)\n\
|
pop() -- remove and return item (default last)\n\
|
||||||
|
@ -2644,7 +2644,7 @@ remove() -- remove first occurrence of an object\n\
|
||||||
reverse() -- reverse the order of the items in the array\n\
|
reverse() -- reverse the order of the items in the array\n\
|
||||||
tofile() -- write all items to a file object\n\
|
tofile() -- write all items to a file object\n\
|
||||||
tolist() -- return the array converted to an ordinary list\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\
|
\n\
|
||||||
Attributes:\n\
|
Attributes:\n\
|
||||||
\n\
|
\n\
|
||||||
|
|
|
@ -322,8 +322,15 @@ PyLong_FromDouble(double dval)
|
||||||
#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
|
#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
|
||||||
#define PY_ABS_SSIZE_T_MIN (0-(size_t)PY_SSIZE_T_MIN)
|
#define PY_ABS_SSIZE_T_MIN (0-(size_t)PY_SSIZE_T_MIN)
|
||||||
|
|
||||||
/* Get a C long int from a long int object.
|
/* Get a C long int from a long int object or any object that has an __int__
|
||||||
Returns -1 and sets an error condition if overflow occurs. */
|
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
|
long
|
||||||
PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
|
PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
|
||||||
|
@ -412,6 +419,9 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
|
||||||
return res;
|
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
|
long
|
||||||
PyLong_AsLong(PyObject *obj)
|
PyLong_AsLong(PyObject *obj)
|
||||||
{
|
{
|
||||||
|
@ -923,7 +933,7 @@ _PyLong_AsByteArray(PyLongObject* v,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new long (or int) object from a C pointer */
|
/* Create a new long int object from a C pointer */
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyLong_FromVoidPtr(void *p)
|
PyLong_FromVoidPtr(void *p)
|
||||||
|
@ -941,15 +951,11 @@ PyLong_FromVoidPtr(void *p)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 *
|
void *
|
||||||
PyLong_AsVoidPtr(PyObject *vv)
|
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
|
#if SIZEOF_VOID_P <= SIZEOF_LONG
|
||||||
long x;
|
long x;
|
||||||
|
|
||||||
|
@ -1130,8 +1136,8 @@ PyLong_FromSize_t(size_t ival)
|
||||||
return (PyObject *)v;
|
return (PyObject *)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a C PY_LONG_LONG int from a long int object.
|
/* Get a C long long int from a long int object or any object that has an
|
||||||
Return -1 and set an error if overflow occurs. */
|
__int__ method. Return -1 and set an error if overflow occurs. */
|
||||||
|
|
||||||
PY_LONG_LONG
|
PY_LONG_LONG
|
||||||
PyLong_AsLongLong(PyObject *vv)
|
PyLong_AsLongLong(PyObject *vv)
|
||||||
|
@ -1287,12 +1293,14 @@ PyLong_AsUnsignedLongLongMask(register PyObject *op)
|
||||||
}
|
}
|
||||||
#undef IS_LITTLE_ENDIAN
|
#undef IS_LITTLE_ENDIAN
|
||||||
|
|
||||||
/* Get a C long long int from a Python long or Python int object.
|
/* Get a C long long int from a long int object or any object that has an
|
||||||
On overflow, returns -1 and sets *overflow to 1 or -1 depending
|
__int__ method.
|
||||||
on the sign of the result. Otherwise *overflow is 0.
|
|
||||||
|
|
||||||
For other errors (e.g., type error), returns -1 and sets an error
|
On overflow, return -1 and set *overflow to 1 or -1 depending on the sign of
|
||||||
condition.
|
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
|
PY_LONG_LONG
|
||||||
|
|
Loading…
Reference in New Issue