From 43571dde7b81f8426e01875c611d29274135355a Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sat, 4 Mar 2017 15:40:48 -0800
Subject: [PATCH 0001/1433] Correct spelling "instanciate" (GH-465) (GH-467)
(cherry picked from commit 6abaed0ddaa1dd9be727ede09f6cd801c467c2ec)
---
Doc/library/asyncio-subprocess.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst
index dc93a74c6d..16ba9a3cd6 100644
--- a/Doc/library/asyncio-subprocess.rst
+++ b/Doc/library/asyncio-subprocess.rst
@@ -80,7 +80,7 @@ Run subprocesses asynchronously using the :mod:`subprocess` module.
however, where :class:`~subprocess.Popen` takes a single argument which is
list of strings, :func:`subprocess_exec` takes multiple string arguments.
- The *protocol_factory* must instanciate a subclass of the
+ The *protocol_factory* must instantiate a subclass of the
:class:`asyncio.SubprocessProtocol` class.
Other parameters:
@@ -123,7 +123,7 @@ Run subprocesses asynchronously using the :mod:`subprocess` module.
using the platform's "shell" syntax. This is similar to the standard library
:class:`subprocess.Popen` class called with ``shell=True``.
- The *protocol_factory* must instanciate a subclass of the
+ The *protocol_factory* must instantiate a subclass of the
:class:`asyncio.SubprocessProtocol` class.
See :meth:`~AbstractEventLoop.subprocess_exec` for more details about
--
GitLab
From 9619ec99470100969a95a86ed8d7a1fab6c27546 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sat, 4 Mar 2017 16:43:57 -0800
Subject: [PATCH 0002/1433] distutils docs: Fix a typo (GH-470) (GH-471)
(cherry picked from commit 2a7bddaab7d6e1f7b243cdbb4fa6f6c8e266b18d)
---
Doc/distutils/examples.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/distutils/examples.rst b/Doc/distutils/examples.rst
index 1f5be9cdb2..4e2761d8a7 100644
--- a/Doc/distutils/examples.rst
+++ b/Doc/distutils/examples.rst
@@ -321,7 +321,7 @@ You can read back this static file, by using the
>>> metadata.description
'Easily download, build, install, upgrade, and uninstall Python packages'
-Notice that the class can also be instanciated with a metadata file path to
+Notice that the class can also be instantiated with a metadata file path to
loads its values::
>>> pkg_info_path = 'distribute-0.6.8-py2.7.egg-info'
--
GitLab
From 38136e2a581ada0382d9bd1df5b32678cbd94b9a Mon Sep 17 00:00:00 2001
From: Ned Deily
Date: Sun, 5 Mar 2017 05:33:38 -0500
Subject: [PATCH 0003/1433] Bump to v3.6.1rc1+.
---
Include/patchlevel.h | 2 +-
Misc/NEWS | 12 ++++++++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/Include/patchlevel.h b/Include/patchlevel.h
index b42a0db2f8..b13794521f 100644
--- a/Include/patchlevel.h
+++ b/Include/patchlevel.h
@@ -23,7 +23,7 @@
#define PY_RELEASE_SERIAL 1
/* Version as a string */
-#define PY_VERSION "3.6.1rc1"
+#define PY_VERSION "3.6.1rc1+"
/*--end constants--*/
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
diff --git a/Misc/NEWS b/Misc/NEWS
index d715d306a3..b342738ac4 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -2,6 +2,18 @@
Python News
+++++++++++
+What's New in Python 3.6.1 final?
+=================================
+
+*Release date: XXXX-XX-XX*
+
+Core and Builtins
+-----------------
+
+Library
+-------
+
+
What's New in Python 3.6.1 release candidate 1
==============================================
--
GitLab
From 3405792b024e9c6b70c0d2355c55a23ac84e1e67 Mon Sep 17 00:00:00 2001
From: Petr Motejlek
Date: Sun, 5 Mar 2017 17:14:06 +0100
Subject: [PATCH 0004/1433] bpo-29615: backport to 3.6 (#478)
---
Lib/test/test_xmlrpc.py | 90 ++++++++++++++++++++++++++++++++++++++++-
Lib/xmlrpc/server.py | 43 +++++++++++---------
Misc/NEWS | 4 ++
3 files changed, 117 insertions(+), 20 deletions(-)
diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py
index df9c79e3df..69de08e9c3 100644
--- a/Lib/test/test_xmlrpc.py
+++ b/Lib/test/test_xmlrpc.py
@@ -343,6 +343,94 @@ class XMLRPCTestCase(unittest.TestCase):
self.assertEqual(p.method(), 5)
self.assertEqual(p.method(), 5)
+
+class SimpleXMLRPCDispatcherTestCase(unittest.TestCase):
+ class DispatchExc(Exception):
+ """Raised inside the dispatched functions when checking for
+ chained exceptions"""
+
+ def test_call_registered_func(self):
+ """Calls explicitly registered function"""
+ # Makes sure any exception raised inside the function has no other
+ # exception chained to it
+
+ exp_params = 1, 2, 3
+
+ def dispatched_func(*params):
+ raise self.DispatchExc(params)
+
+ dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
+ dispatcher.register_function(dispatched_func)
+ with self.assertRaises(self.DispatchExc) as exc_ctx:
+ dispatcher._dispatch('dispatched_func', exp_params)
+ self.assertEqual(exc_ctx.exception.args, (exp_params,))
+ self.assertIsNone(exc_ctx.exception.__cause__)
+ self.assertIsNone(exc_ctx.exception.__context__)
+
+ def test_call_instance_func(self):
+ """Calls a registered instance attribute as a function"""
+ # Makes sure any exception raised inside the function has no other
+ # exception chained to it
+
+ exp_params = 1, 2, 3
+
+ class DispatchedClass:
+ def dispatched_func(self, *params):
+ raise SimpleXMLRPCDispatcherTestCase.DispatchExc(params)
+
+ dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
+ dispatcher.register_instance(DispatchedClass())
+ with self.assertRaises(self.DispatchExc) as exc_ctx:
+ dispatcher._dispatch('dispatched_func', exp_params)
+ self.assertEqual(exc_ctx.exception.args, (exp_params,))
+ self.assertIsNone(exc_ctx.exception.__cause__)
+ self.assertIsNone(exc_ctx.exception.__context__)
+
+ def test_call_dispatch_func(self):
+ """Calls the registered instance's `_dispatch` function"""
+ # Makes sure any exception raised inside the function has no other
+ # exception chained to it
+
+ exp_method = 'method'
+ exp_params = 1, 2, 3
+
+ class TestInstance:
+ def _dispatch(self, method, params):
+ raise SimpleXMLRPCDispatcherTestCase.DispatchExc(
+ method, params)
+
+ dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
+ dispatcher.register_instance(TestInstance())
+ with self.assertRaises(self.DispatchExc) as exc_ctx:
+ dispatcher._dispatch(exp_method, exp_params)
+ self.assertEqual(exc_ctx.exception.args, (exp_method, exp_params))
+ self.assertIsNone(exc_ctx.exception.__cause__)
+ self.assertIsNone(exc_ctx.exception.__context__)
+
+ def test_registered_func_is_none(self):
+ """Calls explicitly registered function which is None"""
+
+ dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
+ dispatcher.register_function(None, name='method')
+ with self.assertRaises(Exception, expected_regex='method'):
+ dispatcher._dispatch('method', ('param',))
+
+ def test_instance_has_no_func(self):
+ """Attempts to call nonexistent function on a registered instance"""
+
+ dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
+ dispatcher.register_instance(object())
+ with self.assertRaises(Exception, expected_regex='method'):
+ dispatcher._dispatch('method', ('param',))
+
+ def test_cannot_locate_func(self):
+ """Calls a function that the dispatcher cannot locate"""
+
+ dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
+ with self.assertRaises(Exception, expected_regex='method'):
+ dispatcher._dispatch('method', ('param',))
+
+
class HelperTestCase(unittest.TestCase):
def test_escape(self):
self.assertEqual(xmlrpclib.escape("a&b"), "a&b")
@@ -1312,7 +1400,7 @@ def test_main():
KeepaliveServerTestCase1, KeepaliveServerTestCase2,
GzipServerTestCase, GzipUtilTestCase,
MultiPathServerTestCase, ServerProxyTestCase, FailingServerTestCase,
- CGIHandlerTestCase)
+ CGIHandlerTestCase, SimpleXMLRPCDispatcherTestCase)
if __name__ == "__main__":
diff --git a/Lib/xmlrpc/server.py b/Lib/xmlrpc/server.py
index 849bfddd84..6faa2d6f8f 100644
--- a/Lib/xmlrpc/server.py
+++ b/Lib/xmlrpc/server.py
@@ -386,31 +386,36 @@ class SimpleXMLRPCDispatcher:
not be called.
"""
- func = None
try:
- # check to see if a matching function has been registered
+ # call the matching registered function
func = self.funcs[method]
except KeyError:
- if self.instance is not None:
- # check for a _dispatch method
- if hasattr(self.instance, '_dispatch'):
- return self.instance._dispatch(method, params)
- else:
- # call instance method directly
- try:
- func = resolve_dotted_attribute(
- self.instance,
- method,
- self.allow_dotted_names
- )
- except AttributeError:
- pass
-
- if func is not None:
- return func(*params)
+ pass
else:
+ if func is not None:
+ return func(*params)
raise Exception('method "%s" is not supported' % method)
+ if self.instance is not None:
+ if hasattr(self.instance, '_dispatch'):
+ # call the `_dispatch` method on the instance
+ return self.instance._dispatch(method, params)
+
+ # call the instance's method directly
+ try:
+ func = resolve_dotted_attribute(
+ self.instance,
+ method,
+ self.allow_dotted_names
+ )
+ except AttributeError:
+ pass
+ else:
+ if func is not None:
+ return func(*params)
+
+ raise Exception('method "%s" is not supported' % method)
+
class SimpleXMLRPCRequestHandler(BaseHTTPRequestHandler):
"""Simple XML-RPC request handler class.
diff --git a/Misc/NEWS b/Misc/NEWS
index b342738ac4..a122298579 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,10 @@ Core and Builtins
Library
-------
+- bpo-29615: SimpleXMLRPCDispatcher no longer chains KeyError (or any other
+ exception) to exception(s) raised in the dispatched methods.
+ Patch by Petr Motejlek.
+
What's New in Python 3.6.1 release candidate 1
==============================================
--
GitLab
From b414e349eb6a6140a81ccec249bae3abe939e836 Mon Sep 17 00:00:00 2001
From: Ivan Levkivskyi
Date: Sun, 5 Mar 2017 20:18:43 +0100
Subject: [PATCH 0005/1433] bpo-29638: Fix spurious refleaks after typing is
imported (#469) (#483)
---
Lib/test/libregrtest/refleak.py | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/Lib/test/libregrtest/refleak.py b/Lib/test/libregrtest/refleak.py
index 3b3d2458b1..e2e58bd872 100644
--- a/Lib/test/libregrtest/refleak.py
+++ b/Lib/test/libregrtest/refleak.py
@@ -143,9 +143,14 @@ def dash_R_cleanup(fs, ps, pic, zdc, abcs):
sys._clear_type_cache()
# Clear ABC registries, restoring previously saved ABC registries.
- for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]:
- if not isabstract(abc):
- continue
+ abs_classes = [getattr(collections.abc, a) for a in collections.abc.__all__]
+ abs_classes = filter(isabstract, abs_classes)
+ if 'typing' in sys.modules:
+ t = sys.modules['typing']
+ # These classes require special treatment because they do not appear
+ # in direct subclasses of collections.abc classes
+ abs_classes = list(abs_classes) + [t.ChainMap, t.Counter, t.DefaultDict]
+ for abc in abs_classes:
for obj in abc.__subclasses__() + [abc]:
obj._abc_registry = abcs.get(obj, WeakSet()).copy()
obj._abc_cache.clear()
--
GitLab
From e544b40faa5ab61b6aba691577d90b2b641f664d Mon Sep 17 00:00:00 2001
From: Steve Dower
Date: Sun, 5 Mar 2017 19:58:06 -0800
Subject: [PATCH 0006/1433] Fixes the upload script to purge the CDN correctly
and display success output. (#466) (#497)
---
Tools/msi/uploadrelease.proj | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Tools/msi/uploadrelease.proj b/Tools/msi/uploadrelease.proj
index 305e84fc2d..75840f2f85 100644
--- a/Tools/msi/uploadrelease.proj
+++ b/Tools/msi/uploadrelease.proj
@@ -8,6 +8,7 @@
$(TARGET)
/srv/www.python.org/ftp/python
true
+ true
false
false
@@ -91,6 +92,7 @@ echo." />
+
--
GitLab
From 4e1a065c20856a00d0fe88ce022b249170608058 Mon Sep 17 00:00:00 2001
From: INADA Naoki
Date: Mon, 6 Mar 2017 17:24:28 +0900
Subject: [PATCH 0007/1433] bpo-29719: Remove Date and Release field in
whatsnew/3.6 (GH-500)
(cherry picked from commit 2225ddaa9e64c086b2b6997b0c9ac50921f7aa85)
---
Doc/whatsnew/3.6.rst | 2 --
1 file changed, 2 deletions(-)
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
index 96fd256b99..a696af4a99 100644
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -2,8 +2,6 @@
What's New In Python 3.6
****************************
-:Release: |release|
-:Date: |today|
:Editors: Elvis Pranskevichus , Yury Selivanov
.. Rules for maintenance:
--
GitLab
From df6d7b406f3d1b2e4e2014751bfa25574c4df222 Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Mon, 6 Mar 2017 18:17:10 +0800
Subject: [PATCH 0008/1433] [3.6] bpo-29714: Fix a regression that bytes format
may fail when containing zero bytes inside. (GH-504)
---
Lib/test/test_bytes.py | 10 ++++++++++
Misc/NEWS | 3 +++
Objects/bytesobject.c | 4 ++--
3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index a103a7d39c..cd82fa6457 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -507,6 +507,11 @@ class BaseBytesTest:
a = b % (b'seventy-nine', 79)
self.assertEqual(a, b'seventy-nine / 100 = 79%')
self.assertIs(type(a), self.type2test)
+ # issue 29714
+ b = self.type2test(b'hello,\x00%b!')
+ b = b % b'world'
+ self.assertEqual(b, b'hello,\x00world!')
+ self.assertIs(type(b), self.type2test)
def test_imod(self):
b = self.type2test(b'hello, %b!')
@@ -519,6 +524,11 @@ class BaseBytesTest:
b %= (b'seventy-nine', 79)
self.assertEqual(b, b'seventy-nine / 100 = 79%')
self.assertIs(type(b), self.type2test)
+ # issue 29714
+ b = self.type2test(b'hello,\x00%b!')
+ b %= b'world'
+ self.assertEqual(b, b'hello,\x00world!')
+ self.assertIs(type(b), self.type2test)
def test_rmod(self):
with self.assertRaises(TypeError):
diff --git a/Misc/NEWS b/Misc/NEWS
index a122298579..1fb78365bb 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.6.1 final?
Core and Builtins
-----------------
+- bpo-29714: Fix a regression that bytes format may fail when containing zero
+ bytes inside.
+
Library
-------
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 5d48440960..801711f7e6 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -619,11 +619,11 @@ _PyBytes_FormatEx(const char *format, Py_ssize_t format_len,
Py_ssize_t len;
char *pos;
- pos = strchr(fmt + 1, '%');
+ pos = (char *)memchr(fmt + 1, '%', fmtcnt);
if (pos != NULL)
len = pos - fmt;
else
- len = format_len - (fmt - format);
+ len = fmtcnt + 1;
assert(len != 0);
memcpy(res, fmt, len);
--
GitLab
From e9effe6bb6b6dcbc9fb13e47811a251a84a807c5 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Mon, 6 Mar 2017 09:15:41 -0800
Subject: [PATCH 0009/1433] fix minor bug in pymalloc. (GH-335) (GH-476)
(cherry picked from commit f669ffff6010a94f2d441200e0fd73e9dea2883e)
---
Doc/c-api/memory.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst
index 3ff545275f..873fb2ac1d 100644
--- a/Doc/c-api/memory.rst
+++ b/Doc/c-api/memory.rst
@@ -391,7 +391,7 @@ with a fixed size of 256 KB. It falls back to :c:func:`PyMem_RawMalloc` and
:c:func:`PyMem_RawRealloc` for allocations larger than 512 bytes.
*pymalloc* is the default allocator of the :c:data:`PYMEM_DOMAIN_MEM` (ex:
-:c:func:`PyObject_Malloc`) and :c:data:`PYMEM_DOMAIN_OBJ` (ex:
+:c:func:`PyMem_Malloc`) and :c:data:`PYMEM_DOMAIN_OBJ` (ex:
:c:func:`PyObject_Malloc`) domains.
The arena allocator uses the following functions:
--
GitLab
From 130c4ec5fbeb0878b88ec6aa06e47c9672566c17 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Mon, 6 Mar 2017 09:31:16 -0800
Subject: [PATCH 0010/1433] bpo-29557: Remove ambiguous line in binhex docs
(GH-90) (GH-475)
"appears to not work in all cases" does not inspire confidence in this
module. I can find no context for what bug this was referencing so it
should be removed.
(cherry picked from commit 6de2b7817fa9403e81dc38f13f3690f0bbf3d064)
---
Doc/library/binhex.rst | 2 --
1 file changed, 2 deletions(-)
diff --git a/Doc/library/binhex.rst b/Doc/library/binhex.rst
index 359ab23b2f..2966e0dbfb 100644
--- a/Doc/library/binhex.rst
+++ b/Doc/library/binhex.rst
@@ -55,5 +55,3 @@ the source for details.
If you code or decode textfiles on non-Macintosh platforms they will still use
the old Macintosh newline convention (carriage-return as end of line).
-As of this writing, :func:`hexbin` appears to not work in all cases.
-
--
GitLab
From 284a2ba140cf11216e9804573d8cea6674ab90d9 Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Tue, 7 Mar 2017 11:53:29 +0800
Subject: [PATCH 0011/1433] bpo-28728: clarify possible test failure due to ISP
(GH-412) (GH-531)
---
Lib/test/test_socket.py | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 97dc3cd76b..5315d475df 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -803,11 +803,6 @@ class GeneralModuleTests(unittest.TestCase):
self.fail("Error testing host resolution mechanisms. (fqdn: %s, all: %s)" % (fqhn, repr(all_host_names)))
def test_host_resolution(self):
- for addr in ['0.1.1.~1', '1+.1.1.1', '::1q', '::1::2',
- '1:1:1:1:1:1:1:1:1']:
- self.assertRaises(OSError, socket.gethostbyname, addr)
- self.assertRaises(OSError, socket.gethostbyaddr, addr)
-
for addr in [support.HOST, '10.0.0.1', '255.255.255.255']:
self.assertEqual(socket.gethostbyname(addr), addr)
@@ -816,6 +811,21 @@ class GeneralModuleTests(unittest.TestCase):
for host in [support.HOST]:
self.assertIn(host, socket.gethostbyaddr(host)[2])
+ def test_host_resolution_bad_address(self):
+ # These are all malformed IP addresses and expected not to resolve to
+ # any result. But some ISPs, e.g. AWS, may successfully resolve these
+ # IPs.
+ explanation = (
+ "resolving an invalid IP address did not raise OSError; "
+ "can be caused by a broken DNS server"
+ )
+ for addr in ['0.1.1.~1', '1+.1.1.1', '::1q', '::1::2',
+ '1:1:1:1:1:1:1:1:1']:
+ with self.assertRaises(OSError):
+ socket.gethostbyname(addr)
+ with self.assertRaises(OSError, msg=explanation):
+ socket.gethostbyaddr(addr)
+
@unittest.skipUnless(hasattr(socket, 'sethostname'), "test needs socket.sethostname()")
@unittest.skipUnless(hasattr(socket, 'gethostname'), "test needs socket.gethostname()")
def test_sethostname(self):
--
GitLab
From 33d70d1721ed8a23d2744f33d5358657adccf4cd Mon Sep 17 00:00:00 2001
From: INADA Naoki
Date: Tue, 7 Mar 2017 17:18:12 +0900
Subject: [PATCH 0012/1433] PCbuild: Add -q option to svn export (GH-537)
Without this option, AppVeyor log is too unreadable.
(cherry picked from commit 8886d5f39286dffa7d9337857b151e7fb4af23fd)
---
PCbuild/get_externals.bat | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat
index 98a755d870..3a2656e961 100644
--- a/PCbuild/get_externals.bat
+++ b/PCbuild/get_externals.bat
@@ -66,7 +66,7 @@ for %%e in (%libraries%) do (
echo.%%e already exists, skipping.
) else (
echo.Fetching %%e...
- svn export %SVNROOT%%%e
+ svn export -q %SVNROOT%%%e
)
)
--
GitLab
From 23b26c4e206427a9e0a1d39240c17a049cf8c732 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Tue, 7 Mar 2017 02:44:11 -0800
Subject: [PATCH 0013/1433] Fixes bpo-29680: Older gdb does not have gdb.error.
(GH-363) (GH-534)
This change is required to make python-dbg.py compatible with GDB versions before 7.3.
(cherry picked from commit 661ca8843fed1183e38db06e52d59ac300bf1c2a)
---
Tools/gdb/libpython.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py
index cc1afbe16d..d28851f9fd 100755
--- a/Tools/gdb/libpython.py
+++ b/Tools/gdb/libpython.py
@@ -714,7 +714,7 @@ class PyDictObjectPtr(PyObjectPtr):
try:
# <= Python 3.5
return keys['dk_entries'], dk_size
- except gdb.error:
+ except RuntimeError:
# >= Python 3.6
pass
--
GitLab
From 78ad039bcf1a8c494cbc8e18380cc30665869c3e Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Wed, 8 Mar 2017 11:43:35 +0800
Subject: [PATCH 0014/1433] bpo-26915: Test identity first in index() and
count() of collections.abc.Sequence (GH-553)
---
Lib/_collections_abc.py | 5 +++--
Lib/test/test_collections.py | 17 +++++++++++++----
Misc/NEWS | 3 +++
3 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py
index b172f3f360..005d884572 100644
--- a/Lib/_collections_abc.py
+++ b/Lib/_collections_abc.py
@@ -908,7 +908,8 @@ class Sequence(Reversible, Collection):
i = start
while stop is None or i < stop:
try:
- if self[i] == value:
+ v = self[i]
+ if v is value or v == value:
return i
except IndexError:
break
@@ -917,7 +918,7 @@ class Sequence(Reversible, Collection):
def count(self, value):
'S.count(value) -> integer -- return number of occurrences of value'
- return sum(1 for v in self if v == value)
+ return sum(1 for v in self if v is value or v == value)
Sequence.register(tuple)
Sequence.register(str)
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
index 87454cc670..47f756213d 100644
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -1310,20 +1310,29 @@ class TestCollectionABCs(ABCTestCase):
class CustomEqualObject:
def __eq__(self, other):
return False
- class CustomSequence(list):
- def __contains__(self, value):
- return Sequence.__contains__(self, value)
+ class CustomSequence(Sequence):
+ def __init__(self, seq):
+ self._seq = seq
+ def __getitem__(self, index):
+ return self._seq[index]
+ def __len__(self):
+ return len(self._seq)
nan = float('nan')
obj = CustomEqualObject()
+ seq = CustomSequence([nan, obj, nan])
containers = [
- CustomSequence([nan, obj]),
+ seq,
ItemsView({1: nan, 2: obj}),
ValuesView({1: nan, 2: obj})
]
for container in containers:
for elem in container:
self.assertIn(elem, container)
+ self.assertEqual(seq.index(nan), 0)
+ self.assertEqual(seq.index(obj), 1)
+ self.assertEqual(seq.count(nan), 2)
+ self.assertEqual(seq.count(obj), 1)
def assertSameSet(self, s1, s2):
# coerce both to a real set then check equality
diff --git a/Misc/NEWS b/Misc/NEWS
index 1fb78365bb..7a03a2d65e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -16,6 +16,9 @@ Core and Builtins
Library
-------
+- bpo-26915: index() and count() methods of collections.abc.Sequence now
+ check identity before checking equality when do comparisons.
+
- bpo-29615: SimpleXMLRPCDispatcher no longer chains KeyError (or any other
exception) to exception(s) raised in the dispatched methods.
Patch by Petr Motejlek.
--
GitLab
From 6a4b04cd337347d074ae0140fb13dca5bd4b11ef Mon Sep 17 00:00:00 2001
From: Benjamin Peterson
Date: Tue, 7 Mar 2017 23:56:59 -0800
Subject: [PATCH 0015/1433] Revert "bpo-29571: Use correct locale encoding in
test_re (#149)" (#554) (#555)
This reverts commit ace5c0fdd9b962e6e886c29dbcea72c53f051dc4.
---
Lib/test/test_re.py | 2 +-
Misc/NEWS | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py
index a506b98be4..b945cf094e 100644
--- a/Lib/test/test_re.py
+++ b/Lib/test/test_re.py
@@ -1402,7 +1402,7 @@ class ReTests(unittest.TestCase):
def test_locale_flag(self):
import locale
- enc = locale.getpreferredencoding(False)
+ _, enc = locale.getlocale(locale.LC_CTYPE)
# Search non-ASCII letter
for i in range(128, 256):
try:
diff --git a/Misc/NEWS b/Misc/NEWS
index 7a03a2d65e..bf3876948f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -134,6 +134,7 @@ Library
- bpo-29110: Fix file object leak in aifc.open() when file is given as a
filesystem path and is not in valid AIFF format. Patch by Anthony Zhang.
+- Issue #24932: Use proper command line parsing in _testembed
- Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap,
improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi,
--
GitLab
From 666165fddf499e80d10a5d9263846ec4534f6a2a Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Wed, 8 Mar 2017 12:29:33 +0200
Subject: [PATCH 0016/1433] [3.6] bpo-28230: Document the pathlib support in
tarfile and add tests. (#559)
---
Doc/library/tarfile.rst | 28 ++++++++++++---
Lib/test/test_tarfile.py | 76 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 100 insertions(+), 4 deletions(-)
diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst
index d8f809753d..337c061107 100644
--- a/Doc/library/tarfile.rst
+++ b/Doc/library/tarfile.rst
@@ -146,6 +146,10 @@ Some facts and figures:
.. versionchanged:: 3.5
The ``'x'`` (exclusive creation) mode was added.
+ .. versionchanged:: 3.6
+ The *name* parameter accepts a :term:`path-like object`.
+
+
.. class:: TarFile
Class for reading and writing tar archives. Do not use this class directly:
@@ -266,7 +270,8 @@ be finalized; only the internally used file object will be closed. See the
All following arguments are optional and can be accessed as instance attributes
as well.
- *name* is the pathname of the archive. It can be omitted if *fileobj* is given.
+ *name* is the pathname of the archive. *name* may be a :term:`path-like object`.
+ It can be omitted if *fileobj* is given.
In this case, the file object's :attr:`name` attribute is used if it exists.
*mode* is either ``'r'`` to read from an existing archive, ``'a'`` to append
@@ -319,6 +324,10 @@ be finalized; only the internally used file object will be closed. See the
.. versionchanged:: 3.5
The ``'x'`` (exclusive creation) mode was added.
+ .. versionchanged:: 3.6
+ The *name* parameter accepts a :term:`path-like object`.
+
+
.. classmethod:: TarFile.open(...)
Alternative constructor. The :func:`tarfile.open` function is actually a
@@ -390,14 +399,17 @@ be finalized; only the internally used file object will be closed. See the
.. versionchanged:: 3.5
Added the *numeric_owner* parameter.
+ .. versionchanged:: 3.6
+ The *path* parameter accepts a :term:`path-like object`.
+
.. method:: TarFile.extract(member, path="", set_attrs=True, *, numeric_owner=False)
Extract a member from the archive to the current working directory, using its
full name. Its file information is extracted as accurately as possible. *member*
may be a filename or a :class:`TarInfo` object. You can specify a different
- directory using *path*. File attributes (owner, mtime, mode) are set unless
- *set_attrs* is false.
+ directory using *path*. *path* may be a :term:`path-like object`.
+ File attributes (owner, mtime, mode) are set unless *set_attrs* is false.
If *numeric_owner* is :const:`True`, the uid and gid numbers from the tarfile
are used to set the owner/group for the extracted files. Otherwise, the named
@@ -418,6 +430,10 @@ be finalized; only the internally used file object will be closed. See the
.. versionchanged:: 3.5
Added the *numeric_owner* parameter.
+ .. versionchanged:: 3.6
+ The *path* parameter accepts a :term:`path-like object`.
+
+
.. method:: TarFile.extractfile(member)
Extract a member from the archive as a file object. *member* may be a filename
@@ -464,7 +480,8 @@ be finalized; only the internally used file object will be closed. See the
Create a :class:`TarInfo` object from the result of :func:`os.stat` or
equivalent on an existing file. The file is either named by *name*, or
- specified as a :term:`file object` *fileobj* with a file descriptor. If
+ specified as a :term:`file object` *fileobj* with a file descriptor.
+ *name* may be a :term:`path-like object`. If
given, *arcname* specifies an alternative name for the file in the
archive, otherwise, the name is taken from *fileobj*’s
:attr:`~io.FileIO.name` attribute, or the *name* argument. The name
@@ -478,6 +495,9 @@ be finalized; only the internally used file object will be closed. See the
The :attr:`~TarInfo.name` may also be modified, in which case *arcname*
could be a dummy string.
+ .. versionchanged:: 3.6
+ The *name* parameter accepts a :term:`path-like object`.
+
.. method:: TarFile.close()
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 619cbc03b2..fc79055421 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -4,6 +4,7 @@ import io
from hashlib import md5
from contextlib import contextmanager
from random import Random
+import pathlib
import unittest
import unittest.mock
@@ -440,6 +441,22 @@ class MiscReadTestBase(CommonReadTest):
self.assertIsInstance(tar.name, bytes)
self.assertEqual(tar.name, os.path.abspath(fobj.name))
+ def test_pathlike_name(self):
+ tarname = pathlib.Path(self.tarname)
+ with tarfile.open(tarname, mode=self.mode) as tar:
+ self.assertIsInstance(tar.name, str)
+ self.assertEqual(tar.name, os.path.abspath(os.fspath(tarname)))
+ with self.taropen(tarname) as tar:
+ self.assertIsInstance(tar.name, str)
+ self.assertEqual(tar.name, os.path.abspath(os.fspath(tarname)))
+ with tarfile.TarFile.open(tarname, mode=self.mode) as tar:
+ self.assertIsInstance(tar.name, str)
+ self.assertEqual(tar.name, os.path.abspath(os.fspath(tarname)))
+ if self.suffix == '':
+ with tarfile.TarFile(tarname, mode='r') as tar:
+ self.assertIsInstance(tar.name, str)
+ self.assertEqual(tar.name, os.path.abspath(os.fspath(tarname)))
+
def test_illegal_mode_arg(self):
with open(tmpname, 'wb'):
pass
@@ -582,6 +599,26 @@ class MiscReadTestBase(CommonReadTest):
finally:
support.rmtree(DIR)
+ def test_extractall_pathlike_name(self):
+ DIR = pathlib.Path(TEMPDIR) / "extractall"
+ with support.temp_dir(DIR), \
+ tarfile.open(tarname, encoding="iso8859-1") as tar:
+ directories = [t for t in tar if t.isdir()]
+ tar.extractall(DIR, directories)
+ for tarinfo in directories:
+ path = DIR / tarinfo.name
+ self.assertEqual(os.path.getmtime(path), tarinfo.mtime)
+
+ def test_extract_pathlike_name(self):
+ dirtype = "ustar/dirtype"
+ DIR = pathlib.Path(TEMPDIR) / "extractall"
+ with support.temp_dir(DIR), \
+ tarfile.open(tarname, encoding="iso8859-1") as tar:
+ tarinfo = tar.getmember(dirtype)
+ tar.extract(tarinfo, path=DIR)
+ extracted = DIR / dirtype
+ self.assertEqual(os.path.getmtime(extracted), tarinfo.mtime)
+
def test_init_close_fobj(self):
# Issue #7341: Close the internal file object in the TarFile
# constructor in case of an error. For the test we rely on
@@ -1092,6 +1129,17 @@ class WriteTest(WriteTestBase, unittest.TestCase):
finally:
support.rmdir(path)
+ def test_gettarinfo_pathlike_name(self):
+ with tarfile.open(tmpname, self.mode) as tar:
+ path = pathlib.Path(TEMPDIR) / "file"
+ with open(path, "wb") as fobj:
+ fobj.write(b"aaa")
+ tarinfo = tar.gettarinfo(path)
+ tarinfo2 = tar.gettarinfo(os.fspath(path))
+ self.assertIsInstance(tarinfo.name, str)
+ self.assertEqual(tarinfo.name, tarinfo2.name)
+ self.assertEqual(tarinfo.size, 3)
+
@unittest.skipUnless(hasattr(os, "link"),
"Missing hardlink implementation")
def test_link_size(self):
@@ -1528,6 +1576,34 @@ class CreateTest(WriteTestBase, unittest.TestCase):
self.assertEqual(len(names), 1)
self.assertIn("spameggs42", names[0])
+ def test_create_pathlike_name(self):
+ with tarfile.open(pathlib.Path(tmpname), self.mode) as tobj:
+ self.assertIsInstance(tobj.name, str)
+ self.assertEqual(tobj.name, os.path.abspath(tmpname))
+ tobj.add(pathlib.Path(self.file_path))
+ names = tobj.getnames()
+ self.assertEqual(len(names), 1)
+ self.assertIn('spameggs42', names[0])
+
+ with self.taropen(tmpname) as tobj:
+ names = tobj.getnames()
+ self.assertEqual(len(names), 1)
+ self.assertIn('spameggs42', names[0])
+
+ def test_create_taropen_pathlike_name(self):
+ with self.taropen(pathlib.Path(tmpname), "x") as tobj:
+ self.assertIsInstance(tobj.name, str)
+ self.assertEqual(tobj.name, os.path.abspath(tmpname))
+ tobj.add(pathlib.Path(self.file_path))
+ names = tobj.getnames()
+ self.assertEqual(len(names), 1)
+ self.assertIn('spameggs42', names[0])
+
+ with self.taropen(tmpname) as tobj:
+ names = tobj.getnames()
+ self.assertEqual(len(names), 1)
+ self.assertIn('spameggs42', names[0])
+
class GzipCreateTest(GzipTest, CreateTest):
pass
--
GitLab
From eb65edd1029876a4a5bb70b009aeb914088ac749 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Wed, 8 Mar 2017 15:45:43 +0200
Subject: [PATCH 0017/1433] [3.6] bpo-28231: The zipfile module now accepts
path-like objects for external paths. (#561)
(cherry picked from commit 8606e9524a7a4065042f7f228dc57eb74f88e4d3)
---
Doc/library/zipfile.rst | 24 +++++++-
Lib/test/test_zipfile.py | 117 ++++++++++++++++++++++++++++++++++-----
Lib/zipfile.py | 20 +++++--
Misc/NEWS | 3 +
4 files changed, 143 insertions(+), 21 deletions(-)
diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst
index 5eb6f10338..4c91759c67 100644
--- a/Doc/library/zipfile.rst
+++ b/Doc/library/zipfile.rst
@@ -132,8 +132,9 @@ ZipFile Objects
.. class:: ZipFile(file, mode='r', compression=ZIP_STORED, allowZip64=True)
- Open a ZIP file, where *file* can be either a path to a file (a string) or a
- file-like object. The *mode* parameter should be ``'r'`` to read an existing
+ Open a ZIP file, where *file* can be a path to a file (a string), a
+ file-like object or a :term:`path-like object`.
+ The *mode* parameter should be ``'r'`` to read an existing
file, ``'w'`` to truncate and write a new file, ``'a'`` to append to an
existing file, or ``'x'`` to exclusively create and write a new file.
If *mode* is ``'x'`` and *file* refers to an existing file,
@@ -183,6 +184,9 @@ ZipFile Objects
Previously, a plain :exc:`RuntimeError` was raised for unrecognized
compression values.
+ .. versionchanged:: 3.6.2
+ The *file* parameter accepts a :term:`path-like object`.
+
.. method:: ZipFile.close()
@@ -284,6 +288,9 @@ ZipFile Objects
Calling :meth:`extract` on a closed ZipFile will raise a
:exc:`ValueError`. Previously, a :exc:`RuntimeError` was raised.
+ .. versionchanged:: 3.6.2
+ The *path* parameter accepts a :term:`path-like object`.
+
.. method:: ZipFile.extractall(path=None, members=None, pwd=None)
@@ -304,6 +311,9 @@ ZipFile Objects
Calling :meth:`extractall` on a closed ZipFile will raise a
:exc:`ValueError`. Previously, a :exc:`RuntimeError` was raised.
+ .. versionchanged:: 3.6.2
+ The *path* parameter accepts a :term:`path-like object`.
+
.. method:: ZipFile.printdir()
@@ -403,6 +413,9 @@ ZipFile Objects
The following data attributes are also available:
+.. attribute:: ZipFile.filename
+
+ Name of the ZIP file.
.. attribute:: ZipFile.debug
@@ -488,6 +501,9 @@ The :class:`PyZipFile` constructor takes the same parameters as the
.. versionadded:: 3.4
The *filterfunc* parameter.
+ .. versionchanged:: 3.6.2
+ The *pathname* parameter accepts a :term:`path-like object`.
+
.. _zipinfo-objects:
@@ -514,6 +530,10 @@ file:
.. versionadded:: 3.6
+ .. versionchanged:: 3.6.2
+ The *filename* parameter accepts a :term:`path-like object`.
+
+
Instances have the following methods and attributes:
.. method:: ZipInfo.is_dir()
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index 0a43b20e2b..d39f05fdb7 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -2,6 +2,7 @@ import contextlib
import io
import os
import importlib.util
+import pathlib
import posixpath
import time
import struct
@@ -13,7 +14,7 @@ from tempfile import TemporaryFile
from random import randint, random, getrandbits
from test.support import script_helper
-from test.support import (TESTFN, findfile, unlink, rmtree, temp_dir,
+from test.support import (TESTFN, findfile, unlink, rmtree, temp_dir, temp_cwd,
requires_zlib, requires_bz2, requires_lzma,
captured_stdout, check_warnings)
@@ -148,6 +149,12 @@ class AbstractTestsWithSourceFile:
for f in get_files(self):
self.zip_open_test(f, self.compression)
+ def test_open_with_pathlike(self):
+ path = pathlib.Path(TESTFN2)
+ self.zip_open_test(path, self.compression)
+ with zipfile.ZipFile(path, "r", self.compression) as zipfp:
+ self.assertIsInstance(zipfp.filename, str)
+
def zip_random_open_test(self, f, compression):
self.make_test_archive(f, compression)
@@ -906,22 +913,56 @@ class PyZipFileTests(unittest.TestCase):
finally:
rmtree(TESTFN2)
+ def test_write_pathlike(self):
+ os.mkdir(TESTFN2)
+ try:
+ with open(os.path.join(TESTFN2, "mod1.py"), "w") as fp:
+ fp.write("print(42)\n")
+
+ with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
+ zipfp.writepy(pathlib.Path(TESTFN2) / "mod1.py")
+ names = zipfp.namelist()
+ self.assertCompiledIn('mod1.py', names)
+ finally:
+ rmtree(TESTFN2)
+
class ExtractTests(unittest.TestCase):
- def test_extract(self):
+
+ def make_test_file(self):
with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
for fpath, fdata in SMALL_TEST_DATA:
zipfp.writestr(fpath, fdata)
+ def test_extract(self):
+ with temp_cwd():
+ self.make_test_file()
+ with zipfile.ZipFile(TESTFN2, "r") as zipfp:
+ for fpath, fdata in SMALL_TEST_DATA:
+ writtenfile = zipfp.extract(fpath)
+
+ # make sure it was written to the right place
+ correctfile = os.path.join(os.getcwd(), fpath)
+ correctfile = os.path.normpath(correctfile)
+
+ self.assertEqual(writtenfile, correctfile)
+
+ # make sure correct data is in correct file
+ with open(writtenfile, "rb") as f:
+ self.assertEqual(fdata.encode(), f.read())
+
+ unlink(writtenfile)
+
+ def _test_extract_with_target(self, target):
+ self.make_test_file()
with zipfile.ZipFile(TESTFN2, "r") as zipfp:
for fpath, fdata in SMALL_TEST_DATA:
- writtenfile = zipfp.extract(fpath)
+ writtenfile = zipfp.extract(fpath, target)
# make sure it was written to the right place
- correctfile = os.path.join(os.getcwd(), fpath)
+ correctfile = os.path.join(target, fpath)
correctfile = os.path.normpath(correctfile)
-
- self.assertEqual(writtenfile, correctfile)
+ self.assertTrue(os.path.samefile(writtenfile, correctfile), (writtenfile, target))
# make sure correct data is in correct file
with open(writtenfile, "rb") as f:
@@ -929,26 +970,50 @@ class ExtractTests(unittest.TestCase):
unlink(writtenfile)
- # remove the test file subdirectories
- rmtree(os.path.join(os.getcwd(), 'ziptest2dir'))
+ unlink(TESTFN2)
+
+ def test_extract_with_target(self):
+ with temp_dir() as extdir:
+ self._test_extract_with_target(extdir)
+
+ def test_extract_with_target_pathlike(self):
+ with temp_dir() as extdir:
+ self._test_extract_with_target(pathlib.Path(extdir))
def test_extract_all(self):
- with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
- for fpath, fdata in SMALL_TEST_DATA:
- zipfp.writestr(fpath, fdata)
+ with temp_cwd():
+ self.make_test_file()
+ with zipfile.ZipFile(TESTFN2, "r") as zipfp:
+ zipfp.extractall()
+ for fpath, fdata in SMALL_TEST_DATA:
+ outfile = os.path.join(os.getcwd(), fpath)
+
+ with open(outfile, "rb") as f:
+ self.assertEqual(fdata.encode(), f.read())
+
+ unlink(outfile)
+ def _test_extract_all_with_target(self, target):
+ self.make_test_file()
with zipfile.ZipFile(TESTFN2, "r") as zipfp:
- zipfp.extractall()
+ zipfp.extractall(target)
for fpath, fdata in SMALL_TEST_DATA:
- outfile = os.path.join(os.getcwd(), fpath)
+ outfile = os.path.join(target, fpath)
with open(outfile, "rb") as f:
self.assertEqual(fdata.encode(), f.read())
unlink(outfile)
- # remove the test file subdirectories
- rmtree(os.path.join(os.getcwd(), 'ziptest2dir'))
+ unlink(TESTFN2)
+
+ def test_extract_all_with_target(self):
+ with temp_dir() as extdir:
+ self._test_extract_all_with_target(extdir)
+
+ def test_extract_all_with_target_pathlike(self):
+ with temp_dir() as extdir:
+ self._test_extract_all_with_target(pathlib.Path(extdir))
def check_file(self, filename, content):
self.assertTrue(os.path.isfile(filename))
@@ -1188,6 +1253,8 @@ class OtherTests(unittest.TestCase):
with open(TESTFN, "w") as fp:
fp.write("this is not a legal zip file\n")
self.assertFalse(zipfile.is_zipfile(TESTFN))
+ # - passing a path-like object
+ self.assertFalse(zipfile.is_zipfile(pathlib.Path(TESTFN)))
# - passing a file object
with open(TESTFN, "rb") as fp:
self.assertFalse(zipfile.is_zipfile(fp))
@@ -2033,6 +2100,26 @@ class ZipInfoTests(unittest.TestCase):
zi = zipfile.ZipInfo.from_file(__file__)
self.assertEqual(posixpath.basename(zi.filename), 'test_zipfile.py')
self.assertFalse(zi.is_dir())
+ self.assertEqual(zi.file_size, os.path.getsize(__file__))
+
+ def test_from_file_pathlike(self):
+ zi = zipfile.ZipInfo.from_file(pathlib.Path(__file__))
+ self.assertEqual(posixpath.basename(zi.filename), 'test_zipfile.py')
+ self.assertFalse(zi.is_dir())
+ self.assertEqual(zi.file_size, os.path.getsize(__file__))
+
+ def test_from_file_bytes(self):
+ zi = zipfile.ZipInfo.from_file(os.fsencode(__file__), 'test')
+ self.assertEqual(posixpath.basename(zi.filename), 'test')
+ self.assertFalse(zi.is_dir())
+ self.assertEqual(zi.file_size, os.path.getsize(__file__))
+
+ def test_from_file_fileno(self):
+ with open(__file__, 'rb') as f:
+ zi = zipfile.ZipInfo.from_file(f.fileno(), 'test')
+ self.assertEqual(posixpath.basename(zi.filename), 'test')
+ self.assertFalse(zi.is_dir())
+ self.assertEqual(zi.file_size, os.path.getsize(__file__))
def test_from_dir(self):
dirpath = os.path.dirname(os.path.abspath(__file__))
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index 7f2b43ce1c..d7f5beba99 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -479,6 +479,8 @@ class ZipInfo (object):
this will be the same as filename, but without a drive letter and with
leading path separators removed).
"""
+ if isinstance(filename, os.PathLike):
+ filename = os.fspath(filename)
st = os.stat(filename)
isdir = stat.S_ISDIR(st.st_mode)
mtime = time.localtime(st.st_mtime)
@@ -1070,6 +1072,8 @@ class ZipFile:
self._comment = b''
# Check if we were passed a file-like object
+ if isinstance(file, os.PathLike):
+ file = os.fspath(file)
if isinstance(file, str):
# No, it's a filename
self._filePassed = 0
@@ -1470,11 +1474,10 @@ class ZipFile:
as possible. `member' may be a filename or a ZipInfo object. You can
specify a different directory using `path'.
"""
- if not isinstance(member, ZipInfo):
- member = self.getinfo(member)
-
if path is None:
path = os.getcwd()
+ else:
+ path = os.fspath(path)
return self._extract_member(member, path, pwd)
@@ -1487,8 +1490,13 @@ class ZipFile:
if members is None:
members = self.namelist()
+ if path is None:
+ path = os.getcwd()
+ else:
+ path = os.fspath(path)
+
for zipinfo in members:
- self.extract(zipinfo, path, pwd)
+ self._extract_member(zipinfo, path, pwd)
@classmethod
def _sanitize_windows_name(cls, arcname, pathsep):
@@ -1509,6 +1517,9 @@ class ZipFile:
"""Extract the ZipInfo object 'member' to a physical
file on the path targetpath.
"""
+ if not isinstance(member, ZipInfo):
+ member = self.getinfo(member)
+
# build the destination pathname, replacing
# forward slashes to platform specific separators.
arcname = member.filename.replace('/', os.path.sep)
@@ -1801,6 +1812,7 @@ class PyZipFile(ZipFile):
If filterfunc(pathname) is given, it is called with every argument.
When it is False, the file or directory is skipped.
"""
+ pathname = os.fspath(pathname)
if filterfunc and not filterfunc(pathname):
if self.debug:
label = 'path' if os.path.isdir(pathname) else 'file'
diff --git a/Misc/NEWS b/Misc/NEWS
index bf3876948f..99ce8c7362 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -16,6 +16,9 @@ Core and Builtins
Library
-------
+- bpo-28231: The zipfile module now accepts path-like objects for external
+ paths.
+
- bpo-26915: index() and count() methods of collections.abc.Sequence now
check identity before checking equality when do comparisons.
--
GitLab
From 7253aded71df8d4bf8684fc78d11c596079211b3 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Wed, 8 Mar 2017 08:19:57 -0800
Subject: [PATCH 0018/1433] bpo-29176: Fix name of the _curses.window class
(#52) (#532)
Set name to "_curses.window" instead of "_curses.curses window" (with
a space!?).
(cherry picked from commit 61e2bc74dfab1ceee332d3f480dcf86c478c87c5)
---
Modules/_cursesmodule.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 3bf2ca7ce1..d88d06e782 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -2082,7 +2082,7 @@ static PyGetSetDef PyCursesWindow_getsets[] = {
PyTypeObject PyCursesWindow_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
- "_curses.curses window", /*tp_name*/
+ "_curses.window", /*tp_name*/
sizeof(PyCursesWindowObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
--
GitLab
From 51b646a55a4a1c4d0df764c4404a062fbcc6b356 Mon Sep 17 00:00:00 2001
From: "n.d. parker"
Date: Wed, 8 Mar 2017 23:27:46 +0100
Subject: [PATCH 0019/1433] Fix the only non-C90 comment to be C90 compatible.
(#568)
---
Include/pyport.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Include/pyport.h b/Include/pyport.h
index 52a91a0d11..426822a81f 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -37,7 +37,7 @@ Used in: Py_SAFE_DOWNCAST
* integral synonyms. Only define the ones we actually need.
*/
-// long long is required. Ensure HAVE_LONG_LONG is defined for compatibility.
+/* long long is required. Ensure HAVE_LONG_LONG is defined for compatibility. */
#ifndef HAVE_LONG_LONG
#define HAVE_LONG_LONG 1
#endif
--
GitLab
From 9cef253ae3251b22d2fbb475fcb7a28805b78c86 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Thu, 9 Mar 2017 10:51:44 +0200
Subject: [PATCH 0020/1433] [3.6] bpo-29768: Fixed compile-time check for expat
version. (#576)
(cherry picked from commit 22e707fa04476710ba5cc7e2206e4ac66743931b)
---
Modules/pyexpat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index b3259d57aa..47f70a27f1 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -1191,7 +1191,7 @@ newxmlparseobject(const char *encoding, const char *namespace_separator, PyObjec
Py_DECREF(self);
return NULL;
}
-#if ((XML_MAJOR_VERSION >= 2) && (XML_MINOR_VERSION >= 1)) || defined(XML_HAS_SET_HASH_SALT)
+#if XML_COMBINED_VERSION >= 20100 || defined(XML_HAS_SET_HASH_SALT)
/* This feature was added upstream in libexpat 2.1.0. Our expat copy
* has a backport of this feature where we also define XML_HAS_SET_HASH_SALT
* to indicate that we can still use it. */
--
GitLab
From 26d013e00f9d4adbcf3e084bbc890c799ff70407 Mon Sep 17 00:00:00 2001
From: orenmn
Date: Thu, 9 Mar 2017 16:06:47 +0200
Subject: [PATCH 0021/1433] [3.6] bpo-28298: make array 'Q', 'L' and 'I' accept
big intables as elements (#579)
---
Lib/test/test_array.py | 39 +++++++++------
Misc/NEWS | 3 ++
Modules/arraymodule.c | 108 +++++++++++++++++++++++------------------
3 files changed, 89 insertions(+), 61 deletions(-)
diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py
index 1f8967ccff..d67f9195eb 100644
--- a/Lib/test/test_array.py
+++ b/Lib/test/test_array.py
@@ -14,14 +14,6 @@ import warnings
import array
from array import _array_reconstructor as array_reconstructor
-try:
- # Try to determine availability of long long independently
- # of the array module under test
- struct.calcsize('@q')
- have_long_long = True
-except struct.error:
- have_long_long = False
-
sizeof_wchar = array.array('u').itemsize
@@ -32,9 +24,7 @@ class ArraySubclassWithKwargs(array.array):
def __init__(self, typecode, newarg=None):
array.array.__init__(self)
-typecodes = "ubBhHiIlLfd"
-if have_long_long:
- typecodes += 'qQ'
+typecodes = 'ubBhHiIlLfdqQ'
class MiscTest(unittest.TestCase):
@@ -1240,7 +1230,26 @@ class NumberTest(BaseTest):
b = array.array(self.typecode, a)
self.assertEqual(a, b)
-class SignedNumberTest(NumberTest):
+class IntegerNumberTest(NumberTest):
+ def test_type_error(self):
+ a = array.array(self.typecode)
+ a.append(42)
+ with self.assertRaises(TypeError):
+ a.append(42.0)
+ with self.assertRaises(TypeError):
+ a[0] = 42.0
+
+class Intable:
+ def __init__(self, num):
+ self._num = num
+ def __int__(self):
+ return self._num
+ def __sub__(self, other):
+ return Intable(int(self) - int(other))
+ def __add__(self, other):
+ return Intable(int(self) + int(other))
+
+class SignedNumberTest(IntegerNumberTest):
example = [-1, 0, 1, 42, 0x7f]
smallerexample = [-1, 0, 1, 42, 0x7e]
biggerexample = [-1, 0, 1, 43, 0x7f]
@@ -1251,8 +1260,9 @@ class SignedNumberTest(NumberTest):
lower = -1 * int(pow(2, a.itemsize * 8 - 1))
upper = int(pow(2, a.itemsize * 8 - 1)) - 1
self.check_overflow(lower, upper)
+ self.check_overflow(Intable(lower), Intable(upper))
-class UnsignedNumberTest(NumberTest):
+class UnsignedNumberTest(IntegerNumberTest):
example = [0, 1, 17, 23, 42, 0xff]
smallerexample = [0, 1, 17, 23, 42, 0xfe]
biggerexample = [0, 1, 17, 23, 43, 0xff]
@@ -1263,6 +1273,7 @@ class UnsignedNumberTest(NumberTest):
lower = 0
upper = int(pow(2, a.itemsize * 8)) - 1
self.check_overflow(lower, upper)
+ self.check_overflow(Intable(lower), Intable(upper))
def test_bytes_extend(self):
s = bytes(self.example)
@@ -1314,12 +1325,10 @@ class UnsignedLongTest(UnsignedNumberTest, unittest.TestCase):
typecode = 'L'
minitemsize = 4
-@unittest.skipIf(not have_long_long, 'need long long support')
class LongLongTest(SignedNumberTest, unittest.TestCase):
typecode = 'q'
minitemsize = 8
-@unittest.skipIf(not have_long_long, 'need long long support')
class UnsignedLongLongTest(UnsignedNumberTest, unittest.TestCase):
typecode = 'Q'
minitemsize = 8
diff --git a/Misc/NEWS b/Misc/NEWS
index 99ce8c7362..299a8388ff 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -16,6 +16,9 @@ Core and Builtins
Library
-------
+- bpo-28298: Fix a bug that prevented array 'Q', 'L' and 'I' from accepting big
+ intables (objects that have __int__) as elements. Patch by Oren Milman.
+
- bpo-28231: The zipfile module now accepts path-like objects for external
paths.
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 2caa8ee5a8..d4221fe4c6 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -331,35 +331,51 @@ II_getitem(arrayobject *ap, Py_ssize_t i)
(unsigned long) ((unsigned int *)ap->ob_item)[i]);
}
+static PyObject *
+get_int_unless_float(PyObject *v)
+{
+ if (PyFloat_Check(v)) {
+ PyErr_SetString(PyExc_TypeError,
+ "array item must be integer");
+ return NULL;
+ }
+ return (PyObject *)_PyLong_FromNbInt(v);
+}
+
static int
II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
{
unsigned long x;
- if (PyLong_Check(v)) {
- x = PyLong_AsUnsignedLong(v);
- if (x == (unsigned long) -1 && PyErr_Occurred())
+ int do_decref = 0; /* if nb_int was called */
+
+ if (!PyLong_Check(v)) {
+ v = get_int_unless_float(v);
+ if (NULL == v) {
return -1;
+ }
+ do_decref = 1;
}
- else {
- long y;
- if (!PyArg_Parse(v, "l;array item must be integer", &y))
- return -1;
- if (y < 0) {
- PyErr_SetString(PyExc_OverflowError,
- "unsigned int is less than minimum");
- return -1;
+ x = PyLong_AsUnsignedLong(v);
+ if (x == (unsigned long)-1 && PyErr_Occurred()) {
+ if (do_decref) {
+ Py_DECREF(v);
}
- x = (unsigned long)y;
-
+ return -1;
}
if (x > UINT_MAX) {
PyErr_SetString(PyExc_OverflowError,
- "unsigned int is greater than maximum");
+ "unsigned int is greater than maximum");
+ if (do_decref) {
+ Py_DECREF(v);
+ }
return -1;
}
-
if (i >= 0)
((unsigned int *)ap->ob_item)[i] = (unsigned int)x;
+
+ if (do_decref) {
+ Py_DECREF(v);
+ }
return 0;
}
@@ -390,31 +406,28 @@ static int
LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
{
unsigned long x;
- if (PyLong_Check(v)) {
- x = PyLong_AsUnsignedLong(v);
- if (x == (unsigned long) -1 && PyErr_Occurred())
- return -1;
- }
- else {
- long y;
- if (!PyArg_Parse(v, "l;array item must be integer", &y))
- return -1;
- if (y < 0) {
- PyErr_SetString(PyExc_OverflowError,
- "unsigned long is less than minimum");
+ int do_decref = 0; /* if nb_int was called */
+
+ if (!PyLong_Check(v)) {
+ v = get_int_unless_float(v);
+ if (NULL == v) {
return -1;
}
- x = (unsigned long)y;
-
+ do_decref = 1;
}
- if (x > ULONG_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "unsigned long is greater than maximum");
+ x = PyLong_AsUnsignedLong(v);
+ if (x == (unsigned long)-1 && PyErr_Occurred()) {
+ if (do_decref) {
+ Py_DECREF(v);
+ }
return -1;
}
-
if (i >= 0)
((unsigned long *)ap->ob_item)[i] = x;
+
+ if (do_decref) {
+ Py_DECREF(v);
+ }
return 0;
}
@@ -446,25 +459,28 @@ static int
QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
{
unsigned long long x;
- if (PyLong_Check(v)) {
- x = PyLong_AsUnsignedLongLong(v);
- if (x == (unsigned long long) -1 && PyErr_Occurred())
+ int do_decref = 0; /* if nb_int was called */
+
+ if (!PyLong_Check(v)) {
+ v = get_int_unless_float(v);
+ if (NULL == v) {
return -1;
+ }
+ do_decref = 1;
}
- else {
- long long y;
- if (!PyArg_Parse(v, "L;array item must be integer", &y))
- return -1;
- if (y < 0) {
- PyErr_SetString(PyExc_OverflowError,
- "unsigned long long is less than minimum");
- return -1;
+ x = PyLong_AsUnsignedLongLong(v);
+ if (x == (unsigned long long)-1 && PyErr_Occurred()) {
+ if (do_decref) {
+ Py_DECREF(v);
}
- x = (unsigned long long)y;
+ return -1;
}
-
if (i >= 0)
((unsigned long long *)ap->ob_item)[i] = x;
+
+ if (do_decref) {
+ Py_DECREF(v);
+ }
return 0;
}
--
GitLab
From 68d29809405dc766966b2b973b8597212fbc3dbd Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Thu, 9 Mar 2017 18:43:39 +0100
Subject: [PATCH 0022/1433] bpo-29619: Convert st_ino using unsigned integer
(#557) (#584)
bpo-29619: os.stat() and os.DirEntry.inodeo() now convert inode
(st_ino) using unsigned integers.
(cherry picked from commit 0f6d73343d342c106cda2219ebb8a6f0c4bd9b3c)
(Misc/NEWS conflict handled manually.)
---
Include/fileutils.h | 2 +-
Modules/posixmodule.c | 13 ++++++++-----
Python/fileutils.c | 4 ++--
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/Include/fileutils.h b/Include/fileutils.h
index b933e98539..900c70faad 100644
--- a/Include/fileutils.h
+++ b/Include/fileutils.h
@@ -22,7 +22,7 @@ PyAPI_FUNC(PyObject *) _Py_device_encoding(int);
#ifdef MS_WINDOWS
struct _Py_stat_struct {
unsigned long st_dev;
- __int64 st_ino;
+ uint64_t st_ino;
unsigned short st_mode;
int st_nlink;
int st_uid;
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 8f8ba255ec..2ea5e2def9 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -1932,11 +1932,13 @@ _pystat_fromstructstat(STRUCT_STAT *st)
return NULL;
PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
-#ifdef HAVE_LARGEFILE_SUPPORT
+#if defined(HAVE_LARGEFILE_SUPPORT) || defined(MS_WINDOWS)
+ Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
PyStructSequence_SET_ITEM(v, 1,
- PyLong_FromLongLong((long long)st->st_ino));
+ PyLong_FromUnsignedLongLong(st->st_ino));
#else
- PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino));
+ Py_BUILD_ASSERT(sizeof(unsigned long) >= sizeof(st->st_ino));
+ PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLong(st->st_ino));
#endif
#ifdef MS_WINDOWS
PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
@@ -11156,7 +11158,7 @@ typedef struct {
PyObject *lstat;
#ifdef MS_WINDOWS
struct _Py_stat_struct win32_lstat;
- __int64 win32_file_index;
+ uint64_t win32_file_index;
int got_file_index;
#else /* POSIX */
#ifdef HAVE_DIRENT_D_TYPE
@@ -11419,7 +11421,8 @@ DirEntry_inode(DirEntry *self)
self->win32_file_index = stat.st_ino;
self->got_file_index = 1;
}
- return PyLong_FromLongLong((long long)self->win32_file_index);
+ Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
+ return PyLong_FromUnsignedLongLong(self->win32_file_index);
#else /* POSIX */
#ifdef HAVE_LARGEFILE_SUPPORT
return PyLong_FromLongLong((long long)self->d_ino);
diff --git a/Python/fileutils.c b/Python/fileutils.c
index e84d66e99a..f3764e4b3c 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -583,7 +583,7 @@ _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag,
FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
result->st_nlink = info->nNumberOfLinks;
- result->st_ino = (((__int64)info->nFileIndexHigh)<<32) + info->nFileIndexLow;
+ result->st_ino = (((uint64_t)info->nFileIndexHigh) << 32) + info->nFileIndexLow;
if (reparse_tag == IO_REPARSE_TAG_SYMLINK) {
/* first clear the S_IFMT bits */
result->st_mode ^= (result->st_mode & S_IFMT);
@@ -653,7 +653,7 @@ _Py_fstat_noraise(int fd, struct _Py_stat_struct *status)
_Py_attribute_data_to_stat(&info, 0, status);
/* specific to fstat() */
- status->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
+ status->st_ino = (((uint64_t)info.nFileIndexHigh) << 32) + info.nFileIndexLow;
return 0;
#else
return fstat(fd, status);
--
GitLab
From 80dfbe30b734f14f76a4e25c7fa8fdb7bdd3936a Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Thu, 9 Mar 2017 21:01:49 +0200
Subject: [PATCH 0023/1433] [3.6] bpo-29773: Add more cases for testing string
to float conversion errors. (#586)
(cherry picked from commit 9e6ac83acae31de2b072e665e177db9fcdf7c049)
---
Lib/test/test_float.py | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py
index ac8473db50..6491f458c3 100644
--- a/Lib/test/test_float.py
+++ b/Lib/test/test_float.py
@@ -119,15 +119,27 @@ class GeneralFloatCases(unittest.TestCase):
self.assertEqual(float(memoryview(b'12.34')[1:4]), 2.3)
def test_error_message(self):
- testlist = ('\xbd', '123\xbd', ' 123 456 ')
- for s in testlist:
- try:
+ def check(s):
+ with self.assertRaises(ValueError, msg='float(%r)' % (s,)) as cm:
float(s)
- except ValueError as e:
- self.assertIn(s.strip(), e.args[0])
- else:
- self.fail("Expected int(%r) to raise a ValueError", s)
-
+ self.assertEqual(str(cm.exception),
+ 'could not convert string to float: %r' % (s,))
+
+ check('\xbd')
+ check('123\xbd')
+ check(' 123 456 ')
+ check(b' 123 456 ')
+
+ # non-ascii digits (error came from non-digit '!')
+ check('\u0663\u0661\u0664!')
+ # embedded NUL
+ check('123\x00')
+ check('123\x00 245')
+ check('123\x00245')
+ # byte string with embedded NUL
+ check(b'123\x00')
+ # non-UTF-8 byte string
+ check(b'123\xa0')
@support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
def test_float_with_comma(self):
--
GitLab
From d9b0b8f63c3db38dc547e0c115e9060f13f2dbcf Mon Sep 17 00:00:00 2001
From: Zachary Ware
Date: Fri, 10 Mar 2017 01:06:43 -0600
Subject: [PATCH 0024/1433] Add Appveyor (GH-324 backport) (GH-491)
---
.github/appveyor.yml | 6 ++++++
README.rst | 4 ++++
2 files changed, 10 insertions(+)
create mode 100644 .github/appveyor.yml
diff --git a/.github/appveyor.yml b/.github/appveyor.yml
new file mode 100644
index 0000000000..5a40005660
--- /dev/null
+++ b/.github/appveyor.yml
@@ -0,0 +1,6 @@
+version: 3.6.1rc1+.{build}
+clone_depth: 5
+build_script:
+- cmd: PCbuild\build.bat -e
+test_script:
+- cmd: PCbuild\rt.bat -q -uall -rwW --slowest --timeout=1200 -j0
diff --git a/README.rst b/README.rst
index 242572c5e3..6b4c2dba30 100644
--- a/README.rst
+++ b/README.rst
@@ -5,6 +5,10 @@ This is Python version 3.6.1 release candidate 1
:alt: CPython build status on Travis CI
:target: https://travis-ci.org/python/cpython
+.. image:: https://ci.appveyor.com/api/projects/status/4mew1a93xdkbf5ua/branch/3.6?svg=true
+ :alt: CPython build status on Appveyor
+ :target: https://ci.appveyor.com/project/python/cpython/branch/3.6
+
.. image:: https://codecov.io/gh/python/cpython/branch/3.6/graph/badge.svg
:alt: CPython code coverage on Codecov
:target: https://codecov.io/gh/python/cpython
--
GitLab
From faaa80fb9887950e7068a9506e3517bcd6562ac2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Langa?=
Date: Fri, 10 Mar 2017 05:30:05 -0800
Subject: [PATCH 0025/1433] Ignore Include/pydtrace_probes.h (#596)
This is a generated file when --with-dtrace is passed. This entry is present in
.hgignore.
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index ed4ebfbbd9..db27597aac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@
.gdb_history
Doc/build/
Doc/venv/
+Include/pydtrace_probes.h
Lib/distutils/command/*.pdb
Lib/lib2to3/*.pickle
Lib/test/data/*
--
GitLab
From ff6f3716279e75b2519133a82b9de0c3601963d9 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Fri, 10 Mar 2017 09:52:03 -0800
Subject: [PATCH 0026/1433] bpo-28739: Document that f-strings cannot be used
as docstring (GH-592) (GH-600)
(cherry picked from commit d4e89287b397c7382c12d3f3d9fd901fd8243b3c)
---
Doc/reference/lexical_analysis.rst | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst
index da7017afff..7f9c664817 100644
--- a/Doc/reference/lexical_analysis.rst
+++ b/Doc/reference/lexical_analysis.rst
@@ -696,6 +696,17 @@ a temporary variable.
>>> f"newline: {newline}"
'newline: 10'
+Formatted string literals cannot be used as docstrings, even if they do not
+include expressions.
+
+::
+
+ >>> def foo():
+ ... f"Not a docstring"
+ ...
+ >>> foo.__doc__ is None
+ True
+
See also :pep:`498` for the proposal that added formatted string literals,
and :meth:`str.format`, which uses a related format string mechanism.
--
GitLab
From 68c5e4c592495f1e0f4f60acb3483beb6aa87be1 Mon Sep 17 00:00:00 2001
From: Brett Cannon
Date: Fri, 10 Mar 2017 14:44:48 -0800
Subject: [PATCH 0027/1433] bpo-28810: Document BUILD_TUPLE_UNPACK_WITH_CALL
bytecode (GH-605)
(cherry picked from commit 7e52c3e7aefb4cdaa0662fc01ff68a5e976b77ca)
---
Doc/library/dis.rst | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index 1c1e1a2aa5..686118f520 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -807,6 +807,15 @@ All of the following opcodes use their arguments.
.. versionadded:: 3.5
+.. opcode:: BUILD_TUPLE_UNPACK_WITH_CALL (count)
+
+ This is similar to :opcode:`BUILD_TUPLE_UNPACK`,
+ but is used for ``f(*x, *y, *z)`` call syntax. The stack item at position
+ ``count + 1`` should be the corresponding callable ``f``.
+
+ .. versionadded:: 3.6
+
+
.. opcode:: BUILD_LIST_UNPACK (count)
This is similar to :opcode:`BUILD_TUPLE_UNPACK`, but pushes a list
@@ -834,14 +843,16 @@ All of the following opcodes use their arguments.
.. versionadded:: 3.5
-.. opcode:: BUILD_MAP_UNPACK_WITH_CALL (oparg)
+.. opcode:: BUILD_MAP_UNPACK_WITH_CALL (count)
This is similar to :opcode:`BUILD_MAP_UNPACK`,
- but is used for ``f(**x, **y, **z)`` call syntax. The lowest byte of
- *oparg* is the count of mappings, the relative position of the
- corresponding callable ``f`` is encoded in the second byte of *oparg*.
+ but is used for ``f(**x, **y, **z)`` call syntax. The stack item at
+ position ``count + 2`` should be the corresponding callable ``f``.
.. versionadded:: 3.5
+ .. versionchanged:: 3.6
+ The position of the callable is determined by adding 2 to the opcode
+ argument instead of encoding it in the second byte of the argument.
.. opcode:: LOAD_ATTR (namei)
--
GitLab
From 4807fa8386f825d0c71192c59f7e33b99a94bebe Mon Sep 17 00:00:00 2001
From: Brett Cannon
Date: Fri, 10 Mar 2017 15:08:52 -0800
Subject: [PATCH 0028/1433] bpo-28810: Document changes to CALL_FUNCTION
opcodes (GH-607)
(cherry picked from commit 4b2a2a425a906c8e4eb8daee14ab1793e225f726)
---
Doc/library/dis.rst | 69 +++++++++++++++++++++++++--------------------
1 file changed, 39 insertions(+), 30 deletions(-)
diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index 686118f520..11d056901b 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -1009,14 +1009,45 @@ All of the following opcodes use their arguments.
.. opcode:: CALL_FUNCTION (argc)
- Calls a function. The low byte of *argc* indicates the number of positional
- parameters, the high byte the number of keyword parameters. On the stack, the
- opcode finds the keyword parameters first. For each keyword argument, the
- value is on top of the key. Below the keyword parameters, the positional
- parameters are on the stack, with the right-most parameter on top. Below the
- parameters, the function object to call is on the stack. Pops all function
- arguments, and the function itself off the stack, and pushes the return
- value.
+ Calls a function. *argc* indicates the number of positional arguments.
+ The positional arguments are on the stack, with the right-most argument
+ on top. Below the arguments, the function object to call is on the stack.
+ Pops all function arguments, and the function itself off the stack, and
+ pushes the return value.
+
+ .. versionchanged:: 3.6
+ This opcode is used only for calls with positional arguments.
+
+
+.. opcode:: CALL_FUNCTION_KW (argc)
+
+ Calls a function. *argc* indicates the number of arguments (positional
+ and keyword). The top element on the stack contains a tuple of keyword
+ argument names. Below the tuple, keyword arguments are on the stack, in
+ the order corresponding to the tuple. Below the keyword arguments, the
+ positional arguments are on the stack, with the right-most parameter on
+ top. Below the arguments, the function object to call is on the stack.
+ Pops all function arguments, and the function itself off the stack, and
+ pushes the return value.
+
+ .. versionchanged:: 3.6
+ Keyword arguments are packed in a tuple instead of a dictionary,
+ *argc* indicates the total number of arguments
+
+
+.. opcode:: CALL_FUNCTION_EX (flags)
+
+ Calls a function. The lowest bit of *flags* indicates whether the
+ var-keyword argument is placed at the top of the stack. Below the
+ var-keyword argument, the var-positional argument is on the stack.
+ Below the arguments, the function object to call is placed.
+ Pops all function arguments, and the function itself off the stack, and
+ pushes the return value. Note that this opcode pops at most three items
+ from the stack. Var-positional and var-keyword arguments are packed
+ by :opcode:`BUILD_MAP_UNPACK_WITH_CALL` and
+ :opcode:`BUILD_MAP_UNPACK_WITH_CALL`.
+
+ .. versionadded:: 3.6
.. opcode:: MAKE_FUNCTION (argc)
@@ -1049,28 +1080,6 @@ All of the following opcodes use their arguments.
two most-significant bytes.
-.. opcode:: CALL_FUNCTION_VAR (argc)
-
- Calls a function. *argc* is interpreted as in :opcode:`CALL_FUNCTION`. The
- top element on the stack contains the variable argument list, followed by
- keyword and positional arguments.
-
-
-.. opcode:: CALL_FUNCTION_KW (argc)
-
- Calls a function. *argc* is interpreted as in :opcode:`CALL_FUNCTION`. The
- top element on the stack contains the keyword arguments dictionary, followed
- by explicit keyword and positional arguments.
-
-
-.. opcode:: CALL_FUNCTION_VAR_KW (argc)
-
- Calls a function. *argc* is interpreted as in :opcode:`CALL_FUNCTION`. The
- top element on the stack contains the keyword arguments dictionary, followed
- by the variable-arguments tuple, followed by explicit keyword and positional
- arguments.
-
-
.. opcode:: FORMAT_VALUE (flags)
Used for implementing formatted literal strings (f-strings). Pops
--
GitLab
From 701f13ab930b62a634579951dc610f737f461135 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Fri, 10 Mar 2017 19:36:26 -0800
Subject: [PATCH 0029/1433] bpo-29784: Fix the reference to shutil.copy in the
docs (GH-602) (GH-608)
(cherry picked from commit 70ee0cd5c2a3dba82cb8e0c0742c012f9134c040)
---
Doc/library/shutil.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst
index a85bf339ae..41e5bafa53 100644
--- a/Doc/library/shutil.rst
+++ b/Doc/library/shutil.rst
@@ -153,7 +153,7 @@ Directory and files operations
is true and *src* is a symbolic link, *dst* will be a copy of
the file *src* refers to.
- :func:`copy` copies the file data and the file's permission
+ :func:`~shutil.copy` copies the file data and the file's permission
mode (see :func:`os.chmod`). Other metadata, like the
file's creation and modification times, is not preserved.
To preserve all file metadata from the original, use
@@ -302,7 +302,7 @@ Directory and files operations
*src* and *dst*, and will be used to copy *src* to *dest* if
:func:`os.rename` cannot be used. If the source is a directory,
:func:`copytree` is called, passing it the :func:`copy_function`. The
- default *copy_function* is :func:`copy2`. Using :func:`copy` as the
+ default *copy_function* is :func:`copy2`. Using :func:`~shutil.copy` as the
*copy_function* allows the move to succeed when it is not possible to also
copy the metadata, at the expense of not copying any of the metadata.
--
GitLab
From 16416c22f9b8d9e067506d3a98f661756c80389c Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Sat, 11 Mar 2017 14:07:30 +0800
Subject: [PATCH 0030/1433] bpo-29770: remove outdated PYO related info
(GH-590) (GH-612)
---
Doc/glossary.rst | 2 +-
Doc/library/zipfile.rst | 6 +++---
Doc/library/zipimport.rst | 2 +-
Doc/using/cmdline.rst | 4 ++--
Modules/main.c | 2 +-
Modules/zipimport.c | 6 +++---
PC/getpathp.c | 4 ++--
PCbuild/rmpyc.py | 20 +++++++-------------
PCbuild/rt.bat | 8 ++++----
Python/pylifecycle.c | 2 +-
10 files changed, 25 insertions(+), 31 deletions(-)
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index 41ee3d83b3..e07ab0df2f 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -155,7 +155,7 @@ Glossary
bytecode
Python source code is compiled into bytecode, the internal representation
of a Python program in the CPython interpreter. The bytecode is also
- cached in ``.pyc`` and ``.pyo`` files so that executing the same file is
+ cached in ``.pyc`` files so that executing the same file is
faster the second time (recompilation from source to bytecode can be
avoided). This "intermediate language" is said to run on a
:term:`virtual machine` that executes the machine code corresponding to
diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst
index 4c91759c67..a5d42118ba 100644
--- a/Doc/library/zipfile.rst
+++ b/Doc/library/zipfile.rst
@@ -464,12 +464,12 @@ The :class:`PyZipFile` constructor takes the same parameters as the
added to the archive, compiling if necessary.
If *pathname* is a file, the filename must end with :file:`.py`, and
- just the (corresponding :file:`\*.py[co]`) file is added at the top level
+ just the (corresponding :file:`\*.pyc`) file is added at the top level
(no path information). If *pathname* is a file that does not end with
:file:`.py`, a :exc:`RuntimeError` will be raised. If it is a directory,
and the directory is not a package directory, then all the files
- :file:`\*.py[co]` are added at the top level. If the directory is a
- package directory, then all :file:`\*.py[co]` are added under the package
+ :file:`\*.pyc` are added at the top level. If the directory is a
+ package directory, then all :file:`\*.pyc` are added under the package
name as a file path, and if any subdirectories are package directories,
all of these are added recursively.
diff --git a/Doc/library/zipimport.rst b/Doc/library/zipimport.rst
index 46b8c245f7..eaae2bb04b 100644
--- a/Doc/library/zipimport.rst
+++ b/Doc/library/zipimport.rst
@@ -9,7 +9,7 @@
--------------
This module adds the ability to import Python modules (:file:`\*.py`,
-:file:`\*.py[co]`) and packages from ZIP-format archives. It is usually not
+:file:`\*.pyc`) and packages from ZIP-format archives. It is usually not
needed to use the :mod:`zipimport` module explicitly; it is automatically used
by the built-in :keyword:`import` mechanism for :data:`sys.path` items that are paths
to ZIP archives.
diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst
index 195f63f0a3..08dc311d83 100644
--- a/Doc/using/cmdline.rst
+++ b/Doc/using/cmdline.rst
@@ -532,8 +532,8 @@ conflict.
.. envvar:: PYTHONDONTWRITEBYTECODE
- If this is set to a non-empty string, Python won't try to write ``.pyc`` or
- ``.pyo`` files on the import of source modules. This is equivalent to
+ If this is set to a non-empty string, Python won't try to write ``.pyc``
+ files on the import of source modules. This is equivalent to
specifying the :option:`-B` option.
diff --git a/Modules/main.c b/Modules/main.c
index 2e6a60b167..2a0b1b37da 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -53,7 +53,7 @@ static const char usage_1[] = "\
Options and arguments (and corresponding environment variables):\n\
-b : issue warnings about str(bytes_instance), str(bytearray_instance)\n\
and comparing bytes/bytearray with str. (-bb: issue errors)\n\
--B : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x\n\
+-B : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x\n\
-c cmd : program passed in as string (terminates option list)\n\
-d : debug output from parser; also PYTHONDEBUG=x\n\
-E : ignore PYTHON* environment variables (such as PYTHONPATH)\n\
diff --git a/Modules/zipimport.c b/Modules/zipimport.c
index 59046aaae4..cccc033d2d 100644
--- a/Modules/zipimport.c
+++ b/Modules/zipimport.c
@@ -1102,7 +1102,7 @@ get_decompress_func(void)
_Py_IDENTIFIER(decompress);
if (importing_zlib != 0)
- /* Someone has a zlib.py[co] in their Zip file;
+ /* Someone has a zlib.pyc in their Zip file;
let's avoid a stack overflow. */
return NULL;
importing_zlib = 1;
@@ -1261,7 +1261,7 @@ eq_mtime(time_t t1, time_t t2)
return d <= 1;
}
-/* Given the contents of a .py[co] file in a buffer, unmarshal the data
+/* Given the contents of a .pyc file in a buffer, unmarshal the data
and return the code object. Return None if it the magic word doesn't
match (we do this instead of raising an exception as we fall back
to .py if available and we don't want to mask other errors).
@@ -1403,7 +1403,7 @@ get_mtime_of_source(ZipImporter *self, PyObject *path)
PyObject *toc_entry, *stripped;
time_t mtime;
- /* strip 'c' or 'o' from *.py[co] */
+ /* strip 'c' from *.pyc */
if (PyUnicode_READY(path) == -1)
return (time_t)-1;
stripped = PyUnicode_FromKindAndData(PyUnicode_KIND(path),
diff --git a/PC/getpathp.c b/PC/getpathp.c
index 1eeebfe9c1..e7be704a9a 100644
--- a/PC/getpathp.c
+++ b/PC/getpathp.c
@@ -185,7 +185,7 @@ exists(wchar_t *filename)
may extend 'filename' by one character.
*/
static int
-ismodule(wchar_t *filename, int update_filename) /* Is module -- check for .pyc/.pyo too */
+ismodule(wchar_t *filename, int update_filename) /* Is module -- check for .pyc too */
{
size_t n;
@@ -196,7 +196,7 @@ ismodule(wchar_t *filename, int update_filename) /* Is module -- check for .pyc/
n = wcsnlen_s(filename, MAXPATHLEN+1);
if (n < MAXPATHLEN) {
int exist = 0;
- filename[n] = Py_OptimizeFlag ? L'o' : L'c';
+ filename[n] = L'c';
filename[n + 1] = L'\0';
exist = exists(filename);
if (!update_filename)
diff --git a/PCbuild/rmpyc.py b/PCbuild/rmpyc.py
index a1e75bb7ae..0b58f68772 100644
--- a/PCbuild/rmpyc.py
+++ b/PCbuild/rmpyc.py
@@ -1,25 +1,19 @@
-# Remove all the .pyc and .pyo files under ../Lib.
+# Remove all the .pyc files under ../Lib.
def deltree(root):
import os
from os.path import join
- npyc = npyo = 0
+ npyc = 0
for root, dirs, files in os.walk(root):
for name in files:
- delete = False
- if name.endswith('.pyc'):
- delete = True
+ # to be thorough
+ if name.endswith(('.pyc', '.pyo')):
npyc += 1
- elif name.endswith('.pyo'):
- delete = True
- npyo += 1
-
- if delete:
os.remove(join(root, name))
- return npyc, npyo
+ return npyc
-npyc, npyo = deltree("../Lib")
-print(npyc, ".pyc deleted,", npyo, ".pyo deleted")
+npyc = deltree("../Lib")
+print(npyc, ".pyc deleted")
diff --git a/PCbuild/rt.bat b/PCbuild/rt.bat
index 35826727f3..e73ac04576 100644
--- a/PCbuild/rt.bat
+++ b/PCbuild/rt.bat
@@ -4,8 +4,8 @@ rem Usage: rt [-d] [-O] [-q] [-x64] regrtest_args
rem -d Run Debug build (python_d.exe). Else release build.
rem -O Run python.exe or python_d.exe (see -d) with -O.
rem -q "quick" -- normally the tests are run twice, the first time
-rem after deleting all the .py[co] files reachable from Lib/.
-rem -q runs the tests just once, and without deleting .py[co] files.
+rem after deleting all the .pyc files reachable from Lib/.
+rem -q runs the tests just once, and without deleting .pyc files.
rem -x64 Run the 64-bit build of python (or python_d if -d was specified)
rem from the 'amd64' dir instead of the 32-bit build in this dir.
rem All leading instances of these switches are shifted off, and
@@ -45,7 +45,7 @@ set exe=%prefix%python%suffix%.exe
set cmd="%exe%" %dashO% -Wd -E -bb -m test %regrtestargs%
if defined qmode goto Qmode
-echo Deleting .pyc/.pyo files ...
+echo Deleting .pyc files ...
"%exe%" "%pcbuild%rmpyc.py"
echo Cleaning _pth files ...
@@ -55,7 +55,7 @@ echo on
%cmd%
@echo off
-echo About to run again without deleting .pyc/.pyo first:
+echo About to run again without deleting .pyc first:
pause
:Qmode
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index a4f7f823bc..af96d6d5fc 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -88,7 +88,7 @@ int Py_BytesWarningFlag; /* Warn on str(bytes) and str(buffer) */
int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */
int Py_FrozenFlag; /* Needed by getpath.c */
int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
-int Py_DontWriteBytecodeFlag; /* Suppress writing bytecode files (*.py[co]) */
+int Py_DontWriteBytecodeFlag; /* Suppress writing bytecode files (*.pyc) */
int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
--
GitLab
From d7a8d32ce2d2b17ea9584759a281235ebfe81a89 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sat, 11 Mar 2017 10:19:51 -0800
Subject: [PATCH 0031/1433] tempfile.rst: Fix some typos (GH-610) (GH-618)
(cherry picked from commit d3b8f98696b905367da3975f73b482bac380b51c)
---
Doc/library/tempfile.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst
index 665261ffb2..c59aca1e18 100644
--- a/Doc/library/tempfile.rst
+++ b/Doc/library/tempfile.rst
@@ -245,12 +245,12 @@ The module uses a global variable to store the name of the directory
used for temporary files returned by :func:`gettempdir`. It can be
set directly to override the selection process, but this is discouraged.
All functions in this module take a *dir* argument which can be used
-to specify the directory and this is the recommend approach.
+to specify the directory and this is the recommended approach.
.. data:: tempdir
When set to a value other than ``None``, this variable defines the
- default value for the *dir* argument to all the functions defined in this
+ default value for the *dir* argument to the functions defined in this
module.
If ``tempdir`` is unset or ``None`` at any call to any of the above
--
GitLab
From b3536df9f8b041142f5e3bf6037c11be06eb7f59 Mon Sep 17 00:00:00 2001
From: Zachary Ware
Date: Sat, 11 Mar 2017 15:42:25 -0600
Subject: [PATCH 0032/1433] Only trigger AppVeyor on code or config changes
(GH-611 backport) (GH-620)
---
.github/appveyor.yml | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/.github/appveyor.yml b/.github/appveyor.yml
index 5a40005660..a369e52415 100644
--- a/.github/appveyor.yml
+++ b/.github/appveyor.yml
@@ -4,3 +4,20 @@ build_script:
- cmd: PCbuild\build.bat -e
test_script:
- cmd: PCbuild\rt.bat -q -uall -rwW --slowest --timeout=1200 -j0
+
+# Only trigger AppVeyor if actual code or its configuration changes
+only_commits:
+ files:
+ - .github/appveyor.yml
+ - .gitattributes
+ - Grammar/
+ - Include/
+ - Lib/
+ - Modules/
+ - Objects/
+ - PC/
+ - PCBuild/
+ - Parser/
+ - Programs/
+ - Python/
+ - Tools/
--
GitLab
From df6f3f6f5743a061d6c3b939136a11ac170ae69e Mon Sep 17 00:00:00 2001
From: Zachary Ware
Date: Sat, 11 Mar 2017 17:16:34 -0600
Subject: [PATCH 0033/1433] fix subprocess on Windows (GH-391 backport)
(GH-623)
---
Lib/subprocess.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 822ddb459e..0db6571f29 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -986,7 +986,7 @@ class Popen(object):
int(not close_fds),
creationflags,
env,
- cwd,
+ os.fspath(cwd) if cwd is not None else None,
startupinfo)
finally:
# Child is launched. Close the parent's copy of those pipe
--
GitLab
From 7c6d6e056460753c916348feee0e4916a97d7c86 Mon Sep 17 00:00:00 2001
From: Zachary Ware
Date: Sat, 11 Mar 2017 22:39:54 -0600
Subject: [PATCH 0034/1433] bpo-29763: Use support.unlink instead of os.unlink
(GH-624) (GH-625)
support.unlink waits for the files to be removed before returning
---
Lib/test/test_site.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py
index 0620b24276..342ec9e43d 100644
--- a/Lib/test/test_site.py
+++ b/Lib/test/test_site.py
@@ -501,15 +501,15 @@ class StartupImportTests(unittest.TestCase):
print(line, file=f)
return exe_file
except:
- os.unlink(_pth_file)
- os.unlink(exe_file)
+ test.support.unlink(_pth_file)
+ test.support.unlink(exe_file)
raise
@classmethod
def _cleanup_underpth_exe(self, exe_file):
_pth_file = os.path.splitext(exe_file)[0] + '._pth'
- os.unlink(_pth_file)
- os.unlink(exe_file)
+ test.support.unlink(_pth_file)
+ test.support.unlink(exe_file)
@classmethod
def _calc_sys_path_for_underpth_nosite(self, sys_prefix, lines):
--
GitLab
From 2f386254e2cf054cc7ee5103b54c1cf16d9fa979 Mon Sep 17 00:00:00 2001
From: Nick Coghlan
Date: Sun, 12 Mar 2017 16:17:46 +1000
Subject: [PATCH 0035/1433] bpo-29656: Handle PR branches in 'make patchcheck'
(#302) (#626)
(cherry picked from commit 482f7a274fa52b7ba34ff308cd9acdcac9f41ba5)
---
Tools/scripts/patchcheck.py | 58 +++++++++++++++++++++++++++++++++----
1 file changed, 52 insertions(+), 6 deletions(-)
diff --git a/Tools/scripts/patchcheck.py b/Tools/scripts/patchcheck.py
index 58b081a9c5..7a04aafa82 100755
--- a/Tools/scripts/patchcheck.py
+++ b/Tools/scripts/patchcheck.py
@@ -12,7 +12,6 @@ import untabify
SRCDIR = sysconfig.get_config_var('srcdir')
-
def n_files_str(count):
"""Return 'N file(s)' with the proper plurality on 'file'."""
return "{} file{}".format(count, "s" if count != 1 else "")
@@ -46,27 +45,73 @@ def mq_patches_applied():
return st.returncode == 0 and bstdout
+def get_git_branch():
+ """Get the symbolic name for the current git branch"""
+ cmd = "git rev-parse --abbrev-ref HEAD".split()
+ try:
+ return subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
+ except subprocess.CalledProcessError:
+ return None
+
+
+def get_git_upstream_remote():
+ """Get the remote name to use for upstream branches
+
+ Uses "upstream" if it exists, "origin" otherwise
+ """
+ cmd = "git remote get-url upstream".split()
+ try:
+ subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
+ except subprocess.CalledProcessError:
+ return "origin"
+ return "upstream"
+
+
+@status("Getting base branch for PR",
+ info=lambda x: x if x is not None else "not a PR branch")
+def get_base_branch():
+ if not os.path.isdir(os.path.join(SRCDIR, '.git')):
+ # Not a git checkout, so there's no base branch
+ return None
+ version = sys.version_info
+ if version.releaselevel == 'alpha':
+ base_branch = "master"
+ else:
+ base_branch = "{0.major}.{0.minor}".format(version)
+ this_branch = get_git_branch()
+ if this_branch is None or this_branch == base_branch:
+ # Not on a git PR branch, so there's no base branch
+ return None
+ upstream_remote = get_git_upstream_remote()
+ return upstream_remote + "/" + base_branch
+
+
@status("Getting the list of files that have been added/changed",
info=lambda x: n_files_str(len(x)))
-def changed_files():
+def changed_files(base_branch=None):
"""Get the list of changed or added files from Mercurial or git."""
if os.path.isdir(os.path.join(SRCDIR, '.hg')):
+ if base_branch is not None:
+ sys.exit('need a git checkout to check PR status')
cmd = 'hg status --added --modified --no-status'
if mq_patches_applied():
cmd += ' --rev qparent'
with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st:
return [x.decode().rstrip() for x in st.stdout]
elif os.path.isdir(os.path.join(SRCDIR, '.git')):
- cmd = 'git status --porcelain'
+ if base_branch:
+ cmd = 'git diff --name-status ' + base_branch
+ else:
+ cmd = 'git status --porcelain'
filenames = []
with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st:
for line in st.stdout:
line = line.decode().rstrip()
- status = set(line[:2])
+ status_text, filename = line.split(maxsplit=1)
+ status = set(status_text)
# modified, added or unmerged files
if not status.intersection('MAU'):
continue
- filename = line[3:]
if ' -> ' in filename:
# file is renamed
filename = filename.split(' -> ', 2)[1].strip()
@@ -165,7 +210,8 @@ def regenerated_pyconfig_h_in(file_paths):
return "not needed"
def main():
- file_paths = changed_files()
+ base_branch = get_base_branch()
+ file_paths = changed_files(base_branch)
python_files = [fn for fn in file_paths if fn.endswith('.py')]
c_files = [fn for fn in file_paths if fn.endswith(('.c', '.h'))]
doc_files = [fn for fn in file_paths if fn.startswith('Doc') and
--
GitLab
From 4652d82a51e6530a4f820588a6209d3295963bdb Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sun, 12 Mar 2017 10:05:05 +0200
Subject: [PATCH 0036/1433] bpo-29746: Update marshal docs to Python 3. (#547)
(#631)
(cherry picked from commit c611a5b1d4fab0123bf622f06c3bfa510221dc32)
---
Doc/c-api/marshal.rst | 8 ++++----
Doc/glossary.rst | 7 +++++++
Doc/library/marshal.rst | 19 ++++++++-----------
Python/marshal.c | 26 ++++++++++++--------------
4 files changed, 31 insertions(+), 29 deletions(-)
diff --git a/Doc/c-api/marshal.rst b/Doc/c-api/marshal.rst
index a6d0f4688d..c6d1d02a2f 100644
--- a/Doc/c-api/marshal.rst
+++ b/Doc/c-api/marshal.rst
@@ -34,7 +34,7 @@ unmarshalling. Version 2 uses a binary format for floating point numbers.
.. c:function:: PyObject* PyMarshal_WriteObjectToString(PyObject *value, int version)
- Return a string object containing the marshalled representation of *value*.
+ Return a bytes object containing the marshalled representation of *value*.
*version* indicates the file format.
@@ -88,10 +88,10 @@ written using these routines?
:exc:`TypeError`) and returns *NULL*.
-.. c:function:: PyObject* PyMarshal_ReadObjectFromString(const char *string, Py_ssize_t len)
+.. c:function:: PyObject* PyMarshal_ReadObjectFromString(const char *data, Py_ssize_t len)
- Return a Python object from the data stream in a character buffer
- containing *len* bytes pointed to by *string*.
+ Return a Python object from the data stream in a byte buffer
+ containing *len* bytes pointed to by *data*.
On error, sets the appropriate exception (:exc:`EOFError` or
:exc:`TypeError`) and returns *NULL*.
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index e07ab0df2f..495934afe7 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -131,6 +131,10 @@ Glossary
binary file
A :term:`file object` able to read and write
:term:`bytes-like objects `.
+ Examples of binary files are files opened in binary mode (``'rb'``,
+ ``'wb'`` or ``'rb+'``), :data:`sys.stdin.buffer`,
+ :data:`sys.stdout.buffer`, and instances of :class:`io.BytesIO` and
+ :class:`gzip.GzipFile`.
.. seealso::
A :term:`text file` reads and writes :class:`str` objects.
@@ -966,6 +970,9 @@ Glossary
A :term:`file object` able to read and write :class:`str` objects.
Often, a text file actually accesses a byte-oriented datastream
and handles the :term:`text encoding` automatically.
+ Examples of text files are files opened in text mode (``'r'`` or ``'w'``),
+ :data:`sys.stdin`, :data:`sys.stdout`, and instances of
+ :class:`io.StringIO`.
.. seealso::
A :term:`binary file` reads and write :class:`bytes` objects.
diff --git a/Doc/library/marshal.rst b/Doc/library/marshal.rst
index 1ffc6effc7..d65afc2004 100644
--- a/Doc/library/marshal.rst
+++ b/Doc/library/marshal.rst
@@ -49,7 +49,7 @@ For format *version* lower than 3, recursive lists, sets and dictionaries cannot
be written (see below).
There are functions that read/write files as well as functions operating on
-strings.
+bytes-like objects.
The module defines these functions:
@@ -57,9 +57,7 @@ The module defines these functions:
.. function:: dump(value, file[, version])
Write the value on the open file. The value must be a supported type. The
- file must be an open file object such as ``sys.stdout`` or returned by
- :func:`open` or :func:`os.popen`. It must be opened in binary mode (``'wb'``
- or ``'w+b'``).
+ file must be a writeable :term:`binary file`.
If the value has (or contains an object that has) an unsupported type, a
:exc:`ValueError` exception is raised --- but garbage data will also be written
@@ -74,8 +72,7 @@ The module defines these functions:
Read one value from the open file and return it. If no valid value is read
(e.g. because the data has a different Python version's incompatible marshal
format), raise :exc:`EOFError`, :exc:`ValueError` or :exc:`TypeError`. The
- file must be an open file object opened in binary mode (``'rb'`` or
- ``'r+b'``).
+ file must be a readable :term:`binary file`.
.. note::
@@ -85,7 +82,7 @@ The module defines these functions:
.. function:: dumps(value[, version])
- Return the string that would be written to a file by ``dump(value, file)``. The
+ Return the bytes object that would be written to a file by ``dump(value, file)``. The
value must be a supported type. Raise a :exc:`ValueError` exception if value
has (or contains an object that has) an unsupported type.
@@ -93,11 +90,11 @@ The module defines these functions:
(see below).
-.. function:: loads(string)
+.. function:: loads(bytes)
- Convert the string to a value. If no valid value is found, raise
- :exc:`EOFError`, :exc:`ValueError` or :exc:`TypeError`. Extra characters in the
- string are ignored.
+ Convert the :term:`bytes-like object` to a value. If no valid value is found, raise
+ :exc:`EOFError`, :exc:`ValueError` or :exc:`TypeError`. Extra bytes in the
+ input are ignored.
In addition, the following constants are defined:
diff --git a/Python/marshal.c b/Python/marshal.c
index 87a4b240a4..7b12ab7510 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -549,7 +549,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
w_object(co->co_lnotab, p);
}
else if (PyObject_CheckBuffer(v)) {
- /* Write unknown bytes-like objects as a byte string */
+ /* Write unknown bytes-like objects as a bytes object */
Py_buffer view;
if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) != 0) {
w_byte(TYPE_UNKNOWN, p);
@@ -1086,7 +1086,7 @@ r_object(RFILE *p)
if (PyErr_Occurred())
break;
if (n < 0 || n > SIZE32_MAX) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)");
+ PyErr_SetString(PyExc_ValueError, "bad marshal data (bytes object size out of range)");
break;
}
v = PyBytes_FromStringAndSize((char *)NULL, n);
@@ -1110,7 +1110,7 @@ r_object(RFILE *p)
if (PyErr_Occurred())
break;
if (n < 0 || n > SIZE32_MAX) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (unicode size out of range)");
+ PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)");
break;
}
goto _read_ascii;
@@ -1150,7 +1150,7 @@ r_object(RFILE *p)
if (PyErr_Occurred())
break;
if (n < 0 || n > SIZE32_MAX) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (unicode size out of range)");
+ PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)");
break;
}
if (n != 0) {
@@ -1612,7 +1612,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)
if (wf.ptr - base > PY_SSIZE_T_MAX) {
Py_DECREF(wf.str);
PyErr_SetString(PyExc_OverflowError,
- "too much marshal data for a string");
+ "too much marshal data for a bytes object");
return NULL;
}
if (_PyBytes_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)) < 0)
@@ -1658,8 +1658,7 @@ PyDoc_STRVAR(dump_doc,
"dump(value, file[, version])\n\
\n\
Write the value on the open file. The value must be a supported type.\n\
-The file must be an open file object such as sys.stdout or returned by\n\
-open() or os.popen(). It must be opened in binary mode ('wb' or 'w+b').\n\
+The file must be a writeable binary file.\n\
\n\
If the value has (or contains an object that has) an unsupported type, a\n\
ValueError exception is raised - but garbage data will also be written\n\
@@ -1715,8 +1714,7 @@ PyDoc_STRVAR(load_doc,
Read one value from the open file and return it. If no valid value is\n\
read (e.g. because the data has a different Python version's\n\
incompatible marshal format), raise EOFError, ValueError or TypeError.\n\
-The file must be an open file object opened in binary mode ('rb' or\n\
-'r+b').\n\
+The file must be a readable binary file.\n\
\n\
Note: If an object containing an unsupported type was marshalled with\n\
dump(), load() will substitute None for the unmarshallable type.");
@@ -1735,7 +1733,7 @@ marshal_dumps(PyObject *self, PyObject *args)
PyDoc_STRVAR(dumps_doc,
"dumps(value[, version])\n\
\n\
-Return the string that would be written to a file by dump(value, file).\n\
+Return the bytes object that would be written to a file by dump(value, file).\n\
The value must be a supported type. Raise a ValueError exception if\n\
value has (or contains an object that has) an unsupported type.\n\
\n\
@@ -1771,8 +1769,8 @@ marshal_loads(PyObject *self, PyObject *args)
PyDoc_STRVAR(loads_doc,
"loads(bytes)\n\
\n\
-Convert the bytes object to a value. If no valid value is found, raise\n\
-EOFError, ValueError or TypeError. Extra characters in the input are\n\
+Convert the bytes-like object to a value. If no valid value is found,\n\
+raise EOFError, ValueError or TypeError. Extra bytes in the input are\n\
ignored.");
static PyMethodDef marshal_methods[] = {
@@ -1810,8 +1808,8 @@ Functions:\n\
\n\
dump() -- write value to a file\n\
load() -- read value from a file\n\
-dumps() -- write value to a string\n\
-loads() -- read value from a string");
+dumps() -- marshal value as a bytes object\n\
+loads() -- read value from a bytes-like object");
--
GitLab
From 61a82a5fbf1a674b91764652ab70f5dbb9ba50f2 Mon Sep 17 00:00:00 2001
From: Nick Coghlan
Date: Sun, 12 Mar 2017 20:00:20 +1000
Subject: [PATCH 0037/1433] bpo-29798: Handle git worktree in `make patchcheck`
(#629) (#633)
In git worktree directories, `.git` is a configuration
file rather than a subdirectory
(cherry picked from commit 6a6d090612dd7deaac2bc0399fad743e5e2db606)
---
Tools/scripts/patchcheck.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Tools/scripts/patchcheck.py b/Tools/scripts/patchcheck.py
index 7a04aafa82..f4ec7d8a30 100755
--- a/Tools/scripts/patchcheck.py
+++ b/Tools/scripts/patchcheck.py
@@ -98,7 +98,10 @@ def changed_files(base_branch=None):
cmd += ' --rev qparent'
with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st:
return [x.decode().rstrip() for x in st.stdout]
- elif os.path.isdir(os.path.join(SRCDIR, '.git')):
+ elif os.path.exists(os.path.join(SRCDIR, '.git')):
+ # We just use an existence check here as:
+ # directory = normal git checkout/clone
+ # file = git worktree directory
if base_branch:
cmd = 'git diff --name-status ' + base_branch
else:
--
GitLab
From c60948464fb0ec116ea227f6bce8a4bb8fb75257 Mon Sep 17 00:00:00 2001
From: Nick Coghlan
Date: Sun, 12 Mar 2017 21:34:22 +1000
Subject: [PATCH 0038/1433] [3.6] bpo-29723: Consistently configure sys.path[0]
(#636)
Directory and zipfile execution previously added
the parent directory of the directory or zipfile
as sys.path[0] and then subsequently overwrote
it with the directory or zipfile itself.
This caused problems in isolated mode, as it
overwrote the "stdlib as a zip archive" entry
in sys.path, as the parent directory was
never added.
The attempted fix to that issue in bpo-29319
created the opposite problem in *non*-isolated
mode, by potentially leaving the parent
directory on sys.path instead of overwriting it.
This change fixes the root cause of the problem
by removing the whole "add-and-overwrite" dance
for sys.path[0], and instead simply never adds
the parent directory to sys.path in the first
place.
(cherry picked from commit d2977a3ae2cc6802921b1e3b6e9d13fcfbda872d)
---
Lib/test/test_cmd_line_script.py | 67 +++++++++++++++++++++++++++++
Misc/NEWS | 8 ++++
Modules/main.c | 72 +++++++++++++++++++-------------
3 files changed, 119 insertions(+), 28 deletions(-)
diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py
index e058ecd086..1587daf8f5 100644
--- a/Lib/test/test_cmd_line_script.py
+++ b/Lib/test/test_cmd_line_script.py
@@ -572,6 +572,73 @@ class CmdLineTest(unittest.TestCase):
self.assertNotIn("\f", text)
self.assertIn("\n 1 + 1 = 2\n ^", text)
+ def test_consistent_sys_path_for_direct_execution(self):
+ # This test case ensures that the following all give the same
+ # sys.path configuration:
+ #
+ # ./python -s script_dir/__main__.py
+ # ./python -s script_dir
+ # ./python -I script_dir
+ script = textwrap.dedent("""\
+ import sys
+ for entry in sys.path:
+ print(entry)
+ """)
+ # Always show full path diffs on errors
+ self.maxDiff = None
+ with support.temp_dir() as work_dir, support.temp_dir() as script_dir:
+ script_name = _make_test_script(script_dir, '__main__', script)
+ # Reference output comes from directly executing __main__.py
+ # We omit PYTHONPATH and user site to align with isolated mode
+ p = spawn_python("-Es", script_name, cwd=work_dir)
+ out_by_name = kill_python(p).decode().splitlines()
+ self.assertEqual(out_by_name[0], script_dir)
+ self.assertNotIn(work_dir, out_by_name)
+ # Directory execution should give the same output
+ p = spawn_python("-Es", script_dir, cwd=work_dir)
+ out_by_dir = kill_python(p).decode().splitlines()
+ self.assertEqual(out_by_dir, out_by_name)
+ # As should directory execution in isolated mode
+ p = spawn_python("-I", script_dir, cwd=work_dir)
+ out_by_dir_isolated = kill_python(p).decode().splitlines()
+ self.assertEqual(out_by_dir_isolated, out_by_dir, out_by_name)
+
+ def test_consistent_sys_path_for_module_execution(self):
+ # This test case ensures that the following both give the same
+ # sys.path configuration:
+ # ./python -sm script_pkg.__main__
+ # ./python -sm script_pkg
+ #
+ # And that this fails as unable to find the package:
+ # ./python -Im script_pkg
+ script = textwrap.dedent("""\
+ import sys
+ for entry in sys.path:
+ print(entry)
+ """)
+ # Always show full path diffs on errors
+ self.maxDiff = None
+ with support.temp_dir() as work_dir:
+ script_dir = os.path.join(work_dir, "script_pkg")
+ os.mkdir(script_dir)
+ script_name = _make_test_script(script_dir, '__main__', script)
+ # Reference output comes from `-m script_pkg.__main__`
+ # We omit PYTHONPATH and user site to better align with the
+ # direct execution test cases
+ p = spawn_python("-sm", "script_pkg.__main__", cwd=work_dir)
+ out_by_module = kill_python(p).decode().splitlines()
+ self.assertEqual(out_by_module[0], '')
+ self.assertNotIn(script_dir, out_by_module)
+ # Package execution should give the same output
+ p = spawn_python("-sm", "script_pkg", cwd=work_dir)
+ out_by_package = kill_python(p).decode().splitlines()
+ self.assertEqual(out_by_package, out_by_module)
+ # Isolated mode should fail with an import error
+ exitcode, stdout, stderr = assert_python_failure(
+ "-Im", "script_pkg", cwd=work_dir
+ )
+ traceback_lines = stderr.decode().splitlines()
+ self.assertIn("No module named script_pkg", traceback_lines[-1])
def test_main():
support.run_unittest(CmdLineTest)
diff --git a/Misc/NEWS b/Misc/NEWS
index 299a8388ff..640c783ed7 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,14 @@ What's New in Python 3.6.1 final?
Core and Builtins
-----------------
+- bpo-29723: The ``sys.path[0]`` initialization change for bpo-29139 caused a
+ regression by revealing an inconsistency in how sys.path is initialized when
+ executing ``__main__`` from a zipfile, directory, or other import location.
+ The interpreter now consistently avoids ever adding the import location's
+ parent directory to ``sys.path``, and ensures no other ``sys.path`` entries
+ are inadvertently modified when inserting the import location named on the
+ command line.
+
- bpo-29714: Fix a regression that bytes format may fail when containing zero
bytes inside.
diff --git a/Modules/main.c b/Modules/main.c
index 2a0b1b37da..475a2fdc36 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -225,55 +225,60 @@ static int RunModule(wchar_t *modname, int set_argv0)
return 0;
}
-static int
-RunMainFromImporter(wchar_t *filename)
+static PyObject *
+AsImportPathEntry(wchar_t *filename)
{
- PyObject *argv0 = NULL, *importer, *sys_path, *sys_path0;
- int sts;
+ PyObject *sys_path0 = NULL, *importer;
- argv0 = PyUnicode_FromWideChar(filename, wcslen(filename));
- if (argv0 == NULL)
+ sys_path0 = PyUnicode_FromWideChar(filename, wcslen(filename));
+ if (sys_path0 == NULL)
goto error;
- importer = PyImport_GetImporter(argv0);
+ importer = PyImport_GetImporter(sys_path0);
if (importer == NULL)
goto error;
if (importer == Py_None) {
- Py_DECREF(argv0);
+ Py_DECREF(sys_path0);
Py_DECREF(importer);
- return -1;
+ return NULL;
}
Py_DECREF(importer);
+ return sys_path0;
+
+error:
+ Py_XDECREF(sys_path0);
+ PySys_WriteStderr("Failed checking if argv[0] is an import path entry\n");
+ PyErr_Print();
+ PyErr_Clear();
+ return NULL;
+}
+
+
+static int
+RunMainFromImporter(PyObject *sys_path0)
+{
+ PyObject *sys_path;
+ int sts;
- /* argv0 is usable as an import source, so put it in sys.path[0]
- and import __main__ */
+ /* Assume sys_path0 has already been checked by AsImportPathEntry,
+ * so put it in sys.path[0] and import __main__ */
sys_path = PySys_GetObject("path");
if (sys_path == NULL) {
PyErr_SetString(PyExc_RuntimeError, "unable to get sys.path");
goto error;
}
- sys_path0 = PyList_GetItem(sys_path, 0);
- sts = 0;
- if (!sys_path0) {
- PyErr_Clear();
- sts = PyList_Append(sys_path, argv0);
- } else if (PyObject_IsTrue(sys_path0)) {
- sts = PyList_Insert(sys_path, 0, argv0);
- } else {
- sts = PyList_SetItem(sys_path, 0, argv0);
- }
+ sts = PyList_Insert(sys_path, 0, sys_path0);
if (sts) {
- argv0 = NULL;
+ sys_path0 = NULL;
goto error;
}
- Py_INCREF(argv0);
sts = RunModule(L"__main__", 0);
return sts != 0;
error:
- Py_XDECREF(argv0);
+ Py_XDECREF(sys_path0);
PyErr_Print();
return 1;
}
@@ -358,6 +363,7 @@ Py_Main(int argc, wchar_t **argv)
int saw_unbuffered_flag = 0;
char *opt;
PyCompilerFlags cf;
+ PyObject *main_importer_path = NULL;
PyObject *warning_option = NULL;
PyObject *warning_options = NULL;
@@ -714,7 +720,17 @@ Py_Main(int argc, wchar_t **argv)
argv[_PyOS_optind] = L"-m";
}
- PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
+ if (filename != NULL) {
+ main_importer_path = AsImportPathEntry(filename);
+ }
+
+ if (main_importer_path != NULL) {
+ /* Let RunMainFromImporter adjust sys.path[0] later */
+ PySys_SetArgvEx(argc-_PyOS_optind, argv+_PyOS_optind, 0);
+ } else {
+ /* Use config settings to decide whether or not to update sys.path[0] */
+ PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
+ }
if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) &&
isatty(fileno(stdin)) &&
@@ -744,11 +760,11 @@ Py_Main(int argc, wchar_t **argv)
sts = -1; /* keep track of whether we've already run __main__ */
- if (filename != NULL) {
- sts = RunMainFromImporter(filename);
+ if (main_importer_path != NULL) {
+ sts = RunMainFromImporter(main_importer_path);
}
- if (sts==-1 && filename!=NULL) {
+ if (sts==-1 && filename != NULL) {
fp = _Py_wfopen(filename, L"r");
if (fp == NULL) {
char *cfilename_buffer;
--
GitLab
From aac875fa2f03cab61ceeaa2621c4c5534c7bcfc2 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sun, 12 Mar 2017 21:52:17 +0200
Subject: [PATCH 0039/1433] [3.6] bpo-8256: Fixed possible failing or crashing
input() (#641)
if attributes "encoding" or "errors" of sys.stdin or sys.stdout are not set or are not strings.
---
Misc/NEWS | 3 +++
Python/bltinmodule.c | 21 ++++++++++++++++-----
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/Misc/NEWS b/Misc/NEWS
index 640c783ed7..eef4dfa335 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -24,6 +24,9 @@ Core and Builtins
Library
-------
+- bpo-8256: Fixed possible failing or crashing input() if attributes "encoding"
+ or "errors" of sys.stdin or sys.stdout are not set or are not strings.
+
- bpo-28298: Fix a bug that prevented array 'Q', 'L' and 'I' from accepting big
intables (objects that have __int__) as elements. Patch by Oren Milman.
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index ef5a34cae9..597e26ec69 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1927,12 +1927,15 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
PyObject *result;
size_t len;
+ /* stdin is a text stream, so it must have an encoding. */
stdin_encoding = _PyObject_GetAttrId(fin, &PyId_encoding);
stdin_errors = _PyObject_GetAttrId(fin, &PyId_errors);
- if (!stdin_encoding || !stdin_errors)
- /* stdin is a text stream, so it must have an
- encoding. */
+ if (!stdin_encoding || !stdin_errors ||
+ !PyUnicode_Check(stdin_encoding) ||
+ !PyUnicode_Check(stdin_errors)) {
+ tty = 0;
goto _readline_errors;
+ }
stdin_encoding_str = PyUnicode_AsUTF8(stdin_encoding);
stdin_errors_str = PyUnicode_AsUTF8(stdin_errors);
if (!stdin_encoding_str || !stdin_errors_str)
@@ -1948,8 +1951,12 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
PyObject *stringpo;
stdout_encoding = _PyObject_GetAttrId(fout, &PyId_encoding);
stdout_errors = _PyObject_GetAttrId(fout, &PyId_errors);
- if (!stdout_encoding || !stdout_errors)
+ if (!stdout_encoding || !stdout_errors ||
+ !PyUnicode_Check(stdout_encoding) ||
+ !PyUnicode_Check(stdout_errors)) {
+ tty = 0;
goto _readline_errors;
+ }
stdout_encoding_str = PyUnicode_AsUTF8(stdout_encoding);
stdout_errors_str = PyUnicode_AsUTF8(stdout_errors);
if (!stdout_encoding_str || !stdout_errors_str)
@@ -2003,13 +2010,17 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
Py_XDECREF(po);
PyMem_FREE(s);
return result;
+
_readline_errors:
Py_XDECREF(stdin_encoding);
Py_XDECREF(stdout_encoding);
Py_XDECREF(stdin_errors);
Py_XDECREF(stdout_errors);
Py_XDECREF(po);
- return NULL;
+ if (tty)
+ return NULL;
+
+ PyErr_Clear();
}
/* Fallback if we're not interactive */
--
GitLab
From fa448de97de85d242491d7ad259ade0732f05db8 Mon Sep 17 00:00:00 2001
From: Yury Selivanov
Date: Sun, 12 Mar 2017 17:04:06 -0400
Subject: [PATCH 0040/1433] Fix wrapping into StopIteration of return values in
generators and coroutines (#644) (#647)
---
Lib/test/test_coroutines.py | 15 +++++++++++++++
Misc/NEWS | 2 ++
Objects/genobject.c | 3 +--
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py
index b4c7b5be6e..a69583b5f9 100644
--- a/Lib/test/test_coroutines.py
+++ b/Lib/test/test_coroutines.py
@@ -1103,6 +1103,21 @@ class CoroutineTest(unittest.TestCase):
"coroutine is being awaited already"):
waiter(coro).send(None)
+ def test_await_16(self):
+ # See https://bugs.python.org/issue29600 for details.
+
+ async def f():
+ return ValueError()
+
+ async def g():
+ try:
+ raise KeyError
+ except:
+ return await f()
+
+ _, result = run_async(g())
+ self.assertIsNone(result.__context__)
+
def test_with_1(self):
class Manager:
def __init__(self, name):
diff --git a/Misc/NEWS b/Misc/NEWS
index eef4dfa335..504b977bc8 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ What's New in Python 3.6.1 final?
Core and Builtins
-----------------
+- bpo-29600: Fix wrapping coroutine return values in StopIteration.
+
- bpo-29723: The ``sys.path[0]`` initialization change for bpo-29139 caused a
regression by revealing an inconsistency in how sys.path is initialized when
executing ``__main__`` from a zipfile, directory, or other import location.
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 2680ab0e12..1c29e296af 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -575,8 +575,7 @@ _PyGen_SetStopIterationValue(PyObject *value)
PyObject *e;
if (value == NULL ||
- (!PyTuple_Check(value) &&
- !PyObject_TypeCheck(value, (PyTypeObject *) PyExc_StopIteration)))
+ (!PyTuple_Check(value) && !PyExceptionInstance_Check(value)))
{
/* Delay exception instantiation if we can */
PyErr_SetObject(PyExc_StopIteration, value);
--
GitLab
From 99f8d33a94c8951fd6b2d5f079d20be698150993 Mon Sep 17 00:00:00 2001
From: Yury Selivanov
Date: Sun, 12 Mar 2017 17:06:16 -0400
Subject: [PATCH 0041/1433] bpo-29742: asyncio get_extra_info() throws
exception (#525) (#645)
---
Lib/asyncio/sslproto.py | 4 +++-
Lib/test/test_asyncio/test_sslproto.py | 12 ++++++++++++
Misc/NEWS | 3 +++
3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py
index 7ad28d6aa0..ab7ff0bf93 100644
--- a/Lib/asyncio/sslproto.py
+++ b/Lib/asyncio/sslproto.py
@@ -543,8 +543,10 @@ class SSLProtocol(protocols.Protocol):
def _get_extra_info(self, name, default=None):
if name in self._extra:
return self._extra[name]
- else:
+ elif self._transport is not None:
return self._transport.get_extra_info(name, default)
+ else:
+ return default
def _start_shutdown(self):
if self._in_shutdown:
diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py
index 59ff0f6967..f1771c5561 100644
--- a/Lib/test/test_asyncio/test_sslproto.py
+++ b/Lib/test/test_asyncio/test_sslproto.py
@@ -95,5 +95,17 @@ class SslProtoHandshakeTests(test_utils.TestCase):
test_utils.run_briefly(self.loop)
self.assertIsInstance(waiter.exception(), ConnectionAbortedError)
+ def test_get_extra_info_on_closed_connection(self):
+ waiter = asyncio.Future(loop=self.loop)
+ ssl_proto = self.ssl_protocol(waiter)
+ self.assertIsNone(ssl_proto._get_extra_info('socket'))
+ default = object()
+ self.assertIs(ssl_proto._get_extra_info('socket', default), default)
+ self.connection_made(ssl_proto)
+ self.assertIsNotNone(ssl_proto._get_extra_info('socket'))
+ ssl_proto.connection_lost(None)
+ self.assertIsNone(ssl_proto._get_extra_info('socket'))
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/Misc/NEWS b/Misc/NEWS
index 504b977bc8..25a24f5200 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -26,6 +26,9 @@ Core and Builtins
Library
-------
+- bpo-29742: get_extra_info() raises exception if get called on closed ssl transport.
+ Patch by Nikolay Kim.
+
- bpo-8256: Fixed possible failing or crashing input() if attributes "encoding"
or "errors" of sys.stdin or sys.stdout are not set or are not strings.
--
GitLab
From 7927abba3449e12d0ae3518b722fdfeb383b4039 Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Mon, 13 Mar 2017 10:36:34 +0800
Subject: [PATCH 0042/1433] fix the name of argument to ftplib.FTP.set_pasv and
fix wording (GH-653) (GH-654)
---
Doc/library/ftplib.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst
index b8c1dcfef2..1153ce77dd 100644
--- a/Doc/library/ftplib.rst
+++ b/Doc/library/ftplib.rst
@@ -255,9 +255,9 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
prints the line to ``sys.stdout``.
-.. method:: FTP.set_pasv(boolean)
+.. method:: FTP.set_pasv(val)
- Enable "passive" mode if *boolean* is true, other disable passive mode.
+ Enable "passive" mode if *val* is true, otherwise disable passive mode.
Passive mode is on by default.
--
GitLab
From 388e2568fc919a177df2d2949b575c553aea84ac Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Mon, 13 Mar 2017 11:03:36 +0800
Subject: [PATCH 0043/1433] ftplib.FTP.retrbinary callback gets a bytes, not a
str (GH-652) (GH-657)
---
Doc/library/ftplib.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst
index 1153ce77dd..7291dfe848 100644
--- a/Doc/library/ftplib.rst
+++ b/Doc/library/ftplib.rst
@@ -235,7 +235,7 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
Retrieve a file in binary transfer mode. *cmd* should be an appropriate
``RETR`` command: ``'RETR filename'``. The *callback* function is called for
- each block of data received, with a single string argument giving the data
+ each block of data received, with a single bytes argument giving the data
block. The optional *blocksize* argument specifies the maximum chunk size to
read on the low-level socket object created to do the actual transfer (which
will also be the largest size of the data blocks passed to *callback*). A
--
GitLab
From faa2cc63e45bc7d7ffab84bebe5a9f4fe065bd96 Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Tue, 14 Mar 2017 15:27:01 +0800
Subject: [PATCH 0044/1433] bpo-28856: Let %b format for bytes support objects
that follow the buffer protocol (GH-664)
---
Lib/test/test_format.py | 8 ++++++--
Misc/NEWS | 3 +++
Objects/bytesobject.c | 15 ++++++++++++++-
3 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py
index 83eb29faf8..b6ba2e566b 100644
--- a/Lib/test/test_format.py
+++ b/Lib/test/test_format.py
@@ -315,10 +315,12 @@ class FormatTest(unittest.TestCase):
testcommon(b"%b", b"abc", b"abc")
testcommon(b"%b", bytearray(b"def"), b"def")
testcommon(b"%b", fb, b"123")
+ testcommon(b"%b", memoryview(b"abc"), b"abc")
# # %s is an alias for %b -- should only be used for Py2/3 code
testcommon(b"%s", b"abc", b"abc")
testcommon(b"%s", bytearray(b"def"), b"def")
testcommon(b"%s", fb, b"123")
+ testcommon(b"%s", memoryview(b"abc"), b"abc")
# %a will give the equivalent of
# repr(some_obj).encode('ascii', 'backslashreplace')
testcommon(b"%a", 3.14, b"3.14")
@@ -377,9 +379,11 @@ class FormatTest(unittest.TestCase):
test_exc(b"%c", 3.14, TypeError,
"%c requires an integer in range(256) or a single byte")
test_exc(b"%b", "Xc", TypeError,
- "%b requires bytes, or an object that implements __bytes__, not 'str'")
+ "%b requires a bytes-like object, "
+ "or an object that implements __bytes__, not 'str'")
test_exc(b"%s", "Wd", TypeError,
- "%b requires bytes, or an object that implements __bytes__, not 'str'")
+ "%b requires a bytes-like object, "
+ "or an object that implements __bytes__, not 'str'")
if maxsize == 2**31-1:
# crashes 2.2.1 and earlier:
diff --git a/Misc/NEWS b/Misc/NEWS
index 25a24f5200..284a2031ee 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ Core and Builtins
- bpo-29600: Fix wrapping coroutine return values in StopIteration.
+- bpo-28856: Fix an oversight that %b format for bytes should support objects
+ follow the buffer protocol.
+
- bpo-29723: The ``sys.path[0]`` initialization change for bpo-29139 caused a
regression by revealing an inconsistency in how sys.path is initialized when
executing ``__main__`` from a zipfile, directory, or other import location.
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 801711f7e6..30c1a7e245 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -528,6 +528,8 @@ byte_converter(PyObject *arg, char *p)
return 0;
}
+static PyObject *_PyBytes_FromBuffer(PyObject *x);
+
static PyObject *
format_obj(PyObject *v, const char **pbuf, Py_ssize_t *plen)
{
@@ -564,8 +566,19 @@ format_obj(PyObject *v, const char **pbuf, Py_ssize_t *plen)
*plen = PyBytes_GET_SIZE(result);
return result;
}
+ /* does it support buffer protocol? */
+ if (PyObject_CheckBuffer(v)) {
+ /* maybe we can avoid making a copy of the buffer object here? */
+ result = _PyBytes_FromBuffer(v);
+ if (result == NULL)
+ return NULL;
+ *pbuf = PyBytes_AS_STRING(result);
+ *plen = PyBytes_GET_SIZE(result);
+ return result;
+ }
PyErr_Format(PyExc_TypeError,
- "%%b requires bytes, or an object that implements __bytes__, not '%.100s'",
+ "%%b requires a bytes-like object, "
+ "or an object that implements __bytes__, not '%.100s'",
Py_TYPE(v)->tp_name);
return NULL;
}
--
GitLab
From 53b2667dcf2a7d13af466a5fb91844f5125a920d Mon Sep 17 00:00:00 2001
From: Michael Seifert
Date: Wed, 15 Mar 2017 08:42:02 +0100
Subject: [PATCH 0045/1433] bpo-29800: Fix crashes in partial.__repr__ if the
keys of partial.keywords are not strings (#649) (#671)
---
Lib/test/test_functools.py | 26 ++++++++++++++++++++++++++
Misc/ACKS | 1 +
Misc/NEWS | 3 +++
Modules/_functoolsmodule.c | 5 ++++-
4 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py
index b7d648d0b1..cd4664cec0 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -402,6 +402,32 @@ class TestPartialC(TestPartial, unittest.TestCase):
else:
self.fail('partial object allowed __dict__ to be deleted')
+ def test_manually_adding_non_string_keyword(self):
+ p = self.partial(capture)
+ # Adding a non-string/unicode keyword to partial kwargs
+ p.keywords[1234] = 'value'
+ r = repr(p)
+ self.assertIn('1234', r)
+ self.assertIn("'value'", r)
+ with self.assertRaises(TypeError):
+ p()
+
+ def test_keystr_replaces_value(self):
+ p = self.partial(capture)
+
+ class MutatesYourDict(object):
+ def __str__(self):
+ p.keywords[self] = ['sth2']
+ return 'astr'
+
+ # Raplacing the value during key formatting should keep the original
+ # value alive (at least long enough).
+ p.keywords[MutatesYourDict()] = ['sth']
+ r = repr(p)
+ self.assertIn('astr', r)
+ self.assertIn("['sth']", r)
+
+
class TestPartialPy(TestPartial, unittest.TestCase):
partial = py_functools.partial
diff --git a/Misc/ACKS b/Misc/ACKS
index c3b29a42a3..03afeb8f38 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1371,6 +1371,7 @@ Federico Schwindt
Barry Scott
Steven Scott
Nick Seidenman
+Michael Seifert
Žiga Seilnacht
Yury Selivanov
Fred Sells
diff --git a/Misc/NEWS b/Misc/NEWS
index 284a2031ee..4c5efefb65 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -29,6 +29,9 @@ Core and Builtins
Library
-------
+- bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords
+ are not strings. Patch by Michael Seifert.
+
- bpo-29742: get_extra_info() raises exception if get called on closed ssl transport.
Patch by Nikolay Kim.
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 7abc9f4640..1bcf16a7e0 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -250,8 +250,11 @@ partial_repr(partialobject *pto)
/* Pack keyword arguments */
assert (PyDict_Check(pto->kw));
for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
- Py_SETREF(arglist, PyUnicode_FromFormat("%U, %U=%R", arglist,
+ /* Prevent key.__str__ from deleting the value. */
+ Py_INCREF(value);
+ Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist,
key, value));
+ Py_DECREF(value);
if (arglist == NULL)
goto done;
}
--
GitLab
From 02c6fa573a0a7f417e21ad9e81bcff3ac61a9fa8 Mon Sep 17 00:00:00 2001
From: Berker Peksag
Date: Wed, 15 Mar 2017 14:12:22 +0300
Subject: [PATCH 0046/1433] Delete duplicate entry in Misc/NEWS (#673)
It has already been added in the build section.
---
Misc/NEWS | 2 --
1 file changed, 2 deletions(-)
diff --git a/Misc/NEWS b/Misc/NEWS
index 4c5efefb65..03f70dc885 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -73,8 +73,6 @@ Core and Builtins
- Issue #28598: Support __rmod__ for subclasses of str being called before
str.__mod__. Patch by Martijn Pieters.
-- bpo-29572: Update Windows build and OS X installers to use OpenSSL 1.0.2k.
-
- bpo-29607: Fix stack_effect computation for CALL_FUNCTION_EX.
Patch by Matthieu Dartiailh.
--
GitLab
From 78add3309b53d68c2c5c118ec63f7485bbf93c9a Mon Sep 17 00:00:00 2001
From: Berker Peksag
Date: Wed, 15 Mar 2017 14:12:53 +0300
Subject: [PATCH 0047/1433] Change assertRaises to assertRaisesRegex in
test_xmlrpc (#481) (#674)
(cherry picked from commit c6b448b36d22769c684bb3276f85c1b47d15ab63)
---
Lib/test/test_xmlrpc.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py
index 69de08e9c3..30025e388d 100644
--- a/Lib/test/test_xmlrpc.py
+++ b/Lib/test/test_xmlrpc.py
@@ -412,7 +412,7 @@ class SimpleXMLRPCDispatcherTestCase(unittest.TestCase):
dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
dispatcher.register_function(None, name='method')
- with self.assertRaises(Exception, expected_regex='method'):
+ with self.assertRaisesRegex(Exception, 'method'):
dispatcher._dispatch('method', ('param',))
def test_instance_has_no_func(self):
@@ -420,14 +420,14 @@ class SimpleXMLRPCDispatcherTestCase(unittest.TestCase):
dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
dispatcher.register_instance(object())
- with self.assertRaises(Exception, expected_regex='method'):
+ with self.assertRaisesRegex(Exception, 'method'):
dispatcher._dispatch('method', ('param',))
def test_cannot_locate_func(self):
"""Calls a function that the dispatcher cannot locate"""
dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
- with self.assertRaises(Exception, expected_regex='method'):
+ with self.assertRaisesRegex(Exception, 'method'):
dispatcher._dispatch('method', ('param',))
--
GitLab
From 0dfd18a1e14e08b0d6459c2dd1898e5bb38020c5 Mon Sep 17 00:00:00 2001
From: Berker Peksag
Date: Thu, 16 Mar 2017 16:22:35 +0300
Subject: [PATCH 0048/1433] Fix stderr bug in json.tool test (#346) (#676)
See https://github.com/python/cpython/pull/201#discussion_r103229425.(cherry picked from commit b4e9087e7b77e8f76feac76f9c1ab21b49c0c766)
---
Lib/test/test_json/test_tool.py | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py
index 15f373664e..9d93f931ca 100644
--- a/Lib/test/test_json/test_tool.py
+++ b/Lib/test/test_json/test_tool.py
@@ -2,7 +2,7 @@ import os
import sys
import textwrap
import unittest
-import subprocess
+from subprocess import Popen, PIPE
from test import support
from test.support.script_helper import assert_python_ok
@@ -61,12 +61,11 @@ class TestTool(unittest.TestCase):
""")
def test_stdin_stdout(self):
- with subprocess.Popen(
- (sys.executable, '-m', 'json.tool'),
- stdin=subprocess.PIPE, stdout=subprocess.PIPE) as proc:
+ args = sys.executable, '-m', 'json.tool'
+ with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc:
out, err = proc.communicate(self.data.encode())
self.assertEqual(out.splitlines(), self.expect.encode().splitlines())
- self.assertEqual(err, None)
+ self.assertEqual(err, b'')
def _create_infile(self):
infile = support.TESTFN
--
GitLab
From 9cd5e87bac51d7b901e3c36bf22728bb1693da59 Mon Sep 17 00:00:00 2001
From: Steve Dower
Date: Thu, 16 Mar 2017 11:03:03 -0700
Subject: [PATCH 0049/1433] Takes vcruntime140.dll from the correct source.
(#684)
---
Tools/msi/make_zip.proj | 9 +++------
Tools/nuget/make_pkg.proj | 8 +++-----
2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/Tools/msi/make_zip.proj b/Tools/msi/make_zip.proj
index f78e6ffa28..b3588b7a0b 100644
--- a/Tools/msi/make_zip.proj
+++ b/Tools/msi/make_zip.proj
@@ -17,15 +17,12 @@
rmdir /q/s "$(IntermediateOutputPath)\zip_$(ArchName)"
"$(PythonExe)" "$(MSBuildThisFileDirectory)\make_zip.py"
$(Arguments) -e -o "$(TargetPath)" -t "$(IntermediateOutputPath)\zip_$(ArchName)" -a $(ArchName)
- set DOC_FILENAME=python$(PythonVersion).chm
-set VCREDIST_PATH=$(VS140COMNTOOLS)\..\..\VC\redist\$(Platform)\Microsoft.VC140.CRT
+ set DOC_FILENAME=python$(PythonVersion).chm
+ $(Environment)%0D%0Aset VCREDIST_PATH=$(CRTRedist)\$(Platform)
-
+
diff --git a/Tools/nuget/make_pkg.proj b/Tools/nuget/make_pkg.proj
index d7e932cee5..464ef0456a 100644
--- a/Tools/nuget/make_pkg.proj
+++ b/Tools/nuget/make_pkg.proj
@@ -34,9 +34,8 @@
$(NugetArguments) -Version "$(NuspecVersion)"
$(NugetArguments) -NoPackageAnalysis -NonInteractive
- setlocal
-set DOC_FILENAME=python$(PythonVersion).chm
-set VCREDIST_PATH=$(VS140COMNTOOLS)\..\..\VC\redist\$(Platform)\Microsoft.VC140.CRT
+ set DOC_FILENAME=python$(PythonVersion).chm
+ $(Environment)%0D%0Aset VCREDIST_PATH=$(CRTRedist)\$(Platform)
@@ -45,8 +44,7 @@ set VCREDIST_PATH=$(VS140COMNTOOLS)\..\..\VC\redist\$(Platform)\Microsoft.VC140.
-
+
--
GitLab
From 3fce38c540681a736b7e5ca7611758f7bc159c9e Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 16 Mar 2017 19:56:56 -0700
Subject: [PATCH 0050/1433] bpo-29820: othergui.rst: Remove outdated
information (GH-685) (GH-688)
(cherry picked from commit 1bb0f3762ec5104014aeed0ae6e9d64598d8fcac)
---
Doc/library/othergui.rst | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/Doc/library/othergui.rst b/Doc/library/othergui.rst
index ee1ce50b6b..d40abe1676 100644
--- a/Doc/library/othergui.rst
+++ b/Doc/library/othergui.rst
@@ -9,14 +9,15 @@ available for Python:
.. seealso::
`PyGObject `_
- provides introspection bindings for C libraries using
+ PyGObject provides introspection bindings for C libraries using
`GObject `_. One of
these libraries is the `GTK+ 3 `_ widget set.
GTK+ comes with many more widgets than Tkinter provides. An online
`Python GTK+ 3 Tutorial `_
is available.
- `PyGTK `_ provides bindings for an older version
+ `PyGTK `_
+ PyGTK provides bindings for an older version
of the library, GTK+ 2. It provides an object oriented interface that
is slightly higher level than the C one. There are also bindings to
`GNOME `_. An online `tutorial
@@ -27,15 +28,10 @@ available for Python:
extensive C++ GUI application development framework that is
available for Unix, Windows and Mac OS X. :program:`sip` is a tool
for generating bindings for C++ libraries as Python classes, and
- is specifically designed for Python. The *PyQt3* bindings have a
- book, `GUI Programming with Python: QT Edition
- `_ by Boudewijn
- Rempt. The *PyQt4* bindings also have a book, `Rapid GUI Programming
- with Python and Qt `_, by Mark
- Summerfield.
+ is specifically designed for Python.
`PySide `_
- is a newer binding to the Qt toolkit, provided by Nokia.
+ PySide is a newer binding to the Qt toolkit, provided by Nokia.
Compared to PyQt, its licensing scheme is friendlier to non-open source
applications.
@@ -49,9 +45,7 @@ available for Python:
documentation and context sensitive help, printing, HTML viewing,
low-level device context drawing, drag and drop, system clipboard access,
an XML-based resource format and more, including an ever growing library
- of user-contributed modules. wxPython has a book, `wxPython in Action
- `_, by Noel Rappin and
- Robin Dunn.
+ of user-contributed modules.
PyGTK, PyQt, and wxPython, all have a modern look and feel and more
widgets than Tkinter. In addition, there are many other GUI toolkits for
--
GitLab
From 4ac01f0ff3e3c9c02f5cc8c55f2fbe4639808f5e Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 16 Mar 2017 20:58:42 -0700
Subject: [PATCH 0051/1433] update test_socket AEAD test for kernel 4.9 and up
(GH-133) (GH-548)
(cherry picked from commit 9764c151c51480a7ca6042b1ccd69be2620ff360)
---
Lib/test/test_socket.py | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 5315d475df..1508f20c9f 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -5479,7 +5479,7 @@ class LinuxKernelCryptoAPI(unittest.TestCase):
self.assertEqual(len(dec), msglen * multiplier)
self.assertEqual(dec, msg * multiplier)
- @support.requires_linux_version(4, 3) # see test_aes_cbc
+ @support.requires_linux_version(4, 9) # see issue29324
def test_aead_aes_gcm(self):
key = bytes.fromhex('c939cc13397c1d37de6ae0e1cb7c423c')
iv = bytes.fromhex('b3d8cc017cbb89b39e0f67e2')
@@ -5502,8 +5502,7 @@ class LinuxKernelCryptoAPI(unittest.TestCase):
op.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT, iv=iv,
assoclen=assoclen, flags=socket.MSG_MORE)
op.sendall(assoc, socket.MSG_MORE)
- op.sendall(plain, socket.MSG_MORE)
- op.sendall(b'\x00' * taglen)
+ op.sendall(plain)
res = op.recv(assoclen + len(plain) + taglen)
self.assertEqual(expected_ct, res[assoclen:-taglen])
self.assertEqual(expected_tag, res[-taglen:])
@@ -5511,7 +5510,7 @@ class LinuxKernelCryptoAPI(unittest.TestCase):
# now with msg
op, _ = algo.accept()
with op:
- msg = assoc + plain + b'\x00' * taglen
+ msg = assoc + plain
op.sendmsg_afalg([msg], op=socket.ALG_OP_ENCRYPT, iv=iv,
assoclen=assoclen)
res = op.recv(assoclen + len(plain) + taglen)
@@ -5522,7 +5521,7 @@ class LinuxKernelCryptoAPI(unittest.TestCase):
pack_uint32 = struct.Struct('I').pack
op, _ = algo.accept()
with op:
- msg = assoc + plain + b'\x00' * taglen
+ msg = assoc + plain
op.sendmsg(
[msg],
([socket.SOL_ALG, socket.ALG_SET_OP, pack_uint32(socket.ALG_OP_ENCRYPT)],
@@ -5530,7 +5529,7 @@ class LinuxKernelCryptoAPI(unittest.TestCase):
[socket.SOL_ALG, socket.ALG_SET_AEAD_ASSOCLEN, pack_uint32(assoclen)],
)
)
- res = op.recv(len(msg))
+ res = op.recv(len(msg) + taglen)
self.assertEqual(expected_ct, res[assoclen:-taglen])
self.assertEqual(expected_tag, res[-taglen:])
@@ -5540,8 +5539,8 @@ class LinuxKernelCryptoAPI(unittest.TestCase):
msg = assoc + expected_ct + expected_tag
op.sendmsg_afalg([msg], op=socket.ALG_OP_DECRYPT, iv=iv,
assoclen=assoclen)
- res = op.recv(len(msg))
- self.assertEqual(plain, res[assoclen:-taglen])
+ res = op.recv(len(msg) - taglen)
+ self.assertEqual(plain, res[assoclen:])
@support.requires_linux_version(4, 3) # see test_aes_cbc
def test_drbg_pr_sha256(self):
--
GitLab
From 7c2081122c2a6b8ea27c3111da7f19f7824fe18a Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 16 Mar 2017 20:59:36 -0700
Subject: [PATCH 0052/1433] Add sockaddr_alg to sock_addr_t (GH-234) (GH-533)
(cherry picked from commit d37c068e695f8ec72b5c1b5a5a5ece2337fda768)
---
Modules/socketmodule.c | 30 ------------------------------
Modules/socketmodule.h | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 30 deletions(-)
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index f4edc062fd..f3654c97e7 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -288,36 +288,6 @@ http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getaddrinfo.c.diff?r1=1.82&
#include
#endif
-#ifdef HAVE_SOCKADDR_ALG
-#include
-#ifndef AF_ALG
-#define AF_ALG 38
-#endif
-#ifndef SOL_ALG
-#define SOL_ALG 279
-#endif
-
-/* Linux 3.19 */
-#ifndef ALG_SET_AEAD_ASSOCLEN
-#define ALG_SET_AEAD_ASSOCLEN 4
-#endif
-#ifndef ALG_SET_AEAD_AUTHSIZE
-#define ALG_SET_AEAD_AUTHSIZE 5
-#endif
-/* Linux 4.8 */
-#ifndef ALG_SET_PUBKEY
-#define ALG_SET_PUBKEY 6
-#endif
-
-#ifndef ALG_OP_SIGN
-#define ALG_OP_SIGN 2
-#endif
-#ifndef ALG_OP_VERIFY
-#define ALG_OP_VERIFY 3
-#endif
-
-#endif /* HAVE_SOCKADDR_ALG */
-
/* Generic socket object definitions and includes */
#define PySocket_BUILDING_SOCKET
#include "socketmodule.h"
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index 3cce927e0b..03f982b910 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -98,6 +98,37 @@ typedef int socklen_t;
#include
#endif
+#ifdef HAVE_SOCKADDR_ALG
+#include
+#ifndef AF_ALG
+#define AF_ALG 38
+#endif
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+/* Linux 3.19 */
+#ifndef ALG_SET_AEAD_ASSOCLEN
+#define ALG_SET_AEAD_ASSOCLEN 4
+#endif
+#ifndef ALG_SET_AEAD_AUTHSIZE
+#define ALG_SET_AEAD_AUTHSIZE 5
+#endif
+/* Linux 4.8 */
+#ifndef ALG_SET_PUBKEY
+#define ALG_SET_PUBKEY 6
+#endif
+
+#ifndef ALG_OP_SIGN
+#define ALG_OP_SIGN 2
+#endif
+#ifndef ALG_OP_VERIFY
+#define ALG_OP_VERIFY 3
+#endif
+
+#endif /* HAVE_SOCKADDR_ALG */
+
+
#ifndef Py__SOCKET_H
#define Py__SOCKET_H
#ifdef __cplusplus
@@ -159,6 +190,9 @@ typedef union sock_addr {
#ifdef HAVE_SYS_KERN_CONTROL_H
struct sockaddr_ctl ctl;
#endif
+#ifdef HAVE_SOCKADDR_ALG
+ struct sockaddr_alg alg;
+#endif
} sock_addr_t;
/* The object holding a socket. It holds some extra information,
--
GitLab
From 948171bf999cf8b3e12048851041d2e04ae3a78c Mon Sep 17 00:00:00 2001
From: Berker Peksag
Date: Fri, 17 Mar 2017 14:59:16 +0300
Subject: [PATCH 0053/1433] bpo-16355: Clarify when inspect.getcomments()
returns None (#428) (#690)
Initial patch by Vajrasky Kok.
(cherry picked from commit 3f2155ffe683080f2a1b28408fa48d43ba92f943)
---
Doc/library/inspect.rst | 4 +++-
Lib/test/test_inspect.py | 5 +++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst
index 3fa44a0c99..4ff2187b45 100644
--- a/Doc/library/inspect.rst
+++ b/Doc/library/inspect.rst
@@ -442,7 +442,9 @@ Retrieving source code
Return in a single string any lines of comments immediately preceding the
object's source code (for a class, function, or method), or at the top of the
- Python source file (if the object is a module).
+ Python source file (if the object is a module). If the object's source code
+ is unavailable, return ``None``. This could happen if the object has been
+ defined in C or the interactive shell.
.. function:: getfile(object)
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index 88eaabe676..cfea281c70 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -387,6 +387,11 @@ class TestRetrievingSourceCode(GetSourceBase):
def test_getcomments(self):
self.assertEqual(inspect.getcomments(mod), '# line 1\n')
self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
+ # If the object source file is not available, return None.
+ co = compile('x=1', '_non_existing_filename.py', 'exec')
+ self.assertIsNone(inspect.getcomments(co))
+ # If the object has been defined in C, return None.
+ self.assertIsNone(inspect.getcomments(list))
def test_getmodule(self):
# Check actual module
--
GitLab
From 46e81d3345b979f835740a228857906dca0f59c0 Mon Sep 17 00:00:00 2001
From: Vinay Sajip
Date: Fri, 17 Mar 2017 19:52:56 +0000
Subject: [PATCH 0054/1433] bpo-29808: Do not fail in SysLogHandler constructor
if syslog isn't available. (#696)
bpo-29808: SysLogHandler: Do not fail if initial connect to syslog failed.
(cherry picked from commit 1b038e073807ecb6fd176edaf3386a8e3205416e)
---
Lib/logging/handlers.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
index 7d779734f3..2356f8d3d2 100644
--- a/Lib/logging/handlers.py
+++ b/Lib/logging/handlers.py
@@ -815,7 +815,14 @@ class SysLogHandler(logging.Handler):
if isinstance(address, str):
self.unixsocket = True
- self._connect_unixsocket(address)
+ # Syslog server may be unavailable during handler initialisation.
+ # C's openlog() function also ignores connection errors.
+ # Moreover, we ignore these errors while logging, so it not worse
+ # to ignore it also here.
+ try:
+ self._connect_unixsocket(address)
+ except OSError:
+ pass
else:
self.unixsocket = False
if socktype is None:
--
GitLab
From 49fc153342f98e0d4ae5a96b88f3e91e4c5861d7 Mon Sep 17 00:00:00 2001
From: Brett Cannon
Date: Fri, 17 Mar 2017 15:41:35 -0700
Subject: [PATCH 0055/1433] Combine the C++ header CI build into the main C
build (GH-697) (GH-704)
This will eliminate one of the builds in Travis, allowing for CI overall to complete faster.
(cherry picked from commit 993d4b3440f2282976901ce66879037c4443868a)
---
.travis.yml | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 27b63c6c08..36961e3879 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -64,15 +64,6 @@ matrix:
# Make the `coverage` command available to Codecov w/ a version of Python that can parse all source files.
- source ./venv/bin/activate
- bash <(curl -s https://codecov.io/bash)
- - os: linux
- language: cpp
- compiler: clang
- env:
- - TESTING="C++ header compatibility"
- before_script:
- - ./configure
- script:
- - echo '#include "Python.h"' > test.cc && $CXX -c test.cc -o /dev/null -I ./Include -I .
# Travis provides only 2 cores, so don't overdue the parallelism and waste memory.
before_script:
@@ -88,6 +79,8 @@ before_script:
script:
# `-r -w` implicitly provided through `make buildbottest`.
- make buildbottest TESTOPTS="-j4"
+ # Test for C++ header compatibility.
+ - echo '#include "Python.h"' > test.cc && $CXX -c test.cc -o /dev/null -I ./Include -I .
notifications:
email: false
--
GitLab
From b044120f048571030552eefab8ba2329a9e76ceb Mon Sep 17 00:00:00 2001
From: Brett Cannon
Date: Sun, 19 Mar 2017 10:03:39 -0700
Subject: [PATCH 0056/1433] Drop C++ header compatibility test (#718) (#719)
The $CXX environment variable is not exported under the 'c' language on Travis.
(cherry picked from commit 77ed11552da3e01dd235b7d68988076866b1f604)
---
.travis.yml | 2 --
1 file changed, 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 36961e3879..66f03dc716 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -79,8 +79,6 @@ before_script:
script:
# `-r -w` implicitly provided through `make buildbottest`.
- make buildbottest TESTOPTS="-j4"
- # Test for C++ header compatibility.
- - echo '#include "Python.h"' > test.cc && $CXX -c test.cc -o /dev/null -I ./Include -I .
notifications:
email: false
--
GitLab
From 69eab3123ed1de4bed4b7dedecabe415f6139bb6 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sun, 19 Mar 2017 20:26:26 +0200
Subject: [PATCH 0057/1433] bpo-28749: Fixed the documentation of the mapping
codec APIs. (#487) (#714)
Added the documentation for PyUnicode_Translate().
(cherry picked from commit c85a26628ceb9624c96c3064e8b99033c026d8a3)
---
Doc/c-api/unicode.rst | 95 +++++++++++++++++++++--------------------
Include/unicodeobject.h | 45 ++++++++-----------
2 files changed, 66 insertions(+), 74 deletions(-)
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
index 02f7ada7be..6e91576ee8 100644
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -1393,77 +1393,78 @@ Character Map Codecs
This codec is special in that it can be used to implement many different codecs
(and this is in fact what was done to obtain most of the standard codecs
included in the :mod:`encodings` package). The codec uses mapping to encode and
-decode characters.
-
-Decoding mappings must map single string characters to single Unicode
-characters, integers (which are then interpreted as Unicode ordinals) or ``None``
-(meaning "undefined mapping" and causing an error).
-
-Encoding mappings must map single Unicode characters to single string
-characters, integers (which are then interpreted as Latin-1 ordinals) or ``None``
-(meaning "undefined mapping" and causing an error).
-
-The mapping objects provided must only support the __getitem__ mapping
-interface.
-
-If a character lookup fails with a LookupError, the character is copied as-is
-meaning that its ordinal value will be interpreted as Unicode or Latin-1 ordinal
-resp. Because of this, mappings only need to contain those mappings which map
-characters to different code points.
+decode characters. The mapping objects provided must support the
+:meth:`__getitem__` mapping interface; dictionaries and sequences work well.
These are the mapping codec APIs:
-.. c:function:: PyObject* PyUnicode_DecodeCharmap(const char *s, Py_ssize_t size, \
+.. c:function:: PyObject* PyUnicode_DecodeCharmap(const char *data, Py_ssize_t size, \
PyObject *mapping, const char *errors)
- Create a Unicode object by decoding *size* bytes of the encoded string *s* using
- the given *mapping* object. Return *NULL* if an exception was raised by the
- codec. If *mapping* is *NULL* latin-1 decoding will be done. Else it can be a
- dictionary mapping byte or a unicode string, which is treated as a lookup table.
- Byte values greater that the length of the string and U+FFFE "characters" are
- treated as "undefined mapping".
+ Create a Unicode object by decoding *size* bytes of the encoded string *s*
+ using the given *mapping* object. Return *NULL* if an exception was raised
+ by the codec.
+
+ If *mapping* is *NULL*, Latin-1 decoding will be applied. Else
+ *mapping* must map bytes ordinals (integers in the range from 0 to 255)
+ to Unicode strings, integers (which are then interpreted as Unicode
+ ordinals) or ``None``. Unmapped data bytes -- ones which cause a
+ :exc:`LookupError`, as well as ones which get mapped to ``None``,
+ ``0xFFFE`` or ``'\ufffe'``, are treated as undefined mappings and cause
+ an error.
.. c:function:: PyObject* PyUnicode_AsCharmapString(PyObject *unicode, PyObject *mapping)
- Encode a Unicode object using the given *mapping* object and return the result
- as Python string object. Error handling is "strict". Return *NULL* if an
+ Encode a Unicode object using the given *mapping* object and return the
+ result as a bytes object. Error handling is "strict". Return *NULL* if an
exception was raised by the codec.
-The following codec API is special in that maps Unicode to Unicode.
-
+ The *mapping* object must map Unicode ordinal integers to bytes objects,
+ integers in the range from 0 to 255 or ``None``. Unmapped character
+ ordinals (ones which cause a :exc:`LookupError`) as well as mapped to
+ ``None`` are treated as "undefined mapping" and cause an error.
-.. c:function:: PyObject* PyUnicode_TranslateCharmap(const Py_UNICODE *s, Py_ssize_t size, \
- PyObject *table, const char *errors)
-
- Translate a :c:type:`Py_UNICODE` buffer of the given *size* by applying a
- character mapping *table* to it and return the resulting Unicode object. Return
- *NULL* when an exception was raised by the codec.
- The *mapping* table must map Unicode ordinal integers to Unicode ordinal
- integers or ``None`` (causing deletion of the character).
+.. c:function:: PyObject* PyUnicode_EncodeCharmap(const Py_UNICODE *s, Py_ssize_t size, \
+ PyObject *mapping, const char *errors)
- Mapping tables need only provide the :meth:`__getitem__` interface; dictionaries
- and sequences work well. Unmapped character ordinals (ones which cause a
- :exc:`LookupError`) are left untouched and are copied as-is.
+ Encode the :c:type:`Py_UNICODE` buffer of the given *size* using the given
+ *mapping* object and return the result as a bytes object. Return *NULL* if
+ an exception was raised by the codec.
.. deprecated-removed:: 3.3 4.0
Part of the old-style :c:type:`Py_UNICODE` API; please migrate to using
- :c:func:`PyUnicode_Translate`. or :ref:`generic codec based API
- `
+ :c:func:`PyUnicode_AsCharmapString` or
+ :c:func:`PyUnicode_AsEncodedString`.
-.. c:function:: PyObject* PyUnicode_EncodeCharmap(const Py_UNICODE *s, Py_ssize_t size, \
+The following codec API is special in that maps Unicode to Unicode.
+
+.. c:function:: PyObject* PyUnicode_Translate(PyObject *unicode, \
PyObject *mapping, const char *errors)
- Encode the :c:type:`Py_UNICODE` buffer of the given *size* using the given
- *mapping* object and return a Python string object. Return *NULL* if an
- exception was raised by the codec.
+ Translate a Unicode object using the given *mapping* object and return the
+ resulting Unicode object. Return *NULL* if an exception was raised by the
+ codec.
+
+ The *mapping* object must map Unicode ordinal integers to Unicode strings,
+ integers (which are then interpreted as Unicode ordinals) or ``None``
+ (causing deletion of the character). Unmapped character ordinals (ones
+ which cause a :exc:`LookupError`) are left untouched and are copied as-is.
+
+
+.. c:function:: PyObject* PyUnicode_TranslateCharmap(const Py_UNICODE *s, Py_ssize_t size, \
+ PyObject *mapping, const char *errors)
+
+ Translate a :c:type:`Py_UNICODE` buffer of the given *size* by applying a
+ character *mapping* table to it and return the resulting Unicode object.
+ Return *NULL* when an exception was raised by the codec.
.. deprecated-removed:: 3.3 4.0
Part of the old-style :c:type:`Py_UNICODE` API; please migrate to using
- :c:func:`PyUnicode_AsCharmapString` or
- :c:func:`PyUnicode_AsEncodedString`.
+ :c:func:`PyUnicode_Translate`. or :ref:`generic codec based API
+ `
MBCS codecs for Windows
diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h
index 587cf03e36..2d0d77e804 100644
--- a/Include/unicodeobject.h
+++ b/Include/unicodeobject.h
@@ -1609,50 +1609,41 @@ PyAPI_FUNC(PyObject*) PyUnicode_EncodeASCII(
This codec uses mappings to encode and decode characters.
- Decoding mappings must map single string characters to single
- Unicode characters, integers (which are then interpreted as Unicode
- ordinals) or None (meaning "undefined mapping" and causing an
- error).
-
- Encoding mappings must map single Unicode characters to single
- string characters, integers (which are then interpreted as Latin-1
- ordinals) or None (meaning "undefined mapping" and causing an
- error).
-
- If a character lookup fails with a LookupError, the character is
- copied as-is meaning that its ordinal value will be interpreted as
- Unicode or Latin-1 ordinal resp. Because of this mappings only need
- to contain those mappings which map characters to different code
- points.
+ Decoding mappings must map byte ordinals (integers in the range from 0 to
+ 255) to Unicode strings, integers (which are then interpreted as Unicode
+ ordinals) or None. Unmapped data bytes (ones which cause a LookupError)
+ as well as mapped to None, 0xFFFE or '\ufffe' are treated as "undefined
+ mapping" and cause an error.
+
+ Encoding mappings must map Unicode ordinal integers to bytes objects,
+ integers in the range from 0 to 255 or None. Unmapped character
+ ordinals (ones which cause a LookupError) as well as mapped to
+ None are treated as "undefined mapping" and cause an error.
*/
PyAPI_FUNC(PyObject*) PyUnicode_DecodeCharmap(
const char *string, /* Encoded string */
Py_ssize_t length, /* size of string */
- PyObject *mapping, /* character mapping
- (char ordinal -> unicode ordinal) */
+ PyObject *mapping, /* decoding mapping */
const char *errors /* error handling */
);
PyAPI_FUNC(PyObject*) PyUnicode_AsCharmapString(
PyObject *unicode, /* Unicode object */
- PyObject *mapping /* character mapping
- (unicode ordinal -> char ordinal) */
+ PyObject *mapping /* encoding mapping */
);
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject*) PyUnicode_EncodeCharmap(
const Py_UNICODE *data, /* Unicode char buffer */
Py_ssize_t length, /* Number of Py_UNICODE chars to encode */
- PyObject *mapping, /* character mapping
- (unicode ordinal -> char ordinal) */
+ PyObject *mapping, /* encoding mapping */
const char *errors /* error handling */
);
PyAPI_FUNC(PyObject*) _PyUnicode_EncodeCharmap(
PyObject *unicode, /* Unicode object */
- PyObject *mapping, /* character mapping
- (unicode ordinal -> char ordinal) */
+ PyObject *mapping, /* encoding mapping */
const char *errors /* error handling */
);
#endif
@@ -1661,8 +1652,8 @@ PyAPI_FUNC(PyObject*) _PyUnicode_EncodeCharmap(
character mapping table to it and return the resulting Unicode
object.
- The mapping table must map Unicode ordinal integers to Unicode
- ordinal integers or None (causing deletion of the character).
+ The mapping table must map Unicode ordinal integers to Unicode strings,
+ Unicode ordinal integers or None (causing deletion of the character).
Mapping tables may be dictionaries or sequences. Unmapped character
ordinals (ones which cause a LookupError) are left untouched and
@@ -1960,8 +1951,8 @@ PyAPI_FUNC(PyObject*) PyUnicode_RSplit(
/* Translate a string by applying a character mapping table to it and
return the resulting Unicode object.
- The mapping table must map Unicode ordinal integers to Unicode
- ordinal integers or None (causing deletion of the character).
+ The mapping table must map Unicode ordinal integers to Unicode strings,
+ Unicode ordinal integers or None (causing deletion of the character).
Mapping tables may be dictionaries or sequences. Unmapped character
ordinals (ones which cause a LookupError) are left untouched and
--
GitLab
From fca705d533970011e50b3f278aab81cead39b00d Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sun, 19 Mar 2017 20:27:16 +0200
Subject: [PATCH 0058/1433] bpo-25455: Fixed crashes in repr of recursive
buffered file-like objects. (#514) (#722)
(cherry picked from commit a5af6e1af77ee0f9294c5776478a9c24d9fbab94)
---
Lib/test/test_fileio.py | 8 +-
Lib/test/test_io.py | 20 +
Misc/NEWS | 800 +++++++++++++++++++++++++++++++++++++++
Modules/_io/bufferedio.c | 14 +-
Modules/_io/fileio.c | 16 +-
Modules/_io/textio.c | 23 +-
6 files changed, 872 insertions(+), 9 deletions(-)
diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py
index 3da210ae19..57a0265620 100644
--- a/Lib/test/test_fileio.py
+++ b/Lib/test/test_fileio.py
@@ -10,7 +10,7 @@ from weakref import proxy
from functools import wraps
from test.support import (TESTFN, TESTFN_UNICODE, check_warnings, run_unittest,
- make_bad_fd, cpython_only)
+ make_bad_fd, cpython_only, swap_attr)
from collections import UserList
import _io # C implementation of io
@@ -176,6 +176,12 @@ class AutoFileTests:
finally:
os.close(fd)
+ def testRecursiveRepr(self):
+ # Issue #25455
+ with swap_attr(self.f, 'name', self.f):
+ with self.assertRaises(RuntimeError):
+ repr(self.f) # Should not crash
+
def testErrors(self):
f = self.f
self.assertFalse(f.isatty())
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index aaa64eadff..8f895fe0bf 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -1014,6 +1014,16 @@ class CommonBufferedTests:
raw.name = b"dummy"
self.assertEqual(repr(b), "<%s name=b'dummy'>" % clsname)
+ def test_recursive_repr(self):
+ # Issue #25455
+ raw = self.MockRawIO()
+ b = self.tp(raw)
+ with support.swap_attr(raw, 'name', b):
+ try:
+ repr(b) # Should not crash
+ except RuntimeError:
+ pass
+
def test_flush_error_on_close(self):
# Test that buffered file is closed despite failed flush
# and that flush() is called before file closed.
@@ -2424,6 +2434,16 @@ class TextIOWrapperTest(unittest.TestCase):
t.buffer.detach()
repr(t) # Should not raise an exception
+ def test_recursive_repr(self):
+ # Issue #25455
+ raw = self.BytesIO()
+ t = self.TextIOWrapper(raw)
+ with support.swap_attr(raw, 'name', t):
+ try:
+ repr(t) # Should not crash
+ except RuntimeError:
+ pass
+
def test_line_buffering(self):
r = self.BytesIO()
b = self.BufferedWriter(r, 1000)
diff --git a/Misc/NEWS b/Misc/NEWS
index 03f70dc885..310e982d78 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -25,6 +25,806 @@ Core and Builtins
- bpo-29714: Fix a regression that bytes format may fail when containing zero
bytes inside.
+- bpo-29568: Escaped percent "%%" in the format string for classic string
+ formatting no longer allows any characters between two percents.
+
+- bpo-29714: Fix a regression that bytes format may fail when containing zero
+ bytes inside.
+
+- bpo-29695: bool(), float(), list() and tuple() no longer take keyword arguments.
+ The first argument of int() can now be passes only as positional argument.
+
+- bpo-20087: Prefer glibc's list of locale aliases to the X11 ones.
+
+- bpo-28893: Set correct __cause__ for errors about invalid awaitables
+ returned from __aiter__ and __anext__.
+
+- bpo-29683: Fixes to memory allocation in _PyCode_SetExtra. Patch by
+ Brian Coleman.
+
+- bpo-29684: Fix minor regression of PyEval_CallObjectWithKeywords.
+ It should raise TypeError when kwargs is not a dict. But it might
+ cause segv when args=NULL and kwargs is not a dict.
+
+- bpo-28598: Support __rmod__ for subclasses of str being called before
+ str.__mod__. Patch by Martijn Pieters.
+
+- bpo-29607: Fix stack_effect computation for CALL_FUNCTION_EX.
+ Patch by Matthieu Dartiailh.
+
+- bpo-29602: Fix incorrect handling of signed zeros in complex constructor for
+ complex subclasses and for inputs having a __complex__ method. Patch
+ by Serhiy Storchaka.
+
+- bpo-29347: Fixed possibly dereferencing undefined pointers
+ when creating weakref objects.
+
+- bpo-29463: Add ``docstring`` field to Module, ClassDef, FunctionDef,
+ and AsyncFunctionDef ast nodes. docstring is not first stmt in their body
+ anymore. It affects ``co_firstlineno`` and ``co_lnotab`` of code object
+ for module and class.
+
+- bpo-29438: Fixed use-after-free problem in key sharing dict.
+
+- bpo-29546: Set the 'path' and 'name' attribute on ImportError for ``from ... import ...``.
+
+- bpo-29546: Improve from-import error message with location
+
+- Issue #29319: Prevent RunMainFromImporter overwriting sys.path[0].
+
+- Issue #29337: Fixed possible BytesWarning when compare the code objects.
+ Warnings could be emitted at compile time.
+
+- Issue #29327: Fixed a crash when pass the iterable keyword argument to
+ sorted().
+
+- Issue #29034: Fix memory leak and use-after-free in os module (path_converter).
+
+- Issue #29159: Fix regression in bytes(x) when x.__index__() raises Exception.
+
+- Issue #29049: Call _PyObject_GC_TRACK() lazily when calling Python function.
+ Calling function is up to 5% faster.
+
+- Issue #28927: bytes.fromhex() and bytearray.fromhex() now ignore all ASCII
+ whitespace, not only spaces. Patch by Robert Xiao.
+
+- Issue #28932: Do not include if it does not exist.
+
+- Issue #25677: Correct the positioning of the syntax error caret for
+ indented blocks. Based on patch by Michael Layzell.
+
+- Issue #29000: Fixed bytes formatting of octals with zero padding in alternate
+ form.
+
+- Issue #18896: Python function can now have more than 255 parameters.
+ collections.namedtuple() now supports tuples with more than 255 elements.
+
+- Issue #28596: The preferred encoding is UTF-8 on Android. Patch written by
+ Chi Hsuan Yen.
+
+- Issue #26919: On Android, operating system data is now always encoded/decoded
+ to/from UTF-8, instead of the locale encoding to avoid inconsistencies with
+ os.fsencode() and os.fsdecode() which are already using UTF-8.
+
+- Issue #28991: functools.lru_cache() was susceptible to an obscure reentrancy
+ bug triggerable by a monkey-patched len() function.
+
+- Issue #28147: Fix a memory leak in split-table dictionaries: setattr()
+ must not convert combined table into split table. Patch written by INADA
+ Naoki.
+
+- Issue #28739: f-string expressions are no longer accepted as docstrings and
+ by ast.literal_eval() even if they do not include expressions.
+
+- Issue #28512: Fixed setting the offset attribute of SyntaxError by
+ PyErr_SyntaxLocationEx() and PyErr_SyntaxLocationObject().
+
+- Issue #28918: Fix the cross compilation of xxlimited when Python has been
+ built with Py_DEBUG defined.
+
+- Issue #23722: Rather than silently producing a class that doesn't support
+ zero-argument ``super()`` in methods, failing to pass the new
+ ``__classcell__`` namespace entry up to ``type.__new__`` now results in a
+ ``DeprecationWarning`` and a class that supports zero-argument ``super()``.
+
+- Issue #28797: Modifying the class __dict__ inside the __set_name__ method of
+ a descriptor that is used inside that class no longer prevents calling the
+ __set_name__ method of other descriptors.
+
+- Issue #28799: Remove the ``PyEval_GetCallStats()`` function and deprecate
+ the untested and undocumented ``sys.callstats()`` function. Remove the
+ ``CALL_PROFILE`` special build: use the :func:`sys.setprofile` function,
+ :mod:`cProfile` or :mod:`profile` to profile function calls.
+
+- Issue #12844: More than 255 arguments can now be passed to a function.
+
+- Issue #28782: Fix a bug in the implementation ``yield from`` when checking
+ if the next instruction is YIELD_FROM. Regression introduced by WORDCODE
+ (issue #26647).
+
+- Issue #28774: Fix error position of the unicode error in ASCII and Latin1
+ encoders when a string returned by the error handler contains multiple
+ non-encodable characters (non-ASCII for the ASCII codec, characters out
+ of the U+0000-U+00FF range for Latin1).
+
+- Issue #28731: Optimize _PyDict_NewPresized() to create correct size dict.
+ Improve speed of dict literal with constant keys up to 30%.
+
+- Issue #28532: Show sys.version when -V option is supplied twice.
+
+- Issue #27100: The with-statement now checks for __enter__ before it
+ checks for __exit__. This gives less confusing error messages when
+ both methods are missing. Patch by Jonathan Ellington.
+
+- Issue #28746: Fix the set_inheritable() file descriptor method on platforms
+ that do not have the ioctl FIOCLEX and FIONCLEX commands.
+
+- Issue #26920: Fix not getting the locale's charset upon initializing the
+ interpreter, on platforms that do not have langinfo.
+
+- Issue #28648: Fixed crash in Py_DecodeLocale() in debug build on Mac OS X
+ when decode astral characters. Patch by Xiang Zhang.
+
+- Issue #28665: Improve speed of the STORE_DEREF opcode by 40%.
+
+- Issue #19398: Extra slash no longer added to sys.path components in case of
+ empty compile-time PYTHONPATH components.
+
+- Issue #28621: Sped up converting int to float by reusing faster bits counting
+ implementation. Patch by Adrian Wielgosik.
+
+- Issue #28580: Optimize iterating split table values.
+ Patch by Xiang Zhang.
+
+- Issue #28583: PyDict_SetDefault didn't combine split table when needed.
+ Patch by Xiang Zhang.
+
+- Issue #28128: Deprecation warning for invalid str and byte escape
+ sequences now prints better information about where the error
+ occurs. Patch by Serhiy Storchaka and Eric Smith.
+
+- Issue #28509: dict.update() no longer allocate unnecessary large memory.
+
+- Issue #28426: Fixed potential crash in PyUnicode_AsDecodedObject() in debug
+ build.
+
+- Issue #28517: Fixed of-by-one error in the peephole optimizer that caused
+ keeping unreachable code.
+
+- Issue #28214: Improved exception reporting for problematic __set_name__
+ attributes.
+
+- Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception
+ loss in PyTraceBack_Here().
+
+- Issue #28183: Optimize and cleanup dict iteration.
+
+- Issue #26081: Added C implementation of asyncio.Future.
+ Original patch by Yury Selivanov.
+
+- Issue #28379: Added sanity checks and tests for PyUnicode_CopyCharacters().
+ Patch by Xiang Zhang.
+
+- Issue #28376: The type of long range iterator is now registered as Iterator.
+ Patch by Oren Milman.
+
+- Issue #28376: Creating instances of range_iterator by calling range_iterator
+ type now is disallowed. Calling iter() on range instance is the only way.
+ Patch by Oren Milman.
+
+- Issue #26906: Resolving special methods of uninitialized type now causes
+ implicit initialization of the type instead of a fail.
+
+- Issue #18287: PyType_Ready() now checks that tp_name is not NULL.
+ Original patch by Niklas Koep.
+
+- Issue #24098: Fixed possible crash when AST is changed in process of
+ compiling it.
+
+- Issue #28201: Dict reduces possibility of 2nd conflict in hash table when
+ hashes have same lower bits.
+
+- Issue #28350: String constants with null character no longer interned.
+
+- Issue #26617: Fix crash when GC runs during weakref callbacks.
+
+- Issue #27942: String constants now interned recursively in tuples and frozensets.
+
+- Issue #28289: ImportError.__init__ now resets not specified attributes.
+
+- Issue #21578: Fixed misleading error message when ImportError called with
+ invalid keyword args.
+
+- Issue #28203: Fix incorrect type in complex(1.0, {2:3}) error message.
+ Patch by Soumya Sharma.
+
+- Issue #28086: Single var-positional argument of tuple subtype was passed
+ unscathed to the C-defined function. Now it is converted to exact tuple.
+
+- Issue #28214: Now __set_name__ is looked up on the class instead of the
+ instance.
+
+- Issue #27955: Fallback on reading /dev/urandom device when the getrandom()
+ syscall fails with EPERM, for example when blocked by SECCOMP.
+
+- Issue #28192: Don't import readline in isolated mode.
+
+- Issue #27441: Remove some redundant assignments to ob_size in longobject.c.
+ Thanks Oren Milman.
+
+- Issue #27222: Clean up redundant code in long_rshift function. Thanks
+ Oren Milman.
+
+- Upgrade internal unicode databases to Unicode version 9.0.0.
+
+- Issue #28131: Fix a regression in zipimport's compile_source(). zipimport
+ should use the same optimization level as the interpreter.
+
+- Issue #28126: Replace Py_MEMCPY with memcpy(). Visual Studio can properly
+ optimize memcpy().
+
+- Issue #28120: Fix dict.pop() for splitted dictionary when trying to remove a
+ "pending key" (Not yet inserted in split-table). Patch by Xiang Zhang.
+
+- Issue #26182: Raise DeprecationWarning when async and await keywords are
+ used as variable/attribute/class/function name.
+
+- Issue #26182: Fix a refleak in code that raises DeprecationWarning.
+
+- Issue #28721: Fix asynchronous generators aclose() and athrow() to
+ handle StopAsyncIteration propagation properly.
+
+- Issue #26110: Speed-up method calls: add LOAD_METHOD and CALL_METHOD
+ opcodes.
+
+Extension Modules
+-----------------
+
+- Issue #29169: Update zlib to 1.2.11.
+
+Library
+-------
+
+- bpo-25455: Fixed crashes in repr of recursive buffered file-like objects.
+
+- bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords
+ are not strings. Patch by Michael Seifert.
+
+- bpo-8256: Fixed possible failing or crashing input() if attributes "encoding"
+ or "errors" of sys.stdin or sys.stdout are not set or are not strings.
+
+- bpo-28692: Using non-integer value for selecting a plural form in gettext is
+ now deprecated.
+
+- bpo-26121: Use C library implementation for math functions erf() and erfc().
+
+- bpo-29619: os.stat() and os.DirEntry.inode() now convert inode (st_ino) using
+ unsigned integers.
+
+- bpo-28298: Fix a bug that prevented array 'Q', 'L' and 'I' from accepting big
+ intables (objects that have __int__) as elements.
+
+- bpo-29645: Speed up importing the webbrowser module. webbrowser.register()
+ is now thread-safe.
+
+- bpo-28231: The zipfile module now accepts path-like objects for external
+ paths.
+
+- bpo-26915: index() and count() methods of collections.abc.Sequence now
+ check identity before checking equality when do comparisons.
+
+- bpo-28682: Added support for bytes paths in os.fwalk().
+
+- bpo-29623: Allow use of path-like object as a single argument in
+ ConfigParser.read(). Patch by David Ellis.
+
+- bpo-9303: Migrate sqlite3 module to _v2 API. Patch by Aviv Palivoda.
+
+- bpo-28963: Fix out of bound iteration in asyncio.Future.remove_done_callback
+ implemented in C.
+
+- bpo-29704: asyncio.subprocess.SubprocessStreamProtocol no longer closes before
+ all pipes are closed.
+
+- bpo-29271: Fix Task.current_task and Task.all_tasks implemented in C
+ to accept None argument as their pure Python implementation.
+
+- bpo-29703: Fix asyncio to support instantiation of new event loops
+ in child processes.
+
+- bpo-29615: SimpleXMLRPCDispatcher no longer chains KeyError (or any other
+ exception) to exception(s) raised in the dispatched methods.
+ Patch by Petr Motejlek.
+
+- bpo-7769: Method register_function() of xmlrpc.server.SimpleXMLRPCDispatcher
+ and its subclasses can now be used as a decorator.
+
+- bpo-29376: Fix assertion error in threading._DummyThread.is_alive().
+
+- bpo-28624: Add a test that checks that cwd parameter of Popen() accepts
+ PathLike objects. Patch by Sayan Chowdhury.
+
+- bpo-28518: Start a transaction implicitly before a DML statement.
+ Patch by Aviv Palivoda.
+
+- bpo-29742: get_extra_info() raises exception if get called on closed ssl transport.
+ Patch by Nikolay Kim.
+
+- Issue #16285: urrlib.parse.quote is now based on RFC 3986 and hence includes
+ '~' in the set of characters that is not quoted by default. Patch by
+ Christian Theune and Ratnadeep Debnath.
+
+- bpo-29532: Altering a kwarg dictionary passed to functools.partial()
+ no longer affects a partial object after creation.
+
+- bpo-29110: Fix file object leak in aifc.open() when file is given as a
+ filesystem path and is not in valid AIFF format. Patch by Anthony Zhang.
+
+- bpo-22807: Add uuid.SafeUUID and uuid.UUID.is_safe to relay information from
+ the platform about whether generated UUIDs are generated with a
+ multiprocessing safe method.
+
+- bpo-29576: Improve some deprecations in importlib. Some deprecated methods
+ now emit DeprecationWarnings and have better descriptive messages.
+
+- bpo-29534: Fixed different behaviour of Decimal.from_float()
+ for _decimal and _pydecimal. Thanks Andrew Nester.
+
+- Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap,
+ improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi,
+ Manuel Krebber, and Łukasz Langa.
+
+- Issue #29100: Fix datetime.fromtimestamp() regression introduced in Python
+ 3.6.0: check minimum and maximum years.
+
+- Issue #29416: Prevent infinite loop in pathlib.Path.mkdir
+
+- Issue #29444: Fixed out-of-bounds buffer access in the group() method of
+ the match object. Based on patch by WGH.
+
+- Issue #29377: Add SlotWrapperType, MethodWrapperType, and
+ MethodDescriptorType built-in types to types module.
+ Original patch by Manuel Krebber.
+
+- Issue #29218: Unused install_misc command is now removed. It has been
+ documented as unused since 2000. Patch by Eric N. Vander Weele.
+
+- Issue #29368: The extend() method is now called instead of the append()
+ method when unpickle collections.deque and other list-like objects.
+ This can speed up unpickling to 2 times.
+
+- Issue #29338: The help of a builtin or extension class now includes the
+ constructor signature if __text_signature__ is provided for the class.
+
+- Issue #29335: Fix subprocess.Popen.wait() when the child process has
+ exited to a stopped instead of terminated state (ex: when under ptrace).
+
+- Issue #29290: Fix a regression in argparse that help messages would wrap at
+ non-breaking spaces.
+
+- Issue #28735: Fixed the comparison of mock.MagickMock with mock.ANY.
+
+- Issue #29197: Removed deprecated function ntpath.splitunc().
+
+- Issue #29210: Removed support of deprecated argument "exclude" in
+ tarfile.TarFile.add().
+
+- Issue #29219: Fixed infinite recursion in the repr of uninitialized
+ ctypes.CDLL instances.
+
+- Issue #29192: Removed deprecated features in the http.cookies module.
+
+- Issue #29193: A format string argument for string.Formatter.format()
+ is now positional-only.
+
+- Issue #29195: Removed support of deprecated undocumented keyword arguments
+ in methods of regular expression objects.
+
+- Issue #28969: Fixed race condition in C implementation of functools.lru_cache.
+ KeyError could be raised when cached function with full cache was
+ simultaneously called from differen threads with the same uncached arguments.
+
+- Issue #20804: The unittest.mock.sentinel attributes now preserve their
+ identity when they are copied or pickled.
+
+- Issue #29142: In urllib.request, suffixes in no_proxy environment variable with
+ leading dots could match related hostnames again (e.g. .b.c matches a.b.c).
+ Patch by Milan Oberkirch.
+
+- Issue #28961: Fix unittest.mock._Call helper: don't ignore the name parameter
+ anymore. Patch written by Jiajun Huang.
+
+- Issue #15812: inspect.getframeinfo() now correctly shows the first line of
+ a context. Patch by Sam Breese.
+
+- Issue #28985: Update authorizer constants in sqlite3 module.
+ Patch by Dingyuan Wang.
+
+- Issue #29094: Offsets in a ZIP file created with extern file object and modes
+ "w" and "x" now are relative to the start of the file.
+
+- Issue #29079: Prevent infinite loop in pathlib.resolve() on Windows
+
+- Issue #13051: Fixed recursion errors in large or resized
+ curses.textpad.Textbox. Based on patch by Tycho Andersen.
+
+- Issue #9770: curses.ascii predicates now work correctly with negative
+ integers.
+
+- Issue #28427: old keys should not remove new values from
+ WeakValueDictionary when collecting from another thread.
+
+- Issue 28923: Remove editor artifacts from Tix.py.
+
+- Issue #28871: Fixed a crash when deallocate deep ElementTree.
+
+- Issue #19542: Fix bugs in WeakValueDictionary.setdefault() and
+ WeakValueDictionary.pop() when a GC collection happens in another
+ thread.
+
+- Issue #20191: Fixed a crash in resource.prlimit() when passing a sequence that
+ doesn't own its elements as limits.
+
+- Issue #16255: subprocess.Popen uses /system/bin/sh on Android as the shell,
+ instead of /bin/sh.
+
+- Issue #28779: multiprocessing.set_forkserver_preload() would crash the
+ forkserver process if a preloaded module instantiated some
+ multiprocessing objects such as locks.
+
+- Issue #26937: The chown() method of the tarfile.TarFile class does not fail
+ now when the grp module cannot be imported, as for example on Android
+ platforms.
+
+- Issue #28847: dbm.dumb now supports reading read-only files and no longer
+ writes the index file when it is not changed. A deprecation warning is now
+ emitted if the index file is missed and recreated in the 'r' and 'w' modes
+ (will be an error in future Python releases).
+
+- Issue #27030: Unknown escapes consisting of ``'\'`` and an ASCII letter in
+ re.sub() replacement templates regular expressions now are errors.
+
+- Issue #28835: Fix a regression introduced in warnings.catch_warnings():
+ call warnings.showwarning() if it was overriden inside the context manager.
+
+- Issue #27172: To assist with upgrades from 2.7, the previously documented
+ deprecation of ``inspect.getfullargspec()`` has been reversed. This decision
+ may be revisited again after the Python 2.7 branch is no longer officially
+ supported.
+
+- Issue #28740: Add sys.getandroidapilevel(): return the build time API version
+ of Android as an integer. Function only available on Android.
+
+- Issue #26273: Add new :data:`socket.TCP_CONGESTION` (Linux 2.6.13) and
+ :data:`socket.TCP_USER_TIMEOUT` (Linux 2.6.37) constants. Patch written by
+ Omar Sandoval.
+
+- Issue #28752: Restored the __reduce__() methods of datetime objects.
+
+- Issue #28727: Regular expression patterns, _sre.SRE_Pattern objects created
+ by re.compile(), become comparable (only x==y and x!=y operators). This
+ change should fix the issue #18383: don't duplicate warning filters when the
+ warnings module is reloaded (thing usually only done in unit tests).
+
+- Issue #20572: Remove the subprocess.Popen.wait endtime parameter. It was
+ deprecated in 3.4 and undocumented prior to that.
+
+- Issue #25659: In ctypes, prevent a crash calling the from_buffer() and
+ from_buffer_copy() methods on abstract classes like Array.
+
+- Issue #28548: In the "http.server" module, parse the protocol version if
+ possible, to avoid using HTTP 0.9 in some error responses.
+
+- Issue #19717: Makes Path.resolve() succeed on paths that do not exist.
+ Patch by Vajrasky Kok
+
+- Issue #28563: Fixed possible DoS and arbitrary code execution when handle
+ plural form selections in the gettext module. The expression parser now
+ supports exact syntax supported by GNU gettext.
+
+- Issue #28387: Fixed possible crash in _io.TextIOWrapper deallocator when
+ the garbage collector is invoked in other thread. Based on patch by
+ Sebastian Cufre.
+
+- Issue #27517: LZMA compressor and decompressor no longer raise exceptions if
+ given empty data twice. Patch by Benjamin Fogle.
+
+- Issue #28549: Fixed segfault in curses's addch() with ncurses6.
+
+- Issue #28449: tarfile.open() with mode "r" or "r:" now tries to open a tar
+ file with compression before trying to open it without compression. Otherwise
+ it had 50% chance failed with ignore_zeros=True.
+
+- Issue #23262: The webbrowser module now supports Firefox 36+ and derived
+ browsers. Based on patch by Oleg Broytman.
+
+- Issue #24241: The webbrowser in an X environment now prefers using the
+ default browser directly. Also, the webbrowser register() function now has
+ a documented 'preferred' argument, to specify browsers to be returned by
+ get() with no arguments. Patch by David Steele
+
+- Issue #27939: Fixed bugs in tkinter.ttk.LabeledScale and tkinter.Scale caused
+ by representing the scale as float value internally in Tk. tkinter.IntVar
+ now works if float value is set to underlying Tk variable.
+
+- Issue #28255: calendar.TextCalendar.prweek() no longer prints a space after
+ a weeks's calendar. calendar.TextCalendar.pryear() no longer prints redundant
+ newline after a year's calendar. Based on patch by Xiang Zhang.
+
+- Issue #28255: calendar.TextCalendar.prmonth() no longer prints a space
+ at the start of new line after printing a month's calendar. Patch by
+ Xiang Zhang.
+
+- Issue #20491: The textwrap.TextWrapper class now honors non-breaking spaces.
+ Based on patch by Kaarle Ritvanen.
+
+- Issue #28353: os.fwalk() no longer fails on broken links.
+
+- Issue #28430: Fix iterator of C implemented asyncio.Future doesn't accept
+ non-None value is passed to it.send(val).
+
+- Issue #27025: Generated names for Tkinter widgets now start by the "!" prefix
+ for readability (was "`").
+
+- Issue #25464: Fixed HList.header_exists() in tkinter.tix module by addin
+ a workaround to Tix library bug.
+
+- Issue #28488: shutil.make_archive() no longer adds entry "./" to ZIP archive.
+
+- Issue #25953: re.sub() now raises an error for invalid numerical group
+ reference in replacement template even if the pattern is not found in
+ the string. Error message for invalid group reference now includes the
+ group index and the position of the reference.
+ Based on patch by SilentGhost.
+
+- Issue #28469: timeit now uses the sequence 1, 2, 5, 10, 20, 50,... instead
+ of 1, 10, 100,... for autoranging.
+
+- Issue #28115: Command-line interface of the zipfile module now uses argparse.
+ Added support of long options.
+
+- Issue #18219: Optimize csv.DictWriter for large number of columns.
+ Patch by Mariatta Wijaya.
+
+- Issue #28448: Fix C implemented asyncio.Future didn't work on Windows.
+
+- Issue #23214: In the "io" module, the argument to BufferedReader and
+ BytesIO's read1() methods is now optional and can be -1, matching the
+ BufferedIOBase specification.
+
+- Issue #28480: Fix error building socket module when multithreading is
+ disabled.
+
+- Issue #28240: timeit: remove ``-c/--clock`` and ``-t/--time`` command line
+ options which were deprecated since Python 3.3.
+
+- Issue #28240: timeit now repeats the benchmarks 5 times instead of only 3
+ to make benchmarks more reliable.
+
+- Issue #28240: timeit autorange now uses a single loop iteration if the
+ benchmark takes less than 10 seconds, instead of 10 iterations.
+ "python3 -m timeit -s 'import time' 'time.sleep(1)'" now takes 4 seconds
+ instead of 40 seconds.
+
+- Distutils.sdist now looks for README and setup.py files with case
+ sensitivity. This behavior matches that found in Setuptools 6.0 and
+ later. See `setuptools 100
+ `_ for rationale.
+
+- Issue #24452: Make webbrowser support Chrome on Mac OS X. Patch by
+ Ned Batchelder.
+
+- Issue #20766: Fix references leaked by pdb in the handling of SIGINT
+ handlers.
+
+- Issue #27998: Fixed bytes path support in os.scandir() on Windows.
+ Patch by Eryk Sun.
+
+- Issue #28317: The disassembler now decodes FORMAT_VALUE argument.
+
+- Issue #26293: Fixed writing ZIP files that starts not from the start of the
+ file. Offsets in ZIP file now are relative to the start of the archive in
+ conforming to the specification.
+
+- Issue #28380: unittest.mock Mock autospec functions now properly support
+ assert_called, assert_not_called, and assert_called_once.
+
+- Issue #28229: lzma module now supports pathlib.
+
+- Issue #28321: Fixed writing non-BMP characters with binary format in plistlib.
+
+- Issue #28225: bz2 module now supports pathlib. Initial patch by Ethan Furman.
+
+- Issue #28227: gzip now supports pathlib. Patch by Ethan Furman.
+
+- Issue #28332: Deprecated silent truncations in socket.htons and socket.ntohs.
+ Original patch by Oren Milman.
+
+- Issue #27358: Optimized merging var-keyword arguments and improved error
+ message when passing a non-mapping as a var-keyword argument.
+
+- Issue #28257: Improved error message when passing a non-iterable as
+ a var-positional argument. Added opcode BUILD_TUPLE_UNPACK_WITH_CALL.
+
+- Issue #28322: Fixed possible crashes when unpickle itertools objects from
+ incorrect pickle data. Based on patch by John Leitch.
+
+- Issue #28228: imghdr now supports pathlib.
+
+- Issue #28226: compileall now supports pathlib.
+
+- Issue #28314: Fix function declaration (C flags) for the getiterator() method
+ of xml.etree.ElementTree.Element.
+
+- Issue #28148: Stop using localtime() and gmtime() in the time
+ module.
+
+ Introduced platform independent _PyTime_localtime API that is
+ similar to POSIX localtime_r, but available on all platforms. Patch
+ by Ed Schouten.
+
+- Issue #28253: Fixed calendar functions for extreme months: 0001-01
+ and 9999-12.
+
+ Methods itermonthdays() and itermonthdays2() are reimplemented so
+ that they don't call itermonthdates() which can cause datetime.date
+ under/overflow.
+
+- Issue #28275: Fixed possible use after free in the decompress()
+ methods of the LZMADecompressor and BZ2Decompressor classes.
+ Original patch by John Leitch.
+
+- Issue #27897: Fixed possible crash in sqlite3.Connection.create_collation()
+ if pass invalid string-like object as a name. Patch by Xiang Zhang.
+
+- Issue #18844: random.choices() now has k as a keyword-only argument
+ to improve the readability of common cases and come into line
+ with the signature used in other languages.
+
+- Issue #18893: Fix invalid exception handling in Lib/ctypes/macholib/dyld.py.
+ Patch by Madison May.
+
+- Issue #27611: Fixed support of default root window in the tkinter.tix module.
+ Added the master parameter in the DisplayStyle constructor.
+
+- Issue #27348: In the traceback module, restore the formatting of exception
+ messages like "Exception: None". This fixes a regression introduced in
+ 3.5a2.
+
+- Issue #25651: Allow falsy values to be used for msg parameter of subTest().
+
+- Issue #27778: Fix a memory leak in os.getrandom() when the getrandom() is
+ interrupted by a signal and a signal handler raises a Python exception.
+
+- Issue #28200: Fix memory leak on Windows in the os module (fix
+ path_converter() function).
+
+- Issue #25400: RobotFileParser now correctly returns default values for
+ crawl_delay and request_rate. Initial patch by Peter Wirtz.
+
+- Issue #27932: Prevent memory leak in win32_ver().
+
+- Fix UnboundLocalError in socket._sendfile_use_sendfile.
+
+- Issue #28075: Check for ERROR_ACCESS_DENIED in Windows implementation of
+ os.stat(). Patch by Eryk Sun.
+
+- Issue #22493: Warning message emitted by using inline flags in the middle of
+ regular expression now contains a (truncated) regex pattern.
+ Patch by Tim Graham.
+
+- Issue #25270: Prevent codecs.escape_encode() from raising SystemError when
+ an empty bytestring is passed.
+
+- Issue #28181: Get antigravity over HTTPS. Patch by Kaartic Sivaraam.
+
+- Issue #25895: Enable WebSocket URL schemes in urllib.parse.urljoin.
+ Patch by Gergely Imreh and Markus Holtermann.
+
+- Issue #28114: Fix a crash in parse_envlist() when env contains byte strings.
+ Patch by Eryk Sun.
+
+- Issue #27599: Fixed buffer overrun in binascii.b2a_qp() and binascii.a2b_qp().
+
+- Issue #27906: Fix socket accept exhaustion during high TCP traffic.
+ Patch by Kevin Conway.
+
+- Issue #28174: Handle when SO_REUSEPORT isn't properly supported.
+ Patch by Seth Michael Larson.
+
+- Issue #26654: Inspect functools.partial in asyncio.Handle.__repr__.
+ Patch by iceboy.
+
+- Issue #26909: Fix slow pipes IO in asyncio.
+ Patch by INADA Naoki.
+
+- Issue #28176: Fix callbacks race in asyncio.SelectorLoop.sock_connect.
+
+- Issue #27759: Fix selectors incorrectly retain invalid file descriptors.
+ Patch by Mark Williams.
+
+- Issue #28325: Remove vestigial MacOS 9 macurl2path module and its tests.
+
+- Issue #28368: Refuse monitoring processes if the child watcher has
+ no loop attached.
+ Patch by Vincent Michel.
+
+- Issue #28369: Raise RuntimeError when transport's FD is used with
+ add_reader, add_writer, etc.
+
+- Issue #28370: Speedup asyncio.StreamReader.readexactly.
+ Patch by Коренберг Марк.
+
+- Issue #28371: Deprecate passing asyncio.Handles to run_in_executor.
+
+- Issue #28372: Fix asyncio to support formatting of non-python coroutines.
+
+- Issue #28399: Remove UNIX socket from FS before binding.
+ Patch by Коренберг Марк.
+
+- Issue #27972: Prohibit Tasks to await on themselves.
+
+- Issue #24142: Reading a corrupt config file left configparser in an
+ invalid state. Original patch by Florian Höch.
+
+- Issue #29581: ABCMeta.__new__ now accepts **kwargs, allowing abstract base
+ classes to use keyword parameters in __init_subclass__. Patch by Nate Soares.
+
+Windows
+-------
+
+- bpo-29579: Removes readme.txt from the installer.
+
+- Issue #25778: winreg does not truncate string correctly (Patch by Eryk Sun)
+
+- Issue #28896: Deprecate WindowsRegistryFinder and disable it by default
+
+- Issue #28522: Fixes mishandled buffer reallocation in getpathp.c
+
+- Issue #28402: Adds signed catalog files for stdlib on Windows.
+
+- Issue #28333: Enables Unicode for ps1/ps2 and input() prompts. (Patch by
+ Eryk Sun)
+
+- Issue #28251: Improvements to help manuals on Windows.
+
+- Issue #28110: launcher.msi has different product codes between 32-bit and
+ 64-bit
+
+- Issue #28161: Opening CON for write access fails
+
+- Issue #28162: WindowsConsoleIO readall() fails if first line starts with
+ Ctrl+Z
+
+- Issue #28163: WindowsConsoleIO fileno() passes wrong flags to
+ _open_osfhandle
+
+- Issue #28164: _PyIO_get_console_type fails for various paths
+
+- Issue #28137: Renames Windows path file to ._pth
+
+- Issue #28138: Windows ._pth file should allow import site
+
+C API
+-----
+
+- Issue #27867: Function PySlice_GetIndicesEx() is deprecated and replaced with
+ a macro if Py_LIMITED_API is not set or set to the value between 0x03050400
+ and 0x03060000 (not including) or 0x03060100 or higher. Added functions
+ PySlice_Unpack() and PySlice_AdjustIndices().
+
+- Issue #29083: Fixed the declaration of some public API functions.
+ PyArg_VaParse() and PyArg_VaParseTupleAndKeywords() were not available in
+ limited API. PyArg_ValidateKeywordArguments(), PyArg_UnpackTuple() and
+ Py_BuildValue() were not available in limited API of version < 3.3 when
+ PY_SSIZE_T_CLEAN is defined.
+
+- Issue #28769: The result of PyUnicode_AsUTF8AndSize() and PyUnicode_AsUTF8()
+ is now of type ``const char *`` rather of ``char *``.
+
+- Issue #29058: All stable API extensions added after Python 3.2 are now
+ available only when Py_LIMITED_API is set to the PY_VERSION_HEX value of
+ the minimum Python version supporting this API.
Library
-------
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index cbe7425eae..efc7d05b7d 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -1416,8 +1416,18 @@ buffered_repr(buffered *self)
res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
}
else {
- res = PyUnicode_FromFormat("<%s name=%R>",
- Py_TYPE(self)->tp_name, nameobj);
+ int status = Py_ReprEnter((PyObject *)self);
+ res = NULL;
+ if (status == 0) {
+ res = PyUnicode_FromFormat("<%s name=%R>",
+ Py_TYPE(self)->tp_name, nameobj);
+ Py_ReprLeave((PyObject *)self);
+ }
+ else if (status > 0) {
+ PyErr_Format(PyExc_RuntimeError,
+ "reentrant call inside %s.__repr__",
+ Py_TYPE(self)->tp_name);
+ }
Py_DECREF(nameobj);
}
return res;
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index 7f3bcab962..833ea8e7b5 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -1082,9 +1082,19 @@ fileio_repr(fileio *self)
self->fd, mode_string(self), self->closefd ? "True" : "False");
}
else {
- res = PyUnicode_FromFormat(
- "<_io.FileIO name=%R mode='%s' closefd=%s>",
- nameobj, mode_string(self), self->closefd ? "True" : "False");
+ int status = Py_ReprEnter((PyObject *)self);
+ res = NULL;
+ if (status == 0) {
+ res = PyUnicode_FromFormat(
+ "<_io.FileIO name=%R mode='%s' closefd=%s>",
+ nameobj, mode_string(self), self->closefd ? "True" : "False");
+ Py_ReprLeave((PyObject *)self);
+ }
+ else if (status > 0) {
+ PyErr_Format(PyExc_RuntimeError,
+ "reentrant call inside %s.__repr__",
+ Py_TYPE(self)->tp_name);
+ }
Py_DECREF(nameobj);
}
return res;
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 4df55626d4..bc8d11efa5 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -2483,6 +2483,7 @@ static PyObject *
textiowrapper_repr(textio *self)
{
PyObject *nameobj, *modeobj, *res, *s;
+ int status;
CHECK_INITIALIZED(self);
@@ -2490,6 +2491,15 @@ textiowrapper_repr(textio *self)
if (res == NULL)
return NULL;
+ status = Py_ReprEnter((PyObject *)self);
+ if (status != 0) {
+ if (status > 0) {
+ PyErr_Format(PyExc_RuntimeError,
+ "reentrant call inside %s.__repr__",
+ Py_TYPE(self)->tp_name);
+ }
+ goto error;
+ }
nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
if (nameobj == NULL) {
if (PyErr_ExceptionMatches(PyExc_Exception))
@@ -2504,7 +2514,7 @@ textiowrapper_repr(textio *self)
goto error;
PyUnicode_AppendAndDel(&res, s);
if (res == NULL)
- return NULL;
+ goto error;
}
modeobj = _PyObject_GetAttrId((PyObject *) self, &PyId_mode);
if (modeobj == NULL) {
@@ -2520,14 +2530,21 @@ textiowrapper_repr(textio *self)
goto error;
PyUnicode_AppendAndDel(&res, s);
if (res == NULL)
- return NULL;
+ goto error;
}
s = PyUnicode_FromFormat("%U encoding=%R>",
res, self->encoding);
Py_DECREF(res);
+ if (status == 0) {
+ Py_ReprLeave((PyObject *)self);
+ }
return s;
-error:
+
+ error:
Py_XDECREF(res);
+ if (status == 0) {
+ Py_ReprLeave((PyObject *)self);
+ }
return NULL;
}
--
GitLab
From da88596a19d2cad0e85a2b3c3290b5b1d97a793d Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sun, 19 Mar 2017 20:53:42 +0200
Subject: [PATCH 0059/1433] bpo-29845: Mark tests that use _testcapi as
CPython-only (#711) (#725)
(cherry picked from commit 24c738a9e91b8f46da6166663d8ce7ec18cec784)
---
Lib/ctypes/test/test_structures.py | 5 ++++-
Lib/test/test_atexit.py | 1 +
Lib/test/test_coroutines.py | 1 +
Lib/test/test_socket.py | 1 +
Lib/test/test_tracemalloc.py | 1 +
5 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py
index 3eded7749e..2e778fb1b4 100644
--- a/Lib/ctypes/test/test_structures.py
+++ b/Lib/ctypes/test/test_structures.py
@@ -2,8 +2,8 @@ import unittest
from ctypes import *
from ctypes.test import need_symbol
from struct import calcsize
-import _testcapi
import _ctypes_test
+import test.support
class SubclassesTest(unittest.TestCase):
def test_subclass(self):
@@ -202,7 +202,10 @@ class StructureTestCase(unittest.TestCase):
"_pack_": -1}
self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
+ @test.support.cpython_only
+ def test_packed_c_limits(self):
# Issue 15989
+ import _testcapi
d = {"_fields_": [("a", c_byte)],
"_pack_": _testcapi.INT_MAX + 1}
self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py
index 172bd25419..c761076c4a 100644
--- a/Lib/test/test_atexit.py
+++ b/Lib/test/test_atexit.py
@@ -143,6 +143,7 @@ class GeneralTest(unittest.TestCase):
self.assertEqual(l, [5])
+@support.cpython_only
class SubinterpreterTest(unittest.TestCase):
def test_callbacks_leak(self):
diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py
index a69583b5f9..2b79a17ea7 100644
--- a/Lib/test/test_coroutines.py
+++ b/Lib/test/test_coroutines.py
@@ -2117,6 +2117,7 @@ class SysSetCoroWrapperTest(unittest.TestCase):
sys.set_coroutine_wrapper(None)
+@support.cpython_only
class CAPITest(unittest.TestCase):
def test_tp_await_1(self):
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 1508f20c9f..2497e47c66 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -906,6 +906,7 @@ class GeneralModuleTests(unittest.TestCase):
self.assertEqual(swapped & mask, mask)
self.assertRaises(OverflowError, func, 1<<34)
+ @support.cpython_only
def testNtoHErrors(self):
good_values = [ 1, 2, 3, 1, 2, 3 ]
bad_values = [ -1, -2, -3, -1, -2, -3 ]
diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py
index 790ab7ee60..742259b439 100644
--- a/Lib/test/test_tracemalloc.py
+++ b/Lib/test/test_tracemalloc.py
@@ -865,6 +865,7 @@ class TestCommandLine(unittest.TestCase):
b'number of frames',
stderr)
+ @unittest.skipIf(_testcapi is None, 'need _testcapi')
def test_pymem_alloc0(self):
# Issue #21639: Check that PyMem_Malloc(0) with tracemalloc enabled
# does not crash.
--
GitLab
From 3d258b1eb453bcbc412d6b252f5bdceae0303f07 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sun, 19 Mar 2017 21:06:29 +0200
Subject: [PATCH 0060/1433] bpo-29116: Fix error messages for concatenating
bytes and bytearray with unsupported type. (#709) (#723)
(cherry picked from commit 6b5a9ec4788770c652bac3bf5d5a0a3b710b82ae)
---
Objects/bytearrayobject.c | 2 +-
Objects/bytesobject.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index a8d6980250..d456678d46 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -254,7 +254,7 @@ PyByteArray_Concat(PyObject *a, PyObject *b)
if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||
PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
- Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
+ Py_TYPE(b)->tp_name, Py_TYPE(a)->tp_name);
goto done;
}
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 30c1a7e245..c95a46d184 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -1438,7 +1438,7 @@ bytes_concat(PyObject *a, PyObject *b)
if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||
PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
- Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
+ Py_TYPE(b)->tp_name, Py_TYPE(a)->tp_name);
goto done;
}
--
GitLab
From d1f566f6bddc67e9870eaa75ae477208b9a199be Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sun, 19 Mar 2017 20:55:16 -0700
Subject: [PATCH 0061/1433] bpo-29856: Fix typo in curses documentation
(GH-730) (GH-731)
From Shifted Dxit -> Shifted Exit in Doc/library/curses.rst
(cherry picked from commit 64508780d72769e4c7afc67a511c057261c578f6)
---
Doc/library/curses.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst
index d746eafaea..d51085506c 100644
--- a/Doc/library/curses.rst
+++ b/Doc/library/curses.rst
@@ -1443,7 +1443,7 @@ The exact keycaps available are system dependent.
+-------------------+--------------------------------------------+
| ``KEY_SEOL`` | Shifted Clear line |
+-------------------+--------------------------------------------+
-| ``KEY_SEXIT`` | Shifted Dxit |
+| ``KEY_SEXIT`` | Shifted Exit |
+-------------------+--------------------------------------------+
| ``KEY_SFIND`` | Shifted Find |
+-------------------+--------------------------------------------+
--
GitLab
From 6fad4090ec9a27f8572bb00661b9890f01fb62f7 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Mon, 20 Mar 2017 09:13:47 +0200
Subject: [PATCH 0062/1433] bpo-28876: bool of large range raises OverflowError
(#699) (#734)
(cherry picked from commit e46fb8611867fa3b407a813f53137929b7cb4a10)
---
Lib/test/test_range.py | 17 +++++++++++++----
Misc/NEWS | 3 +++
Objects/rangeobject.c | 12 +++++++++++-
3 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py
index 9e11e518f6..679759ec6d 100644
--- a/Lib/test/test_range.py
+++ b/Lib/test/test_range.py
@@ -99,20 +99,24 @@ class RangeTest(unittest.TestCase):
x = range(10**20+10, 10**20, 3)
self.assertEqual(len(x), 0)
self.assertEqual(len(list(x)), 0)
+ self.assertFalse(x)
x = range(10**20, 10**20+10, -3)
self.assertEqual(len(x), 0)
self.assertEqual(len(list(x)), 0)
+ self.assertFalse(x)
x = range(10**20+10, 10**20, -3)
self.assertEqual(len(x), 4)
self.assertEqual(len(list(x)), 4)
+ self.assertTrue(x)
# Now test range() with longs
- self.assertEqual(list(range(-2**100)), [])
- self.assertEqual(list(range(0, -2**100)), [])
- self.assertEqual(list(range(0, 2**100, -1)), [])
- self.assertEqual(list(range(0, 2**100, -1)), [])
+ for x in [range(-2**100),
+ range(0, -2**100),
+ range(0, 2**100, -1)]:
+ self.assertEqual(list(x), [])
+ self.assertFalse(x)
a = int(10 * sys.maxsize)
b = int(100 * sys.maxsize)
@@ -153,6 +157,7 @@ class RangeTest(unittest.TestCase):
step = x[1] - x[0]
length = 1 + ((x[-1] - x[0]) // step)
return length
+
a = -sys.maxsize
b = sys.maxsize
expected_len = b - a
@@ -160,6 +165,7 @@ class RangeTest(unittest.TestCase):
self.assertIn(a, x)
self.assertNotIn(b, x)
self.assertRaises(OverflowError, len, x)
+ self.assertTrue(x)
self.assertEqual(_range_len(x), expected_len)
self.assertEqual(x[0], a)
idx = sys.maxsize+1
@@ -177,6 +183,7 @@ class RangeTest(unittest.TestCase):
self.assertIn(a, x)
self.assertNotIn(b, x)
self.assertRaises(OverflowError, len, x)
+ self.assertTrue(x)
self.assertEqual(_range_len(x), expected_len)
self.assertEqual(x[0], a)
idx = sys.maxsize+1
@@ -195,6 +202,7 @@ class RangeTest(unittest.TestCase):
self.assertIn(a, x)
self.assertNotIn(b, x)
self.assertRaises(OverflowError, len, x)
+ self.assertTrue(x)
self.assertEqual(_range_len(x), expected_len)
self.assertEqual(x[0], a)
idx = sys.maxsize+1
@@ -213,6 +221,7 @@ class RangeTest(unittest.TestCase):
self.assertIn(a, x)
self.assertNotIn(b, x)
self.assertRaises(OverflowError, len, x)
+ self.assertTrue(x)
self.assertEqual(_range_len(x), expected_len)
self.assertEqual(x[0], a)
idx = sys.maxsize+1
diff --git a/Misc/NEWS b/Misc/NEWS
index 310e982d78..7e87a28145 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -39,6 +39,9 @@ Core and Builtins
- bpo-28893: Set correct __cause__ for errors about invalid awaitables
returned from __aiter__ and __anext__.
+- bpo-28876: ``bool(range)`` works even if ``len(range)``
+ raises :exc:`OverflowError`.
+
- bpo-29683: Fixes to memory allocation in _PyCode_SetExtra. Patch by
Brian Coleman.
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c
index 8449fc7a24..8f5fc434bd 100644
--- a/Objects/rangeobject.c
+++ b/Objects/rangeobject.c
@@ -668,6 +668,16 @@ static PyMappingMethods range_as_mapping = {
(objobjargproc)0, /* mp_ass_subscript */
};
+static int
+range_bool(rangeobject* self)
+{
+ return PyObject_IsTrue(self->length);
+}
+
+static PyNumberMethods range_as_number = {
+ .nb_bool = (inquiry)range_bool,
+};
+
static PyObject * range_iter(PyObject *seq);
static PyObject * range_reverse(PyObject *seq);
@@ -707,7 +717,7 @@ PyTypeObject PyRange_Type = {
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc)range_repr, /* tp_repr */
- 0, /* tp_as_number */
+ &range_as_number, /* tp_as_number */
&range_as_sequence, /* tp_as_sequence */
&range_as_mapping, /* tp_as_mapping */
(hashfunc)range_hash, /* tp_hash */
--
GitLab
From fcd79ada4e4cf335372538b34c8eb89cf09f84b2 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Mon, 20 Mar 2017 14:54:52 +0200
Subject: [PATCH 0063/1433] Fix "NotImplentedError" typo in constants
documentation (#692) (#739)
`NotImplentedError` --> `NotImplementedError`
(cherry picked from commit 05f53735c8912f8df1077e897f052571e13c3496)
---
Doc/library/constants.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/library/constants.rst b/Doc/library/constants.rst
index f0742cee55..469a3eed60 100644
--- a/Doc/library/constants.rst
+++ b/Doc/library/constants.rst
@@ -46,7 +46,7 @@ A small number of constants live in the built-in namespace. They are:
.. note::
- ``NotImplentedError`` and ``NotImplemented`` are not interchangeable,
+ ``NotImplementedError`` and ``NotImplemented`` are not interchangeable,
even though they have similar names and purposes.
See :exc:`NotImplementedError` for details on when to use it.
--
GitLab
From e9213d929d7b0075539e87416f6a6fb86c27454b Mon Sep 17 00:00:00 2001
From: Ned Deily
Date: Tue, 21 Mar 2017 00:35:08 -0400
Subject: [PATCH 0064/1433] bpo-27593: Revise git SCM build info. (#744) (#745)
Use --short form of git hash. Use output from "git describe" for tag.
Expected outputs:
1. previous hg
2. previous git
3. updated git
Release (tagged) build:
1. Python 3.7.0a0 (v3.7.0a0:4def2a2901a5, ...
2. Python 3.7.0a0 (v3.7.0a0^0:05f53735c8912f8df1077e897f052571e13c3496, ...
3. Python 3.7.0a0 (v3.7.0a0:05f53735c8, ...
Development build:
1. Python 3.7.0a0 (default:41df79263a11, ...
2. Python 3.7.0a0 (master:05f53735c8912f8df1077e897f052571e13c3496, ...
3. Python 3.7.0a0 (heads/master-dirty:05f53735c8, ...
"dirty" means the working tree has uncommitted changes.
See "git help describe" for more info.
(cherry picked from commit 554626ada769abf82a5dabe6966afa4265acb6a6)
---
PCbuild/pythoncore.vcxproj | 4 ++--
configure | 4 ++--
configure.ac | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index d7e9473638..6ea184877f 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -414,8 +414,8 @@
-
-
+
+
$([System.IO.File]::ReadAllText('$(IntDir)gitbranch.txt').Trim())
$([System.IO.File]::ReadAllText('$(IntDir)gitversion.txt').Trim())
diff --git a/configure b/configure
index d4eccb1d68..abe1dc5abd 100755
--- a/configure
+++ b/configure
@@ -2743,8 +2743,8 @@ HAS_GIT=no-repository
fi
if test $HAS_GIT = found
then
- GITVERSION="git -C \$(srcdir) rev-parse HEAD"
- GITTAG="git -C \$(srcdir) name-rev --tags --name-only HEAD"
+ GITVERSION="git -C \$(srcdir) rev-parse --short HEAD"
+ GITTAG="git -C \$(srcdir) describe --all --always --dirty"
GITBRANCH="git -C \$(srcdir) name-rev --name-only HEAD"
else
GITVERSION=""
diff --git a/configure.ac b/configure.ac
index f00a2a6fa4..9eacf52559 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,8 +37,8 @@ HAS_GIT=no-repository
fi
if test $HAS_GIT = found
then
- GITVERSION="git -C \$(srcdir) rev-parse HEAD"
- GITTAG="git -C \$(srcdir) name-rev --tags --name-only HEAD"
+ GITVERSION="git -C \$(srcdir) rev-parse --short HEAD"
+ GITTAG="git -C \$(srcdir) describe --all --always --dirty"
GITBRANCH="git -C \$(srcdir) name-rev --name-only HEAD"
else
GITVERSION=""
--
GitLab
From fe30339534c602af1123e1402e44a1463f91f2e5 Mon Sep 17 00:00:00 2001
From: INADA Naoki
Date: Wed, 22 Mar 2017 03:46:26 +0900
Subject: [PATCH 0065/1433] bpo-29859: Fix error messages from return codes for
pthread_* calls (GH-753)
(cherry picked from commit d7fa6b259e00fca04dbf816bfcf4115fdda14bb7)
---
Misc/NEWS | 3 +++
Python/thread_pthread.h | 24 +++++++++++++-----------
2 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/Misc/NEWS b/Misc/NEWS
index 7e87a28145..aad9248069 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.6.1 final?
Core and Builtins
-----------------
+- bpo-29859: Show correct error messages when any of the pthread_* calls in
+ thread_pthread.h fails.
+
- bpo-29600: Fix wrapping coroutine return values in StopIteration.
- bpo-28856: Fix an oversight that %b format for bytes should support objects
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index 27e0dc84bc..ba7393f03d 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -143,6 +143,8 @@ typedef struct {
} pthread_lock;
#define CHECK_STATUS(name) if (status != 0) { perror(name); error = 1; }
+#define CHECK_STATUS_PTHREAD(name) if (status != 0) { fprintf(stderr, \
+ "%s: %s\n", name, strerror(status)); error = 1; }
/*
* Initialization.
@@ -417,7 +419,7 @@ PyThread_allocate_lock(void)
status = pthread_mutex_init(&lock->mut,
pthread_mutexattr_default);
- CHECK_STATUS("pthread_mutex_init");
+ CHECK_STATUS_PTHREAD("pthread_mutex_init");
/* Mark the pthread mutex underlying a Python mutex as
pure happens-before. We can't simply mark the
Python-level mutex as a mutex because it can be
@@ -427,7 +429,7 @@ PyThread_allocate_lock(void)
status = pthread_cond_init(&lock->lock_released,
pthread_condattr_default);
- CHECK_STATUS("pthread_cond_init");
+ CHECK_STATUS_PTHREAD("pthread_cond_init");
if (error) {
PyMem_RawFree((void *)lock);
@@ -452,10 +454,10 @@ PyThread_free_lock(PyThread_type_lock lock)
* and must have the cond destroyed first.
*/
status = pthread_cond_destroy( &thelock->lock_released );
- CHECK_STATUS("pthread_cond_destroy");
+ CHECK_STATUS_PTHREAD("pthread_cond_destroy");
status = pthread_mutex_destroy( &thelock->mut );
- CHECK_STATUS("pthread_mutex_destroy");
+ CHECK_STATUS_PTHREAD("pthread_mutex_destroy");
PyMem_RawFree((void *)thelock);
}
@@ -472,7 +474,7 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
lock, microseconds, intr_flag));
status = pthread_mutex_lock( &thelock->mut );
- CHECK_STATUS("pthread_mutex_lock[1]");
+ CHECK_STATUS_PTHREAD("pthread_mutex_lock[1]");
if (thelock->locked == 0) {
success = PY_LOCK_ACQUIRED;
@@ -494,13 +496,13 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
&thelock->mut, &ts);
if (status == ETIMEDOUT)
break;
- CHECK_STATUS("pthread_cond_timed_wait");
+ CHECK_STATUS_PTHREAD("pthread_cond_timed_wait");
}
else {
status = pthread_cond_wait(
&thelock->lock_released,
&thelock->mut);
- CHECK_STATUS("pthread_cond_wait");
+ CHECK_STATUS_PTHREAD("pthread_cond_wait");
}
if (intr_flag && status == 0 && thelock->locked) {
@@ -518,7 +520,7 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
}
if (success == PY_LOCK_ACQUIRED) thelock->locked = 1;
status = pthread_mutex_unlock( &thelock->mut );
- CHECK_STATUS("pthread_mutex_unlock[1]");
+ CHECK_STATUS_PTHREAD("pthread_mutex_unlock[1]");
if (error) success = PY_LOCK_FAILURE;
dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n",
@@ -536,16 +538,16 @@ PyThread_release_lock(PyThread_type_lock lock)
dprintf(("PyThread_release_lock(%p) called\n", lock));
status = pthread_mutex_lock( &thelock->mut );
- CHECK_STATUS("pthread_mutex_lock[3]");
+ CHECK_STATUS_PTHREAD("pthread_mutex_lock[3]");
thelock->locked = 0;
/* wake up someone (anyone, if any) waiting on the lock */
status = pthread_cond_signal( &thelock->lock_released );
- CHECK_STATUS("pthread_cond_signal");
+ CHECK_STATUS_PTHREAD("pthread_cond_signal");
status = pthread_mutex_unlock( &thelock->mut );
- CHECK_STATUS("pthread_mutex_unlock[3]");
+ CHECK_STATUS_PTHREAD("pthread_mutex_unlock[3]");
}
#endif /* USE_SEMAPHORES */
--
GitLab
From 677df6ecade6ff503d3c3c93cf157ed12fec9386 Mon Sep 17 00:00:00 2001
From: Ned Deily
Date: Tue, 21 Mar 2017 20:21:49 -0400
Subject: [PATCH 0066/1433] Revert and fix Misc/NEWS after merge error in
fca705d53397. (#755)
---
Misc/NEWS | 805 +-----------------------------------------------------
1 file changed, 3 insertions(+), 802 deletions(-)
diff --git a/Misc/NEWS b/Misc/NEWS
index aad9248069..2e0f00be11 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,9 @@ Core and Builtins
- bpo-29859: Show correct error messages when any of the pthread_* calls in
thread_pthread.h fails.
+- bpo-28876: ``bool(range)`` works even if ``len(range)``
+ raises :exc:`OverflowError`.
+
- bpo-29600: Fix wrapping coroutine return values in StopIteration.
- bpo-28856: Fix an oversight that %b format for bytes should support objects
@@ -28,813 +31,12 @@ Core and Builtins
- bpo-29714: Fix a regression that bytes format may fail when containing zero
bytes inside.
-- bpo-29568: Escaped percent "%%" in the format string for classic string
- formatting no longer allows any characters between two percents.
-
-- bpo-29714: Fix a regression that bytes format may fail when containing zero
- bytes inside.
-
-- bpo-29695: bool(), float(), list() and tuple() no longer take keyword arguments.
- The first argument of int() can now be passes only as positional argument.
-
-- bpo-20087: Prefer glibc's list of locale aliases to the X11 ones.
-
-- bpo-28893: Set correct __cause__ for errors about invalid awaitables
- returned from __aiter__ and __anext__.
-
-- bpo-28876: ``bool(range)`` works even if ``len(range)``
- raises :exc:`OverflowError`.
-
-- bpo-29683: Fixes to memory allocation in _PyCode_SetExtra. Patch by
- Brian Coleman.
-
-- bpo-29684: Fix minor regression of PyEval_CallObjectWithKeywords.
- It should raise TypeError when kwargs is not a dict. But it might
- cause segv when args=NULL and kwargs is not a dict.
-
-- bpo-28598: Support __rmod__ for subclasses of str being called before
- str.__mod__. Patch by Martijn Pieters.
-
-- bpo-29607: Fix stack_effect computation for CALL_FUNCTION_EX.
- Patch by Matthieu Dartiailh.
-
-- bpo-29602: Fix incorrect handling of signed zeros in complex constructor for
- complex subclasses and for inputs having a __complex__ method. Patch
- by Serhiy Storchaka.
-
-- bpo-29347: Fixed possibly dereferencing undefined pointers
- when creating weakref objects.
-
-- bpo-29463: Add ``docstring`` field to Module, ClassDef, FunctionDef,
- and AsyncFunctionDef ast nodes. docstring is not first stmt in their body
- anymore. It affects ``co_firstlineno`` and ``co_lnotab`` of code object
- for module and class.
-
-- bpo-29438: Fixed use-after-free problem in key sharing dict.
-
-- bpo-29546: Set the 'path' and 'name' attribute on ImportError for ``from ... import ...``.
-
-- bpo-29546: Improve from-import error message with location
-
-- Issue #29319: Prevent RunMainFromImporter overwriting sys.path[0].
-
-- Issue #29337: Fixed possible BytesWarning when compare the code objects.
- Warnings could be emitted at compile time.
-
-- Issue #29327: Fixed a crash when pass the iterable keyword argument to
- sorted().
-
-- Issue #29034: Fix memory leak and use-after-free in os module (path_converter).
-
-- Issue #29159: Fix regression in bytes(x) when x.__index__() raises Exception.
-
-- Issue #29049: Call _PyObject_GC_TRACK() lazily when calling Python function.
- Calling function is up to 5% faster.
-
-- Issue #28927: bytes.fromhex() and bytearray.fromhex() now ignore all ASCII
- whitespace, not only spaces. Patch by Robert Xiao.
-
-- Issue #28932: Do not include if it does not exist.
-
-- Issue #25677: Correct the positioning of the syntax error caret for
- indented blocks. Based on patch by Michael Layzell.
-
-- Issue #29000: Fixed bytes formatting of octals with zero padding in alternate
- form.
-
-- Issue #18896: Python function can now have more than 255 parameters.
- collections.namedtuple() now supports tuples with more than 255 elements.
-
-- Issue #28596: The preferred encoding is UTF-8 on Android. Patch written by
- Chi Hsuan Yen.
-
-- Issue #26919: On Android, operating system data is now always encoded/decoded
- to/from UTF-8, instead of the locale encoding to avoid inconsistencies with
- os.fsencode() and os.fsdecode() which are already using UTF-8.
-
-- Issue #28991: functools.lru_cache() was susceptible to an obscure reentrancy
- bug triggerable by a monkey-patched len() function.
-
-- Issue #28147: Fix a memory leak in split-table dictionaries: setattr()
- must not convert combined table into split table. Patch written by INADA
- Naoki.
-
-- Issue #28739: f-string expressions are no longer accepted as docstrings and
- by ast.literal_eval() even if they do not include expressions.
-
-- Issue #28512: Fixed setting the offset attribute of SyntaxError by
- PyErr_SyntaxLocationEx() and PyErr_SyntaxLocationObject().
-
-- Issue #28918: Fix the cross compilation of xxlimited when Python has been
- built with Py_DEBUG defined.
-
-- Issue #23722: Rather than silently producing a class that doesn't support
- zero-argument ``super()`` in methods, failing to pass the new
- ``__classcell__`` namespace entry up to ``type.__new__`` now results in a
- ``DeprecationWarning`` and a class that supports zero-argument ``super()``.
-
-- Issue #28797: Modifying the class __dict__ inside the __set_name__ method of
- a descriptor that is used inside that class no longer prevents calling the
- __set_name__ method of other descriptors.
-
-- Issue #28799: Remove the ``PyEval_GetCallStats()`` function and deprecate
- the untested and undocumented ``sys.callstats()`` function. Remove the
- ``CALL_PROFILE`` special build: use the :func:`sys.setprofile` function,
- :mod:`cProfile` or :mod:`profile` to profile function calls.
-
-- Issue #12844: More than 255 arguments can now be passed to a function.
-
-- Issue #28782: Fix a bug in the implementation ``yield from`` when checking
- if the next instruction is YIELD_FROM. Regression introduced by WORDCODE
- (issue #26647).
-
-- Issue #28774: Fix error position of the unicode error in ASCII and Latin1
- encoders when a string returned by the error handler contains multiple
- non-encodable characters (non-ASCII for the ASCII codec, characters out
- of the U+0000-U+00FF range for Latin1).
-
-- Issue #28731: Optimize _PyDict_NewPresized() to create correct size dict.
- Improve speed of dict literal with constant keys up to 30%.
-
-- Issue #28532: Show sys.version when -V option is supplied twice.
-
-- Issue #27100: The with-statement now checks for __enter__ before it
- checks for __exit__. This gives less confusing error messages when
- both methods are missing. Patch by Jonathan Ellington.
-
-- Issue #28746: Fix the set_inheritable() file descriptor method on platforms
- that do not have the ioctl FIOCLEX and FIONCLEX commands.
-
-- Issue #26920: Fix not getting the locale's charset upon initializing the
- interpreter, on platforms that do not have langinfo.
-
-- Issue #28648: Fixed crash in Py_DecodeLocale() in debug build on Mac OS X
- when decode astral characters. Patch by Xiang Zhang.
-
-- Issue #28665: Improve speed of the STORE_DEREF opcode by 40%.
-
-- Issue #19398: Extra slash no longer added to sys.path components in case of
- empty compile-time PYTHONPATH components.
-
-- Issue #28621: Sped up converting int to float by reusing faster bits counting
- implementation. Patch by Adrian Wielgosik.
-
-- Issue #28580: Optimize iterating split table values.
- Patch by Xiang Zhang.
-
-- Issue #28583: PyDict_SetDefault didn't combine split table when needed.
- Patch by Xiang Zhang.
-
-- Issue #28128: Deprecation warning for invalid str and byte escape
- sequences now prints better information about where the error
- occurs. Patch by Serhiy Storchaka and Eric Smith.
-
-- Issue #28509: dict.update() no longer allocate unnecessary large memory.
-
-- Issue #28426: Fixed potential crash in PyUnicode_AsDecodedObject() in debug
- build.
-
-- Issue #28517: Fixed of-by-one error in the peephole optimizer that caused
- keeping unreachable code.
-
-- Issue #28214: Improved exception reporting for problematic __set_name__
- attributes.
-
-- Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception
- loss in PyTraceBack_Here().
-
-- Issue #28183: Optimize and cleanup dict iteration.
-
-- Issue #26081: Added C implementation of asyncio.Future.
- Original patch by Yury Selivanov.
-
-- Issue #28379: Added sanity checks and tests for PyUnicode_CopyCharacters().
- Patch by Xiang Zhang.
-
-- Issue #28376: The type of long range iterator is now registered as Iterator.
- Patch by Oren Milman.
-
-- Issue #28376: Creating instances of range_iterator by calling range_iterator
- type now is disallowed. Calling iter() on range instance is the only way.
- Patch by Oren Milman.
-
-- Issue #26906: Resolving special methods of uninitialized type now causes
- implicit initialization of the type instead of a fail.
-
-- Issue #18287: PyType_Ready() now checks that tp_name is not NULL.
- Original patch by Niklas Koep.
-
-- Issue #24098: Fixed possible crash when AST is changed in process of
- compiling it.
-
-- Issue #28201: Dict reduces possibility of 2nd conflict in hash table when
- hashes have same lower bits.
-
-- Issue #28350: String constants with null character no longer interned.
-
-- Issue #26617: Fix crash when GC runs during weakref callbacks.
-
-- Issue #27942: String constants now interned recursively in tuples and frozensets.
-
-- Issue #28289: ImportError.__init__ now resets not specified attributes.
-
-- Issue #21578: Fixed misleading error message when ImportError called with
- invalid keyword args.
-
-- Issue #28203: Fix incorrect type in complex(1.0, {2:3}) error message.
- Patch by Soumya Sharma.
-
-- Issue #28086: Single var-positional argument of tuple subtype was passed
- unscathed to the C-defined function. Now it is converted to exact tuple.
-
-- Issue #28214: Now __set_name__ is looked up on the class instead of the
- instance.
-
-- Issue #27955: Fallback on reading /dev/urandom device when the getrandom()
- syscall fails with EPERM, for example when blocked by SECCOMP.
-
-- Issue #28192: Don't import readline in isolated mode.
-
-- Issue #27441: Remove some redundant assignments to ob_size in longobject.c.
- Thanks Oren Milman.
-
-- Issue #27222: Clean up redundant code in long_rshift function. Thanks
- Oren Milman.
-
-- Upgrade internal unicode databases to Unicode version 9.0.0.
-
-- Issue #28131: Fix a regression in zipimport's compile_source(). zipimport
- should use the same optimization level as the interpreter.
-
-- Issue #28126: Replace Py_MEMCPY with memcpy(). Visual Studio can properly
- optimize memcpy().
-
-- Issue #28120: Fix dict.pop() for splitted dictionary when trying to remove a
- "pending key" (Not yet inserted in split-table). Patch by Xiang Zhang.
-
-- Issue #26182: Raise DeprecationWarning when async and await keywords are
- used as variable/attribute/class/function name.
-
-- Issue #26182: Fix a refleak in code that raises DeprecationWarning.
-
-- Issue #28721: Fix asynchronous generators aclose() and athrow() to
- handle StopAsyncIteration propagation properly.
-
-- Issue #26110: Speed-up method calls: add LOAD_METHOD and CALL_METHOD
- opcodes.
-
-Extension Modules
------------------
-
-- Issue #29169: Update zlib to 1.2.11.
Library
-------
- bpo-25455: Fixed crashes in repr of recursive buffered file-like objects.
-- bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords
- are not strings. Patch by Michael Seifert.
-
-- bpo-8256: Fixed possible failing or crashing input() if attributes "encoding"
- or "errors" of sys.stdin or sys.stdout are not set or are not strings.
-
-- bpo-28692: Using non-integer value for selecting a plural form in gettext is
- now deprecated.
-
-- bpo-26121: Use C library implementation for math functions erf() and erfc().
-
-- bpo-29619: os.stat() and os.DirEntry.inode() now convert inode (st_ino) using
- unsigned integers.
-
-- bpo-28298: Fix a bug that prevented array 'Q', 'L' and 'I' from accepting big
- intables (objects that have __int__) as elements.
-
-- bpo-29645: Speed up importing the webbrowser module. webbrowser.register()
- is now thread-safe.
-
-- bpo-28231: The zipfile module now accepts path-like objects for external
- paths.
-
-- bpo-26915: index() and count() methods of collections.abc.Sequence now
- check identity before checking equality when do comparisons.
-
-- bpo-28682: Added support for bytes paths in os.fwalk().
-
-- bpo-29623: Allow use of path-like object as a single argument in
- ConfigParser.read(). Patch by David Ellis.
-
-- bpo-9303: Migrate sqlite3 module to _v2 API. Patch by Aviv Palivoda.
-
-- bpo-28963: Fix out of bound iteration in asyncio.Future.remove_done_callback
- implemented in C.
-
-- bpo-29704: asyncio.subprocess.SubprocessStreamProtocol no longer closes before
- all pipes are closed.
-
-- bpo-29271: Fix Task.current_task and Task.all_tasks implemented in C
- to accept None argument as their pure Python implementation.
-
-- bpo-29703: Fix asyncio to support instantiation of new event loops
- in child processes.
-
-- bpo-29615: SimpleXMLRPCDispatcher no longer chains KeyError (or any other
- exception) to exception(s) raised in the dispatched methods.
- Patch by Petr Motejlek.
-
-- bpo-7769: Method register_function() of xmlrpc.server.SimpleXMLRPCDispatcher
- and its subclasses can now be used as a decorator.
-
-- bpo-29376: Fix assertion error in threading._DummyThread.is_alive().
-
-- bpo-28624: Add a test that checks that cwd parameter of Popen() accepts
- PathLike objects. Patch by Sayan Chowdhury.
-
-- bpo-28518: Start a transaction implicitly before a DML statement.
- Patch by Aviv Palivoda.
-
-- bpo-29742: get_extra_info() raises exception if get called on closed ssl transport.
- Patch by Nikolay Kim.
-
-- Issue #16285: urrlib.parse.quote is now based on RFC 3986 and hence includes
- '~' in the set of characters that is not quoted by default. Patch by
- Christian Theune and Ratnadeep Debnath.
-
-- bpo-29532: Altering a kwarg dictionary passed to functools.partial()
- no longer affects a partial object after creation.
-
-- bpo-29110: Fix file object leak in aifc.open() when file is given as a
- filesystem path and is not in valid AIFF format. Patch by Anthony Zhang.
-
-- bpo-22807: Add uuid.SafeUUID and uuid.UUID.is_safe to relay information from
- the platform about whether generated UUIDs are generated with a
- multiprocessing safe method.
-
-- bpo-29576: Improve some deprecations in importlib. Some deprecated methods
- now emit DeprecationWarnings and have better descriptive messages.
-
-- bpo-29534: Fixed different behaviour of Decimal.from_float()
- for _decimal and _pydecimal. Thanks Andrew Nester.
-
-- Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap,
- improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi,
- Manuel Krebber, and Łukasz Langa.
-
-- Issue #29100: Fix datetime.fromtimestamp() regression introduced in Python
- 3.6.0: check minimum and maximum years.
-
-- Issue #29416: Prevent infinite loop in pathlib.Path.mkdir
-
-- Issue #29444: Fixed out-of-bounds buffer access in the group() method of
- the match object. Based on patch by WGH.
-
-- Issue #29377: Add SlotWrapperType, MethodWrapperType, and
- MethodDescriptorType built-in types to types module.
- Original patch by Manuel Krebber.
-
-- Issue #29218: Unused install_misc command is now removed. It has been
- documented as unused since 2000. Patch by Eric N. Vander Weele.
-
-- Issue #29368: The extend() method is now called instead of the append()
- method when unpickle collections.deque and other list-like objects.
- This can speed up unpickling to 2 times.
-
-- Issue #29338: The help of a builtin or extension class now includes the
- constructor signature if __text_signature__ is provided for the class.
-
-- Issue #29335: Fix subprocess.Popen.wait() when the child process has
- exited to a stopped instead of terminated state (ex: when under ptrace).
-
-- Issue #29290: Fix a regression in argparse that help messages would wrap at
- non-breaking spaces.
-
-- Issue #28735: Fixed the comparison of mock.MagickMock with mock.ANY.
-
-- Issue #29197: Removed deprecated function ntpath.splitunc().
-
-- Issue #29210: Removed support of deprecated argument "exclude" in
- tarfile.TarFile.add().
-
-- Issue #29219: Fixed infinite recursion in the repr of uninitialized
- ctypes.CDLL instances.
-
-- Issue #29192: Removed deprecated features in the http.cookies module.
-
-- Issue #29193: A format string argument for string.Formatter.format()
- is now positional-only.
-
-- Issue #29195: Removed support of deprecated undocumented keyword arguments
- in methods of regular expression objects.
-
-- Issue #28969: Fixed race condition in C implementation of functools.lru_cache.
- KeyError could be raised when cached function with full cache was
- simultaneously called from differen threads with the same uncached arguments.
-
-- Issue #20804: The unittest.mock.sentinel attributes now preserve their
- identity when they are copied or pickled.
-
-- Issue #29142: In urllib.request, suffixes in no_proxy environment variable with
- leading dots could match related hostnames again (e.g. .b.c matches a.b.c).
- Patch by Milan Oberkirch.
-
-- Issue #28961: Fix unittest.mock._Call helper: don't ignore the name parameter
- anymore. Patch written by Jiajun Huang.
-
-- Issue #15812: inspect.getframeinfo() now correctly shows the first line of
- a context. Patch by Sam Breese.
-
-- Issue #28985: Update authorizer constants in sqlite3 module.
- Patch by Dingyuan Wang.
-
-- Issue #29094: Offsets in a ZIP file created with extern file object and modes
- "w" and "x" now are relative to the start of the file.
-
-- Issue #29079: Prevent infinite loop in pathlib.resolve() on Windows
-
-- Issue #13051: Fixed recursion errors in large or resized
- curses.textpad.Textbox. Based on patch by Tycho Andersen.
-
-- Issue #9770: curses.ascii predicates now work correctly with negative
- integers.
-
-- Issue #28427: old keys should not remove new values from
- WeakValueDictionary when collecting from another thread.
-
-- Issue 28923: Remove editor artifacts from Tix.py.
-
-- Issue #28871: Fixed a crash when deallocate deep ElementTree.
-
-- Issue #19542: Fix bugs in WeakValueDictionary.setdefault() and
- WeakValueDictionary.pop() when a GC collection happens in another
- thread.
-
-- Issue #20191: Fixed a crash in resource.prlimit() when passing a sequence that
- doesn't own its elements as limits.
-
-- Issue #16255: subprocess.Popen uses /system/bin/sh on Android as the shell,
- instead of /bin/sh.
-
-- Issue #28779: multiprocessing.set_forkserver_preload() would crash the
- forkserver process if a preloaded module instantiated some
- multiprocessing objects such as locks.
-
-- Issue #26937: The chown() method of the tarfile.TarFile class does not fail
- now when the grp module cannot be imported, as for example on Android
- platforms.
-
-- Issue #28847: dbm.dumb now supports reading read-only files and no longer
- writes the index file when it is not changed. A deprecation warning is now
- emitted if the index file is missed and recreated in the 'r' and 'w' modes
- (will be an error in future Python releases).
-
-- Issue #27030: Unknown escapes consisting of ``'\'`` and an ASCII letter in
- re.sub() replacement templates regular expressions now are errors.
-
-- Issue #28835: Fix a regression introduced in warnings.catch_warnings():
- call warnings.showwarning() if it was overriden inside the context manager.
-
-- Issue #27172: To assist with upgrades from 2.7, the previously documented
- deprecation of ``inspect.getfullargspec()`` has been reversed. This decision
- may be revisited again after the Python 2.7 branch is no longer officially
- supported.
-
-- Issue #28740: Add sys.getandroidapilevel(): return the build time API version
- of Android as an integer. Function only available on Android.
-
-- Issue #26273: Add new :data:`socket.TCP_CONGESTION` (Linux 2.6.13) and
- :data:`socket.TCP_USER_TIMEOUT` (Linux 2.6.37) constants. Patch written by
- Omar Sandoval.
-
-- Issue #28752: Restored the __reduce__() methods of datetime objects.
-
-- Issue #28727: Regular expression patterns, _sre.SRE_Pattern objects created
- by re.compile(), become comparable (only x==y and x!=y operators). This
- change should fix the issue #18383: don't duplicate warning filters when the
- warnings module is reloaded (thing usually only done in unit tests).
-
-- Issue #20572: Remove the subprocess.Popen.wait endtime parameter. It was
- deprecated in 3.4 and undocumented prior to that.
-
-- Issue #25659: In ctypes, prevent a crash calling the from_buffer() and
- from_buffer_copy() methods on abstract classes like Array.
-
-- Issue #28548: In the "http.server" module, parse the protocol version if
- possible, to avoid using HTTP 0.9 in some error responses.
-
-- Issue #19717: Makes Path.resolve() succeed on paths that do not exist.
- Patch by Vajrasky Kok
-
-- Issue #28563: Fixed possible DoS and arbitrary code execution when handle
- plural form selections in the gettext module. The expression parser now
- supports exact syntax supported by GNU gettext.
-
-- Issue #28387: Fixed possible crash in _io.TextIOWrapper deallocator when
- the garbage collector is invoked in other thread. Based on patch by
- Sebastian Cufre.
-
-- Issue #27517: LZMA compressor and decompressor no longer raise exceptions if
- given empty data twice. Patch by Benjamin Fogle.
-
-- Issue #28549: Fixed segfault in curses's addch() with ncurses6.
-
-- Issue #28449: tarfile.open() with mode "r" or "r:" now tries to open a tar
- file with compression before trying to open it without compression. Otherwise
- it had 50% chance failed with ignore_zeros=True.
-
-- Issue #23262: The webbrowser module now supports Firefox 36+ and derived
- browsers. Based on patch by Oleg Broytman.
-
-- Issue #24241: The webbrowser in an X environment now prefers using the
- default browser directly. Also, the webbrowser register() function now has
- a documented 'preferred' argument, to specify browsers to be returned by
- get() with no arguments. Patch by David Steele
-
-- Issue #27939: Fixed bugs in tkinter.ttk.LabeledScale and tkinter.Scale caused
- by representing the scale as float value internally in Tk. tkinter.IntVar
- now works if float value is set to underlying Tk variable.
-
-- Issue #28255: calendar.TextCalendar.prweek() no longer prints a space after
- a weeks's calendar. calendar.TextCalendar.pryear() no longer prints redundant
- newline after a year's calendar. Based on patch by Xiang Zhang.
-
-- Issue #28255: calendar.TextCalendar.prmonth() no longer prints a space
- at the start of new line after printing a month's calendar. Patch by
- Xiang Zhang.
-
-- Issue #20491: The textwrap.TextWrapper class now honors non-breaking spaces.
- Based on patch by Kaarle Ritvanen.
-
-- Issue #28353: os.fwalk() no longer fails on broken links.
-
-- Issue #28430: Fix iterator of C implemented asyncio.Future doesn't accept
- non-None value is passed to it.send(val).
-
-- Issue #27025: Generated names for Tkinter widgets now start by the "!" prefix
- for readability (was "`").
-
-- Issue #25464: Fixed HList.header_exists() in tkinter.tix module by addin
- a workaround to Tix library bug.
-
-- Issue #28488: shutil.make_archive() no longer adds entry "./" to ZIP archive.
-
-- Issue #25953: re.sub() now raises an error for invalid numerical group
- reference in replacement template even if the pattern is not found in
- the string. Error message for invalid group reference now includes the
- group index and the position of the reference.
- Based on patch by SilentGhost.
-
-- Issue #28469: timeit now uses the sequence 1, 2, 5, 10, 20, 50,... instead
- of 1, 10, 100,... for autoranging.
-
-- Issue #28115: Command-line interface of the zipfile module now uses argparse.
- Added support of long options.
-
-- Issue #18219: Optimize csv.DictWriter for large number of columns.
- Patch by Mariatta Wijaya.
-
-- Issue #28448: Fix C implemented asyncio.Future didn't work on Windows.
-
-- Issue #23214: In the "io" module, the argument to BufferedReader and
- BytesIO's read1() methods is now optional and can be -1, matching the
- BufferedIOBase specification.
-
-- Issue #28480: Fix error building socket module when multithreading is
- disabled.
-
-- Issue #28240: timeit: remove ``-c/--clock`` and ``-t/--time`` command line
- options which were deprecated since Python 3.3.
-
-- Issue #28240: timeit now repeats the benchmarks 5 times instead of only 3
- to make benchmarks more reliable.
-
-- Issue #28240: timeit autorange now uses a single loop iteration if the
- benchmark takes less than 10 seconds, instead of 10 iterations.
- "python3 -m timeit -s 'import time' 'time.sleep(1)'" now takes 4 seconds
- instead of 40 seconds.
-
-- Distutils.sdist now looks for README and setup.py files with case
- sensitivity. This behavior matches that found in Setuptools 6.0 and
- later. See `setuptools 100
- `_ for rationale.
-
-- Issue #24452: Make webbrowser support Chrome on Mac OS X. Patch by
- Ned Batchelder.
-
-- Issue #20766: Fix references leaked by pdb in the handling of SIGINT
- handlers.
-
-- Issue #27998: Fixed bytes path support in os.scandir() on Windows.
- Patch by Eryk Sun.
-
-- Issue #28317: The disassembler now decodes FORMAT_VALUE argument.
-
-- Issue #26293: Fixed writing ZIP files that starts not from the start of the
- file. Offsets in ZIP file now are relative to the start of the archive in
- conforming to the specification.
-
-- Issue #28380: unittest.mock Mock autospec functions now properly support
- assert_called, assert_not_called, and assert_called_once.
-
-- Issue #28229: lzma module now supports pathlib.
-
-- Issue #28321: Fixed writing non-BMP characters with binary format in plistlib.
-
-- Issue #28225: bz2 module now supports pathlib. Initial patch by Ethan Furman.
-
-- Issue #28227: gzip now supports pathlib. Patch by Ethan Furman.
-
-- Issue #28332: Deprecated silent truncations in socket.htons and socket.ntohs.
- Original patch by Oren Milman.
-
-- Issue #27358: Optimized merging var-keyword arguments and improved error
- message when passing a non-mapping as a var-keyword argument.
-
-- Issue #28257: Improved error message when passing a non-iterable as
- a var-positional argument. Added opcode BUILD_TUPLE_UNPACK_WITH_CALL.
-
-- Issue #28322: Fixed possible crashes when unpickle itertools objects from
- incorrect pickle data. Based on patch by John Leitch.
-
-- Issue #28228: imghdr now supports pathlib.
-
-- Issue #28226: compileall now supports pathlib.
-
-- Issue #28314: Fix function declaration (C flags) for the getiterator() method
- of xml.etree.ElementTree.Element.
-
-- Issue #28148: Stop using localtime() and gmtime() in the time
- module.
-
- Introduced platform independent _PyTime_localtime API that is
- similar to POSIX localtime_r, but available on all platforms. Patch
- by Ed Schouten.
-
-- Issue #28253: Fixed calendar functions for extreme months: 0001-01
- and 9999-12.
-
- Methods itermonthdays() and itermonthdays2() are reimplemented so
- that they don't call itermonthdates() which can cause datetime.date
- under/overflow.
-
-- Issue #28275: Fixed possible use after free in the decompress()
- methods of the LZMADecompressor and BZ2Decompressor classes.
- Original patch by John Leitch.
-
-- Issue #27897: Fixed possible crash in sqlite3.Connection.create_collation()
- if pass invalid string-like object as a name. Patch by Xiang Zhang.
-
-- Issue #18844: random.choices() now has k as a keyword-only argument
- to improve the readability of common cases and come into line
- with the signature used in other languages.
-
-- Issue #18893: Fix invalid exception handling in Lib/ctypes/macholib/dyld.py.
- Patch by Madison May.
-
-- Issue #27611: Fixed support of default root window in the tkinter.tix module.
- Added the master parameter in the DisplayStyle constructor.
-
-- Issue #27348: In the traceback module, restore the formatting of exception
- messages like "Exception: None". This fixes a regression introduced in
- 3.5a2.
-
-- Issue #25651: Allow falsy values to be used for msg parameter of subTest().
-
-- Issue #27778: Fix a memory leak in os.getrandom() when the getrandom() is
- interrupted by a signal and a signal handler raises a Python exception.
-
-- Issue #28200: Fix memory leak on Windows in the os module (fix
- path_converter() function).
-
-- Issue #25400: RobotFileParser now correctly returns default values for
- crawl_delay and request_rate. Initial patch by Peter Wirtz.
-
-- Issue #27932: Prevent memory leak in win32_ver().
-
-- Fix UnboundLocalError in socket._sendfile_use_sendfile.
-
-- Issue #28075: Check for ERROR_ACCESS_DENIED in Windows implementation of
- os.stat(). Patch by Eryk Sun.
-
-- Issue #22493: Warning message emitted by using inline flags in the middle of
- regular expression now contains a (truncated) regex pattern.
- Patch by Tim Graham.
-
-- Issue #25270: Prevent codecs.escape_encode() from raising SystemError when
- an empty bytestring is passed.
-
-- Issue #28181: Get antigravity over HTTPS. Patch by Kaartic Sivaraam.
-
-- Issue #25895: Enable WebSocket URL schemes in urllib.parse.urljoin.
- Patch by Gergely Imreh and Markus Holtermann.
-
-- Issue #28114: Fix a crash in parse_envlist() when env contains byte strings.
- Patch by Eryk Sun.
-
-- Issue #27599: Fixed buffer overrun in binascii.b2a_qp() and binascii.a2b_qp().
-
-- Issue #27906: Fix socket accept exhaustion during high TCP traffic.
- Patch by Kevin Conway.
-
-- Issue #28174: Handle when SO_REUSEPORT isn't properly supported.
- Patch by Seth Michael Larson.
-
-- Issue #26654: Inspect functools.partial in asyncio.Handle.__repr__.
- Patch by iceboy.
-
-- Issue #26909: Fix slow pipes IO in asyncio.
- Patch by INADA Naoki.
-
-- Issue #28176: Fix callbacks race in asyncio.SelectorLoop.sock_connect.
-
-- Issue #27759: Fix selectors incorrectly retain invalid file descriptors.
- Patch by Mark Williams.
-
-- Issue #28325: Remove vestigial MacOS 9 macurl2path module and its tests.
-
-- Issue #28368: Refuse monitoring processes if the child watcher has
- no loop attached.
- Patch by Vincent Michel.
-
-- Issue #28369: Raise RuntimeError when transport's FD is used with
- add_reader, add_writer, etc.
-
-- Issue #28370: Speedup asyncio.StreamReader.readexactly.
- Patch by Коренберг Марк.
-
-- Issue #28371: Deprecate passing asyncio.Handles to run_in_executor.
-
-- Issue #28372: Fix asyncio to support formatting of non-python coroutines.
-
-- Issue #28399: Remove UNIX socket from FS before binding.
- Patch by Коренберг Марк.
-
-- Issue #27972: Prohibit Tasks to await on themselves.
-
-- Issue #24142: Reading a corrupt config file left configparser in an
- invalid state. Original patch by Florian Höch.
-
-- Issue #29581: ABCMeta.__new__ now accepts **kwargs, allowing abstract base
- classes to use keyword parameters in __init_subclass__. Patch by Nate Soares.
-
-Windows
--------
-
-- bpo-29579: Removes readme.txt from the installer.
-
-- Issue #25778: winreg does not truncate string correctly (Patch by Eryk Sun)
-
-- Issue #28896: Deprecate WindowsRegistryFinder and disable it by default
-
-- Issue #28522: Fixes mishandled buffer reallocation in getpathp.c
-
-- Issue #28402: Adds signed catalog files for stdlib on Windows.
-
-- Issue #28333: Enables Unicode for ps1/ps2 and input() prompts. (Patch by
- Eryk Sun)
-
-- Issue #28251: Improvements to help manuals on Windows.
-
-- Issue #28110: launcher.msi has different product codes between 32-bit and
- 64-bit
-
-- Issue #28161: Opening CON for write access fails
-
-- Issue #28162: WindowsConsoleIO readall() fails if first line starts with
- Ctrl+Z
-
-- Issue #28163: WindowsConsoleIO fileno() passes wrong flags to
- _open_osfhandle
-
-- Issue #28164: _PyIO_get_console_type fails for various paths
-
-- Issue #28137: Renames Windows path file to ._pth
-
-- Issue #28138: Windows ._pth file should allow import site
-
-C API
------
-
-- Issue #27867: Function PySlice_GetIndicesEx() is deprecated and replaced with
- a macro if Py_LIMITED_API is not set or set to the value between 0x03050400
- and 0x03060000 (not including) or 0x03060100 or higher. Added functions
- PySlice_Unpack() and PySlice_AdjustIndices().
-
-- Issue #29083: Fixed the declaration of some public API functions.
- PyArg_VaParse() and PyArg_VaParseTupleAndKeywords() were not available in
- limited API. PyArg_ValidateKeywordArguments(), PyArg_UnpackTuple() and
- Py_BuildValue() were not available in limited API of version < 3.3 when
- PY_SSIZE_T_CLEAN is defined.
-
-- Issue #28769: The result of PyUnicode_AsUTF8AndSize() and PyUnicode_AsUTF8()
- is now of type ``const char *`` rather of ``char *``.
-
-- Issue #29058: All stable API extensions added after Python 3.2 are now
- available only when Py_LIMITED_API is set to the PY_VERSION_HEX value of
- the minimum Python version supporting this API.
-
-Library
--------
-
- bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords
are not strings. Patch by Michael Seifert.
@@ -966,7 +168,6 @@ Library
- bpo-29110: Fix file object leak in aifc.open() when file is given as a
filesystem path and is not in valid AIFF format. Patch by Anthony Zhang.
-- Issue #24932: Use proper command line parsing in _testembed
- Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap,
improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi,
--
GitLab
From 1688e64925967ba41df682211efaa8d066c4b3e2 Mon Sep 17 00:00:00 2001
From: Ned Deily
Date: Tue, 21 Mar 2017 20:39:58 -0400
Subject: [PATCH 0067/1433] Bump to 3.6.2rc1 development.
---
Include/patchlevel.h | 2 +-
Misc/NEWS | 50 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/Include/patchlevel.h b/Include/patchlevel.h
index 54a9ab6ff7..a658e9f584 100644
--- a/Include/patchlevel.h
+++ b/Include/patchlevel.h
@@ -23,7 +23,7 @@
#define PY_RELEASE_SERIAL 0
/* Version as a string */
-#define PY_VERSION "3.6.1"
+#define PY_VERSION "3.6.1+"
/*--end constants--*/
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
diff --git a/Misc/NEWS b/Misc/NEWS
index 4807bd0fcc..bb37f0479e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -2,6 +2,56 @@
Python News
+++++++++++
+What's New in Python 3.6.2 release candidate 1?
+===============================================
+
+*Release date: XXXX-XX-XX*
+
+Core and Builtins
+-----------------
+
+- bpo-29859: Show correct error messages when any of the pthread_* calls in
+ thread_pthread.h fails.
+
+- bpo-28876: ``bool(range)`` works even if ``len(range)``
+ raises :exc:`OverflowError`.
+
+- bpo-29600: Fix wrapping coroutine return values in StopIteration.
+
+- bpo-28856: Fix an oversight that %b format for bytes should support objects
+ follow the buffer protocol.
+
+- bpo-29714: Fix a regression that bytes format may fail when containing zero
+ bytes inside.
+
+Library
+-------
+
+- bpo-25455: Fixed crashes in repr of recursive buffered file-like objects.
+
+- bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords
+ are not strings. Patch by Michael Seifert.
+
+- bpo-29742: get_extra_info() raises exception if get called on closed ssl transport.
+ Patch by Nikolay Kim.
+
+- bpo-8256: Fixed possible failing or crashing input() if attributes "encoding"
+ or "errors" of sys.stdin or sys.stdout are not set or are not strings.
+
+- bpo-28298: Fix a bug that prevented array 'Q', 'L' and 'I' from accepting big
+ intables (objects that have __int__) as elements. Patch by Oren Milman.
+
+- bpo-28231: The zipfile module now accepts path-like objects for external
+ paths.
+
+- bpo-26915: index() and count() methods of collections.abc.Sequence now
+ check identity before checking equality when do comparisons.
+
+- bpo-29615: SimpleXMLRPCDispatcher no longer chains KeyError (or any other
+ exception) to exception(s) raised in the dispatched methods.
+ Patch by Petr Motejlek.
+
+
What's New in Python 3.6.1?
===========================
--
GitLab
From af839fe2fef12dbbc8083fc7f01daee48a85a916 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Wed, 22 Mar 2017 07:45:23 +0200
Subject: [PATCH 0068/1433] bpo-29864: Don't use Py_SIZE for dict object.
(#747) (#750)
---
Objects/dictobject.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index a0c1977037..8bcc931148 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1929,7 +1929,7 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
PyObject *key;
Py_hash_t hash;
- if (dictresize(mp, ESTIMATE_SIZE(Py_SIZE(iterable)))) {
+ if (dictresize(mp, ESTIMATE_SIZE(((PyDictObject *)iterable)->ma_used))) {
Py_DECREF(d);
return NULL;
}
--
GitLab
From 72c51136c6269112f4c37ef14f972c89b92c272c Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Wed, 22 Mar 2017 15:26:53 +0800
Subject: [PATCH 0069/1433] fix function name in tabnanny documentation
(GH-762)
---
Doc/library/tabnanny.rst | 8 ++++----
Lib/tabnanny.py | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Doc/library/tabnanny.rst b/Doc/library/tabnanny.rst
index 1edb0fbabb..dfe688a2f9 100644
--- a/Doc/library/tabnanny.rst
+++ b/Doc/library/tabnanny.rst
@@ -48,14 +48,14 @@ described below.
.. exception:: NannyNag
- Raised by :func:`tokeneater` if detecting an ambiguous indent. Captured and
+ Raised by :func:`process_tokens` if detecting an ambiguous indent. Captured and
handled in :func:`check`.
-.. function:: tokeneater(type, token, start, end, line)
+.. function:: process_tokens(tokens)
- This function is used by :func:`check` as a callback parameter to the function
- :func:`tokenize.tokenize`.
+ This function is used by :func:`check` to process tokens generated by the
+ :mod:`tokenize` module.
.. XXX document errprint, format_witnesses, Whitespace, check_equal, indents,
reset_globals
diff --git a/Lib/tabnanny.py b/Lib/tabnanny.py
index 46e0f56a39..bfb670c902 100755
--- a/Lib/tabnanny.py
+++ b/Lib/tabnanny.py
@@ -59,7 +59,7 @@ def main():
class NannyNag(Exception):
"""
- Raised by tokeneater() if detecting an ambiguous indent.
+ Raised by process_tokens() if detecting an ambiguous indent.
Captured and handled in check().
"""
def __init__(self, lineno, msg, line):
--
GitLab
From c0f3e21a23356133c30926b6cdf3e0e70cbc8486 Mon Sep 17 00:00:00 2001
From: INADA Naoki
Date: Wed, 22 Mar 2017 17:14:03 +0900
Subject: [PATCH 0070/1433] doc: minor fix for library/profile (GH-766)
(cherry picked from commit bd3d8ba3b22da0bad018b53a3e6610ae03c5aa49)
---
Doc/library/profile.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst
index bd67fe486a..b4b1479e2c 100644
--- a/Doc/library/profile.rst
+++ b/Doc/library/profile.rst
@@ -85,11 +85,11 @@ next line: ``Ordered by: standard name``, indicates that the text string in the
far right column was used to sort the output. The column headings include:
ncalls
- for the number of calls,
+ for the number of calls.
tottime
- for the total time spent in the given function (and excluding time made in
- calls to sub-functions)
+ for the total time spent in the given function (and excluding time made in
+ calls to sub-functions)
percall
is the quotient of ``tottime`` divided by ``ncalls``
--
GitLab
From 906118d8c68160ed4a3d15cec803d1ee57836517 Mon Sep 17 00:00:00 2001
From: INADA Naoki
Date: Wed, 22 Mar 2017 21:09:41 +0900
Subject: [PATCH 0071/1433] bpo-28331: fix impl-detail label is removed when
content is translated. (GH-769)
(cherry picked from commit c351ce6a2c923c5016e48ecbf7b1e4833031d154)
---
Doc/tools/extensions/pyspecific.py | 14 ++++++++++++--
Doc/tools/templates/dummy.html | 6 ++++++
2 files changed, 18 insertions(+), 2 deletions(-)
create mode 100644 Doc/tools/templates/dummy.html
diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py
index 1141d6c5ac..865f2edee0 100644
--- a/Doc/tools/extensions/pyspecific.py
+++ b/Doc/tools/extensions/pyspecific.py
@@ -21,6 +21,7 @@ from docutils import nodes, utils
from sphinx import addnodes
from sphinx.builders import Builder
+from sphinx.locale import translators
from sphinx.util.nodes import split_explicit_title
from sphinx.util.compat import Directive
from sphinx.writers.html import HTMLTranslator
@@ -103,16 +104,25 @@ class ImplementationDetail(Directive):
optional_arguments = 1
final_argument_whitespace = True
+ # This text is copied to templates/dummy.html
+ label_text = 'CPython implementation detail:'
+
def run(self):
pnode = nodes.compound(classes=['impl-detail'])
+ label = translators['sphinx'].gettext(self.label_text)
content = self.content
- add_text = nodes.strong('CPython implementation detail:',
- 'CPython implementation detail:')
+ add_text = nodes.strong(label, label)
if self.arguments:
n, m = self.state.inline_text(self.arguments[0], self.lineno)
pnode.append(nodes.paragraph('', '', *(n + m)))
self.state.nested_parse(content, self.content_offset, pnode)
if pnode.children and isinstance(pnode[0], nodes.paragraph):
+ content = nodes.inline(pnode[0].rawsource, translatable=True)
+ content.source = pnode[0].source
+ content.line = pnode[0].line
+ content += pnode[0].children
+ pnode[0].replace_self(nodes.paragraph('', '', content,
+ translatable=False))
pnode[0].insert(0, add_text)
pnode[0].insert(1, nodes.Text(' '))
else:
diff --git a/Doc/tools/templates/dummy.html b/Doc/tools/templates/dummy.html
new file mode 100644
index 0000000000..6e43be2323
--- /dev/null
+++ b/Doc/tools/templates/dummy.html
@@ -0,0 +1,6 @@
+This file is not an actual template, but used to add some
+texts in extensions to sphinx.pot file.
+
+In extensions/pyspecific.py:
+
+{% trans %}CPython implementation detail:{% endtrans %}
--
GitLab
From ee51327a2329eb9c2bfbb6ea673cfab4299450b0 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Wed, 22 Mar 2017 18:56:56 -0700
Subject: [PATCH 0072/1433] Remove an outdated statement in execution model
docs (GH-754) (GH-775)
(cherry picked from commit fad7f1560669af1766c583c7ef242c55d8c8de41)
---
Doc/reference/executionmodel.rst | 6 ------
1 file changed, 6 deletions(-)
diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst
index 5f1ea92ed4..f0dbbd1edf 100644
--- a/Doc/reference/executionmodel.rst
+++ b/Doc/reference/executionmodel.rst
@@ -194,12 +194,6 @@ This means that the following code will print 42::
i = 42
f()
-There are several cases where Python statements are illegal when used in
-conjunction with nested scopes that contain free variables.
-
-If a variable is referenced in an enclosing scope, it is illegal to delete the
-name. An error will be reported at compile time.
-
.. XXX from * also invalid with relative imports (at least currently)
The :func:`eval` and :func:`exec` functions do not have access to the full
--
GitLab
From 90eafdb1546604c0e9bc207723484b6816570cfe Mon Sep 17 00:00:00 2001
From: Christophe Zeitouny
Date: Fri, 24 Mar 2017 04:20:40 -0700
Subject: [PATCH 0073/1433] faulthandler: Restore the old sigaltstack during
teardown (GH-777) (GH-797)
(cherry picked from commit 20fbf8accd494fd15b0fc4c84928178c71ead4d1)
---
Misc/ACKS | 1 +
Misc/NEWS | 3 +++
Modules/faulthandler.c | 17 ++++++++++++++++-
3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/Misc/ACKS b/Misc/ACKS
index 03afeb8f38..2b23702f22 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1709,6 +1709,7 @@ Artur Zaprzala
Mike Zarnstorff
Yury V. Zaytsev
Siebren van der Zee
+Christophe Zeitouny
Nickolai Zeldovich
Yuxiao Zeng
Uwe Zessin
diff --git a/Misc/NEWS b/Misc/NEWS
index 1835d1e389..687c5c06ef 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,9 @@ Core and Builtins
Library
-------
+- bpo-29884: faulthandler: Restore the old sigaltstack during teardown.
+ Patch by Christophe Zeitouny.
+
- bpo-25455: Fixed crashes in repr of recursive buffered file-like objects.
- bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 1c1e4fb7d1..2f8b624fd1 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -124,6 +124,7 @@ static const size_t faulthandler_nsignals = \
#ifdef HAVE_SIGALTSTACK
static stack_t stack;
+static stack_t old_stack;
#endif
@@ -1310,7 +1311,7 @@ int _PyFaulthandler_Init(void)
stack.ss_size = SIGSTKSZ;
stack.ss_sp = PyMem_Malloc(stack.ss_size);
if (stack.ss_sp != NULL) {
- err = sigaltstack(&stack, NULL);
+ err = sigaltstack(&stack, &old_stack);
if (err) {
PyMem_Free(stack.ss_sp);
stack.ss_sp = NULL;
@@ -1366,6 +1367,20 @@ void _PyFaulthandler_Fini(void)
faulthandler_disable();
#ifdef HAVE_SIGALTSTACK
if (stack.ss_sp != NULL) {
+ /* Fetch the current alt stack */
+ stack_t current_stack;
+ if (sigaltstack(NULL, ¤t_stack) == 0) {
+ if (current_stack.ss_sp == stack.ss_sp) {
+ /* The current alt stack is the one that we installed.
+ It is safe to restore the old stack that we found when
+ we installed ours */
+ sigaltstack(&old_stack, NULL);
+ } else {
+ /* Someone switched to a different alt stack and didn't
+ restore ours when they were done (if they're done).
+ There's not much we can do in this unlikely case */
+ }
+ }
PyMem_Free(stack.ss_sp);
stack.ss_sp = NULL;
}
--
GitLab
From cc3331fec8b7a61c3f06c097eac85bfa38490758 Mon Sep 17 00:00:00 2001
From: Antoine Pitrou
Date: Fri, 24 Mar 2017 14:45:34 +0100
Subject: [PATCH 0074/1433] bpo-29861: release references to multiprocessing
Pool tasks (#743) (#800)
* bpo-29861: release references to multiprocessing Pool tasks (#743)
* bpo-29861: release references to multiprocessing Pool tasks
Release references to tasks, their arguments and their results as soon
as they are finished, instead of keeping them alive until another task
arrives.
* Comments in test
(cherry picked from commit 8988945cdc27ffa86ba8c624e095b51c459f5154)
* Fix Misc/NEWS (hopefully)
---
Lib/multiprocessing/pool.py | 7 ++++++-
Lib/test/_test_multiprocessing.py | 28 ++++++++++++++++++++++++++++
Misc/NEWS | 3 +++
3 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/Lib/multiprocessing/pool.py b/Lib/multiprocessing/pool.py
index ffdf42614d..ae8cec4479 100644
--- a/Lib/multiprocessing/pool.py
+++ b/Lib/multiprocessing/pool.py
@@ -128,6 +128,8 @@ def worker(inqueue, outqueue, initializer=None, initargs=(), maxtasks=None,
util.debug("Possible encoding error while sending result: %s" % (
wrapped))
put((job, i, (False, wrapped)))
+
+ task = job = result = func = args = kwds = None
completed += 1
util.debug('worker exiting after %d tasks' % completed)
@@ -402,10 +404,11 @@ class Pool(object):
if set_length:
util.debug('doing set_length()')
set_length(i+1)
+ finally:
+ task = taskseq = job = None
else:
util.debug('task handler got sentinel')
-
try:
# tell result handler to finish when cache is empty
util.debug('task handler sending sentinel to result handler')
@@ -445,6 +448,7 @@ class Pool(object):
cache[job]._set(i, obj)
except KeyError:
pass
+ task = job = obj = None
while cache and thread._state != TERMINATE:
try:
@@ -461,6 +465,7 @@ class Pool(object):
cache[job]._set(i, obj)
except KeyError:
pass
+ task = job = obj = None
if hasattr(outqueue, '_reader'):
util.debug('ensuring that outqueue is not full')
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index b5f4782546..1d3bb0f8ba 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -18,6 +18,7 @@ import random
import logging
import struct
import operator
+import weakref
import test.support
import test.support.script_helper
@@ -1738,6 +1739,19 @@ def raise_large_valuerror(wait):
time.sleep(wait)
raise ValueError("x" * 1024**2)
+def identity(x):
+ return x
+
+class CountedObject(object):
+ n_instances = 0
+
+ def __new__(cls):
+ cls.n_instances += 1
+ return object.__new__(cls)
+
+ def __del__(self):
+ type(self).n_instances -= 1
+
class SayWhenError(ValueError): pass
def exception_throwing_generator(total, when):
@@ -1746,6 +1760,7 @@ def exception_throwing_generator(total, when):
raise SayWhenError("Somebody said when")
yield i
+
class _TestPool(BaseTestCase):
@classmethod
@@ -2000,6 +2015,19 @@ class _TestPool(BaseTestCase):
# check that we indeed waited for all jobs
self.assertGreater(time.time() - t_start, 0.9)
+ def test_release_task_refs(self):
+ # Issue #29861: task arguments and results should not be kept
+ # alive after we are done with them.
+ objs = [CountedObject() for i in range(10)]
+ refs = [weakref.ref(o) for o in objs]
+ self.pool.map(identity, objs)
+
+ del objs
+ self.assertEqual(set(wr() for wr in refs), {None})
+ # With a process pool, copies of the objects are returned, check
+ # they were released too.
+ self.assertEqual(CountedObject.n_instances, 0)
+
def raising():
raise KeyError("key")
diff --git a/Misc/NEWS b/Misc/NEWS
index 687c5c06ef..0c7eaea5a8 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,9 @@ Core and Builtins
Library
-------
+- bpo-29861: Release references to tasks, their arguments and their results
+ as soon as they are finished in multiprocessing.Pool.
+
- bpo-29884: faulthandler: Restore the old sigaltstack during teardown.
Patch by Christophe Zeitouny.
--
GitLab
From 8c8785b2f8e4048cef350f89c686266f4519b67c Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Fri, 24 Mar 2017 21:46:25 +0200
Subject: [PATCH 0075/1433] =?UTF-8?q?bpo-25803:=20Avoid=20incorrect=20erro?=
=?UTF-8?q?rs=20raised=20by=20Path.mkdir(exist=5Fok=3DTrue)=E2=80=A6=20(#8?=
=?UTF-8?q?06)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
when the OS gives priority to errors such as EACCES over EEXIST.
(cherry picked from commit af7b9ec5c855366feef4c67dc492d64b3baf84ca)
---
Lib/pathlib.py | 32 +++++++++++++++-----------------
Lib/test/test_pathlib.py | 5 +++++
Misc/NEWS | 3 +++
3 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/Lib/pathlib.py b/Lib/pathlib.py
index 9f347216b1..8c1cb96bad 100644
--- a/Lib/pathlib.py
+++ b/Lib/pathlib.py
@@ -1220,25 +1220,23 @@ class Path(PurePath):
os.close(fd)
def mkdir(self, mode=0o777, parents=False, exist_ok=False):
+ """
+ Create a new directory at this given path.
+ """
if self._closed:
self._raise_closed()
- if not parents:
- try:
- self._accessor.mkdir(self, mode)
- except FileExistsError:
- if not exist_ok or not self.is_dir():
- raise
- else:
- try:
- self._accessor.mkdir(self, mode)
- except FileExistsError:
- if not exist_ok or not self.is_dir():
- raise
- except OSError as e:
- if e.errno != ENOENT or self.parent == self:
- raise
- self.parent.mkdir(parents=True)
- self._accessor.mkdir(self, mode)
+ try:
+ self._accessor.mkdir(self, mode)
+ except FileNotFoundError:
+ if not parents or self.parent == self:
+ raise
+ self.parent.mkdir(parents=True)
+ self._accessor.mkdir(self, mode)
+ except OSError:
+ # Cannot rely on checking for EEXIST, since the operating system
+ # could give priority to other errors like EACCES or EROFS
+ if not exist_ok or not self.is_dir():
+ raise
def chmod(self, mode):
"""
diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py
index 88a93e5802..3ff9726d43 100644
--- a/Lib/test/test_pathlib.py
+++ b/Lib/test/test_pathlib.py
@@ -1776,6 +1776,11 @@ class _BasePathTest(object):
self.assertTrue(p.exists())
self.assertEqual(p.stat().st_ctime, st_ctime_first)
+ def test_mkdir_exist_ok_root(self):
+ # Issue #25803: A drive root could raise PermissionError on Windows
+ self.cls('/').resolve().mkdir(exist_ok=True)
+ self.cls('/').resolve().mkdir(parents=True, exist_ok=True)
+
@only_nt # XXX: not sure how to test this on POSIX
def test_mkdir_with_unknown_drive(self):
for d in 'ZYXWVUTSRQPONMLKJIHGFEDCBA':
diff --git a/Misc/NEWS b/Misc/NEWS
index 0c7eaea5a8..9798a3a449 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,9 @@ Core and Builtins
Library
-------
+- bpo-25803: Avoid incorrect errors raised by Path.mkdir(exist_ok=True)
+ when the OS gives priority to errors such as EACCES over EEXIST.
+
- bpo-29861: Release references to tasks, their arguments and their results
as soon as they are finished in multiprocessing.Pool.
--
GitLab
From 74bfcc314b188e1e8c90e442270e36d6510755ee Mon Sep 17 00:00:00 2001
From: Brett Cannon
Date: Fri, 24 Mar 2017 14:18:53 -0700
Subject: [PATCH 0076/1433] bpo-28810: Document remaining bytecode changes in
3.6 (GH-651) (GH-808)
(cherry picked from commit 8f9e1bbf2dbdf46a0bf920279568a31460043376)
---
Doc/library/dis.rst | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index 11d056901b..c795782034 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -20,6 +20,10 @@ interpreter.
between versions of Python. Use of this module should not be considered to
work across Python VMs or Python releases.
+ .. versionchanged:: 3.6
+ Use 2 bytes for each instruction. Previously the number of bytes varied
+ by instruction.
+
Example: Given the function :func:`myfunc`::
@@ -210,6 +214,11 @@ operation is being performed, so the intermediate analysis object isn't useful:
This generator function uses the ``co_firstlineno`` and ``co_lnotab``
attributes of the code object *code* to find the offsets which are starts of
lines in the source code. They are generated as ``(offset, lineno)`` pairs.
+ See :source:`Objects/lnotab_notes.txt` for the ``co_lnotab`` format and
+ how to decode it.
+
+ .. versionchanged:: 3.6
+ Line numbers can be decreasing. Before, they were always increasing.
.. function:: findlabels(code)
@@ -1105,8 +1114,13 @@ All of the following opcodes use their arguments.
.. opcode:: HAVE_ARGUMENT
This is not really an opcode. It identifies the dividing line between
- opcodes which don't take arguments ``< HAVE_ARGUMENT`` and those which do
- ``>= HAVE_ARGUMENT``.
+ opcodes which don't use their argument and those that do
+ (``< HAVE_ARGUMENT`` and ``>= HAVE_ARGUMENT``, respectively).
+
+ .. versionchanged:: 3.6
+ Now every instruction has an argument, but opcodes ``< HAVE_ARGUMENT``
+ ignore it. Before, only opcodes ``>= HAVE_ARGUMENT`` had an argument.
+
.. _opcode_collections:
--
GitLab
From 5dafaece67cb576ef96579fb5ddcbf62e0827b0d Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Fri, 24 Mar 2017 20:04:40 -0700
Subject: [PATCH 0077/1433] bpo-29892: Fix wrong markup on doc-lib-functions
(GH-802) (GH-810)
(cherry picked from commit 29540cdf6c66df9f806375a95078c0c63192ef78)
---
Doc/library/functions.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index c26037bd9e..64c9569766 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -1072,7 +1072,7 @@ are always available. They are listed here in alphabetical order.
* The ``'x'`` mode was added.
* :exc:`IOError` used to be raised, it is now an alias of :exc:`OSError`.
* :exc:`FileExistsError` is now raised if the file opened in exclusive
- * creation mode (``'x'``) already exists.
+ creation mode (``'x'``) already exists.
.. versionchanged::
3.4
--
GitLab
From 8b82236952619c3838865ff535e5ce77b59b4a78 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sat, 25 Mar 2017 03:41:59 -0700
Subject: [PATCH 0078/1433] bpo-29862: Fix grammar in importlib.reload()
exception (GH-809) (GH-811)
(cherry picked from commit 9f0aa4843f8c26937d5817f27cac4aae9c0a034f)
---
Lib/importlib/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Lib/importlib/__init__.py b/Lib/importlib/__init__.py
index b6a9f82e05..8b11d22b02 100644
--- a/Lib/importlib/__init__.py
+++ b/Lib/importlib/__init__.py
@@ -136,7 +136,7 @@ def reload(module):
"""
if not module or not isinstance(module, types.ModuleType):
- raise TypeError("reload() argument must be module")
+ raise TypeError("reload() argument must be a module")
try:
name = module.__spec__.name
except AttributeError:
--
GitLab
From ceff32fb833e7be42508ffa73344e2e56865e54b Mon Sep 17 00:00:00 2001
From: Ned Deily
Date: Sun, 26 Mar 2017 13:58:13 -0400
Subject: [PATCH 0079/1433] bpo-29888: Fix the link referring to the "Python
download page" (GH-824) (GH-826)
(cherry picked from commit f8beb9831acd5cf80b9c56aea5864e16118c5400)
---
Doc/tools/templates/download.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/tools/templates/download.html b/Doc/tools/templates/download.html
index de84ae3abc..3a05cb6979 100644
--- a/Doc/tools/templates/download.html
+++ b/Doc/tools/templates/download.html
@@ -42,7 +42,7 @@ in the table are the size of the download files in megabytes.
These archives contain all the content in the documentation.
HTML Help (.chm) files are made available in the "Windows" section
-on the Python
+on the Python
download page.
--
GitLab
From d2fc7824104172b47cdcea09d7ce699d5bfc2ba6 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sun, 26 Mar 2017 19:53:37 -0700
Subject: [PATCH 0080/1433] import sys before we use it on line 9 (GH-828)
(GH-833)
(cherry picked from commit 0579e81f30d00da562f021760d5b6a9c35186520)
---
Lib/idlelib/pyshell.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py
index f3ee391ca0..dd6c997abc 100755
--- a/Lib/idlelib/pyshell.py
+++ b/Lib/idlelib/pyshell.py
@@ -1,5 +1,7 @@
#! /usr/bin/env python3
+import sys
+
try:
from tkinter import *
except ImportError:
@@ -25,7 +27,6 @@ from platform import python_version, system
import re
import socket
import subprocess
-import sys
import threading
import time
import tokenize
--
GitLab
From abc68484b2c523b500802cb8e8913531e0ff9a8d Mon Sep 17 00:00:00 2001
From: Zachary Ware
Date: Sun, 26 Mar 2017 22:53:57 -0500
Subject: [PATCH 0081/1433] Treat Sphinx warnings as errors (GH-832) (GH-834)
* Treat Sphinx warnings as errors (GH-832)
(cherry picked from commit 334e9ec938ea9876baadef15edb135d6d2aff30c)
* Remove unused suspicious rules
---
.travis.yml | 2 +-
Doc/tools/susp-ignored.csv | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 66f03dc716..3496a1abba 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -39,7 +39,7 @@ matrix:
- cd Doc
- make venv
script:
- - make check suspicious html PYTHON="./venv/bin/python" SPHINXBUILD="./venv/bin/python -m sphinx" SPHINXOPTS="-q"
+ - make check suspicious html PYTHON="./venv/bin/python" SPHINXBUILD="./venv/bin/python -m sphinx" SPHINXOPTS="-q -W"
- os: linux
language: c
compiler: clang
diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv
index c6e03119ae..166374cb90 100644
--- a/Doc/tools/susp-ignored.csv
+++ b/Doc/tools/susp-ignored.csv
@@ -324,6 +324,4 @@ whatsnew/3.5,,::,>>> addr6 = ipaddress.IPv6Address('::1')
whatsnew/3.5,,:root,ERROR:root:exception
whatsnew/3.5,,:exception,ERROR:root:exception
whatsnew/changelog,,:version,import sys; I = version[:version.index(' ')]
-whatsnew/changelog,,:gz,": TarFile opened with external fileobj and ""w:gz"" mode didn't"
-whatsnew/changelog,,::,": Use ""127.0.0.1"" or ""::1"" instead of ""localhost"" as much as"
whatsnew/changelog,,`,"for readability (was ""`"")."
--
GitLab
From bc2031470eac4b199692921b4e97730c85ceb678 Mon Sep 17 00:00:00 2001
From: Zachary Ware
Date: Mon, 27 Mar 2017 00:35:56 -0500
Subject: [PATCH 0082/1433] Minor test cleanup (GH-837) (GH-838)
* Remove unused test file
* Remove duplicated text in sndhdrdata README
(cherry picked from commit b8a7daf077dab18e9e3701c5380b542ae0aa9a94)
---
Lib/test/185test.db | Bin 16384 -> 0 bytes
Lib/test/sndhdrdata/README | 7 -------
2 files changed, 7 deletions(-)
delete mode 100644 Lib/test/185test.db
diff --git a/Lib/test/185test.db b/Lib/test/185test.db
deleted file mode 100644
index 14cb5e258bc0961fa22527dcb5d947a6a0fd5480..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 16384
zcmZQz6HR1bU|?ck5O~PIAi%)Dz`(=6z{mi>3>;7f6O?8K(;#Vx0>-I%wU0rXAZCEf
zf%51`aX{QdM;k}28V!Nb5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R
z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fk74mO#J`(|M7p}|Hr`a|NsC0
zAlIcZFr+dtq%bhpq%blBgG5I0Xb6mkz_1SiM+Qgm`X1izZx|SuU%<+PVejuz4~~Yw
zXb4~lfktx%2GeRR5~D(+Aut*OqaiRF0;3@?8UjN$1Pl%T|Ns9N)XpEpqaiRF0;3@?
i8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd72GHv|BWwg_zi
diff --git a/Lib/test/sndhdrdata/README b/Lib/test/sndhdrdata/README
index 8a17c0041a..b2cb664615 100644
--- a/Lib/test/sndhdrdata/README
+++ b/Lib/test/sndhdrdata/README
@@ -3,10 +3,3 @@ following commands:
dd if=/dev/zero of=sndhdr.raw bs=20 count=1
sox -s -2 -c 2 -r 44100 sndhdr.raw sndhdr.
-
-Sound file samples used by Lib/test/test_sndhdr.py and generated using the
-following commands:
-
- dd if=/dev/zero of=sndhdr.raw bs=20 count=1
- sox -s -2 -c 2 -r 44100 sndhdr.raw sndhdr.
-
--
GitLab
From 08f9f71162dedeec51ad99bac1b26eb0ab014400 Mon Sep 17 00:00:00 2001
From: Brett Cannon
Date: Mon, 27 Mar 2017 16:46:31 -0700
Subject: [PATCH 0083/1433] Drop the standard gcc test build on Travis (GH-853)
(GH-859)
Instead have gcc be used for the coverage build so gcc is exercised in at least one place.
(cherry picked from commit ad2f9e2c8a0b44b3e6aec9d28ba59e13239236f7)
---
.travis.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 3496a1abba..5fee6cd767 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,11 +15,11 @@ os:
- linux
# macOS builds are disabled as the machines are under-provisioned on Travis,
# adding up to an extra hour completing a full CI run.
- #- osx
compiler:
- clang
- - gcc
+ # gcc also works, but to keep the # of concurrent builds down, we use one C
+ # compiler here and the other to run the coverage build.
env:
- TESTING=cpython
@@ -32,7 +32,7 @@ matrix:
include:
- os: linux
language: python
- python: 3.5
+ python: 3.6
env:
- TESTING=docs
before_script:
@@ -42,7 +42,7 @@ matrix:
- make check suspicious html PYTHON="./venv/bin/python" SPHINXBUILD="./venv/bin/python -m sphinx" SPHINXOPTS="-q -W"
- os: linux
language: c
- compiler: clang
+ compiler: gcc
env:
- TESTING=coverage
before_script:
--
GitLab
From 596506216104613591218c2896cdb49fa0b7e5bb Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Mon, 27 Mar 2017 17:02:29 -0700
Subject: [PATCH 0084/1433] bpo-29677: DOC: clarify documentation for `round`
(GH-357) (GH-862)
(cherry picked from commit 6003db7db5fec545c01923c198a5fdfca5a91538)
---
Doc/library/functions.rst | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 64c9569766..2c0ea71c47 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -1262,7 +1262,8 @@ are always available. They are listed here in alphabetical order.
closest multiple of 10 to the power minus *ndigits*; if two multiples are
equally close, rounding is done toward the even choice (so, for example,
both ``round(0.5)`` and ``round(-0.5)`` are ``0``, and ``round(1.5)`` is
- ``2``). The return value is an integer if called with one argument,
+ ``2``). Any integer value is valid for *ndigits* (positive, zero, or
+ negative). The return value is an integer if called with one argument,
otherwise of the same type as *number*.
.. note::
--
GitLab
From f01de61a8efea8319c65365898982f929d59a895 Mon Sep 17 00:00:00 2001
From: INADA Naoki
Date: Wed, 29 Mar 2017 00:25:26 +0900
Subject: [PATCH 0085/1433] bpo-29643: Fix check for --enable-optimizations
(GH-869)
The presence of the ``--enable-optimizations`` flag is indicated by the
value of ``$enableval``, but the configure script was checking ``$withval``,
resulting in the ``--enable-optimizations`` flag being effectively ignored.
(cherry picked from commit 8cea5929f52801b0ce5928b46ef836e99a24321a)
---
Misc/NEWS | 5 +++++
configure | 2 +-
configure.ac | 2 +-
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/Misc/NEWS b/Misc/NEWS
index 9798a3a449..45c5c78287 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -60,6 +60,11 @@ Library
exception) to exception(s) raised in the dispatched methods.
Patch by Petr Motejlek.
+Build
+-----
+
+- bpo-29643: Fix ``--enable-optimization`` didn't work.
+
What's New in Python 3.6.1?
===========================
diff --git a/configure b/configure
index abe1dc5abd..8bdb82ba4a 100755
--- a/configure
+++ b/configure
@@ -6521,7 +6521,7 @@ $as_echo_n "checking for --enable-optimizations... " >&6; }
# Check whether --enable-optimizations was given.
if test "${enable_optimizations+set}" = set; then :
enableval=$enable_optimizations;
-if test "$withval" != no
+if test "$enableval" != no
then
Py_OPT='true'
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
diff --git a/configure.ac b/configure.ac
index 9eacf52559..6b331d5742 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1274,7 +1274,7 @@ Py_OPT='false'
AC_MSG_CHECKING(for --enable-optimizations)
AC_ARG_ENABLE(optimizations, AS_HELP_STRING([--enable-optimizations], [Enable expensive optimizations (PGO, etc). Disabled by default.]),
[
-if test "$withval" != no
+if test "$enableval" != no
then
Py_OPT='true'
AC_MSG_RESULT(yes);
--
GitLab
From c4021af50526f488c0c280e7c7eaa83ef80ae1df Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Tue, 28 Mar 2017 09:33:54 -0700
Subject: [PATCH 0086/1433] bpo-16011: clarify that 'in' always returns a
boolean value (GH-874)
(cherry picked from commit 0ae7c8bd614d3aa1fcaf2d71a10ff1148c80d9b5)
---
Doc/reference/expressions.rst | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst
index f4a82699b0..d80768ac07 100644
--- a/Doc/reference/expressions.rst
+++ b/Doc/reference/expressions.rst
@@ -1431,28 +1431,29 @@ Membership test operations
--------------------------
The operators :keyword:`in` and :keyword:`not in` test for membership. ``x in
-s`` evaluates to true if *x* is a member of *s*, and false otherwise. ``x not
-in s`` returns the negation of ``x in s``. All built-in sequences and set types
-support this as well as dictionary, for which :keyword:`in` tests whether the
-dictionary has a given key. For container types such as list, tuple, set,
-frozenset, dict, or collections.deque, the expression ``x in y`` is equivalent
+s`` evaluates to ``True`` if *x* is a member of *s*, and ``False`` otherwise.
+``x not in s`` returns the negation of ``x in s``. All built-in sequences and
+set types support this as well as dictionary, for which :keyword:`in` tests
+whether the dictionary has a given key. For container types such as list, tuple,
+set, frozenset, dict, or collections.deque, the expression ``x in y`` is equivalent
to ``any(x is e or x == e for e in y)``.
-For the string and bytes types, ``x in y`` is true if and only if *x* is a
+For the string and bytes types, ``x in y`` is ``True`` if and only if *x* is a
substring of *y*. An equivalent test is ``y.find(x) != -1``. Empty strings are
always considered to be a substring of any other string, so ``"" in "abc"`` will
return ``True``.
For user-defined classes which define the :meth:`__contains__` method, ``x in
-y`` is true if and only if ``y.__contains__(x)`` is true.
+y`` returns ``True`` if ``y.__contains__(x)`` returns a true value, and
+``False`` otherwise.
For user-defined classes which do not define :meth:`__contains__` but do define
-:meth:`__iter__`, ``x in y`` is true if some value ``z`` with ``x == z`` is
+:meth:`__iter__`, ``x in y`` is ``True`` if some value ``z`` with ``x == z`` is
produced while iterating over ``y``. If an exception is raised during the
iteration, it is as if :keyword:`in` raised that exception.
Lastly, the old-style iteration protocol is tried: if a class defines
-:meth:`__getitem__`, ``x in y`` is true if and only if there is a non-negative
+:meth:`__getitem__`, ``x in y`` is ``True`` if and only if there is a non-negative
integer index *i* such that ``x == y[i]``, and all lower integer indices do not
raise :exc:`IndexError` exception. (If any other exception is raised, it is as
if :keyword:`in` raised that exception).
--
GitLab
From 346dcd65e6b832a35b4cfc15b7309b51a38e9ca2 Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Wed, 29 Mar 2017 12:50:28 +0800
Subject: [PATCH 0087/1433] bpo-28699: fix abnormal behaviour of pools in
multiprocessing.pool (GH-882)
an exception raised at the very first of an iterable would cause pools behave abnormally
(swallow the exception or hang)
---
Lib/multiprocessing/pool.py | 79 +++++++++++++++++++++----------
Lib/test/_test_multiprocessing.py | 59 ++++++++++++++++++++++-
Misc/NEWS | 4 ++
3 files changed, 117 insertions(+), 25 deletions(-)
diff --git a/Lib/multiprocessing/pool.py b/Lib/multiprocessing/pool.py
index ae8cec4479..a545f3c1a1 100644
--- a/Lib/multiprocessing/pool.py
+++ b/Lib/multiprocessing/pool.py
@@ -118,7 +118,7 @@ def worker(inqueue, outqueue, initializer=None, initargs=(), maxtasks=None,
try:
result = (True, func(*args, **kwds))
except Exception as e:
- if wrap_exception:
+ if wrap_exception and func is not _helper_reraises_exception:
e = ExceptionWithTraceback(e, e.__traceback__)
result = (False, e)
try:
@@ -133,6 +133,10 @@ def worker(inqueue, outqueue, initializer=None, initargs=(), maxtasks=None,
completed += 1
util.debug('worker exiting after %d tasks' % completed)
+def _helper_reraises_exception(ex):
+ 'Pickle-able helper function for use by _guarded_task_generation.'
+ raise ex
+
#
# Class representing a process pool
#
@@ -277,6 +281,17 @@ class Pool(object):
return self._map_async(func, iterable, starmapstar, chunksize,
callback, error_callback)
+ def _guarded_task_generation(self, result_job, func, iterable):
+ '''Provides a generator of tasks for imap and imap_unordered with
+ appropriate handling for iterables which throw exceptions during
+ iteration.'''
+ try:
+ i = -1
+ for i, x in enumerate(iterable):
+ yield (result_job, i, func, (x,), {})
+ except Exception as e:
+ yield (result_job, i+1, _helper_reraises_exception, (e,), {})
+
def imap(self, func, iterable, chunksize=1):
'''
Equivalent of `map()` -- can be MUCH slower than `Pool.map()`.
@@ -285,15 +300,23 @@ class Pool(object):
raise ValueError("Pool not running")
if chunksize == 1:
result = IMapIterator(self._cache)
- self._taskqueue.put((((result._job, i, func, (x,), {})
- for i, x in enumerate(iterable)), result._set_length))
+ self._taskqueue.put(
+ (
+ self._guarded_task_generation(result._job, func, iterable),
+ result._set_length
+ ))
return result
else:
assert chunksize > 1
task_batches = Pool._get_tasks(func, iterable, chunksize)
result = IMapIterator(self._cache)
- self._taskqueue.put((((result._job, i, mapstar, (x,), {})
- for i, x in enumerate(task_batches)), result._set_length))
+ self._taskqueue.put(
+ (
+ self._guarded_task_generation(result._job,
+ mapstar,
+ task_batches),
+ result._set_length
+ ))
return (item for chunk in result for item in chunk)
def imap_unordered(self, func, iterable, chunksize=1):
@@ -304,15 +327,23 @@ class Pool(object):
raise ValueError("Pool not running")
if chunksize == 1:
result = IMapUnorderedIterator(self._cache)
- self._taskqueue.put((((result._job, i, func, (x,), {})
- for i, x in enumerate(iterable)), result._set_length))
+ self._taskqueue.put(
+ (
+ self._guarded_task_generation(result._job, func, iterable),
+ result._set_length
+ ))
return result
else:
assert chunksize > 1
task_batches = Pool._get_tasks(func, iterable, chunksize)
result = IMapUnorderedIterator(self._cache)
- self._taskqueue.put((((result._job, i, mapstar, (x,), {})
- for i, x in enumerate(task_batches)), result._set_length))
+ self._taskqueue.put(
+ (
+ self._guarded_task_generation(result._job,
+ mapstar,
+ task_batches),
+ result._set_length
+ ))
return (item for chunk in result for item in chunk)
def apply_async(self, func, args=(), kwds={}, callback=None,
@@ -323,7 +354,7 @@ class Pool(object):
if self._state != RUN:
raise ValueError("Pool not running")
result = ApplyResult(self._cache, callback, error_callback)
- self._taskqueue.put(([(result._job, None, func, args, kwds)], None))
+ self._taskqueue.put(([(result._job, 0, func, args, kwds)], None))
return result
def map_async(self, func, iterable, chunksize=None, callback=None,
@@ -354,8 +385,14 @@ class Pool(object):
task_batches = Pool._get_tasks(func, iterable, chunksize)
result = MapResult(self._cache, chunksize, len(iterable), callback,
error_callback=error_callback)
- self._taskqueue.put((((result._job, i, mapper, (x,), {})
- for i, x in enumerate(task_batches)), None))
+ self._taskqueue.put(
+ (
+ self._guarded_task_generation(result._job,
+ mapper,
+ task_batches),
+ None
+ )
+ )
return result
@staticmethod
@@ -377,33 +414,27 @@ class Pool(object):
for taskseq, set_length in iter(taskqueue.get, None):
task = None
- i = -1
try:
- for i, task in enumerate(taskseq):
+ # iterating taskseq cannot fail
+ for task in taskseq:
if thread._state:
util.debug('task handler found thread._state != RUN')
break
try:
put(task)
except Exception as e:
- job, ind = task[:2]
+ job, idx = task[:2]
try:
- cache[job]._set(ind, (False, e))
+ cache[job]._set(idx, (False, e))
except KeyError:
pass
else:
if set_length:
util.debug('doing set_length()')
- set_length(i+1)
+ idx = task[1] if task else -1
+ set_length(idx + 1)
continue
break
- except Exception as ex:
- job, ind = task[:2] if task else (0, 0)
- if job in cache:
- cache[job]._set(ind + 1, (False, ex))
- if set_length:
- util.debug('doing set_length()')
- set_length(i+1)
finally:
task = taskseq = job = None
else:
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index 1d3bb0f8ba..771bbf2426 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -1755,6 +1755,8 @@ class CountedObject(object):
class SayWhenError(ValueError): pass
def exception_throwing_generator(total, when):
+ if when == -1:
+ raise SayWhenError("Somebody said when")
for i in range(total):
if i == when:
raise SayWhenError("Somebody said when")
@@ -1833,6 +1835,32 @@ class _TestPool(BaseTestCase):
except multiprocessing.TimeoutError:
self.fail("pool.map_async with chunksize stalled on null list")
+ def test_map_handle_iterable_exception(self):
+ if self.TYPE == 'manager':
+ self.skipTest('test not appropriate for {}'.format(self.TYPE))
+
+ # SayWhenError seen at the very first of the iterable
+ with self.assertRaises(SayWhenError):
+ self.pool.map(sqr, exception_throwing_generator(1, -1), 1)
+ # again, make sure it's reentrant
+ with self.assertRaises(SayWhenError):
+ self.pool.map(sqr, exception_throwing_generator(1, -1), 1)
+
+ with self.assertRaises(SayWhenError):
+ self.pool.map(sqr, exception_throwing_generator(10, 3), 1)
+
+ class SpecialIterable:
+ def __iter__(self):
+ return self
+ def __next__(self):
+ raise SayWhenError
+ def __len__(self):
+ return 1
+ with self.assertRaises(SayWhenError):
+ self.pool.map(sqr, SpecialIterable(), 1)
+ with self.assertRaises(SayWhenError):
+ self.pool.map(sqr, SpecialIterable(), 1)
+
def test_async(self):
res = self.pool.apply_async(sqr, (7, TIMEOUT1,))
get = TimingWrapper(res.get)
@@ -1863,6 +1891,13 @@ class _TestPool(BaseTestCase):
if self.TYPE == 'manager':
self.skipTest('test not appropriate for {}'.format(self.TYPE))
+ # SayWhenError seen at the very first of the iterable
+ it = self.pool.imap(sqr, exception_throwing_generator(1, -1), 1)
+ self.assertRaises(SayWhenError, it.__next__)
+ # again, make sure it's reentrant
+ it = self.pool.imap(sqr, exception_throwing_generator(1, -1), 1)
+ self.assertRaises(SayWhenError, it.__next__)
+
it = self.pool.imap(sqr, exception_throwing_generator(10, 3), 1)
for i in range(3):
self.assertEqual(next(it), i*i)
@@ -1889,6 +1924,17 @@ class _TestPool(BaseTestCase):
if self.TYPE == 'manager':
self.skipTest('test not appropriate for {}'.format(self.TYPE))
+ # SayWhenError seen at the very first of the iterable
+ it = self.pool.imap_unordered(sqr,
+ exception_throwing_generator(1, -1),
+ 1)
+ self.assertRaises(SayWhenError, it.__next__)
+ # again, make sure it's reentrant
+ it = self.pool.imap_unordered(sqr,
+ exception_throwing_generator(1, -1),
+ 1)
+ self.assertRaises(SayWhenError, it.__next__)
+
it = self.pool.imap_unordered(sqr,
exception_throwing_generator(10, 3),
1)
@@ -1970,7 +2016,7 @@ class _TestPool(BaseTestCase):
except Exception as e:
exc = e
else:
- raise AssertionError('expected RuntimeError')
+ self.fail('expected RuntimeError')
self.assertIs(type(exc), RuntimeError)
self.assertEqual(exc.args, (123,))
cause = exc.__cause__
@@ -1984,6 +2030,17 @@ class _TestPool(BaseTestCase):
sys.excepthook(*sys.exc_info())
self.assertIn('raise RuntimeError(123) # some comment',
f1.getvalue())
+ # _helper_reraises_exception should not make the error
+ # a remote exception
+ with self.Pool(1) as p:
+ try:
+ p.map(sqr, exception_throwing_generator(1, -1), 1)
+ except Exception as e:
+ exc = e
+ else:
+ self.fail('expected SayWhenError')
+ self.assertIs(type(exc), SayWhenError)
+ self.assertIs(exc.__cause__, None)
@classmethod
def _test_wrapped_exception(cls):
diff --git a/Misc/NEWS b/Misc/NEWS
index 45c5c78287..fbaa840638 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,10 @@ Core and Builtins
Library
-------
+- bpo-28699: Fixed a bug in pools in multiprocessing.pool that raising an
+ exception at the very first of an iterable may swallow the exception or
+ make the program hang. Patch by Davin Potts and Xiang Zhang.
+
- bpo-25803: Avoid incorrect errors raised by Path.mkdir(exist_ok=True)
when the OS gives priority to errors such as EACCES over EEXIST.
--
GitLab
From 2609c9ee78c53d501914a5a90dbe094d9a8c3c97 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Wed, 29 Mar 2017 19:10:07 -0700
Subject: [PATCH 0088/1433] bpo-29677: DOC: clarify documentation for `round`
(GH-877) (GH-892)
(cherry picked from commit 85deefcf61d3cc192846f41a4ccc6df17da60c98)
---
Doc/library/functions.rst | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 2c0ea71c47..90fb07af22 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -1254,9 +1254,9 @@ are always available. They are listed here in alphabetical order.
.. function:: round(number[, ndigits])
- Return the floating point value *number* rounded to *ndigits* digits after
- the decimal point. If *ndigits* is omitted or is ``None``, it returns the
- nearest integer to its input. Delegates to ``number.__round__(ndigits)``.
+ Return *number* rounded to *ndigits* precision after the decimal
+ point. If *ndigits* is omitted or is ``None``, it returns the
+ nearest integer to its input.
For the built-in types supporting :func:`round`, values are rounded to the
closest multiple of 10 to the power minus *ndigits*; if two multiples are
@@ -1266,6 +1266,9 @@ are always available. They are listed here in alphabetical order.
negative). The return value is an integer if called with one argument,
otherwise of the same type as *number*.
+ For a general Python object ``number``, ``round(number, ndigits)`` delegates to
+ ``number.__round__(ndigits)``.
+
.. note::
The behavior of :func:`round` for floats can be surprising: for example,
--
GitLab
From da6ad2f780d187fbfdea330d1037766ae7bdb778 Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Wed, 29 Mar 2017 22:29:00 -0700
Subject: [PATCH 0089/1433] bpo-29917: DOC: Remove link from PyMethodDef (#890)
(#894)
(cherry picked from commit c3c7ef088583cc12bd218138036d1edb6de9c63f)
---
Doc/c-api/structures.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst
index f48119391f..c080f317be 100644
--- a/Doc/c-api/structures.rst
+++ b/Doc/c-api/structures.rst
@@ -241,7 +241,7 @@ definition with the same method name.
+==================+=============+===============================+
| :attr:`name` | char \* | name of the member |
+------------------+-------------+-------------------------------+
- | :attr:`type` | int | the type of the member in the |
+ | :attr:`!type` | int | the type of the member in the |
| | | C struct |
+------------------+-------------+-------------------------------+
| :attr:`offset` | Py_ssize_t | the offset in bytes that the |
@@ -256,7 +256,7 @@ definition with the same method name.
| | | docstring |
+------------------+-------------+-------------------------------+
- :attr:`type` can be one of many ``T_`` macros corresponding to various C
+ :attr:`!type` can be one of many ``T_`` macros corresponding to various C
types. When the member is accessed in Python, it will be converted to the
equivalent Python type.
--
GitLab
From 1b43a959fb1dd2e08dbf51bbc644df5ff2eb357e Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Wed, 29 Mar 2017 23:56:52 -0700
Subject: [PATCH 0090/1433] Remove an unrequired TODO in test_urllib2. (#897)
(#900)
(cherry picked from commit e6911a44f69c0d302db60f49952a9cf69da69a2b)
---
Lib/test/test_urllib2.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index 34329f8716..308acb3724 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -1414,7 +1414,6 @@ class HandlerTests(unittest.TestCase):
self.assertEqual(req.host, "proxy.example.com:3128")
self.assertEqual(req.get_header("Proxy-authorization"), "FooBar")
- # TODO: This should be only for OSX
@unittest.skipUnless(sys.platform == 'darwin', "only relevant for OSX")
def test_osx_proxy_bypass(self):
bypass = {
--
GitLab
From a6b4e1902250d6f28ca6d083ce1c8d7e9b91974b Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Thu, 30 Mar 2017 18:08:21 +0300
Subject: [PATCH 0091/1433] bpo-27863: Fixed multiple crashes in ElementTree.
(#765) (#903)
(cherry picked from commit 576def096ec7b64814e038f03290031f172886c3)
---
Lib/test/test_xml_etree.py | 112 +++++++++++++++++++++++++++++++++++++
Misc/NEWS | 3 +
Modules/_elementtree.c | 100 +++++++++++++++++----------------
3 files changed, 167 insertions(+), 48 deletions(-)
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index c0144d1cb8..dbdad23a74 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -1879,6 +1879,118 @@ class BadElementTest(ElementTestCase, unittest.TestCase):
with self.assertRaises(RuntimeError):
repr(e) # Should not crash
+ def test_element_get_text(self):
+ # Issue #27863
+ class X(str):
+ def __del__(self):
+ try:
+ elem.text
+ except NameError:
+ pass
+
+ b = ET.TreeBuilder()
+ b.start('tag', {})
+ b.data('ABCD')
+ b.data(X('EFGH'))
+ b.data('IJKL')
+ b.end('tag')
+
+ elem = b.close()
+ self.assertEqual(elem.text, 'ABCDEFGHIJKL')
+
+ def test_element_get_tail(self):
+ # Issue #27863
+ class X(str):
+ def __del__(self):
+ try:
+ elem[0].tail
+ except NameError:
+ pass
+
+ b = ET.TreeBuilder()
+ b.start('root', {})
+ b.start('tag', {})
+ b.end('tag')
+ b.data('ABCD')
+ b.data(X('EFGH'))
+ b.data('IJKL')
+ b.end('root')
+
+ elem = b.close()
+ self.assertEqual(elem[0].tail, 'ABCDEFGHIJKL')
+
+ def test_element_iter(self):
+ # Issue #27863
+ state = {
+ 'tag': 'tag',
+ '_children': [None], # non-Element
+ 'attrib': 'attr',
+ 'tail': 'tail',
+ 'text': 'text',
+ }
+
+ e = ET.Element('tag')
+ try:
+ e.__setstate__(state)
+ except AttributeError:
+ e.__dict__ = state
+
+ it = e.iter()
+ self.assertIs(next(it), e)
+ self.assertRaises(AttributeError, next, it)
+
+ def test_subscr(self):
+ # Issue #27863
+ class X:
+ def __index__(self):
+ del e[:]
+ return 1
+
+ e = ET.Element('elem')
+ e.append(ET.Element('child'))
+ e[:X()] # shouldn't crash
+
+ e.append(ET.Element('child'))
+ e[0:10:X()] # shouldn't crash
+
+ def test_ass_subscr(self):
+ # Issue #27863
+ class X:
+ def __index__(self):
+ e[:] = []
+ return 1
+
+ e = ET.Element('elem')
+ for _ in range(10):
+ e.insert(0, ET.Element('child'))
+
+ e[0:10:X()] = [] # shouldn't crash
+
+ def test_treebuilder_start(self):
+ # Issue #27863
+ def element_factory(x, y):
+ return []
+ b = ET.TreeBuilder(element_factory=element_factory)
+
+ b.start('tag', {})
+ b.data('ABCD')
+ self.assertRaises(AttributeError, b.start, 'tag2', {})
+ del b
+ gc_collect()
+
+ def test_treebuilder_end(self):
+ # Issue #27863
+ def element_factory(x, y):
+ return []
+ b = ET.TreeBuilder(element_factory=element_factory)
+
+ b.start('tag', {})
+ b.data('ABCD')
+ self.assertRaises(AttributeError, b.end, 'tag')
+ del b
+ gc_collect()
+
+
class MutatingElementPath(str):
def __new__(cls, elem, *args):
self = str.__new__(cls, *args)
diff --git a/Misc/NEWS b/Misc/NEWS
index fbaa840638..2caa8f360d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,9 @@ Core and Builtins
Library
-------
+- bpo-27863: Fixed multiple crashes in ElementTree caused by race conditions
+ and wrong types.
+
- bpo-28699: Fixed a bug in pools in multiprocessing.pool that raising an
exception at the very first of an iterable may swallow the exception or
make the program hang. Patch by Davin Potts and Xiang Zhang.
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 2cda98e611..e3350d194d 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -131,7 +131,7 @@ elementtree_free(void *m)
LOCAL(PyObject*)
list_join(PyObject* list)
{
- /* join list elements (destroying the list in the process) */
+ /* join list elements */
PyObject* joiner;
PyObject* result;
@@ -140,8 +140,6 @@ list_join(PyObject* list)
return NULL;
result = PyUnicode_Join(joiner, list);
Py_DECREF(joiner);
- if (result)
- Py_DECREF(list);
return result;
}
@@ -508,15 +506,17 @@ element_get_text(ElementObject* self)
{
/* return borrowed reference to text attribute */
- PyObject* res = self->text;
+ PyObject *res = self->text;
if (JOIN_GET(res)) {
res = JOIN_OBJ(res);
if (PyList_CheckExact(res)) {
- res = list_join(res);
- if (!res)
+ PyObject *tmp = list_join(res);
+ if (!tmp)
return NULL;
- self->text = res;
+ self->text = tmp;
+ Py_DECREF(res);
+ res = tmp;
}
}
@@ -528,15 +528,17 @@ element_get_tail(ElementObject* self)
{
/* return borrowed reference to text attribute */
- PyObject* res = self->tail;
+ PyObject *res = self->tail;
if (JOIN_GET(res)) {
res = JOIN_OBJ(res);
if (PyList_CheckExact(res)) {
- res = list_join(res);
- if (!res)
+ PyObject *tmp = list_join(res);
+ if (!tmp)
return NULL;
- self->tail = res;
+ self->tail = tmp;
+ Py_DECREF(res);
+ res = tmp;
}
}
@@ -2147,6 +2149,12 @@ elementiter_next(ElementIterObject *it)
continue;
}
+ if (!PyObject_TypeCheck(extra->children[child_index], &Element_Type)) {
+ PyErr_Format(PyExc_AttributeError,
+ "'%.100s' object has no attribute 'iter'",
+ Py_TYPE(extra->children[child_index])->tp_name);
+ return NULL;
+ }
elem = (ElementObject *)extra->children[child_index];
item->child_index++;
Py_INCREF(elem);
@@ -2396,40 +2404,51 @@ treebuilder_dealloc(TreeBuilderObject *self)
/* helpers for handling of arbitrary element-like objects */
static int
-treebuilder_set_element_text_or_tail(PyObject *element, PyObject *data,
+treebuilder_set_element_text_or_tail(PyObject *element, PyObject **data,
PyObject **dest, _Py_Identifier *name)
{
if (Element_CheckExact(element)) {
- Py_DECREF(JOIN_OBJ(*dest));
- *dest = JOIN_SET(data, PyList_CheckExact(data));
+ PyObject *tmp = JOIN_OBJ(*dest);
+ *dest = JOIN_SET(*data, PyList_CheckExact(*data));
+ *data = NULL;
+ Py_DECREF(tmp);
return 0;
}
else {
- PyObject *joined = list_join(data);
+ PyObject *joined = list_join(*data);
int r;
if (joined == NULL)
return -1;
r = _PyObject_SetAttrId(element, name, joined);
Py_DECREF(joined);
- return r;
+ if (r < 0)
+ return -1;
+ Py_CLEAR(*data);
+ return 0;
}
}
-/* These two functions steal a reference to data */
-static int
-treebuilder_set_element_text(PyObject *element, PyObject *data)
+LOCAL(int)
+treebuilder_flush_data(TreeBuilderObject* self)
{
- _Py_IDENTIFIER(text);
- return treebuilder_set_element_text_or_tail(
- element, data, &((ElementObject *) element)->text, &PyId_text);
-}
+ PyObject *element = self->last;
-static int
-treebuilder_set_element_tail(PyObject *element, PyObject *data)
-{
- _Py_IDENTIFIER(tail);
- return treebuilder_set_element_text_or_tail(
- element, data, &((ElementObject *) element)->tail, &PyId_tail);
+ if (!self->data) {
+ return 0;
+ }
+
+ if (self->this == element) {
+ _Py_IDENTIFIER(text);
+ return treebuilder_set_element_text_or_tail(
+ element, &self->data,
+ &((ElementObject *) element)->text, &PyId_text);
+ }
+ else {
+ _Py_IDENTIFIER(tail);
+ return treebuilder_set_element_text_or_tail(
+ element, &self->data,
+ &((ElementObject *) element)->tail, &PyId_tail);
+ }
}
static int
@@ -2479,16 +2498,8 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
PyObject* this;
elementtreestate *st = ET_STATE_GLOBAL;
- if (self->data) {
- if (self->this == self->last) {
- if (treebuilder_set_element_text(self->last, self->data))
- return NULL;
- }
- else {
- if (treebuilder_set_element_tail(self->last, self->data))
- return NULL;
- }
- self->data = NULL;
+ if (treebuilder_flush_data(self) < 0) {
+ return NULL;
}
if (!self->element_factory || self->element_factory == Py_None) {
@@ -2591,15 +2602,8 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
{
PyObject* item;
- if (self->data) {
- if (self->this == self->last) {
- if (treebuilder_set_element_text(self->last, self->data))
- return NULL;
- } else {
- if (treebuilder_set_element_tail(self->last, self->data))
- return NULL;
- }
- self->data = NULL;
+ if (treebuilder_flush_data(self) < 0) {
+ return NULL;
}
if (self->index == 0) {
--
GitLab
From bf4bb2e43030661e568d5d4b046e8b9351cc164c Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Thu, 30 Mar 2017 19:46:59 +0300
Subject: [PATCH 0092/1433] bpo-29935: Fixed error messages in the index()
method of tuple, list and deque (#887) (#907)
when pass indices of wrong type.
(cherry picked from commit d4edfc9abffca965e76ebc5957a92031a4d6c4d4)
---
Include/ceval.h | 1 +
Misc/NEWS | 3 +++
Modules/_collectionsmodule.c | 4 ++--
Objects/listobject.c | 4 ++--
Objects/tupleobject.c | 4 ++--
Python/ceval.c | 26 +++++++++++++++++++++-----
6 files changed, 31 insertions(+), 11 deletions(-)
diff --git a/Include/ceval.h b/Include/ceval.h
index 89c6062f11..1e482729a1 100644
--- a/Include/ceval.h
+++ b/Include/ceval.h
@@ -216,6 +216,7 @@ PyAPI_FUNC(Py_ssize_t) _PyEval_RequestCodeExtraIndex(freefunc);
#ifndef Py_LIMITED_API
PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *);
+PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *);
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(void);
#endif
diff --git a/Misc/NEWS b/Misc/NEWS
index 2caa8f360d..e8cd8f0221 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.6.2 release candidate 1?
Core and Builtins
-----------------
+- bpo-29935: Fixed error messages in the index() method of tuple, list and deque
+ when pass indices of wrong type.
+
- bpo-29859: Show correct error messages when any of the pthread_* calls in
thread_pthread.h fails.
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
index e6111c64e7..30157701d7 100644
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -1051,8 +1051,8 @@ deque_index(dequeobject *deque, PyObject *args)
int cmp;
if (!PyArg_ParseTuple(args, "O|O&O&:index", &v,
- _PyEval_SliceIndex, &start,
- _PyEval_SliceIndex, &stop))
+ _PyEval_SliceIndexNotNone, &start,
+ _PyEval_SliceIndexNotNone, &stop))
return NULL;
if (start < 0) {
start += Py_SIZE(deque);
diff --git a/Objects/listobject.c b/Objects/listobject.c
index dcd7b5efe5..cde281a0f6 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2153,8 +2153,8 @@ listindex(PyListObject *self, PyObject *args)
PyObject *v;
if (!PyArg_ParseTuple(args, "O|O&O&:index", &v,
- _PyEval_SliceIndex, &start,
- _PyEval_SliceIndex, &stop))
+ _PyEval_SliceIndexNotNone, &start,
+ _PyEval_SliceIndexNotNone, &stop))
return NULL;
if (start < 0) {
start += Py_SIZE(self);
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index c0ff499e72..52f20f4fe8 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -522,8 +522,8 @@ tupleindex(PyTupleObject *self, PyObject *args)
PyObject *v;
if (!PyArg_ParseTuple(args, "O|O&O&:index", &v,
- _PyEval_SliceIndex, &start,
- _PyEval_SliceIndex, &stop))
+ _PyEval_SliceIndexNotNone, &start,
+ _PyEval_SliceIndexNotNone, &stop))
return NULL;
if (start < 0) {
start += Py_SIZE(self);
diff --git a/Python/ceval.c b/Python/ceval.c
index 9cac771abd..bce86ab12c 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -5074,14 +5074,10 @@ do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
Return 0 on error, 1 on success.
*/
-/* Note: If v is NULL, return success without storing into *pi. This
- is because_PyEval_SliceIndex() is called by apply_slice(), which can be
- called by the SLICE opcode with v and/or w equal to NULL.
-*/
int
_PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
{
- if (v != NULL) {
+ if (v != Py_None) {
Py_ssize_t x;
if (PyIndex_Check(v)) {
x = PyNumber_AsSsize_t(v, NULL);
@@ -5099,6 +5095,26 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
return 1;
}
+int
+_PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
+{
+ Py_ssize_t x;
+ if (PyIndex_Check(v)) {
+ x = PyNumber_AsSsize_t(v, NULL);
+ if (x == -1 && PyErr_Occurred())
+ return 0;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "slice indices must be integers or "
+ "have an __index__ method");
+ return 0;
+ }
+ *pi = x;
+ return 1;
+}
+
+
#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\
"BaseException is not allowed"
--
GitLab
From 7b5b1379ac2c1e89ebf90b88b5d32457910e975e Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 30 Mar 2017 12:27:19 -0700
Subject: [PATCH 0093/1433] bpo-29928: Add f-string to the Glossary (GH-864)
(GH-914)
(cherry picked from commit 33db068dac7686e37736f7ecf8abb2aee0345cf2)
---
Doc/glossary.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index 495934afe7..81238414ef 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -320,6 +320,11 @@ Glossary
A module written in C or C++, using Python's C API to interact with the
core and with user code.
+ f-string
+ String literals prefixed with ``'f'`` or ``'F'`` are commonly called
+ "f-strings" which is short for
+ :ref:`formatted string literals `. See also :pep:`498`.
+
file object
An object exposing a file-oriented API (with methods such as
:meth:`read()` or :meth:`write()`) to an underlying resource. Depending
--
GitLab
From 599bb181036f724629a515317f0f39520950d51c Mon Sep 17 00:00:00 2001
From: "T. Wouters"
Date: Thu, 30 Mar 2017 12:48:23 -0700
Subject: [PATCH 0094/1433] bpo-29942: Fix the use of recursion in
itertools.chain.from_iterable. (#911)
* bpo-29942: Fix the use of recursion in itertools.chain.from_iterable.
Fix the use of recursion in itertools.chain.from_iterable. Using recursion
is unnecessary, and can easily cause stack overflows, especially when
building in low optimization modes or with Py_DEBUG enabled.
(cherry picked from commit 5466d4af5fe76ec0a5fbc8a05675287d9e8e9d14)
---
Lib/test/test_itertools.py | 8 ++++++
Misc/NEWS | 3 +++
Modules/itertoolsmodule.c | 52 ++++++++++++++++++++------------------
3 files changed, 39 insertions(+), 24 deletions(-)
diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py
index ea1f57caad..c431f0dc6e 100644
--- a/Lib/test/test_itertools.py
+++ b/Lib/test/test_itertools.py
@@ -1976,6 +1976,14 @@ class RegressionTests(unittest.TestCase):
self.assertRaises(AssertionError, list, cycle(gen1()))
self.assertEqual(hist, [0,1])
+ def test_long_chain_of_empty_iterables(self):
+ # Make sure itertools.chain doesn't run into recursion limits when
+ # dealing with long chains of empty iterables. Even with a high
+ # number this would probably only fail in Py_DEBUG mode.
+ it = chain.from_iterable(() for unused in range(10000000))
+ with self.assertRaises(StopIteration):
+ next(it)
+
class SubclassWithKwargsTest(unittest.TestCase):
def test_keywords_in_subclass(self):
# count is not subclassable...
diff --git a/Misc/NEWS b/Misc/NEWS
index e8cd8f0221..5ea4f66e76 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -30,6 +30,9 @@ Core and Builtins
Library
-------
+- bpo-29942: Fix a crash in itertools.chain.from_iterable when encountering
+ long runs of empty iterables.
+
- bpo-27863: Fixed multiple crashes in ElementTree caused by race conditions
and wrong types.
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 6bf04cbee3..8e22ec9c4b 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -1864,33 +1864,37 @@ chain_next(chainobject *lz)
{
PyObject *item;
- if (lz->source == NULL)
- return NULL; /* already stopped */
-
- if (lz->active == NULL) {
- PyObject *iterable = PyIter_Next(lz->source);
- if (iterable == NULL) {
- Py_CLEAR(lz->source);
- return NULL; /* no more input sources */
- }
- lz->active = PyObject_GetIter(iterable);
- Py_DECREF(iterable);
+ /* lz->source is the iterator of iterables. If it's NULL, we've already
+ * consumed them all. lz->active is the current iterator. If it's NULL,
+ * we should grab a new one from lz->source. */
+ while (lz->source != NULL) {
if (lz->active == NULL) {
- Py_CLEAR(lz->source);
- return NULL; /* input not iterable */
+ PyObject *iterable = PyIter_Next(lz->source);
+ if (iterable == NULL) {
+ Py_CLEAR(lz->source);
+ return NULL; /* no more input sources */
+ }
+ lz->active = PyObject_GetIter(iterable);
+ Py_DECREF(iterable);
+ if (lz->active == NULL) {
+ Py_CLEAR(lz->source);
+ return NULL; /* input not iterable */
+ }
}
+ item = (*Py_TYPE(lz->active)->tp_iternext)(lz->active);
+ if (item != NULL)
+ return item;
+ if (PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches(PyExc_StopIteration))
+ PyErr_Clear();
+ else
+ return NULL; /* input raised an exception */
+ }
+ /* lz->active is consumed, try with the next iterable. */
+ Py_CLEAR(lz->active);
}
- item = (*Py_TYPE(lz->active)->tp_iternext)(lz->active);
- if (item != NULL)
- return item;
- if (PyErr_Occurred()) {
- if (PyErr_ExceptionMatches(PyExc_StopIteration))
- PyErr_Clear();
- else
- return NULL; /* input raised an exception */
- }
- Py_CLEAR(lz->active);
- return chain_next(lz); /* recurse and use next active */
+ /* Everything had been consumed already. */
+ return NULL;
}
static PyObject *
--
GitLab
From 8d1f935945ca8cf3665315e0f82358fffe689353 Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Thu, 30 Mar 2017 23:15:51 -0700
Subject: [PATCH 0095/1433] Remove catching OSError in ftphandler test. Only
URLError is raised in urllib.request module. (#918) (#920)
(cherry picked from commit ed3dd1c02af6872bd0748f7b9a5dadb89f7b830f)
---
Lib/test/test_urllib2.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index 308acb3724..b537fca3c3 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -830,7 +830,6 @@ class HandlerTests(unittest.TestCase):
for url, ftp in [
("file://ftp.example.com//foo.txt", False),
("file://ftp.example.com///foo.txt", False),
-# XXXX bug: fails with OSError, should be URLError
("file://ftp.example.com/foo.txt", False),
("file://somehost//foo/something.txt", False),
("file://localhost//foo/something.txt", False),
@@ -839,7 +838,7 @@ class HandlerTests(unittest.TestCase):
try:
h.file_open(req)
# XXXX remove OSError when bug fixed
- except (urllib.error.URLError, OSError):
+ except urllib.error.URLError:
self.assertFalse(ftp)
else:
self.assertIs(o.req, req)
@@ -1689,7 +1688,6 @@ class HandlerTests(unittest.TestCase):
self.assertTrue(conn.fakesock.closed, "Connection not closed")
-
class MiscTests(unittest.TestCase):
def opener_has_handler(self, opener, handler_class):
--
GitLab
From 4c75fbb485c0e42181aab95c2ae92c597915827c Mon Sep 17 00:00:00 2001
From: INADA Naoki
Date: Fri, 31 Mar 2017 15:43:10 +0900
Subject: [PATCH 0096/1433] bpo-29952: Use usual terminology of dict (GH-922)
s/keys and elements/keys and values/
(cherry picked from commit cdcac039fb447f2ab04efcacbe663751bb2cb4ec)
---
Doc/reference/expressions.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst
index d80768ac07..c4f6c55c7c 100644
--- a/Doc/reference/expressions.rst
+++ b/Doc/reference/expressions.rst
@@ -1355,7 +1355,7 @@ built-in types.
true).
* Mappings (instances of :class:`dict`) compare equal if and only if they have
- equal `(key, value)` pairs. Equality comparison of the keys and elements
+ equal `(key, value)` pairs. Equality comparison of the keys and values
enforces reflexivity.
Order comparisons (``<``, ``>``, ``<=``, and ``>=``) raise :exc:`TypeError`.
--
GitLab
From 0a17e584461b14ff65ec287048f53911dbb22222 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Fri, 31 Mar 2017 02:12:18 -0700
Subject: [PATCH 0097/1433] bpo-28810: Update lnotab_notes.txt (GH-665)
(GH-919)
(cherry picked from commit 9135275cba680902e6caf29461f0423dc570190d)
---
Objects/lnotab_notes.txt | 50 ++++++++++++++++++++++------------------
1 file changed, 28 insertions(+), 22 deletions(-)
diff --git a/Objects/lnotab_notes.txt b/Objects/lnotab_notes.txt
index 515375772e..3dab2b9866 100644
--- a/Objects/lnotab_notes.txt
+++ b/Objects/lnotab_notes.txt
@@ -1,17 +1,18 @@
All about co_lnotab, the line number table.
Code objects store a field named co_lnotab. This is an array of unsigned bytes
-disguised as a Python string. It is used to map bytecode offsets to source code
-line #s for tracebacks and to identify line number boundaries for line tracing.
+disguised as a Python bytes object. It is used to map bytecode offsets to
+source code line #s for tracebacks and to identify line number boundaries for
+line tracing.
The array is conceptually a compressed list of
(bytecode offset increment, line number increment)
pairs. The details are important and delicate, best illustrated by example:
byte code offset source code line number
- 0 1
- 6 2
- 50 7
+ 0 1
+ 6 2
+ 50 7
350 207
361 208
@@ -24,7 +25,8 @@ look like:
The above doesn't really work, but it's a start. An unsigned byte (byte code
offset) can't hold negative values, or values larger than 255, a signed byte
(line number) can't hold values larger than 127 or less than -128, and the
-above example contains two such values. So we make two tweaks:
+above example contains two such values. (Note that before 3.6, line number
+was also encoded by an unsigned byte.) So we make two tweaks:
(a) there's a deep assumption that byte code offsets increase monotonically,
and
@@ -52,7 +54,7 @@ the example above, assemble_lnotab in compile.c should not (as was actually done
until 2.2) expand 300, 200 to
255, 255, 45, 45,
but to
- 255, 0, 45, 128, 0, 72.
+ 255, 0, 45, 127, 0, 73.
The above is sufficient to reconstruct line numbers for tracebacks, but not for
line tracing. Tracing is handled by PyCode_CheckLineNumber() in codeobject.c
@@ -83,30 +85,34 @@ Consider this code:
1: def f(a):
2: while a:
-3: print 1,
+3: print(1)
4: break
5: else:
-6: print 2,
+6: print(2)
which compiles to this:
- 2 0 SETUP_LOOP 19 (to 22)
- >> 3 LOAD_FAST 0 (a)
- 6 POP_JUMP_IF_FALSE 17
+ 2 0 SETUP_LOOP 26 (to 28)
+ >> 2 LOAD_FAST 0 (a)
+ 4 POP_JUMP_IF_FALSE 18
- 3 9 LOAD_CONST 1 (1)
- 12 PRINT_ITEM
+ 3 6 LOAD_GLOBAL 0 (print)
+ 8 LOAD_CONST 1 (1)
+ 10 CALL_FUNCTION 1
+ 12 POP_TOP
- 4 13 BREAK_LOOP
- 14 JUMP_ABSOLUTE 3
- >> 17 POP_BLOCK
+ 4 14 BREAK_LOOP
+ 16 JUMP_ABSOLUTE 2
+ >> 18 POP_BLOCK
- 6 18 LOAD_CONST 2 (2)
- 21 PRINT_ITEM
- >> 22 LOAD_CONST 0 (None)
- 25 RETURN_VALUE
+ 6 20 LOAD_GLOBAL 0 (print)
+ 22 LOAD_CONST 2 (2)
+ 24 CALL_FUNCTION 1
+ 26 POP_TOP
+ >> 28 LOAD_CONST 0 (None)
+ 30 RETURN_VALUE
-If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 17
+If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 18
and the co_lnotab will claim that execution has moved to line 4, which is wrong.
In this case, we could instead associate the POP_BLOCK with line 5, but that
would break jumps around loops without else clauses.
--
GitLab
From 7d5d13d8d003ae5b62bb8c9ef1d1f310eaabc506 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Fri, 31 Mar 2017 23:23:49 +0300
Subject: [PATCH 0098/1433] =?UTF-8?q?bpo-29953:=20Fix=20memory=20leaks=20i?=
=?UTF-8?q?n=20the=20replace()=20method=20of=20datetime=20and=20t=E2=80=A6?=
=?UTF-8?q?=20(#933)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
objects when pass out of bound fold argument.
(cherry picked from commit 314d6fca36a4eaa0541218431d14804fadec6488)
---
Lib/test/datetimetester.py | 5 +++++
Misc/NEWS | 3 +++
Modules/_datetimemodule.c | 21 ++++++++++-----------
3 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index 2350125f6d..bccd97aa3c 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -4313,6 +4313,11 @@ class TestLocalTimeDisambiguation(unittest.TestCase):
dt = dt.replace(fold=1, tzinfo=Eastern)
self.assertEqual(t.replace(tzinfo=None).fold, 1)
self.assertEqual(dt.replace(tzinfo=None).fold, 1)
+ # Out of bounds.
+ with self.assertRaises(ValueError):
+ t.replace(fold=2)
+ with self.assertRaises(ValueError):
+ dt.replace(fold=2)
# Check that fold is a keyword-only argument
with self.assertRaises(TypeError):
t.replace(1, 1, 1, None, 1)
diff --git a/Misc/NEWS b/Misc/NEWS
index 5ea4f66e76..c1bcdc1e93 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -30,6 +30,9 @@ Core and Builtins
Library
-------
+- bpo-29953: Fixed memory leaks in the replace() method of datetime and time
+ objects when pass out of bound fold argument.
+
- bpo-29942: Fix a crash in itertools.chain.from_iterable when encountering
long runs of empty iterables.
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index c784d0f4a9..c2ad9a203e 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -3926,16 +3926,16 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
time_kws,
&hh, &mm, &ss, &us, &tzinfo, &fold))
return NULL;
+ if (fold != 0 && fold != 1) {
+ PyErr_SetString(PyExc_ValueError,
+ "fold must be either 0 or 1");
+ return NULL;
+ }
tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
if (tuple == NULL)
return NULL;
clone = time_new(Py_TYPE(self), tuple, NULL);
if (clone != NULL) {
- if (fold != 0 && fold != 1) {
- PyErr_SetString(PyExc_ValueError,
- "fold must be either 0 or 1");
- return NULL;
- }
TIME_SET_FOLD(clone, fold);
}
Py_DECREF(tuple);
@@ -5019,17 +5019,16 @@ datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
&y, &m, &d, &hh, &mm, &ss, &us,
&tzinfo, &fold))
return NULL;
+ if (fold != 0 && fold != 1) {
+ PyErr_SetString(PyExc_ValueError,
+ "fold must be either 0 or 1");
+ return NULL;
+ }
tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
if (tuple == NULL)
return NULL;
clone = datetime_new(Py_TYPE(self), tuple, NULL);
-
if (clone != NULL) {
- if (fold != 0 && fold != 1) {
- PyErr_SetString(PyExc_ValueError,
- "fold must be either 0 or 1");
- return NULL;
- }
DATE_SET_FOLD(clone, fold);
}
Py_DECREF(tuple);
--
GitLab
From efde51ad54c58353f25ff80c8d30dbee82ef33a3 Mon Sep 17 00:00:00 2001
From: INADA Naoki
Date: Sat, 1 Apr 2017 23:29:31 +0900
Subject: [PATCH 0099/1433] bpo-29949: Fix set memory usage regression (GH-945)
Revert "Minor factoring: move redundant resize scaling logic into the resize function."
This reverts commit 4897300276d870f99459c82b937f0ac22450f0b6.
(cherry picked from commit e82cf8675bacd7a03de508ed11865fc2701dcef5)
---
Misc/NEWS | 2 ++
Objects/setobject.c | 11 +++++------
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/Misc/NEWS b/Misc/NEWS
index c1bcdc1e93..e61a165238 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ What's New in Python 3.6.2 release candidate 1?
Core and Builtins
-----------------
+- bpo-29949: Fix memory usage regression of set and frozenset object.
+
- bpo-29935: Fixed error messages in the index() method of tuple, list and deque
when pass indices of wrong type.
diff --git a/Objects/setobject.c b/Objects/setobject.c
index fdb9d3600d..9fe28138c0 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -236,7 +236,7 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
entry->hash = hash;
if ((size_t)so->fill*3 < mask*2)
return 0;
- return set_table_resize(so, so->used);
+ return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
found_active:
Py_DECREF(key);
@@ -304,7 +304,6 @@ set_table_resize(PySetObject *so, Py_ssize_t minused)
setentry small_copy[PySet_MINSIZE];
assert(minused >= 0);
- minused = (minused > 50000) ? minused * 2 : minused * 4;
/* Find the smallest table size > minused. */
/* XXX speed-up with intrinsics */
@@ -646,8 +645,8 @@ set_merge(PySetObject *so, PyObject *otherset)
* that there will be no (or few) overlapping keys.
*/
if ((so->fill + other->used)*3 >= so->mask*2) {
- if (set_table_resize(so, so->used + other->used) != 0)
- return -1;
+ if (set_table_resize(so, (so->used + other->used)*2) != 0)
+ return -1;
}
so_entry = so->table;
other_entry = other->table;
@@ -990,7 +989,7 @@ set_update_internal(PySetObject *so, PyObject *other)
if (dictsize < 0)
return -1;
if ((so->fill + dictsize)*3 >= so->mask*2) {
- if (set_table_resize(so, so->used + dictsize) != 0)
+ if (set_table_resize(so, (so->used + dictsize)*2) != 0)
return -1;
}
while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
@@ -1511,7 +1510,7 @@ set_difference_update_internal(PySetObject *so, PyObject *other)
/* If more than 1/4th are dummies, then resize them away. */
if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4)
return 0;
- return set_table_resize(so, so->used);
+ return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
}
static PyObject *
--
GitLab
From 4415b823a08163a8728d13ff06565efb12353fc0 Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Sat, 1 Apr 2017 19:57:04 -0700
Subject: [PATCH 0100/1433] Add helpful explaination to test_password_manager
tests. (#936) (#941)
Also uncomment and fix a path test.
(cherry picked from commit 1f5425ff69ea0531d869b4f9fa28bd3f66ca3de7)
---
Lib/test/test_urllib2.py | 41 +++++++++++++++++++++++++---------------
1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index b537fca3c3..d50211c598 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -141,44 +141,55 @@ class RequestHdrsTests(unittest.TestCase):
mgr = urllib.request.HTTPPasswordMgr()
add = mgr.add_password
find_user_pass = mgr.find_user_password
+
add("Some Realm", "http://example.com/", "joe", "password")
add("Some Realm", "http://example.com/ni", "ni", "ni")
- add("c", "http://example.com/foo", "foo", "ni")
- add("c", "http://example.com/bar", "bar", "nini")
- add("b", "http://example.com/", "first", "blah")
- add("b", "http://example.com/", "second", "spam")
- add("a", "http://example.com", "1", "a")
add("Some Realm", "http://c.example.com:3128", "3", "c")
add("Some Realm", "d.example.com", "4", "d")
add("Some Realm", "e.example.com:3128", "5", "e")
+ # For the same realm, password set the highest path is the winner.
self.assertEqual(find_user_pass("Some Realm", "example.com"),
('joe', 'password'))
-
- #self.assertEqual(find_user_pass("Some Realm", "http://example.com/ni"),
- # ('ni', 'ni'))
-
+ self.assertEqual(find_user_pass("Some Realm", "http://example.com/ni"),
+ ('joe', 'password'))
self.assertEqual(find_user_pass("Some Realm", "http://example.com"),
('joe', 'password'))
self.assertEqual(find_user_pass("Some Realm", "http://example.com/"),
('joe', 'password'))
- self.assertEqual(
- find_user_pass("Some Realm", "http://example.com/spam"),
- ('joe', 'password'))
- self.assertEqual(
- find_user_pass("Some Realm", "http://example.com/spam/spam"),
- ('joe', 'password'))
+ self.assertEqual(find_user_pass("Some Realm",
+ "http://example.com/spam"),
+ ('joe', 'password'))
+
+ self.assertEqual(find_user_pass("Some Realm",
+ "http://example.com/spam/spam"),
+ ('joe', 'password'))
+
+ # You can have different passwords for different paths.
+
+ add("c", "http://example.com/foo", "foo", "ni")
+ add("c", "http://example.com/bar", "bar", "nini")
+
self.assertEqual(find_user_pass("c", "http://example.com/foo"),
('foo', 'ni'))
+
self.assertEqual(find_user_pass("c", "http://example.com/bar"),
('bar', 'nini'))
+
+ # For the same path, newer password should be considered.
+
+ add("b", "http://example.com/", "first", "blah")
+ add("b", "http://example.com/", "second", "spam")
+
self.assertEqual(find_user_pass("b", "http://example.com/"),
('second', 'spam'))
# No special relationship between a.example.com and example.com:
+ add("a", "http://example.com", "1", "a")
self.assertEqual(find_user_pass("a", "http://example.com/"),
('1', 'a'))
+
self.assertEqual(find_user_pass("a", "http://a.example.com/"),
(None, None))
--
GitLab
From a71a3ad54d14483cfaebd8e0fb96c97c798d9e32 Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Sat, 1 Apr 2017 20:00:36 -0700
Subject: [PATCH 0101/1433] bpo-26947: DOC: clarify wording on hashable in
glossary (#948) (#957)
(cherry picked from commit 64c887ab3a400cf91bde4f0c5ef69eacc88bc5e1)
---
Doc/glossary.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index 81238414ef..dba9186d93 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -467,9 +467,9 @@ Glossary
Hashability makes an object usable as a dictionary key and a set member,
because these data structures use the hash value internally.
- All of Python's immutable built-in objects are hashable, while no mutable
- containers (such as lists or dictionaries) are. Objects which are
- instances of user-defined classes are hashable by default; they all
+ All of Python's immutable built-in objects are hashable; mutable
+ containers (such as lists or dictionaries) are not. Objects which are
+ instances of user-defined classes are hashable by default. They all
compare unequal (except with themselves), and their hash value is derived
from their :func:`id`.
--
GitLab
From 90e3518225bafaff01469ed48c472ae7db5686f0 Mon Sep 17 00:00:00 2001
From: "T. Wouters"
Date: Sat, 1 Apr 2017 20:20:05 -0700
Subject: [PATCH 0102/1433] bpo-29941: Assert fixes (#886) (#955)
Make a non-Py_DEBUG, asserts-enabled build of CPython possible. This means
making sure helper functions are defined when NDEBUG is not defined, not
just when Py_DEBUG is defined.
Also fix a division-by-zero in obmalloc.c that went unnoticed because in
Py_DEBUG mode, elsize is never zero.
(cherry picked from commit a00c3fd12d421e41b769debd7df717d17b0deed5 and 06bb4873d6a9ac303701d08a851d6cd9a51e02a3)
---
Include/unicodeobject.h | 4 ++++
Objects/dictobject.c | 2 +-
Objects/obmalloc.c | 2 +-
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h
index 2d0d77e804..5b877185f2 100644
--- a/Include/unicodeobject.h
+++ b/Include/unicodeobject.h
@@ -2309,6 +2309,10 @@ PyAPI_FUNC(Py_UNICODE*) PyUnicode_AsUnicodeCopy(
PyAPI_FUNC(int) _PyUnicode_CheckConsistency(
PyObject *op,
int check_content);
+#elif !defined(NDEBUG)
+/* For asserts that call _PyUnicode_CheckConsistency(), which would
+ * otherwise be a problem when building with asserts but without Py_DEBUG. */
+#define _PyUnicode_CheckConsistency(op, check_content) PyUnicode_Check(op)
#endif
#ifndef Py_LIMITED_API
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 8bcc931148..566d1a5ac8 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -436,7 +436,7 @@ static PyObject *empty_values[1] = { NULL };
/* #define DEBUG_PYDICT */
-#ifdef Py_DEBUG
+#ifndef NDEBUG
static int
_PyDict_CheckConsistency(PyDictObject *mp)
{
diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index a1142f3b09..32e7ecbe1e 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -1227,7 +1227,7 @@ _PyObject_Alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
_Py_AllocatedBlocks++;
- assert(nelem <= PY_SSIZE_T_MAX / elsize);
+ assert(elsize == 0 || nelem <= PY_SSIZE_T_MAX / elsize);
nbytes = nelem * elsize;
#ifdef WITH_VALGRIND
--
GitLab
From c4e557ed9933499e1c97644ea12ad77ba064e829 Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Sun, 2 Apr 2017 01:36:58 -0700
Subject: [PATCH 0103/1433] Minor spell fix and formatting fixes in urllib
tests. (#959) (#961)
(cherry picked from commit efbd4ea65dbb9f87b1afeec6a760802756badee5)
---
Lib/test/test_urllib.py | 6 +++++-
Lib/test/test_urllibnet.py | 2 +-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py
index 5084486e5a..fa3757cc94 100644
--- a/Lib/test/test_urllib.py
+++ b/Lib/test/test_urllib.py
@@ -206,6 +206,7 @@ class urlopen_FileTests(unittest.TestCase):
def test_relativelocalfile(self):
self.assertRaises(ValueError,urllib.request.urlopen,'./' + self.pathname)
+
class ProxyTests(unittest.TestCase):
def setUp(self):
@@ -259,6 +260,7 @@ class ProxyTests(unittest.TestCase):
self.assertFalse(bypass('newdomain.com')) # no port
self.assertFalse(bypass('newdomain.com:1235')) # wrong port
+
class ProxyTests_withOrderedEnv(unittest.TestCase):
def setUp(self):
@@ -294,6 +296,7 @@ class ProxyTests_withOrderedEnv(unittest.TestCase):
proxies = urllib.request.getproxies_environment()
self.assertEqual('http://somewhere:3128', proxies['http'])
+
class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin, FakeFTPMixin):
"""Test urlopen() opening a fake http connection."""
@@ -432,7 +435,6 @@ Connection: close
finally:
self.unfakeftp()
-
def test_userpass_inurl(self):
self.fakehttp(b"HTTP/1.0 200 OK\r\n\r\nHello!")
try:
@@ -476,6 +478,7 @@ Connection: close
"https://localhost", cafile="/nonexistent/path", context=context
)
+
class urlopen_DataTests(unittest.TestCase):
"""Test urlopen() opening a data URL."""
@@ -549,6 +552,7 @@ class urlopen_DataTests(unittest.TestCase):
# missing padding character
self.assertRaises(ValueError,urllib.request.urlopen,'data:;base64,Cg=')
+
class urlretrieve_FileTests(unittest.TestCase):
"""Test urllib.urlretrieve() on local files"""
diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py
index 949716c2b5..865a7f4f5f 100644
--- a/Lib/test/test_urllibnet.py
+++ b/Lib/test/test_urllibnet.py
@@ -29,7 +29,7 @@ class URLTimeoutTest(unittest.TestCase):
class urlopenNetworkTests(unittest.TestCase):
- """Tests urllib.reqest.urlopen using the network.
+ """Tests urllib.request.urlopen using the network.
These tests are not exhaustive. Assuming that testing using files does a
good job overall of some of the basic interface features. There are no
--
GitLab
From d184c20e359907e326696724a3395ce1d542f42e Mon Sep 17 00:00:00 2001
From: cocoatomo
Date: Tue, 4 Apr 2017 01:26:32 +0900
Subject: [PATCH 0104/1433] Keep the c-api exception doc up-to-date (#966)
cherry-pick'ed from ec1f5df..e3d6db3
---
Doc/c-api/exceptions.rst | 205 ++++++++++++++++++++++++++++-----------
Misc/ACKS | 1 +
2 files changed, 150 insertions(+), 56 deletions(-)
diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst
index 037b85cfd1..3516a16903 100644
--- a/Doc/c-api/exceptions.rst
+++ b/Doc/c-api/exceptions.rst
@@ -750,6 +750,61 @@ All standard Python exceptions are available as global variables whose names are
:c:type:`PyObject\*`; they are all class objects. For completeness, here are all
the variables:
+.. index::
+ single: PyExc_BaseException
+ single: PyExc_Exception
+ single: PyExc_ArithmeticError
+ single: PyExc_AssertionError
+ single: PyExc_AttributeError
+ single: PyExc_BlockingIOError
+ single: PyExc_BrokenPipeError
+ single: PyExc_BufferError
+ single: PyExc_ChildProcessError
+ single: PyExc_ConnectionAbortedError
+ single: PyExc_ConnectionError
+ single: PyExc_ConnectionRefusedError
+ single: PyExc_ConnectionResetError
+ single: PyExc_EOFError
+ single: PyExc_FileExistsError
+ single: PyExc_FileNotFoundError
+ single: PyExc_FloatingPointError
+ single: PyExc_GeneratorExit
+ single: PyExc_ImportError
+ single: PyExc_IndentationError
+ single: PyExc_IndexError
+ single: PyExc_InterruptedError
+ single: PyExc_IsADirectoryError
+ single: PyExc_KeyError
+ single: PyExc_KeyboardInterrupt
+ single: PyExc_LookupError
+ single: PyExc_MemoryError
+ single: PyExc_ModuleNotFoundError
+ single: PyExc_NameError
+ single: PyExc_NotADirectoryError
+ single: PyExc_NotImplementedError
+ single: PyExc_OSError
+ single: PyExc_OverflowError
+ single: PyExc_PermissionError
+ single: PyExc_ProcessLookupError
+ single: PyExc_RecursionError
+ single: PyExc_ReferenceError
+ single: PyExc_RuntimeError
+ single: PyExc_StopAsyncIteration
+ single: PyExc_StopIteration
+ single: PyExc_SyntaxError
+ single: PyExc_SystemError
+ single: PyExc_SystemExit
+ single: PyExc_TabError
+ single: PyExc_TimeoutError
+ single: PyExc_TypeError
+ single: PyExc_UnboundLocalError
+ single: PyExc_UnicodeDecodeError
+ single: PyExc_UnicodeEncodeError
+ single: PyExc_UnicodeError
+ single: PyExc_UnicodeTranslateError
+ single: PyExc_ValueError
+ single: PyExc_ZeroDivisionError
+
+-----------------------------------------+---------------------------------+----------+
| C Name | Python Name | Notes |
+=========================================+=================================+==========+
@@ -759,8 +814,6 @@ the variables:
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_ArithmeticError` | :exc:`ArithmeticError` | \(1) |
+-----------------------------------------+---------------------------------+----------+
-| :c:data:`PyExc_LookupError` | :exc:`LookupError` | \(1) |
-+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_AssertionError` | :exc:`AssertionError` | |
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_AttributeError` | :exc:`AttributeError` | |
@@ -769,27 +822,31 @@ the variables:
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_BrokenPipeError` | :exc:`BrokenPipeError` | |
+-----------------------------------------+---------------------------------+----------+
-| :c:data:`PyExc_ChildProcessError` | :exc:`ChildProcessError` | |
+| :c:data:`PyExc_BufferError` | :exc:`BufferError` | |
+-----------------------------------------+---------------------------------+----------+
-| :c:data:`PyExc_ConnectionError` | :exc:`ConnectionError` | |
+| :c:data:`PyExc_ChildProcessError` | :exc:`ChildProcessError` | |
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_ConnectionAbortedError` | :exc:`ConnectionAbortedError` | |
+-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_ConnectionError` | :exc:`ConnectionError` | |
++-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_ConnectionRefusedError` | :exc:`ConnectionRefusedError` | |
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_ConnectionResetError` | :exc:`ConnectionResetError` | |
+-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_EOFError` | :exc:`EOFError` | |
++-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_FileExistsError` | :exc:`FileExistsError` | |
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_FileNotFoundError` | :exc:`FileNotFoundError` | |
+-----------------------------------------+---------------------------------+----------+
-| :c:data:`PyExc_EOFError` | :exc:`EOFError` | |
-+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_FloatingPointError` | :exc:`FloatingPointError` | |
+-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_GeneratorExit` | :exc:`GeneratorExit` | |
++-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_ImportError` | :exc:`ImportError` | |
+-----------------------------------------+---------------------------------+----------+
-| :c:data:`PyExc_ModuleNotFoundError` | :exc:`ModuleNotFoundError` | |
+| :c:data:`PyExc_IndentationError` | :exc:`IndentationError` | |
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_IndexError` | :exc:`IndexError` | |
+-----------------------------------------+---------------------------------+----------+
@@ -801,8 +858,12 @@ the variables:
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_KeyboardInterrupt` | :exc:`KeyboardInterrupt` | |
+-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_LookupError` | :exc:`LookupError` | \(1) |
++-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_MemoryError` | :exc:`MemoryError` | |
+-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_ModuleNotFoundError` | :exc:`ModuleNotFoundError` | |
++-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_NameError` | :exc:`NameError` | |
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_NotADirectoryError` | :exc:`NotADirectoryError` | |
@@ -823,16 +884,32 @@ the variables:
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_RuntimeError` | :exc:`RuntimeError` | |
+-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_StopAsyncIteration` | :exc:`StopAsyncIteration` | |
++-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_StopIteration` | :exc:`StopIteration` | |
++-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_SyntaxError` | :exc:`SyntaxError` | |
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_SystemError` | :exc:`SystemError` | |
+-----------------------------------------+---------------------------------+----------+
-| :c:data:`PyExc_TimeoutError` | :exc:`TimeoutError` | |
-+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_SystemExit` | :exc:`SystemExit` | |
+-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_TabError` | :exc:`TabError` | |
++-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_TimeoutError` | :exc:`TimeoutError` | |
++-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_TypeError` | :exc:`TypeError` | |
+-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_UnboundLocalError` | :exc:`UnboundLocalError` | |
++-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_UnicodeDecodeError` | :exc:`UnicodeDecodeError` | |
++-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_UnicodeEncodeError` | :exc:`UnicodeEncodeError` | |
++-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_UnicodeError` | :exc:`UnicodeError` | |
++-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_UnicodeTranslateError` | :exc:`UnicodeTranslateError` | |
++-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_ValueError` | :exc:`ValueError` | |
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_ZeroDivisionError` | :exc:`ZeroDivisionError` | |
@@ -849,11 +926,18 @@ the variables:
and :c:data:`PyExc_TimeoutError` were introduced following :pep:`3151`.
.. versionadded:: 3.5
- :c:data:`PyExc_RecursionError`.
+ :c:data:`PyExc_StopAsyncIteration` and :c:data:`PyExc_RecursionError`.
+.. versionadded:: 3.6
+ :c:data:`PyExc_ModuleNotFoundError`.
These are compatibility aliases to :c:data:`PyExc_OSError`:
+.. index::
+ single: PyExc_EnvironmentError
+ single: PyExc_IOError
+ single: PyExc_WindowsError
+
+-------------------------------------+----------+
| C Name | Notes |
+=====================================+==========+
@@ -867,52 +951,6 @@ These are compatibility aliases to :c:data:`PyExc_OSError`:
.. versionchanged:: 3.3
These aliases used to be separate exception types.
-
-.. index::
- single: PyExc_BaseException
- single: PyExc_Exception
- single: PyExc_ArithmeticError
- single: PyExc_LookupError
- single: PyExc_AssertionError
- single: PyExc_AttributeError
- single: PyExc_BlockingIOError
- single: PyExc_BrokenPipeError
- single: PyExc_ConnectionError
- single: PyExc_ConnectionAbortedError
- single: PyExc_ConnectionRefusedError
- single: PyExc_ConnectionResetError
- single: PyExc_EOFError
- single: PyExc_FileExistsError
- single: PyExc_FileNotFoundError
- single: PyExc_FloatingPointError
- single: PyExc_ImportError
- single: PyExc_IndexError
- single: PyExc_InterruptedError
- single: PyExc_IsADirectoryError
- single: PyExc_KeyError
- single: PyExc_KeyboardInterrupt
- single: PyExc_MemoryError
- single: PyExc_NameError
- single: PyExc_NotADirectoryError
- single: PyExc_NotImplementedError
- single: PyExc_OSError
- single: PyExc_OverflowError
- single: PyExc_PermissionError
- single: PyExc_ProcessLookupError
- single: PyExc_RecursionError
- single: PyExc_ReferenceError
- single: PyExc_RuntimeError
- single: PyExc_SyntaxError
- single: PyExc_SystemError
- single: PyExc_SystemExit
- single: PyExc_TimeoutError
- single: PyExc_TypeError
- single: PyExc_ValueError
- single: PyExc_ZeroDivisionError
- single: PyExc_EnvironmentError
- single: PyExc_IOError
- single: PyExc_WindowsError
-
Notes:
(1)
@@ -924,3 +962,58 @@ Notes:
(3)
Only defined on Windows; protect code that uses this by testing that the
preprocessor macro ``MS_WINDOWS`` is defined.
+
+Standard Warnings
+=================
+
+All standard Python warning categories are available as global variables whose
+names are ``PyExc_`` followed by the Python exception name. These have the type
+:c:type:`PyObject\*`; they are all class objects. For completeness, here are all
+the variables:
+
+.. index::
+ single: PyExc_Warning
+ single: PyExc_BytesWarning
+ single: PyExc_DepricationWarning
+ single: PyExc_FutureWarning
+ single: PyExc_ImportWarning
+ single: PyExc_PendingDeprecationWarning
+ single: PyExc_ResourceWarning
+ single: PyExc_RuntimeWarning
+ single: PyExc_SyntaxWarning
+ single: PyExc_UnicodeWarning
+ single: PyExc_UserWarning
+
++------------------------------------------+---------------------------------+----------+
+| C Name | Python Name | Notes |
++==========================================+=================================+==========+
+| :c:data:`PyExc_Warning` | :exc:`Warning` | \(1) |
++------------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_BytesWarning` | :exc:`BytesWarning` | |
++------------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_DeprecationWarning` | :exc:`DeprecationWarning` | |
++------------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_FutureWarning` | :exc:`FutureWarning` | |
++------------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_ImportWarning` | :exc:`ImportWarning` | |
++------------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_PendingDepricationWarning`| :exc:`PendingDeprecationWarning`| |
++------------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_ResourceWarning` | :exc:`ResourceWarning` | |
++------------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_RuntimeWarning` | :exc:`RuntimeWarning` | |
++------------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_SyntaxWarning` | :exc:`SyntaxWarning` | |
++------------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_UnicodeWarning` | :exc:`UnicodeWarning` | |
++------------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_UserWarning` | :exc:`UserWarning` | |
++------------------------------------------+---------------------------------+----------+
+
+.. versionadded:: 3.2
+ :c:data:`PyExc_ResourceWarning`.
+
+Notes:
+
+(1)
+ This is a base class for other standard warning categories.
diff --git a/Misc/ACKS b/Misc/ACKS
index 2b23702f22..b5da02a63a 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -775,6 +775,7 @@ Jason Killen
Jan Kim
Taek Joo Kim
Sam Kimbrel
+Tomohiko Kinebuchi
James King
W. Trevor King
Paul Kippes
--
GitLab
From cb1e002c07622e027e80a3843d27a623d1617430 Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Mon, 3 Apr 2017 22:27:15 -0700
Subject: [PATCH 0105/1433] bpo-29725: DOC: add text for arraysize in
sqlite3.Cursor (#947) (#985)
(cherry picked from commit 02e12138000da834f23719521a011fa93763384d)
---
Doc/library/sqlite3.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst
index d1f7a6f120..9fef7d7f03 100644
--- a/Doc/library/sqlite3.rst
+++ b/Doc/library/sqlite3.rst
@@ -640,6 +640,11 @@ Cursor Objects
.. versionchanged:: 3.6
Added support for the ``REPLACE`` statement.
+ .. attribute:: arraysize
+
+ Read/write attribute that controls the number of rows returned by :meth:`fetchmany`.
+ The default value is 1 which means a single row would be fetched per call.
+
.. attribute:: description
This read-only attribute provides the column names of the last query. To
--
GitLab
From ce92be1825c5ca1d3e6bff24598f3aa54c000b22 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Tue, 4 Apr 2017 11:49:14 +0200
Subject: [PATCH 0106/1433] remove merge=union attribute for Misc/NEWS (GH-460)
(GH-988)
(cherry picked from commit 060d2d776a29341c079cce37220324f9775140ba)
---
.gitattributes | 2 --
1 file changed, 2 deletions(-)
diff --git a/.gitattributes b/.gitattributes
index 55a3f49922..82694d81f2 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,3 @@
-Misc/NEWS merge=union
-
*.pck binary
Lib/test/cjkencodings/* binary
Lib/test/decimaltestdata/*.decTest binary
--
GitLab
From ba980e8ef01dfaf484defd6e7a19ea5375de1338 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Wed, 5 Apr 2017 13:18:18 +0300
Subject: [PATCH 0107/1433] Miscellaneous minor fixes of Misc/NEWS formatting.
(#1002) (#1003)
(cherry picked from commit a0157b5f11e621f2196af4e918b9f07688a6cd1c)
---
Misc/NEWS | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/Misc/NEWS b/Misc/NEWS
index e61a165238..fa20ea16cd 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -290,7 +290,7 @@ Library
- Issue #28427: old keys should not remove new values from
WeakValueDictionary when collecting from another thread.
-- Issue 28923: Remove editor artifacts from Tix.py.
+- Issue #28923: Remove editor artifacts from Tix.py.
- Issue #29055: Neaten-up empty population error on random.choice()
by suppressing the upstream exception.
@@ -1058,7 +1058,7 @@ Core and Builtins
alpha releases, where backslashes are allowed anywhere in an
f-string. Also, require that expressions inside f-strings be
enclosed within literal braces, and not escapes like
- f'\x7b"hi"\x7d'.
+ ``f'\x7b"hi"\x7d'``.
- Issue #28046: Remove platform-specific directories from sys.path.
@@ -1277,7 +1277,7 @@ Library
- Issue #24277: The new email API is no longer provisional, and the docs
have been reorganized and rewritten to emphasize the new API.
-- Issue #22450: urllib now includes an "Accept: */*" header among the
+- Issue #22450: urllib now includes an ``Accept: */*`` header among the
default headers. This makes the results of REST API requests more
consistent and predictable especially when proxy servers are involved.
@@ -1296,9 +1296,9 @@ Library
characters, not on arbitrary unicode line breaks. This also fixes a bug in
HTTP header parsing.
-- Issue 27331: The email.mime classes now all accept an optional policy keyword.
+- Issue #27331: The email.mime classes now all accept an optional policy keyword.
-- Issue 27988: Fix email iter_attachments incorrect mutation of payload list.
+- Issue #27988: Fix email iter_attachments incorrect mutation of payload list.
- Issue #16113: Add SHA-3 and SHAKE support to hashlib module.
@@ -2406,7 +2406,7 @@ Core and Builtins
in ``def f(): 1.0``.
- Issue #4806: Avoid masking the original TypeError exception when using star
- (*) unpacking in function calls. Based on patch by Hagen Fürstenau and
+ (``*``) unpacking in function calls. Based on patch by Hagen Fürstenau and
Daniel Urban.
- Issue #26146: Add a new kind of AST node: ``ast.Constant``. It can be used
@@ -2964,7 +2964,7 @@ Library
- Issue #25672: In the ssl module, enable the SSL_MODE_RELEASE_BUFFERS mode
option if it is safe to do so.
-- Issue #26012: Don't traverse into symlinks for ** pattern in
+- Issue #26012: Don't traverse into symlinks for ``**`` pattern in
pathlib.Path.[r]glob().
- Issue #24120: Ignore PermissionError when traversing a tree with
@@ -3100,7 +3100,7 @@ Library
- Issue #25584: Added "escape" to the __all__ list in the glob module.
-- Issue #25584: Fixed recursive glob() with patterns starting with '\*\*'.
+- Issue #25584: Fixed recursive glob() with patterns starting with ``**``.
- Issue #25446: Fix regression in smtplib's AUTH LOGIN support.
@@ -3735,7 +3735,7 @@ Library
- Issue #28427: old keys should not remove new values from
WeakValueDictionary when collecting from another thread.
-- Issue 28923: Remove editor artifacts from Tix.py.
+- Issue #28923: Remove editor artifacts from Tix.py.
- Issue #28871: Fixed a crash when deallocate deep ElementTree.
@@ -3858,7 +3858,7 @@ Library
- Issue #27599: Fixed buffer overrun in binascii.b2a_qp() and binascii.a2b_qp().
-- Issue #19003:m email.generator now replaces only \r and/or \n line
+- Issue #19003:m email.generator now replaces only ``\r`` and/or ``\n`` line
endings, per the RFC, instead of all unicode line endings.
- Issue #28019: itertools.count() no longer rounds non-integer step in range
@@ -3881,7 +3881,7 @@ Library
- Issue #27445: Don't pass str(_charset) to MIMEText.set_payload().
Patch by Claude Paroz.
-- Issue #22450: urllib now includes an "Accept: */*" header among the
+- Issue #22450: urllib now includes an ``Accept: */*`` header among the
default headers. This makes the results of REST API requests more
consistent and predictable especially when proxy servers are involved.
@@ -3896,7 +3896,7 @@ Library
characters, not on arbitrary unicode line breaks. This also fixes a bug in
HTTP header parsing.
-- Issue 27988: Fix email iter_attachments incorrect mutation of payload list.
+- Issue #27988: Fix email iter_attachments incorrect mutation of payload list.
- Issue #27691: Fix ssl module's parsing of GEN_RID subject alternative name
fields in X.509 certs.
@@ -4347,7 +4347,7 @@ Core and Builtins
cookie names.
- Issue #4806: Avoid masking the original TypeError exception when using star
- (*) unpacking in function calls. Based on patch by Hagen Fürstenau and
+ (``*``) unpacking in function calls. Based on patch by Hagen Fürstenau and
Daniel Urban.
- Issue #27138: Fix the doc comment for FileFinder.find_spec().
@@ -4727,7 +4727,7 @@ Library
- Issue #25672: In the ssl module, enable the SSL_MODE_RELEASE_BUFFERS mode
option if it is safe to do so.
-- Issue #26012: Don't traverse into symlinks for ** pattern in
+- Issue #26012: Don't traverse into symlinks for ``**`` pattern in
pathlib.Path.[r]glob().
- Issue #24120: Ignore PermissionError when traversing a tree with
@@ -5137,7 +5137,7 @@ Library
- Issue #25584: Added "escape" to the __all__ list in the glob module.
-- Issue #25584: Fixed recursive glob() with patterns starting with '\*\*'.
+- Issue #25584: Fixed recursive glob() with patterns starting with ``**``.
- Issue #25446: Fix regression in smtplib's AUTH LOGIN support.
@@ -6680,7 +6680,7 @@ Library
- Issue #23521: Corrected pure python implementation of timedelta division.
- * Eliminated OverflowError from timedelta * float for some floats;
+ * Eliminated OverflowError from ``timedelta * float`` for some floats;
* Corrected rounding in timedlta true division.
- Issue #21619: Popen objects no longer leave a zombie after exit in the with
@@ -7479,7 +7479,7 @@ Library
character instead of truncating it. Based on patch by Victor Stinner.
- Issue #13968: The glob module now supports recursive search in
- subdirectories using the "**" pattern.
+ subdirectories using the ``**`` pattern.
- Issue #21951: Fixed a crash in Tkinter on AIX when called Tcl command with
empty string or tuple argument.
--
GitLab
From ed278448daa4afb78d1af57b0c179097477f9832 Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Thu, 6 Apr 2017 08:38:38 -0700
Subject: [PATCH 0108/1433] correct parse_qs and parse_qsl test case
descriptions. (#968) (#997)
(cherry picked from commit 257b980b316a5206ecf6c23b958e2b7c4df4f3de)
---
Lib/test/test_urlparse.py | 12 ++++++------
Lib/urllib/parse.py | 30 +++++++++++++++++-------------
2 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
index 99c5c033e3..3c89ed928f 100644
--- a/Lib/test/test_urlparse.py
+++ b/Lib/test/test_urlparse.py
@@ -6,8 +6,8 @@ RFC2396_BASE = "http://a/b/c/d;p?q"
RFC3986_BASE = 'http://a/b/c/d;p?q'
SIMPLE_BASE = 'http://a/b/c/d'
-# A list of test cases. Each test case is a two-tuple that contains
-# a string with the query and a dictionary with the expected result.
+# Each parse_qsl testcase is a two-tuple that contains
+# a string with the query and a list with the expected result.
parse_qsl_test_cases = [
("", []),
@@ -42,6 +42,9 @@ parse_qsl_test_cases = [
(b"a=1;a=2", [(b'a', b'1'), (b'a', b'2')]),
]
+# Each parse_qs testcase is a two-tuple that contains
+# a string with the query and a dictionary with the expected result.
+
parse_qs_test_cases = [
("", {}),
("&", {}),
@@ -290,7 +293,6 @@ class UrlParseTestCase(unittest.TestCase):
def test_RFC2396(self):
# cases from RFC 2396
-
self.checkJoin(RFC2396_BASE, 'g:h', 'g:h')
self.checkJoin(RFC2396_BASE, 'g', 'http://a/b/c/g')
self.checkJoin(RFC2396_BASE, './g', 'http://a/b/c/g')
@@ -333,9 +335,7 @@ class UrlParseTestCase(unittest.TestCase):
# self.checkJoin(RFC2396_BASE, '/./g', 'http://a/./g')
# self.checkJoin(RFC2396_BASE, '/../g', 'http://a/../g')
-
def test_RFC3986(self):
- # Test cases from RFC3986
self.checkJoin(RFC3986_BASE, '?y','http://a/b/c/d;p?y')
self.checkJoin(RFC3986_BASE, ';x', 'http://a/b/c/;x')
self.checkJoin(RFC3986_BASE, 'g:h','g:h')
@@ -363,7 +363,7 @@ class UrlParseTestCase(unittest.TestCase):
self.checkJoin(RFC3986_BASE, '../../g','http://a/g')
self.checkJoin(RFC3986_BASE, '../../../g', 'http://a/g')
- #Abnormal Examples
+ # Abnormal Examples
# The 'abnormal scenarios' are incompatible with RFC2986 parsing
# Tests are here for reference.
diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py
index 958767a08d..32de25b374 100644
--- a/Lib/urllib/parse.py
+++ b/Lib/urllib/parse.py
@@ -612,6 +612,7 @@ def unquote(string, encoding='utf-8', errors='replace'):
append(bits[i + 1])
return ''.join(res)
+
def parse_qs(qs, keep_blank_values=False, strict_parsing=False,
encoding='utf-8', errors='replace'):
"""Parse a query given as a string argument.
@@ -633,6 +634,8 @@ def parse_qs(qs, keep_blank_values=False, strict_parsing=False,
encoding and errors: specify how to decode percent-encoded sequences
into Unicode characters, as accepted by the bytes.decode() method.
+
+ Returns a dictionary.
"""
parsed_result = {}
pairs = parse_qsl(qs, keep_blank_values, strict_parsing,
@@ -644,28 +647,29 @@ def parse_qs(qs, keep_blank_values=False, strict_parsing=False,
parsed_result[name] = [value]
return parsed_result
+
def parse_qsl(qs, keep_blank_values=False, strict_parsing=False,
encoding='utf-8', errors='replace'):
"""Parse a query given as a string argument.
- Arguments:
+ Arguments:
- qs: percent-encoded query string to be parsed
+ qs: percent-encoded query string to be parsed
- keep_blank_values: flag indicating whether blank values in
- percent-encoded queries should be treated as blank strings. A
- true value indicates that blanks should be retained as blank
- strings. The default false value indicates that blank values
- are to be ignored and treated as if they were not included.
+ keep_blank_values: flag indicating whether blank values in
+ percent-encoded queries should be treated as blank strings.
+ A true value indicates that blanks should be retained as blank
+ strings. The default false value indicates that blank values
+ are to be ignored and treated as if they were not included.
- strict_parsing: flag indicating what to do with parsing errors. If
- false (the default), errors are silently ignored. If true,
- errors raise a ValueError exception.
+ strict_parsing: flag indicating what to do with parsing errors. If
+ false (the default), errors are silently ignored. If true,
+ errors raise a ValueError exception.
- encoding and errors: specify how to decode percent-encoded sequences
- into Unicode characters, as accepted by the bytes.decode() method.
+ encoding and errors: specify how to decode percent-encoded sequences
+ into Unicode characters, as accepted by the bytes.decode() method.
- Returns a list, as G-d intended.
+ Returns a list, as G-d intended.
"""
qs, _coerce_result = _coerce_args(qs)
pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
--
GitLab
From 19d61b265fabed01ebfb8eae9855f2ee59ff591b Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Fri, 7 Apr 2017 00:56:59 -0700
Subject: [PATCH 0109/1433] Remove Invalid comment in test_urllib2.py. (#1022)
(cherry picked from commit fd0cd07a5a3c964c084f4efc5bbcb89dd2193ee6)
---
Lib/test/test_urllib2.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index d50211c598..876fcd4199 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -848,7 +848,6 @@ class HandlerTests(unittest.TestCase):
req = Request(url)
try:
h.file_open(req)
- # XXXX remove OSError when bug fixed
except urllib.error.URLError:
self.assertFalse(ftp)
else:
--
GitLab
From 616d3eb7ef96f1a27bbff68fba6e5d229257d936 Mon Sep 17 00:00:00 2001
From: Barry Warsaw
Date: Fri, 7 Apr 2017 16:50:13 -0400
Subject: [PATCH 0110/1433] Fix a minor typo. (#1032) (#1037)
(cherry picked from commit dd9a0a14c89d57e43898d4b866b8c161e4ff8506)
---
Doc/library/asyncio-protocol.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst
index 482ffbbed3..3f55506c66 100644
--- a/Doc/library/asyncio-protocol.rst
+++ b/Doc/library/asyncio-protocol.rst
@@ -384,7 +384,7 @@ The following callbacks are called on :class:`Protocol` instances:
.. method:: Protocol.eof_received()
- Calls when the other end signals it won't send any more data
+ Called when the other end signals it won't send any more data
(for example by calling :meth:`write_eof`, if the other end also uses
asyncio).
--
GitLab
From d0d575a6db8cb3b2a720be9f404af3d754da9a5d Mon Sep 17 00:00:00 2001
From: Vinay Sajip
Date: Fri, 7 Apr 2017 23:23:08 +0100
Subject: [PATCH 0111/1433] bpo-29939: suppress compiler warnings in
_ctypes_test (#1038)
bpo-29939: Changed test code to suppress a compiler warning, while taking care to avoid the code being optimized out by the compiler.
(cherry picked from commit 164d30eb1e66575dafee6af4fca4cbf52c7fbe6a)
---
Modules/_ctypes/_ctypes_test.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c
index 59d56d0d21..6119ecdaf9 100644
--- a/Modules/_ctypes/_ctypes_test.c
+++ b/Modules/_ctypes/_ctypes_test.c
@@ -52,9 +52,9 @@ _testfunc_cbk_large_struct(Test in, void (*func)(Test))
EXPORT(void)
_testfunc_large_struct_update_value(Test in)
{
- in.first = 0x0badf00d;
- in.second = 0x0badf00d;
- in.third = 0x0badf00d;
+ ((volatile Test *)&in)->first = 0x0badf00d;
+ ((volatile Test *)&in)->second = 0x0badf00d;
+ ((volatile Test *)&in)->third = 0x0badf00d;
}
EXPORT(void)testfunc_array(int values[4])
--
GitLab
From c26b19d5c7aba51b50a4d7fb5f8291036cb9da24 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sat, 8 Apr 2017 11:18:14 +0300
Subject: [PATCH 0112/1433] Expand the PySlice_GetIndicesEx macro. (#1023)
(#1044)
(cherry picked from commit b879fe82e7e5c3f7673c9a7fa4aad42bd05445d8)
---
Modules/_ctypes/_ctypes.c | 10 ++++------
Modules/_elementtree.c | 12 ++++++------
Modules/_testbuffer.c | 7 ++++---
Modules/arraymodule.c | 11 ++++++-----
Modules/mmapmodule.c | 9 ++++-----
Objects/bytearrayobject.c | 12 ++++++------
Objects/bytesobject.c | 6 +++---
Objects/listobject.c | 10 ++++++----
Objects/memoryobject.c | 4 ++--
Objects/tupleobject.c | 6 +++---
Objects/unicodeobject.c | 5 +++--
11 files changed, 47 insertions(+), 45 deletions(-)
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index df3aedec6e..12234e254e 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -4273,11 +4273,10 @@ Array_subscript(PyObject *myself, PyObject *item)
PyObject *np;
Py_ssize_t start, stop, step, slicelen, cur, i;
- if (PySlice_GetIndicesEx(item,
- self->b_length, &start, &stop,
- &step, &slicelen) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+ slicelen = PySlice_AdjustIndices(self->b_length, &start, &stop, step);
stgdict = PyObject_stgdict((PyObject *)self);
assert(stgdict); /* Cannot be NULL for array object instances */
@@ -4414,11 +4413,10 @@ Array_ass_subscript(PyObject *myself, PyObject *item, PyObject *value)
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelen, otherlen, i, cur;
- if (PySlice_GetIndicesEx(item,
- self->b_length, &start, &stop,
- &step, &slicelen) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return -1;
}
+ slicelen = PySlice_AdjustIndices(self->b_length, &start, &stop, step);
if ((step < 0 && start < stop) ||
(step > 0 && start > stop))
stop = start;
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index e3350d194d..bef702ebe6 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -1712,11 +1712,11 @@ element_subscr(PyObject* self_, PyObject* item)
if (!self->extra)
return PyList_New(0);
- if (PySlice_GetIndicesEx(item,
- self->extra->length,
- &start, &stop, &step, &slicelen) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+ slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
+ step);
if (slicelen <= 0)
return PyList_New(0);
@@ -1768,11 +1768,11 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
return -1;
}
- if (PySlice_GetIndicesEx(item,
- self->extra->length,
- &start, &stop, &step, &slicelen) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return -1;
}
+ slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
+ step);
if (value == NULL) {
/* Delete slice */
diff --git a/Modules/_testbuffer.c b/Modules/_testbuffer.c
index 4e1ce6851a..6b8ab34d93 100644
--- a/Modules/_testbuffer.c
+++ b/Modules/_testbuffer.c
@@ -1715,10 +1715,10 @@ init_slice(Py_buffer *base, PyObject *key, int dim)
{
Py_ssize_t start, stop, step, slicelength;
- if (PySlice_GetIndicesEx(key, base->shape[dim],
- &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
return -1;
}
+ slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
if (base->suboffsets == NULL || dim == 0) {
@@ -1935,9 +1935,10 @@ slice_indices(PyObject *self, PyObject *args)
"first argument must be a slice object");
return NULL;
}
- if (PySlice_GetIndicesEx(key, len, &s[0], &s[1], &s[2], &s[3]) < 0) {
+ if (PySlice_Unpack(key, &s[0], &s[1], &s[2]) < 0) {
return NULL;
}
+ s[3] = PySlice_AdjustIndices(len, &s[0], &s[1], s[2]);
ret = PyTuple_New(4);
if (ret == NULL)
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index d4221fe4c6..64e0f172fd 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -2297,10 +2297,11 @@ array_subscr(arrayobject* self, PyObject* item)
arrayobject* ar;
int itemsize = self->ob_descr->itemsize;
- if (PySlice_GetIndicesEx(item, Py_SIZE(self),
- &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+ slicelength = PySlice_AdjustIndices(Py_SIZE(self), &start, &stop,
+ step);
if (slicelength <= 0) {
return newarrayobject(&Arraytype, 0, self->ob_descr);
@@ -2368,11 +2369,11 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
return (*self->ob_descr->setitem)(self, i, value);
}
else if (PySlice_Check(item)) {
- if (PySlice_GetIndicesEx(item,
- Py_SIZE(self), &start, &stop,
- &step, &slicelength) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return -1;
}
+ slicelength = PySlice_AdjustIndices(Py_SIZE(self), &start, &stop,
+ step);
}
else {
PyErr_SetString(PyExc_TypeError,
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 5f1615ff82..426b7caceb 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -806,10 +806,10 @@ mmap_subscript(mmap_object *self, PyObject *item)
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelen;
- if (PySlice_GetIndicesEx(item, self->size,
- &start, &stop, &step, &slicelen) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+ slicelen = PySlice_AdjustIndices(self->size, &start, &stop, step);
if (slicelen <= 0)
return PyBytes_FromStringAndSize("", 0);
@@ -932,11 +932,10 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
Py_ssize_t start, stop, step, slicelen;
Py_buffer vbuf;
- if (PySlice_GetIndicesEx(item,
- self->size, &start, &stop,
- &step, &slicelen) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return -1;
}
+ slicelen = PySlice_AdjustIndices(self->size, &start, &stop, step);
if (value == NULL) {
PyErr_SetString(PyExc_TypeError,
"mmap object doesn't support slice deletion");
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index d456678d46..a9c8ca6f1f 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -400,11 +400,11 @@ bytearray_subscript(PyByteArrayObject *self, PyObject *index)
}
else if (PySlice_Check(index)) {
Py_ssize_t start, stop, step, slicelength, cur, i;
- if (PySlice_GetIndicesEx(index,
- PyByteArray_GET_SIZE(self),
- &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_Unpack(index, &start, &stop, &step) < 0) {
return NULL;
}
+ slicelength = PySlice_AdjustIndices(PyByteArray_GET_SIZE(self),
+ &start, &stop, step);
if (slicelength <= 0)
return PyByteArray_FromStringAndSize("", 0);
@@ -630,11 +630,11 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu
}
}
else if (PySlice_Check(index)) {
- if (PySlice_GetIndicesEx(index,
- PyByteArray_GET_SIZE(self),
- &start, &stop, &step, &slicelen) < 0) {
+ if (PySlice_Unpack(index, &start, &stop, &step) < 0) {
return -1;
}
+ slicelen = PySlice_AdjustIndices(PyByteArray_GET_SIZE(self), &start,
+ &stop, step);
}
else {
PyErr_Format(PyExc_TypeError,
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index c95a46d184..4c55294d9d 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -1683,11 +1683,11 @@ bytes_subscript(PyBytesObject* self, PyObject* item)
char* result_buf;
PyObject* result;
- if (PySlice_GetIndicesEx(item,
- PyBytes_GET_SIZE(self),
- &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+ slicelength = PySlice_AdjustIndices(PyBytes_GET_SIZE(self), &start,
+ &stop, step);
if (slicelength <= 0) {
return PyBytes_FromStringAndSize("", 0);
diff --git a/Objects/listobject.c b/Objects/listobject.c
index cde281a0f6..547bdf0b95 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2420,10 +2420,11 @@ list_subscript(PyListObject* self, PyObject* item)
PyObject* it;
PyObject **src, **dest;
- if (PySlice_GetIndicesEx(item, Py_SIZE(self),
- &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+ slicelength = PySlice_AdjustIndices(Py_SIZE(self), &start, &stop,
+ step);
if (slicelength <= 0) {
return PyList_New(0);
@@ -2469,10 +2470,11 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
- if (PySlice_GetIndicesEx(item, Py_SIZE(self),
- &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return -1;
}
+ slicelength = PySlice_AdjustIndices(Py_SIZE(self), &start, &stop,
+ step);
if (step == 1)
return list_ass_slice(self, start, stop, value);
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index b1798a2073..e1ac728178 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -2285,10 +2285,10 @@ init_slice(Py_buffer *base, PyObject *key, int dim)
{
Py_ssize_t start, stop, step, slicelength;
- if (PySlice_GetIndicesEx(key, base->shape[dim],
- &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
return -1;
}
+ slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
if (base->suboffsets == NULL || dim == 0) {
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 52f20f4fe8..0dada74dc7 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -720,11 +720,11 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
PyObject* it;
PyObject **src, **dest;
- if (PySlice_GetIndicesEx(item,
- PyTuple_GET_SIZE(self),
- &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+ slicelength = PySlice_AdjustIndices(PyTuple_GET_SIZE(self), &start,
+ &stop, step);
if (slicelength <= 0) {
return PyTuple_New(0);
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index a5ae454b49..949205adf9 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -13915,10 +13915,11 @@ unicode_subscript(PyObject* self, PyObject* item)
int src_kind, dest_kind;
Py_UCS4 ch, max_char, kind_limit;
- if (PySlice_GetIndicesEx(item, PyUnicode_GET_LENGTH(self),
- &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+ slicelength = PySlice_AdjustIndices(PyUnicode_GET_LENGTH(self),
+ &start, &stop, step);
if (slicelength <= 0) {
_Py_RETURN_UNICODE_EMPTY();
--
GitLab
From af685f9050416da8050e0ec11a8dff9afd4130e7 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sat, 8 Apr 2017 11:25:47 +0300
Subject: [PATCH 0113/1433] bpo-29998: Pickling and copying ImportError now
preserves name and path (#1010) (#1042)
attributes.
(cherry picked from commit b785396ab451b0c9d6ae9ee5a9e56c810209a6cb)
---
Lib/test/test_exceptions.py | 20 ++++++++++++++++
Misc/NEWS | 3 +++
Objects/exceptions.c | 48 +++++++++++++++++++++++++++++++++++++
3 files changed, 71 insertions(+)
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 48379222c3..960fc0f1bf 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -1,5 +1,6 @@
# Python test set -- part 5, built-in exceptions
+import copy
import os
import sys
import unittest
@@ -1119,6 +1120,25 @@ class ImportErrorTests(unittest.TestCase):
exc = ImportError(arg)
self.assertEqual(str(arg), str(exc))
+ def test_copy_pickle(self):
+ for kwargs in (dict(),
+ dict(name='somename'),
+ dict(path='somepath'),
+ dict(name='somename', path='somepath')):
+ orig = ImportError('test', **kwargs)
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ exc = pickle.loads(pickle.dumps(orig, proto))
+ self.assertEqual(exc.args, ('test',))
+ self.assertEqual(exc.msg, 'test')
+ self.assertEqual(exc.name, orig.name)
+ self.assertEqual(exc.path, orig.path)
+ for c in copy.copy, copy.deepcopy:
+ exc = c(orig)
+ self.assertEqual(exc.args, ('test',))
+ self.assertEqual(exc.msg, 'test')
+ self.assertEqual(exc.name, orig.name)
+ self.assertEqual(exc.path, orig.path)
+
if __name__ == '__main__':
unittest.main()
diff --git a/Misc/NEWS b/Misc/NEWS
index fa20ea16cd..83f9e7a685 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -32,6 +32,9 @@ Core and Builtins
Library
-------
+- bpo-29998: Pickling and copying ImportError now preserves name and path
+ attributes.
+
- bpo-29953: Fixed memory leaks in the replace() method of datetime and time
objects when pass out of bound fold argument.
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index f63f06a145..d158b9768d 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -686,6 +686,53 @@ ImportError_str(PyImportErrorObject *self)
}
}
+static PyObject *
+ImportError_getstate(PyImportErrorObject *self)
+{
+ PyObject *dict = ((PyBaseExceptionObject *)self)->dict;
+ if (self->name || self->path) {
+ _Py_IDENTIFIER(name);
+ _Py_IDENTIFIER(path);
+ dict = dict ? PyDict_Copy(dict) : PyDict_New();
+ if (dict == NULL)
+ return NULL;
+ if (self->name && _PyDict_SetItemId(dict, &PyId_name, self->name) < 0) {
+ Py_DECREF(dict);
+ return NULL;
+ }
+ if (self->path && _PyDict_SetItemId(dict, &PyId_path, self->path) < 0) {
+ Py_DECREF(dict);
+ return NULL;
+ }
+ return dict;
+ }
+ else if (dict) {
+ Py_INCREF(dict);
+ return dict;
+ }
+ else {
+ Py_RETURN_NONE;
+ }
+}
+
+/* Pickling support */
+static PyObject *
+ImportError_reduce(PyImportErrorObject *self)
+{
+ PyObject *res;
+ PyObject *args;
+ PyObject *state = ImportError_getstate(self);
+ if (state == NULL)
+ return NULL;
+ args = ((PyBaseExceptionObject *)self)->args;
+ if (state == Py_None)
+ res = PyTuple_Pack(2, Py_TYPE(self), args);
+ else
+ res = PyTuple_Pack(3, Py_TYPE(self), args, state);
+ Py_DECREF(state);
+ return res;
+}
+
static PyMemberDef ImportError_members[] = {
{"msg", T_OBJECT, offsetof(PyImportErrorObject, msg), 0,
PyDoc_STR("exception message")},
@@ -697,6 +744,7 @@ static PyMemberDef ImportError_members[] = {
};
static PyMethodDef ImportError_methods[] = {
+ {"__reduce__", (PyCFunction)ImportError_reduce, METH_NOARGS},
{NULL}
};
--
GitLab
From 4c116cb3b3ee38cae229f7e0df0cd2045fe73c27 Mon Sep 17 00:00:00 2001
From: Nick Coghlan
Date: Sun, 9 Apr 2017 19:22:36 +1000
Subject: [PATCH 0114/1433] bpo-29798: Handle git worktree in patchcheck
(#1058) (#1060)
The original attempted fix missed an `isdir()` call in
`get_base_branch()`.
(cherry picked from commit 2abfdf5a81383d3b1ed6b7321903a9a168c373c5)
---
Tools/scripts/patchcheck.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Tools/scripts/patchcheck.py b/Tools/scripts/patchcheck.py
index f4ec7d8a30..33a9fead87 100755
--- a/Tools/scripts/patchcheck.py
+++ b/Tools/scripts/patchcheck.py
@@ -70,7 +70,7 @@ def get_git_upstream_remote():
@status("Getting base branch for PR",
info=lambda x: x if x is not None else "not a PR branch")
def get_base_branch():
- if not os.path.isdir(os.path.join(SRCDIR, '.git')):
+ if not os.path.exists(os.path.join(SRCDIR, '.git')):
# Not a git checkout, so there's no base branch
return None
version = sys.version_info
--
GitLab
From a524d6307273e3920d410452ace89610c843f051 Mon Sep 17 00:00:00 2001
From: Nick Coghlan
Date: Sun, 9 Apr 2017 20:57:04 +1000
Subject: [PATCH 0115/1433] bpo-29506: Clarify deep copy note in copy module
The reference to administrative data was confusing to readers,
so this simplifies the note to explain that deep copying may copy
more then you intended, such as data that you expected to be
shared between copies.
(cherry picked from commit 19e04942562a980ad2519f6ff79c455a7472783b)
---
Doc/library/copy.rst | 4 ++--
Misc/ACKS | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst
index d0b861d469..2041d9175e 100644
--- a/Doc/library/copy.rst
+++ b/Doc/library/copy.rst
@@ -47,8 +47,8 @@ copy operations:
* Recursive objects (compound objects that, directly or indirectly, contain a
reference to themselves) may cause a recursive loop.
-* Because deep copy copies *everything* it may copy too much, e.g.,
- even administrative data structures that should be shared even between copies.
+* Because deep copy copies everything it may copy too much, such as data
+ which is intended to be shared between copies.
The :func:`deepcopy` function avoids these problems by:
diff --git a/Misc/ACKS b/Misc/ACKS
index b5da02a63a..72070e19f6 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -770,6 +770,7 @@ Lawrence Kesteloot
Vivek Khera
Dhiru Kholia
Akshit Khurana
+Sanyam Khurana
Mads Kiilerich
Jason Killen
Jan Kim
--
GitLab
From 854ca174a92970d11d9b063af46e00d132832944 Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Sun, 9 Apr 2017 10:15:06 -0700
Subject: [PATCH 0116/1433] Remove invalid comment in urllib.request. (#1055)
(cherry picked from commit a2a9ddd923a849124bdd1c484f70f02df6fde0e9)
---
Lib/urllib/request.py | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
index b6690c3d0e..3e82000466 100644
--- a/Lib/urllib/request.py
+++ b/Lib/urllib/request.py
@@ -1658,14 +1658,10 @@ else:
of the 'file' scheme; not recommended for general use."""
return quote(pathname)
-# This really consists of two pieces:
-# (1) a class which handles opening of all sorts of URLs
-# (plus assorted utilities etc.)
-# (2) a set of functions for parsing URLs
-# XXX Should these be separated out into different modules?
-
ftpcache = {}
+
+
class URLopener:
"""Class to open URLs.
This is a class rather than just a subroutine because we may need
--
GitLab
From 90eb7a9ff4ce38b5c4e3662bdd42a0ed513893a2 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sun, 9 Apr 2017 15:15:57 -0700
Subject: [PATCH 0117/1433] [3.6] Correct typo in configparser.rst (GH-1012)
(GH-1025)
(cherry picked from commit 01fa9ae5460b00bf1ced500c797176ebd3fb060d)
---
Doc/library/configparser.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst
index af57cba2b5..04c2a82092 100644
--- a/Doc/library/configparser.rst
+++ b/Doc/library/configparser.rst
@@ -34,8 +34,8 @@ can be customized by end users easily.
.. seealso::
Module :mod:`shlex`
- Support for a creating Unix shell-like mini-languages which can be used
- as an alternate format for application configuration files.
+ Support for creating Unix shell-like mini-languages which can be used as
+ an alternate format for application configuration files.
Module :mod:`json`
The json module implements a subset of JavaScript syntax which can also
--
GitLab
From 577fc04a7157f6e904cffd6a0e1ad83d3460acd6 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sun, 9 Apr 2017 15:17:06 -0700
Subject: [PATCH 0118/1433] [3.6] bpo-29549: Fixes docstring for str.index
(GH-256) (GH-1028)
(cherry picked from commit 43ba8861e0ad044efafa46a7cc04e12ac5df640e)
---
Objects/bytes_methods.c | 13 ++++++++++---
Objects/unicodeobject.c | 12 ++++++++++--
2 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c
index d5c4fe6346..625e242d56 100644
--- a/Objects/bytes_methods.c
+++ b/Objects/bytes_methods.c
@@ -542,7 +542,11 @@ _Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args)
PyDoc_STRVAR_shared(_Py_index__doc__,
"B.index(sub[, start[, end]]) -> int\n\
\n\
-Like B.find() but raise ValueError when the subsection is not found.");
+Return the lowest index in B where subsection sub is found,\n\
+such that sub is contained within B[start,end]. Optional\n\
+arguments start and end are interpreted as in slice notation.\n\
+\n\
+Raises ValueError when the subsection is not found.");
PyObject *
_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args)
@@ -579,7 +583,11 @@ _Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args)
PyDoc_STRVAR_shared(_Py_rindex__doc__,
"B.rindex(sub[, start[, end]]) -> int\n\
\n\
-Like B.rfind() but raise ValueError when the subsection is not found.");
+Return the highest index in B where subsection sub is found,\n\
+such that sub is contained within B[start,end]. Optional\n\
+arguments start and end are interpreted as in slice notation.\n\
+\n\
+Raise ValueError when the subsection is not found.");
PyObject *
_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args)
@@ -811,4 +819,3 @@ PyDoc_STRVAR_shared(_Py_zfill__doc__,
"\n"
"Pad a numeric string B with zeros on the left, to fill a field\n"
"of the specified width. B is never truncated.");
-
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 949205adf9..7871043681 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -11701,7 +11701,11 @@ unicode_hash(PyObject *self)
PyDoc_STRVAR(index__doc__,
"S.index(sub[, start[, end]]) -> int\n\
\n\
-Like S.find() but raise ValueError when the substring is not found.");
+Return the lowest index in S where substring sub is found, \n\
+such that sub is contained within S[start:end]. Optional\n\
+arguments start and end are interpreted as in slice notation.\n\
+\n\
+Raises ValueError when the substring is not found.");
static PyObject *
unicode_index(PyObject *self, PyObject *args)
@@ -12758,7 +12762,11 @@ unicode_rfind(PyObject *self, PyObject *args)
PyDoc_STRVAR(rindex__doc__,
"S.rindex(sub[, start[, end]]) -> int\n\
\n\
-Like S.rfind() but raise ValueError when the substring is not found.");
+Return the highest index in S where substring sub is found,\n\
+such that sub is contained within S[start:end]. Optional\n\
+arguments start and end are interpreted as in slice notation.\n\
+\n\
+Raises ValueError when the substring is not found.");
static PyObject *
unicode_rindex(PyObject *self, PyObject *args)
--
GitLab
From 28ddd3c905836907bf0c4df909067d3a054358c1 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sun, 9 Apr 2017 15:17:28 -0700
Subject: [PATCH 0119/1433] [3.6] Improvements to typing documentation (GH-967)
(GH-1053)
Documents a few omitted classes and adds NamedTuple methods.
(cherry picked from commit 45d22c256bce3afcf57f49032a6b20fdec4f26ad)
---
Doc/library/typing.rst | 50 ++++++++++++++++++++++++++++++++++++------
1 file changed, 43 insertions(+), 7 deletions(-)
diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst
index d130e1759d..2cfc37f695 100644
--- a/Doc/library/typing.rst
+++ b/Doc/library/typing.rst
@@ -508,6 +508,14 @@ The module defines the following classes, functions and decorators:
An ABC with one abstract method ``__float__``.
+.. class:: SupportsComplex
+
+ An ABC with one abstract method ``__complex__``.
+
+.. class:: SupportsBytes
+
+ An ABC with one abstract method ``__bytes__``.
+
.. class:: SupportsAbs
An ABC with one abstract method ``__abs__`` that is covariant
@@ -658,7 +666,19 @@ The module defines the following classes, functions and decorators:
.. class:: DefaultDict(collections.defaultdict, MutableMapping[KT, VT])
- A generic version of :class:`collections.defaultdict`
+ A generic version of :class:`collections.defaultdict`.
+
+.. class:: Counter(collections.Counter, Dict[T, int])
+
+ A generic version of :class:`collections.Counter`.
+
+ .. versionadded:: 3.6.1
+
+.. class:: ChainMap(collections.ChainMap, MutableMapping[KT, VT])
+
+ A generic version of :class:`collections.ChainMap`.
+
+ .. versionadded:: 3.6.1
.. class:: Generator(Iterator[T_co], Generic[T_co, T_contra, V_co])
@@ -742,9 +762,12 @@ The module defines the following classes, functions and decorators:
This defines the generic type ``IO[AnyStr]`` and aliases ``TextIO``
and ``BinaryIO`` for respectively ``IO[str]`` and ``IO[bytes]``.
- These representing the types of I/O streams such as returned by
+ These represent the types of I/O streams such as returned by
:func:`open`.
+ These types are also accessible directly as ``typing.IO``,
+ ``typing.TextIO``, and ``typing.BinaryIO``.
+
.. class:: re
Wrapper namespace for regular expression matching types.
@@ -756,6 +779,9 @@ The module defines the following classes, functions and decorators:
``Pattern[str]``, ``Pattern[bytes]``, ``Match[str]``, or
``Match[bytes]``.
+ These types are also accessible directly as ``typing.Pattern``
+ and ``typing.Match``.
+
.. class:: NamedTuple
Typed version of namedtuple.
@@ -782,10 +808,20 @@ The module defines the following classes, functions and decorators:
Fields with a default value must come after any fields without a default.
The resulting class has two extra attributes: ``_field_types``,
- giving a dict mapping field names to types, and ``field_defaults``, a dict
+ giving a dict mapping field names to types, and ``_field_defaults``, a dict
mapping field names to default values. (The field names are in the
``_fields`` attribute, which is part of the namedtuple API.)
+ ``NamedTuple`` subclasses can also have docstrings and methods::
+
+ class Employee(NamedTuple):
+ """Represents an employee."""
+ name: str
+ id: int = 3
+
+ def __repr__(self) -> str:
+ return f''
+
Backward-compatible usage::
Employee = NamedTuple('Employee', [('name', str), ('id', int)])
@@ -794,7 +830,7 @@ The module defines the following classes, functions and decorators:
Added support for :pep:`526` variable annotation syntax.
.. versionchanged:: 3.6.1
- Added support for default values.
+ Added support for default values, methods, and docstrings.
.. function:: NewType(typ)
@@ -972,9 +1008,9 @@ The module defines the following classes, functions and decorators:
:data:`ClassVar` is not a class itself, and should not
be used with :func:`isinstance` or :func:`issubclass`.
- Note that :data:`ClassVar` does not change Python runtime behavior;
- it can be used by 3rd party type checkers, so that the following
- code might flagged as an error by those::
+ :data:`ClassVar` does not change Python runtime behavior, but
+ it can be used by third-party type checkers. For example, a type checker
+ might flag the following code as an error::
enterprise_d = Starship(3000)
enterprise_d.stats = {} # Error, setting class variable on instance
--
GitLab
From 03066a05f5cdf96bc3bf15718f586877860f2d47 Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Sun, 9 Apr 2017 20:37:44 -0700
Subject: [PATCH 0120/1433] Remove OSError related comment in urllib.request.
(#1072)
(cherry picked from commit 6dfcc81f6b1c82a71a1c876e14424fb8b3573447)
---
Lib/urllib/request.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
index 3e82000466..96921440ed 100644
--- a/Lib/urllib/request.py
+++ b/Lib/urllib/request.py
@@ -1488,7 +1488,6 @@ class FileHandler(BaseHandler):
origurl = 'file://' + filename
return addinfourl(open(localfile, 'rb'), headers, origurl)
except OSError as exp:
- # users shouldn't expect OSErrors coming from urlopen()
raise URLError(exp)
raise URLError('file not on local host')
--
GitLab
From f0c416799b33742af36d7c6608b9a422615fb3d2 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Wed, 12 Apr 2017 20:02:21 -0700
Subject: [PATCH 0121/1433] [3.6] bpo-30047: Fix a typo in
Doc/library/select.rst (GH-1086) (GH-1098)
(cherry picked from commit 3e0f1fc4e0ffcfcc706015fa3d67c262948ef171)
---
Doc/library/select.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/library/select.rst b/Doc/library/select.rst
index f97118ebe0..bd5442c6a2 100644
--- a/Doc/library/select.rst
+++ b/Doc/library/select.rst
@@ -290,7 +290,7 @@ Edge and Level Trigger Polling (epoll) Objects
| :const:`EPOLLEXCLUSIVE` | Wake only one epoll object when the |
| | associated fd has an event. The default (if |
| | this flag is not set) is to wake all epoll |
- | | objects polling on on a fd. |
+ | | objects polling on a fd. |
+-------------------------+-----------------------------------------------+
| :const:`EPOLLRDHUP` | Stream socket peer closed connection or shut |
| | down writing half of connection. |
--
GitLab
From 14944c62300f741488c2f28cb91ad1e3fef7343b Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Thu, 13 Apr 2017 11:14:17 +0800
Subject: [PATCH 0122/1433] bpo-26985: Add missing info of code object in
inspect documentation (GH-1090) (GH-1099)
---
Doc/library/inspect.rst | 379 +++++++++++++++++++++-------------------
Lib/inspect.py | 30 ++--
Misc/NEWS | 5 +
3 files changed, 223 insertions(+), 191 deletions(-)
diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst
index 4ff2187b45..6be28a2b31 100644
--- a/Doc/library/inspect.rst
+++ b/Doc/library/inspect.rst
@@ -34,185 +34,198 @@ provided as convenient choices for the second argument to :func:`getmembers`.
They also help you determine when you can expect to find the following special
attributes:
-+-----------+-----------------+---------------------------+
-| Type | Attribute | Description |
-+===========+=================+===========================+
-| module | __doc__ | documentation string |
-+-----------+-----------------+---------------------------+
-| | __file__ | filename (missing for |
-| | | built-in modules) |
-+-----------+-----------------+---------------------------+
-| class | __doc__ | documentation string |
-+-----------+-----------------+---------------------------+
-| | __name__ | name with which this |
-| | | class was defined |
-+-----------+-----------------+---------------------------+
-| | __qualname__ | qualified name |
-+-----------+-----------------+---------------------------+
-| | __module__ | name of module in which |
-| | | this class was defined |
-+-----------+-----------------+---------------------------+
-| method | __doc__ | documentation string |
-+-----------+-----------------+---------------------------+
-| | __name__ | name with which this |
-| | | method was defined |
-+-----------+-----------------+---------------------------+
-| | __qualname__ | qualified name |
-+-----------+-----------------+---------------------------+
-| | __func__ | function object |
-| | | containing implementation |
-| | | of method |
-+-----------+-----------------+---------------------------+
-| | __self__ | instance to which this |
-| | | method is bound, or |
-| | | ``None`` |
-+-----------+-----------------+---------------------------+
-| function | __doc__ | documentation string |
-+-----------+-----------------+---------------------------+
-| | __name__ | name with which this |
-| | | function was defined |
-+-----------+-----------------+---------------------------+
-| | __qualname__ | qualified name |
-+-----------+-----------------+---------------------------+
-| | __code__ | code object containing |
-| | | compiled function |
-| | | :term:`bytecode` |
-+-----------+-----------------+---------------------------+
-| | __defaults__ | tuple of any default |
-| | | values for positional or |
-| | | keyword parameters |
-+-----------+-----------------+---------------------------+
-| | __kwdefaults__ | mapping of any default |
-| | | values for keyword-only |
-| | | parameters |
-+-----------+-----------------+---------------------------+
-| | __globals__ | global namespace in which |
-| | | this function was defined |
-+-----------+-----------------+---------------------------+
-| | __annotations__ | mapping of parameters |
-| | | names to annotations; |
-| | | ``"return"`` key is |
-| | | reserved for return |
-| | | annotations. |
-+-----------+-----------------+---------------------------+
-| traceback | tb_frame | frame object at this |
-| | | level |
-+-----------+-----------------+---------------------------+
-| | tb_lasti | index of last attempted |
-| | | instruction in bytecode |
-+-----------+-----------------+---------------------------+
-| | tb_lineno | current line number in |
-| | | Python source code |
-+-----------+-----------------+---------------------------+
-| | tb_next | next inner traceback |
-| | | object (called by this |
-| | | level) |
-+-----------+-----------------+---------------------------+
-| frame | f_back | next outer frame object |
-| | | (this frame's caller) |
-+-----------+-----------------+---------------------------+
-| | f_builtins | builtins namespace seen |
-| | | by this frame |
-+-----------+-----------------+---------------------------+
-| | f_code | code object being |
-| | | executed in this frame |
-+-----------+-----------------+---------------------------+
-| | f_globals | global namespace seen by |
-| | | this frame |
-+-----------+-----------------+---------------------------+
-| | f_lasti | index of last attempted |
-| | | instruction in bytecode |
-+-----------+-----------------+---------------------------+
-| | f_lineno | current line number in |
-| | | Python source code |
-+-----------+-----------------+---------------------------+
-| | f_locals | local namespace seen by |
-| | | this frame |
-+-----------+-----------------+---------------------------+
-| | f_restricted | 0 or 1 if frame is in |
-| | | restricted execution mode |
-+-----------+-----------------+---------------------------+
-| | f_trace | tracing function for this |
-| | | frame, or ``None`` |
-+-----------+-----------------+---------------------------+
-| code | co_argcount | number of arguments (not |
-| | | including \* or \*\* |
-| | | args) |
-+-----------+-----------------+---------------------------+
-| | co_code | string of raw compiled |
-| | | bytecode |
-+-----------+-----------------+---------------------------+
-| | co_consts | tuple of constants used |
-| | | in the bytecode |
-+-----------+-----------------+---------------------------+
-| | co_filename | name of file in which |
-| | | this code object was |
-| | | created |
-+-----------+-----------------+---------------------------+
-| | co_firstlineno | number of first line in |
-| | | Python source code |
-+-----------+-----------------+---------------------------+
-| | co_flags | bitmap of ``CO_*`` flags, |
-| | | read more :ref:`here |
-| | | `|
-+-----------+-----------------+---------------------------+
-| | co_lnotab | encoded mapping of line |
-| | | numbers to bytecode |
-| | | indices |
-+-----------+-----------------+---------------------------+
-| | co_name | name with which this code |
-| | | object was defined |
-+-----------+-----------------+---------------------------+
-| | co_names | tuple of names of local |
-| | | variables |
-+-----------+-----------------+---------------------------+
-| | co_nlocals | number of local variables |
-+-----------+-----------------+---------------------------+
-| | co_stacksize | virtual machine stack |
-| | | space required |
-+-----------+-----------------+---------------------------+
-| | co_varnames | tuple of names of |
-| | | arguments and local |
-| | | variables |
-+-----------+-----------------+---------------------------+
-| generator | __name__ | name |
-+-----------+-----------------+---------------------------+
-| | __qualname__ | qualified name |
-+-----------+-----------------+---------------------------+
-| | gi_frame | frame |
-+-----------+-----------------+---------------------------+
-| | gi_running | is the generator running? |
-+-----------+-----------------+---------------------------+
-| | gi_code | code |
-+-----------+-----------------+---------------------------+
-| | gi_yieldfrom | object being iterated by |
-| | | ``yield from``, or |
-| | | ``None`` |
-+-----------+-----------------+---------------------------+
-| coroutine | __name__ | name |
-+-----------+-----------------+---------------------------+
-| | __qualname__ | qualified name |
-+-----------+-----------------+---------------------------+
-| | cr_await | object being awaited on, |
-| | | or ``None`` |
-+-----------+-----------------+---------------------------+
-| | cr_frame | frame |
-+-----------+-----------------+---------------------------+
-| | cr_running | is the coroutine running? |
-+-----------+-----------------+---------------------------+
-| | cr_code | code |
-+-----------+-----------------+---------------------------+
-| builtin | __doc__ | documentation string |
-+-----------+-----------------+---------------------------+
-| | __name__ | original name of this |
-| | | function or method |
-+-----------+-----------------+---------------------------+
-| | __qualname__ | qualified name |
-+-----------+-----------------+---------------------------+
-| | __self__ | instance to which a |
-| | | method is bound, or |
-| | | ``None`` |
-+-----------+-----------------+---------------------------+
++-----------+-------------------+---------------------------+
+| Type | Attribute | Description |
++===========+===================+===========================+
+| module | __doc__ | documentation string |
++-----------+-------------------+---------------------------+
+| | __file__ | filename (missing for |
+| | | built-in modules) |
++-----------+-------------------+---------------------------+
+| class | __doc__ | documentation string |
++-----------+-------------------+---------------------------+
+| | __name__ | name with which this |
+| | | class was defined |
++-----------+-------------------+---------------------------+
+| | __qualname__ | qualified name |
++-----------+-------------------+---------------------------+
+| | __module__ | name of module in which |
+| | | this class was defined |
++-----------+-------------------+---------------------------+
+| method | __doc__ | documentation string |
++-----------+-------------------+---------------------------+
+| | __name__ | name with which this |
+| | | method was defined |
++-----------+-------------------+---------------------------+
+| | __qualname__ | qualified name |
++-----------+-------------------+---------------------------+
+| | __func__ | function object |
+| | | containing implementation |
+| | | of method |
++-----------+-------------------+---------------------------+
+| | __self__ | instance to which this |
+| | | method is bound, or |
+| | | ``None`` |
++-----------+-------------------+---------------------------+
+| function | __doc__ | documentation string |
++-----------+-------------------+---------------------------+
+| | __name__ | name with which this |
+| | | function was defined |
++-----------+-------------------+---------------------------+
+| | __qualname__ | qualified name |
++-----------+-------------------+---------------------------+
+| | __code__ | code object containing |
+| | | compiled function |
+| | | :term:`bytecode` |
++-----------+-------------------+---------------------------+
+| | __defaults__ | tuple of any default |
+| | | values for positional or |
+| | | keyword parameters |
++-----------+-------------------+---------------------------+
+| | __kwdefaults__ | mapping of any default |
+| | | values for keyword-only |
+| | | parameters |
++-----------+-------------------+---------------------------+
+| | __globals__ | global namespace in which |
+| | | this function was defined |
++-----------+-------------------+---------------------------+
+| | __annotations__ | mapping of parameters |
+| | | names to annotations; |
+| | | ``"return"`` key is |
+| | | reserved for return |
+| | | annotations. |
++-----------+-------------------+---------------------------+
+| traceback | tb_frame | frame object at this |
+| | | level |
++-----------+-------------------+---------------------------+
+| | tb_lasti | index of last attempted |
+| | | instruction in bytecode |
++-----------+-------------------+---------------------------+
+| | tb_lineno | current line number in |
+| | | Python source code |
++-----------+-------------------+---------------------------+
+| | tb_next | next inner traceback |
+| | | object (called by this |
+| | | level) |
++-----------+-------------------+---------------------------+
+| frame | f_back | next outer frame object |
+| | | (this frame's caller) |
++-----------+-------------------+---------------------------+
+| | f_builtins | builtins namespace seen |
+| | | by this frame |
++-----------+-------------------+---------------------------+
+| | f_code | code object being |
+| | | executed in this frame |
++-----------+-------------------+---------------------------+
+| | f_globals | global namespace seen by |
+| | | this frame |
++-----------+-------------------+---------------------------+
+| | f_lasti | index of last attempted |
+| | | instruction in bytecode |
++-----------+-------------------+---------------------------+
+| | f_lineno | current line number in |
+| | | Python source code |
++-----------+-------------------+---------------------------+
+| | f_locals | local namespace seen by |
+| | | this frame |
++-----------+-------------------+---------------------------+
+| | f_restricted | 0 or 1 if frame is in |
+| | | restricted execution mode |
++-----------+-------------------+---------------------------+
+| | f_trace | tracing function for this |
+| | | frame, or ``None`` |
++-----------+-------------------+---------------------------+
+| code | co_argcount | number of arguments (not |
+| | | including keyword only |
+| | | arguments, \* or \*\* |
+| | | args) |
++-----------+-------------------+---------------------------+
+| | co_code | string of raw compiled |
+| | | bytecode |
++-----------+-------------------+---------------------------+
+| | co_cellvars | tuple of names of cell |
+| | | variables (referenced by |
+| | | containing scopes) |
++-----------+-------------------+---------------------------+
+| | co_consts | tuple of constants used |
+| | | in the bytecode |
++-----------+-------------------+---------------------------+
+| | co_filename | name of file in which |
+| | | this code object was |
+| | | created |
++-----------+-------------------+---------------------------+
+| | co_firstlineno | number of first line in |
+| | | Python source code |
++-----------+-------------------+---------------------------+
+| | co_flags | bitmap of ``CO_*`` flags, |
+| | | read more :ref:`here |
+| | | `|
++-----------+-------------------+---------------------------+
+| | co_lnotab | encoded mapping of line |
+| | | numbers to bytecode |
+| | | indices |
++-----------+-------------------+---------------------------+
+| | co_freevars | tuple of names of free |
+| | | variables (referenced via |
+| | | a function's closure) |
++-----------+-------------------+---------------------------+
+| | co_kwonlyargcount | number of keyword only |
+| | | arguments (not including |
+| | | \*\* arg) |
++-----------+-------------------+---------------------------+
+| | co_name | name with which this code |
+| | | object was defined |
++-----------+-------------------+---------------------------+
+| | co_names | tuple of names of local |
+| | | variables |
++-----------+-------------------+---------------------------+
+| | co_nlocals | number of local variables |
++-----------+-------------------+---------------------------+
+| | co_stacksize | virtual machine stack |
+| | | space required |
++-----------+-------------------+---------------------------+
+| | co_varnames | tuple of names of |
+| | | arguments and local |
+| | | variables |
++-----------+-------------------+---------------------------+
+| generator | __name__ | name |
++-----------+-------------------+---------------------------+
+| | __qualname__ | qualified name |
++-----------+-------------------+---------------------------+
+| | gi_frame | frame |
++-----------+-------------------+---------------------------+
+| | gi_running | is the generator running? |
++-----------+-------------------+---------------------------+
+| | gi_code | code |
++-----------+-------------------+---------------------------+
+| | gi_yieldfrom | object being iterated by |
+| | | ``yield from``, or |
+| | | ``None`` |
++-----------+-------------------+---------------------------+
+| coroutine | __name__ | name |
++-----------+-------------------+---------------------------+
+| | __qualname__ | qualified name |
++-----------+-------------------+---------------------------+
+| | cr_await | object being awaited on, |
+| | | or ``None`` |
++-----------+-------------------+---------------------------+
+| | cr_frame | frame |
++-----------+-------------------+---------------------------+
+| | cr_running | is the coroutine running? |
++-----------+-------------------+---------------------------+
+| | cr_code | code |
++-----------+-------------------+---------------------------+
+| builtin | __doc__ | documentation string |
++-----------+-------------------+---------------------------+
+| | __name__ | original name of this |
+| | | function or method |
++-----------+-------------------+---------------------------+
+| | __qualname__ | qualified name |
++-----------+-------------------+---------------------------+
+| | __self__ | instance to which a |
+| | | method is bound, or |
+| | | ``None`` |
++-----------+-------------------+---------------------------+
.. versionchanged:: 3.5
@@ -1268,6 +1281,10 @@ Code Objects Bit Flags
Python code objects have a ``co_flags`` attribute, which is a bitmap of
the following flags:
+.. data:: CO_OPTIMIZED
+
+ The code object is optimized, using fast locals.
+
.. data:: CO_NEWLOCALS
If set, a new dict will be created for the frame's ``f_locals`` when
@@ -1281,6 +1298,10 @@ the following flags:
The code object has a variable keyword parameter (``**kwargs``-like).
+.. data:: CO_NESTED
+
+ The flag is set when the code object is a nested function.
+
.. data:: CO_GENERATOR
The flag is set when the code object is a generator function, i.e.
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 4d56ef5d41..a2dcb888a0 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -253,18 +253,24 @@ def iscode(object):
"""Return true if the object is a code object.
Code objects provide these attributes:
- co_argcount number of arguments (not including * or ** args)
- co_code string of raw compiled bytecode
- co_consts tuple of constants used in the bytecode
- co_filename name of file in which this code object was created
- co_firstlineno number of first line in Python source code
- co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
- co_lnotab encoded mapping of line numbers to bytecode indices
- co_name name with which this code object was defined
- co_names tuple of names of local variables
- co_nlocals number of local variables
- co_stacksize virtual machine stack space required
- co_varnames tuple of names of arguments and local variables"""
+ co_argcount number of arguments (not including *, ** args
+ or keyword only arguments)
+ co_code string of raw compiled bytecode
+ co_cellvars tuple of names of cell variables
+ co_consts tuple of constants used in the bytecode
+ co_filename name of file in which this code object was created
+ co_firstlineno number of first line in Python source code
+ co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
+ | 16=nested | 32=generator | 64=nofree | 128=coroutine
+ | 256=iterable_coroutine | 512=async_generator
+ co_freevars tuple of names of free variables
+ co_kwonlyargcount number of keyword only arguments (not including ** arg)
+ co_lnotab encoded mapping of line numbers to bytecode indices
+ co_name name with which this code object was defined
+ co_names tuple of names of local variables
+ co_nlocals number of local variables
+ co_stacksize virtual machine stack space required
+ co_varnames tuple of names of arguments and local variables"""
return isinstance(object, types.CodeType)
def isbuiltin(object):
diff --git a/Misc/NEWS b/Misc/NEWS
index 83f9e7a685..dd1fa12d7c 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -86,6 +86,11 @@ Build
- bpo-29643: Fix ``--enable-optimization`` didn't work.
+Documentation
+-------------
+
+- bpo-26985: Add missing info of code object in inspect documentation.
+
What's New in Python 3.6.1?
===========================
--
GitLab
From bc9025012fc5ae007283e9ef345dba0ba08cf2b9 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Wed, 12 Apr 2017 20:45:54 -0700
Subject: [PATCH 0123/1433] [3.6] Remove superfluous comment in urllib.error.
(GH-1076) (GH-1101)
(cherry picked from commit 6fab78e9027f9ebd6414995580781b480433e595)
---
Lib/urllib/error.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/Lib/urllib/error.py b/Lib/urllib/error.py
index c5b675d161..851515bc30 100644
--- a/Lib/urllib/error.py
+++ b/Lib/urllib/error.py
@@ -16,10 +16,6 @@ import urllib.response
__all__ = ['URLError', 'HTTPError', 'ContentTooShortError']
-# do these error classes make sense?
-# make sure all of the OSError stuff is overridden. we just want to be
-# subtypes.
-
class URLError(OSError):
# URLError is a sub-type of OSError, but it doesn't share any of
# the implementation. need to override __init__ and __str__.
--
GitLab
From bd1173f202f5a3990063d980368e7ad1edc9b5b5 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Wed, 12 Apr 2017 20:52:39 -0700
Subject: [PATCH 0124/1433] [3.6] Clarify exception handler scope in contextlib
(GH-1103)
Moved explicit raise from inside try to try...else.
(cherry picked from commit 680e20beee8bbce9f857b8e7795009191f98b0ba)
---
Lib/contextlib.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Lib/contextlib.py b/Lib/contextlib.py
index 8421968525..e91cf460e5 100644
--- a/Lib/contextlib.py
+++ b/Lib/contextlib.py
@@ -98,7 +98,6 @@ class _GeneratorContextManager(ContextDecorator, AbstractContextManager):
value = type()
try:
self.gen.throw(type, value, traceback)
- raise RuntimeError("generator didn't stop after throw()")
except StopIteration as exc:
# Suppress StopIteration *unless* it's the same exception that
# was passed to throw(). This prevents a StopIteration
@@ -124,6 +123,8 @@ class _GeneratorContextManager(ContextDecorator, AbstractContextManager):
#
if sys.exc_info()[1] is not value:
raise
+ else:
+ raise RuntimeError("generator didn't stop after throw()")
def contextmanager(func):
--
GitLab
From 9b409ff41ceb2d7ea7e8d25a7bbf5eb7d46625f3 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 13 Apr 2017 02:50:21 -0700
Subject: [PATCH 0125/1433] [3.6] bpo-29692: contextlib.contextmanager may
incorrectly unchain RuntimeError (GH-949) (#1105)
contextlib._GeneratorContextManager.__exit__ includes a special case to deal with
PEP 479 RuntimeErrors created when `StopIteration` is thrown into the context
manager body.
Previously this check was too permissive, and undid one level of chaining on *all*
RuntimeError instances, not just those that wrapped a StopIteration instance.
(cherry picked from commit 00c75e9a45ff0366c185e9e8a2e23af5a35481b0)
---
Lib/contextlib.py | 12 ++++++------
Lib/test/test_contextlib.py | 23 +++++++++++++++++++++++
Misc/NEWS | 3 +++
3 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/Lib/contextlib.py b/Lib/contextlib.py
index e91cf460e5..5e47054954 100644
--- a/Lib/contextlib.py
+++ b/Lib/contextlib.py
@@ -88,7 +88,7 @@ class _GeneratorContextManager(ContextDecorator, AbstractContextManager):
try:
next(self.gen)
except StopIteration:
- return
+ return False
else:
raise RuntimeError("generator didn't stop")
else:
@@ -110,7 +110,7 @@ class _GeneratorContextManager(ContextDecorator, AbstractContextManager):
# Likewise, avoid suppressing if a StopIteration exception
# was passed to throw() and later wrapped into a RuntimeError
# (see PEP 479).
- if exc.__cause__ is value:
+ if type is StopIteration and exc.__cause__ is value:
return False
raise
except:
@@ -121,10 +121,10 @@ class _GeneratorContextManager(ContextDecorator, AbstractContextManager):
# fixes the impedance mismatch between the throw() protocol
# and the __exit__() protocol.
#
- if sys.exc_info()[1] is not value:
- raise
- else:
- raise RuntimeError("generator didn't stop after throw()")
+ if sys.exc_info()[1] is value:
+ return False
+ raise
+ raise RuntimeError("generator didn't stop after throw()")
def contextmanager(func):
diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py
index c04c804af5..b1a467d952 100644
--- a/Lib/test/test_contextlib.py
+++ b/Lib/test/test_contextlib.py
@@ -152,6 +152,29 @@ def woohoo():
else:
self.fail('StopIteration was suppressed')
+ def test_contextmanager_do_not_unchain_non_stopiteration_exceptions(self):
+ @contextmanager
+ def test_issue29692():
+ try:
+ yield
+ except Exception as exc:
+ raise RuntimeError('issue29692:Chained') from exc
+ try:
+ with test_issue29692():
+ raise ZeroDivisionError
+ except Exception as ex:
+ self.assertIs(type(ex), RuntimeError)
+ self.assertEqual(ex.args[0], 'issue29692:Chained')
+ self.assertIsInstance(ex.__cause__, ZeroDivisionError)
+
+ try:
+ with test_issue29692():
+ raise StopIteration('issue29692:Unchained')
+ except Exception as ex:
+ self.assertIs(type(ex), StopIteration)
+ self.assertEqual(ex.args[0], 'issue29692:Unchained')
+ self.assertIsNone(ex.__cause__)
+
def _create_contextmanager_attribs(self):
def attribs(**kw):
def decorate(func):
diff --git a/Misc/NEWS b/Misc/NEWS
index dd1fa12d7c..6e2db58a92 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -31,6 +31,9 @@ Core and Builtins
Library
-------
+- bpo-29692: Fixed arbitrary unchaining of RuntimeError exceptions in
+ contextlib.contextmanager.
+ Patch by Siddharth Velankar.
- bpo-29998: Pickling and copying ImportError now preserves name and path
attributes.
--
GitLab
From 97a40b7a5b2979fb17e1751c139fd4ba1ebd5276 Mon Sep 17 00:00:00 2001
From: Nevada Sanchez
Date: Thu, 13 Apr 2017 06:21:05 -0400
Subject: [PATCH 0126/1433] bpo-29869: Allow underscores in numeric literals in
lib2to3. (GH-752)
---
Lib/lib2to3/pgen2/tokenize.py | 16 ++++++++--------
Lib/lib2to3/tests/data/py3_test_grammar.py | 22 ++++++++++++++++++++++
2 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py
index d14db60f7d..fba0fa2c00 100644
--- a/Lib/lib2to3/pgen2/tokenize.py
+++ b/Lib/lib2to3/pgen2/tokenize.py
@@ -54,16 +54,16 @@ Comment = r'#[^\r\n]*'
Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
Name = r'[a-zA-Z_]\w*'
-Binnumber = r'0[bB][01]*'
-Hexnumber = r'0[xX][\da-fA-F]*[lL]?'
-Octnumber = r'0[oO]?[0-7]*[lL]?'
-Decnumber = r'[1-9]\d*[lL]?'
+Binnumber = r'0[bB]_?[01]+(?:_[01]+)*'
+Hexnumber = r'0[xX]_?[\da-fA-F]+(?:_[\da-fA-F]+)*[lL]?'
+Octnumber = r'0[oO]?_?[0-7]+(?:_[0-7]+)*[lL]?'
+Decnumber = group(r'[1-9]\d*(?:_\d+)*[lL]?', '0[lL]?')
Intnumber = group(Binnumber, Hexnumber, Octnumber, Decnumber)
-Exponent = r'[eE][-+]?\d+'
-Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent)
-Expfloat = r'\d+' + Exponent
+Exponent = r'[eE][-+]?\d+(?:_\d+)*'
+Pointfloat = group(r'\d+(?:_\d+)*\.(?:\d+(?:_\d+)*)?', r'\.\d+(?:_\d+)*') + maybe(Exponent)
+Expfloat = r'\d+(?:_\d+)*' + Exponent
Floatnumber = group(Pointfloat, Expfloat)
-Imagnumber = group(r'\d+[jJ]', Floatnumber + r'[jJ]')
+Imagnumber = group(r'\d+(?:_\d+)*[jJ]', Floatnumber + r'[jJ]')
Number = group(Imagnumber, Floatnumber, Intnumber)
# Tail end of ' string.
diff --git a/Lib/lib2to3/tests/data/py3_test_grammar.py b/Lib/lib2to3/tests/data/py3_test_grammar.py
index cf31a5411a..0b9bee0ab4 100644
--- a/Lib/lib2to3/tests/data/py3_test_grammar.py
+++ b/Lib/lib2to3/tests/data/py3_test_grammar.py
@@ -72,6 +72,28 @@ class TokenTests(unittest.TestCase):
x = 0b100000000000000000000000000000000000000000000000000000000000000000000
x = 0B111111111111111111111111111111111111111111111111111111111111111111111
+ def testUnderscoresInNumbers(self):
+ # Integers
+ x = 1_0
+ x = 123_456_7_89
+ x = 0xabc_123_4_5
+ x = 0X_abc_123
+ x = 0B11_01
+ x = 0b_11_01
+ x = 0o45_67
+ x = 0O_45_67
+
+ # Floats
+ x = 3_1.4
+ x = 03_1.4
+ x = 3_1.
+ x = .3_1
+ x = 3.1_4
+ x = 0_3.1_4
+ x = 3e1_4
+ x = 3_1e+4_1
+ x = 3_1E-4_1
+
def testFloats(self):
x = 3.14
x = 314.
--
GitLab
From 84c2d75489a84174d8993aea292828662e35a50f Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 13 Apr 2017 04:03:16 -0700
Subject: [PATCH 0127/1433] Revert "bpo-29869: Allow underscores in numeric
literals in lib2to3. (GH-752)" (GH-1109)
This reverts commit 97a40b7a5b2979fb17e1751c139fd4ba1ebd5276.
The commit is supposed to go to the master branch first.
---
Lib/lib2to3/pgen2/tokenize.py | 16 ++++++++--------
Lib/lib2to3/tests/data/py3_test_grammar.py | 22 ----------------------
2 files changed, 8 insertions(+), 30 deletions(-)
diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py
index fba0fa2c00..d14db60f7d 100644
--- a/Lib/lib2to3/pgen2/tokenize.py
+++ b/Lib/lib2to3/pgen2/tokenize.py
@@ -54,16 +54,16 @@ Comment = r'#[^\r\n]*'
Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
Name = r'[a-zA-Z_]\w*'
-Binnumber = r'0[bB]_?[01]+(?:_[01]+)*'
-Hexnumber = r'0[xX]_?[\da-fA-F]+(?:_[\da-fA-F]+)*[lL]?'
-Octnumber = r'0[oO]?_?[0-7]+(?:_[0-7]+)*[lL]?'
-Decnumber = group(r'[1-9]\d*(?:_\d+)*[lL]?', '0[lL]?')
+Binnumber = r'0[bB][01]*'
+Hexnumber = r'0[xX][\da-fA-F]*[lL]?'
+Octnumber = r'0[oO]?[0-7]*[lL]?'
+Decnumber = r'[1-9]\d*[lL]?'
Intnumber = group(Binnumber, Hexnumber, Octnumber, Decnumber)
-Exponent = r'[eE][-+]?\d+(?:_\d+)*'
-Pointfloat = group(r'\d+(?:_\d+)*\.(?:\d+(?:_\d+)*)?', r'\.\d+(?:_\d+)*') + maybe(Exponent)
-Expfloat = r'\d+(?:_\d+)*' + Exponent
+Exponent = r'[eE][-+]?\d+'
+Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent)
+Expfloat = r'\d+' + Exponent
Floatnumber = group(Pointfloat, Expfloat)
-Imagnumber = group(r'\d+(?:_\d+)*[jJ]', Floatnumber + r'[jJ]')
+Imagnumber = group(r'\d+[jJ]', Floatnumber + r'[jJ]')
Number = group(Imagnumber, Floatnumber, Intnumber)
# Tail end of ' string.
diff --git a/Lib/lib2to3/tests/data/py3_test_grammar.py b/Lib/lib2to3/tests/data/py3_test_grammar.py
index 0b9bee0ab4..cf31a5411a 100644
--- a/Lib/lib2to3/tests/data/py3_test_grammar.py
+++ b/Lib/lib2to3/tests/data/py3_test_grammar.py
@@ -72,28 +72,6 @@ class TokenTests(unittest.TestCase):
x = 0b100000000000000000000000000000000000000000000000000000000000000000000
x = 0B111111111111111111111111111111111111111111111111111111111111111111111
- def testUnderscoresInNumbers(self):
- # Integers
- x = 1_0
- x = 123_456_7_89
- x = 0xabc_123_4_5
- x = 0X_abc_123
- x = 0B11_01
- x = 0b_11_01
- x = 0o45_67
- x = 0O_45_67
-
- # Floats
- x = 3_1.4
- x = 03_1.4
- x = 3_1.
- x = .3_1
- x = 3.1_4
- x = 0_3.1_4
- x = 3e1_4
- x = 3_1e+4_1
- x = 3_1E-4_1
-
def testFloats(self):
x = 3.14
x = 314.
--
GitLab
From 119d94ad37a99ecb0b8329467d04cd9d909e310e Mon Sep 17 00:00:00 2001
From: Berker Peksag
Date: Thu, 13 Apr 2017 16:17:01 +0300
Subject: [PATCH 0128/1433] bpo-29791: Clarify that flush is keyword-only
argument (GH-1093)
Reported by Lucio Ricardo Montero Valenzuela.
(cherry picked from commit 61b9ac93712df8092a25223cd56fa6528359792b)
---
Doc/library/functions.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 90fb07af22..9126535eec 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -1125,7 +1125,7 @@ are always available. They are listed here in alphabetical order.
.. function:: print(*objects, sep=' ', end='\\n', file=sys.stdout, flush=False)
Print *objects* to the text stream *file*, separated by *sep* and followed
- by *end*. *sep*, *end* and *file*, if present, must be given as keyword
+ by *end*. *sep*, *end*, *file* and *flush*, if present, must be given as keyword
arguments.
All non-keyword arguments are converted to strings like :func:`str` does and
--
GitLab
From 936633282220768a6fec9bd6bb53ee9e3ec354df Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Thu, 13 Apr 2017 19:41:19 +0300
Subject: [PATCH 0129/1433] bpo-30021: Add examples for re.escape(). (#1048)
(#1115)
And fix the parameter name.
(cherry picked from commit 8fc7bc2b7631ee819ee614e47b6f44bacebe1574)
---
Doc/library/re.rst | 17 ++++++++++++++---
Doc/tools/susp-ignored.csv | 2 ++
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/Doc/library/re.rst b/Doc/library/re.rst
index 9cced51270..944c6fb10d 100644
--- a/Doc/library/re.rst
+++ b/Doc/library/re.rst
@@ -784,11 +784,22 @@ form.
Unmatched groups are replaced with an empty string.
-.. function:: escape(string)
+.. function:: escape(pattern)
- Escape all the characters in pattern except ASCII letters, numbers and ``'_'``.
+ Escape all the characters in *pattern* except ASCII letters, numbers and ``'_'``.
This is useful if you want to match an arbitrary literal string that may
- have regular expression metacharacters in it.
+ have regular expression metacharacters in it. For example::
+
+ >>> print(re.escape('python.exe'))
+ python\.exe
+
+ >>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:"
+ >>> print('[%s]+' % re.escape(legal_chars))
+ [abcdefghijklmnopqrstuvwxyz0123456789\!\#\$\%\&\'\*\+\-\.\^_\`\|\~\:]+
+
+ >>> operators = ['+', '-', '*', '/', '**']
+ >>> print('|'.join(map(re.escape, sorted(operators, reverse=True))))
+ \/|\-|\+|\*\*|\*
.. versionchanged:: 3.3
The ``'_'`` character is no longer escaped.
diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv
index 166374cb90..57b0cf12f5 100644
--- a/Doc/tools/susp-ignored.csv
+++ b/Doc/tools/susp-ignored.csv
@@ -302,6 +302,8 @@ whatsnew/3.2,,:feed,>>> urllib.parse.urlparse('http://[dead:beef:cafe:5417:affe:
whatsnew/3.2,,:gz,">>> with tarfile.open(name='myarchive.tar.gz', mode='w:gz') as tf:"
whatsnew/3.2,,:location,zope9-location = ${zope9:location}
whatsnew/3.2,,:prefix,zope-conf = ${custom:prefix}/etc/zope.conf
+library/re,,`,!#$%&'*+-.^_`|~:
+library/re,,`,\!\#\$\%\&\'\*\+\-\.\^_\`\|\~\:
library/tarfile,,:xz,'x:xz'
library/xml.etree.elementtree,,:sometag,prefix:sometag
library/xml.etree.elementtree,,:fictional,"
Date: Thu, 13 Apr 2017 14:11:48 -0700
Subject: [PATCH 0130/1433] convert from long long to PyLong loselessly (#1106)
(#1121)
---
Modules/_testcapimodule.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index f09205f63c..b25f4434ff 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3812,7 +3812,7 @@ test_PyTime_AsTimeval(PyObject *self, PyObject *args)
if (_PyTime_AsTimeval(t, &tv, round) < 0)
return NULL;
- seconds = PyLong_FromLong((long long)tv.tv_sec);
+ seconds = PyLong_FromLongLong(tv.tv_sec);
if (seconds == NULL)
return NULL;
return Py_BuildValue("Nl", seconds, tv.tv_usec);
--
GitLab
From c5c24cfaf9fe9a38f0901756cd797bd12524a8b7 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 13 Apr 2017 16:37:51 -0700
Subject: [PATCH 0131/1433] [3.6] Fix a typo in Doc/library/functions.rst
(GH-1117) (GH-1123)
Replace `For object's ... ` with `For objects ...`
(cherry picked from commit 873ef20d0007b4b120933473e6252d2309a70102)
---
Doc/library/functions.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 9126535eec..138f7d027c 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -610,7 +610,7 @@ are always available. They are listed here in alphabetical order.
.. note::
- For object's with custom :meth:`__hash__` methods, note that :func:`hash`
+ For objects with custom :meth:`__hash__` methods, note that :func:`hash`
truncates the return value based on the bit width of the host machine.
See :meth:`__hash__` for details.
--
GitLab
From 2cdf087d1fd48f7d0f95b5a0b31b9a624fa84751 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 13 Apr 2017 16:54:49 -0700
Subject: [PATCH 0132/1433] [3.6] bpo-29869: Allow underscores in numeric
literals in lib2to3. (GH-1119) (GH-1122)
* Allow underscores in numeric literals in lib2to3.
* Stricter literal parsing for Python 3.6 in lib2to3.pgen2.tokenize.
* Add test case for underscores in literals in Python 3.
(cherry picked from commit a6e395dffadf8c5124903c01ad69fefa36b1a935)
---
Lib/lib2to3/pgen2/tokenize.py | 16 ++++++++--------
Lib/lib2to3/tests/data/py3_test_grammar.py | 22 ++++++++++++++++++++++
2 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py
index d14db60f7d..fba0fa2c00 100644
--- a/Lib/lib2to3/pgen2/tokenize.py
+++ b/Lib/lib2to3/pgen2/tokenize.py
@@ -54,16 +54,16 @@ Comment = r'#[^\r\n]*'
Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
Name = r'[a-zA-Z_]\w*'
-Binnumber = r'0[bB][01]*'
-Hexnumber = r'0[xX][\da-fA-F]*[lL]?'
-Octnumber = r'0[oO]?[0-7]*[lL]?'
-Decnumber = r'[1-9]\d*[lL]?'
+Binnumber = r'0[bB]_?[01]+(?:_[01]+)*'
+Hexnumber = r'0[xX]_?[\da-fA-F]+(?:_[\da-fA-F]+)*[lL]?'
+Octnumber = r'0[oO]?_?[0-7]+(?:_[0-7]+)*[lL]?'
+Decnumber = group(r'[1-9]\d*(?:_\d+)*[lL]?', '0[lL]?')
Intnumber = group(Binnumber, Hexnumber, Octnumber, Decnumber)
-Exponent = r'[eE][-+]?\d+'
-Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent)
-Expfloat = r'\d+' + Exponent
+Exponent = r'[eE][-+]?\d+(?:_\d+)*'
+Pointfloat = group(r'\d+(?:_\d+)*\.(?:\d+(?:_\d+)*)?', r'\.\d+(?:_\d+)*') + maybe(Exponent)
+Expfloat = r'\d+(?:_\d+)*' + Exponent
Floatnumber = group(Pointfloat, Expfloat)
-Imagnumber = group(r'\d+[jJ]', Floatnumber + r'[jJ]')
+Imagnumber = group(r'\d+(?:_\d+)*[jJ]', Floatnumber + r'[jJ]')
Number = group(Imagnumber, Floatnumber, Intnumber)
# Tail end of ' string.
diff --git a/Lib/lib2to3/tests/data/py3_test_grammar.py b/Lib/lib2to3/tests/data/py3_test_grammar.py
index cf31a5411a..0b9bee0ab4 100644
--- a/Lib/lib2to3/tests/data/py3_test_grammar.py
+++ b/Lib/lib2to3/tests/data/py3_test_grammar.py
@@ -72,6 +72,28 @@ class TokenTests(unittest.TestCase):
x = 0b100000000000000000000000000000000000000000000000000000000000000000000
x = 0B111111111111111111111111111111111111111111111111111111111111111111111
+ def testUnderscoresInNumbers(self):
+ # Integers
+ x = 1_0
+ x = 123_456_7_89
+ x = 0xabc_123_4_5
+ x = 0X_abc_123
+ x = 0B11_01
+ x = 0b_11_01
+ x = 0o45_67
+ x = 0O_45_67
+
+ # Floats
+ x = 3_1.4
+ x = 03_1.4
+ x = 3_1.
+ x = .3_1
+ x = 3.1_4
+ x = 0_3.1_4
+ x = 3e1_4
+ x = 3_1e+4_1
+ x = 3_1E-4_1
+
def testFloats(self):
x = 3.14
x = 314.
--
GitLab
From cbc46afa59dcc43c2c8c90ae7a0a0dc404325a89 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 13 Apr 2017 19:26:16 -0700
Subject: [PATCH 0133/1433] [3.6] bpo-29694: race condition in pathlib mkdir
with flags parents=True (GH-1089). (GH-1126)
(cherry picked from commit 22a594a0047d7706537ff2ac676cdc0f1dcb329c)
---
Lib/pathlib.py | 4 ++--
Lib/test/test_pathlib.py | 30 ++++++++++++++++++++++++++++++
Misc/NEWS | 4 ++++
3 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/Lib/pathlib.py b/Lib/pathlib.py
index 8c1cb96bad..70f5cba76f 100644
--- a/Lib/pathlib.py
+++ b/Lib/pathlib.py
@@ -1230,8 +1230,8 @@ class Path(PurePath):
except FileNotFoundError:
if not parents or self.parent == self:
raise
- self.parent.mkdir(parents=True)
- self._accessor.mkdir(self, mode)
+ self.parent.mkdir(parents=True, exist_ok=True)
+ self.mkdir(mode, parents=False, exist_ok=exist_ok)
except OSError:
# Cannot rely on checking for EEXIST, since the operating system
# could give priority to other errors like EACCES or EROFS
diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py
index 3ff9726d43..846f721e8d 100644
--- a/Lib/test/test_pathlib.py
+++ b/Lib/test/test_pathlib.py
@@ -8,6 +8,7 @@ import socket
import stat
import tempfile
import unittest
+from unittest import mock
from test import support
android_not_root = support.android_not_root
@@ -1816,6 +1817,35 @@ class _BasePathTest(object):
p.mkdir(exist_ok=True)
self.assertEqual(cm.exception.errno, errno.EEXIST)
+ def test_mkdir_concurrent_parent_creation(self):
+ for pattern_num in range(32):
+ p = self.cls(BASE, 'dirCPC%d' % pattern_num)
+ self.assertFalse(p.exists())
+
+ def my_mkdir(path, mode=0o777):
+ path = str(path)
+ # Emulate another process that would create the directory
+ # just before we try to create it ourselves. We do it
+ # in all possible pattern combinations, assuming that this
+ # function is called at most 5 times (dirCPC/dir1/dir2,
+ # dirCPC/dir1, dirCPC, dirCPC/dir1, dirCPC/dir1/dir2).
+ if pattern.pop():
+ os.mkdir(path, mode) # from another process
+ concurrently_created.add(path)
+ os.mkdir(path, mode) # our real call
+
+ pattern = [bool(pattern_num & (1 << n)) for n in range(5)]
+ concurrently_created = set()
+ p12 = p / 'dir1' / 'dir2'
+ try:
+ with mock.patch("pathlib._normal_accessor.mkdir", my_mkdir):
+ p12.mkdir(parents=True, exist_ok=False)
+ except FileExistsError:
+ self.assertIn(str(p12), concurrently_created)
+ else:
+ self.assertNotIn(str(p12), concurrently_created)
+ self.assertTrue(p.exists())
+
@with_symlinks
def test_symlink_to(self):
P = self.cls(BASE)
diff --git a/Misc/NEWS b/Misc/NEWS
index 6e2db58a92..e623457cdd 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -31,6 +31,10 @@ Core and Builtins
Library
-------
+
+- bpo-29694: Fixed race condition in pathlib mkdir with flags
+ parents=True. Patch by Armin Rigo.
+
- bpo-29692: Fixed arbitrary unchaining of RuntimeError exceptions in
contextlib.contextmanager.
Patch by Siddharth Velankar.
--
GitLab
From 413a8913aee255d0635e4ddbb9c343d9e5e76fea Mon Sep 17 00:00:00 2001
From: Antoine Pitrou
Date: Fri, 14 Apr 2017 13:37:46 +0200
Subject: [PATCH 0134/1433] Relax test timing (bpo-29861) to avoid sporadic
failures (#1120) (#1132)
(cherry picked from commit 685cdb9acc3fca04a9897d88b89771ddfd50e772)
---
Lib/test/_test_multiprocessing.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index 771bbf2426..57ada12746 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -2080,6 +2080,7 @@ class _TestPool(BaseTestCase):
self.pool.map(identity, objs)
del objs
+ time.sleep(DELTA) # let threaded cleanup code run
self.assertEqual(set(wr() for wr in refs), {None})
# With a process pool, copies of the objects are returned, check
# they were released too.
--
GitLab
From 7ac96ec60e944bbfa290c869225dc48b542b6884 Mon Sep 17 00:00:00 2001
From: Jack McCracken
Date: Fri, 14 Apr 2017 10:44:34 -0400
Subject: [PATCH 0135/1433] Fix misplaced positional argument in OS X support
library (#1137)
---
Lib/_osx_support.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Lib/_osx_support.py b/Lib/_osx_support.py
index eadf06f20e..e37852e253 100644
--- a/Lib/_osx_support.py
+++ b/Lib/_osx_support.py
@@ -210,7 +210,7 @@ def _remove_universal_flags(_config_vars):
# Do not alter a config var explicitly overridden by env var
if cv in _config_vars and cv not in os.environ:
flags = _config_vars[cv]
- flags = re.sub(r'-arch\s+\w+\s', ' ', flags, re.ASCII)
+ flags = re.sub(r'-arch\s+\w+\s', ' ', flags, flags=re.ASCII)
flags = re.sub('-isysroot [^ \t]*', ' ', flags)
_save_modified_value(_config_vars, cv, flags)
--
GitLab
From 2e30eb6a98fb9b47e840528b41f1fc4446c69f36 Mon Sep 17 00:00:00 2001
From: Benjamin Peterson
Date: Fri, 14 Apr 2017 09:59:34 -0700
Subject: [PATCH 0136/1433] improve alignment autoconf test (#1129) (#1139)
Replace the deprecated AC_TRY_RUN with AC_RUN_IFELSE. Also, standardize the
variable name and allow for caching of the result.
---
aclocal.m4 | 4 ++--
configure | 35 +++++++++++++++++++++++++----------
configure.ac | 19 +++++++++----------
3 files changed, 36 insertions(+), 22 deletions(-)
diff --git a/aclocal.m4 b/aclocal.m4
index 9a9cc55728..2a745e5746 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -13,7 +13,7 @@
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
-dnl serial 11 (pkg-config-0.29)
+dnl serial 11 (pkg-config-0.29.1)
dnl
dnl Copyright © 2004 Scott James Remnant .
dnl Copyright © 2012-2015 Dan Nicholson
@@ -55,7 +55,7 @@ dnl
dnl See the "Since" comment for each macro you use to see what version
dnl of the macros you require.
m4_defun([PKG_PREREQ],
-[m4_define([PKG_MACROS_VERSION], [0.29])
+[m4_define([PKG_MACROS_VERSION], [0.29.1])
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ
diff --git a/configure b/configure
index 8bdb82ba4a..6a1b9e4edc 100755
--- a/configure
+++ b/configure
@@ -784,6 +784,7 @@ infodir
docdir
oldincludedir
includedir
+runstatedir
localstatedir
sharedstatedir
sysconfdir
@@ -894,6 +895,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1146,6 +1148,15 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1283,7 +1294,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir
+ libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@@ -1436,6 +1447,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -9697,8 +9709,11 @@ esac
# check for systems that require aligned memory access
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking aligned memory access is required" >&5
$as_echo_n "checking aligned memory access is required... " >&6; }
-if test "$cross_compiling" = yes; then :
- aligned_required=yes
+if ${ac_cv_aligned_required+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_aligned_required=yes
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -9715,26 +9730,26 @@ int main()
return 1;
return 0;
}
-
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
- aligned_required=no
+ ac_cv_aligned_required=no
else
- aligned_required=yes
+ ac_cv_aligned_required=yes
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-if test "$aligned_required" = yes ; then
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_aligned_required" >&5
+$as_echo "$ac_cv_aligned_required" >&6; }
+if test "$ac_cv_aligned_required" = yes ; then
$as_echo "#define HAVE_ALIGNED_REQUIRED 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $aligned_required" >&5
-$as_echo "$aligned_required" >&6; }
-
# str, bytes and memoryview hash algorithm
diff --git a/configure.ac b/configure.ac
index 6b331d5742..2c8e246f22 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2696,7 +2696,8 @@ esac
# check for systems that require aligned memory access
AC_MSG_CHECKING(aligned memory access is required)
-AC_TRY_RUN([
+AC_CACHE_VAL(ac_cv_aligned_required,
+[AC_RUN_IFELSE([AC_LANG_SOURCE([[
int main()
{
char s[16];
@@ -2708,18 +2709,16 @@ int main()
if (*p1 == *p2)
return 1;
return 0;
-}
- ],
- [aligned_required=no],
- [aligned_required=yes],
- [aligned_required=yes])
-
-if test "$aligned_required" = yes ; then
+}]])],
+[ac_cv_aligned_required=no],
+[ac_cv_aligned_required=yes],
+[ac_cv_aligned_required=yes])
+])
+AC_MSG_RESULT($ac_cv_aligned_required)
+if test "$ac_cv_aligned_required" = yes ; then
AC_DEFINE([HAVE_ALIGNED_REQUIRED], [1],
[Define if aligned memory access is required])
fi
-AC_MSG_RESULT($aligned_required)
-
# str, bytes and memoryview hash algorithm
AH_TEMPLATE(Py_HASH_ALGORITHM,
--
GitLab
From 8e7201342dc6eef201bfa4f533ad89a8144fd693 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Fri, 14 Apr 2017 18:34:11 -0700
Subject: [PATCH 0137/1433] [3.6] bpo-29738: Fix memory leak in _get_crl_dp
(GH-526) (GH-1142)
* Remove conditional on free of `dps`, since `dps` is now allocated for
all versions of OpenSSL
* Remove call to `x509_check_ca` since it was only used to cache
the `crldp` field of the certificate
CRL_DIST_POINTS_free is available in all supported versions of OpenSSL
(recent 0.9.8+) and LibreSSL.
(cherry picked from commit 2849cc34a8db93d448a62d69c462402347b50dcb)
---
Modules/_ssl.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index c0a7b8e105..2a2c18fe2f 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -1210,10 +1210,6 @@ _get_crl_dp(X509 *certificate) {
int i, j;
PyObject *lst, *res = NULL;
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- /* Calls x509v3_cache_extensions and sets up crldp */
- X509_check_ca(certificate);
-#endif
dps = X509_get_ext_d2i(certificate, NID_crl_distribution_points, NULL, NULL);
if (dps == NULL)
@@ -1258,9 +1254,7 @@ _get_crl_dp(X509 *certificate) {
done:
Py_XDECREF(lst);
-#if OPENSSL_VERSION_NUMBER < 0x10001000L
- sk_DIST_POINT_free(dps);
-#endif
+ CRL_DIST_POINTS_free(dps);
return res;
}
--
GitLab
From 05bfbcd233b2f5ba0d0634a380092d6ead6b35e1 Mon Sep 17 00:00:00 2001
From: Michael Seifert
Date: Sat, 15 Apr 2017 04:03:41 +0200
Subject: [PATCH 0138/1433] [3.6] bpo-30059: Include Py_Ellipsis in C API
documentation (GH-1018) (GH-1149)
---
Doc/c-api/slice.rst | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/Doc/c-api/slice.rst b/Doc/c-api/slice.rst
index a825164918..8b695e065a 100644
--- a/Doc/c-api/slice.rst
+++ b/Doc/c-api/slice.rst
@@ -56,3 +56,14 @@ Slice Objects
.. versionchanged:: 3.2
The parameter type for the *slice* parameter was ``PySliceObject*``
before.
+
+
+Ellipsis Object
+---------------
+
+
+.. c:var:: PyObject *Py_Ellipsis
+
+ The Python ``Ellipsis`` object. This object has no methods. It needs to be
+ treated just like any other object with respect to reference counts. Like
+ :c:data:`Py_None` it is a singleton object.
--
GitLab
From d5fa5f3ce7d9003bbd3975d1bf634043305ae18f Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Sat, 15 Apr 2017 13:25:15 +0800
Subject: [PATCH 0139/1433] bpo-30068: add missing iter(self) in
_io._IOBase.readlines when hint is present (#1130) (#1150)
---
Lib/test/test_io.py | 1 +
Misc/NEWS | 8 +++++---
Modules/_io/iobase.c | 25 +++++++++++++++++--------
3 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index 8f895fe0bf..e04baefef0 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -3498,6 +3498,7 @@ class MiscIOTest(unittest.TestCase):
self.assertRaises(ValueError, f.readinto1, bytearray(1024))
self.assertRaises(ValueError, f.readline)
self.assertRaises(ValueError, f.readlines)
+ self.assertRaises(ValueError, f.readlines, 1)
self.assertRaises(ValueError, f.seek, 0)
self.assertRaises(ValueError, f.tell)
self.assertRaises(ValueError, f.truncate)
diff --git a/Misc/NEWS b/Misc/NEWS
index e623457cdd..7628ed5cab 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -32,12 +32,14 @@ Core and Builtins
Library
-------
+- bpo-30068: _io._IOBase.readlines will check if it's closed first when
+ hint is present.
+
- bpo-29694: Fixed race condition in pathlib mkdir with flags
parents=True. Patch by Armin Rigo.
-- bpo-29692: Fixed arbitrary unchaining of RuntimeError exceptions in
- contextlib.contextmanager.
- Patch by Siddharth Velankar.
+- bpo-29692: Fixed arbitrary unchaining of RuntimeError exceptions in
+ contextlib.contextmanager. Patch by Siddharth Velankar.
- bpo-29998: Pickling and copying ImportError now preserves name and path
attributes.
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index 472ef3b97c..f7986d7e52 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -650,7 +650,7 @@ _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint)
/*[clinic end generated code: output=2f50421677fa3dea input=1961c4a95e96e661]*/
{
Py_ssize_t length = 0;
- PyObject *result;
+ PyObject *result, *it = NULL;
result = PyList_New(0);
if (result == NULL)
@@ -664,19 +664,22 @@ _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint)
PyObject *ret = _PyObject_CallMethodId(result, &PyId_extend, "O", self);
if (ret == NULL) {
- Py_DECREF(result);
- return NULL;
+ goto error;
}
Py_DECREF(ret);
return result;
}
+ it = PyObject_GetIter(self);
+ if (it == NULL) {
+ goto error;
+ }
+
while (1) {
- PyObject *line = PyIter_Next(self);
+ PyObject *line = PyIter_Next(it);
if (line == NULL) {
if (PyErr_Occurred()) {
- Py_DECREF(result);
- return NULL;
+ goto error;
}
else
break; /* StopIteration raised */
@@ -684,8 +687,7 @@ _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint)
if (PyList_Append(result, line) < 0) {
Py_DECREF(line);
- Py_DECREF(result);
- return NULL;
+ goto error;
}
length += PyObject_Size(line);
Py_DECREF(line);
@@ -693,7 +695,14 @@ _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint)
if (length > hint)
break;
}
+
+ Py_DECREF(it);
return result;
+
+ error:
+ Py_XDECREF(it);
+ Py_DECREF(result);
+ return NULL;
}
/*[clinic input]
--
GitLab
From 8e5b52a8da07e781bda50ba0a7065b1058495a37 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sun, 16 Apr 2017 12:04:45 +0300
Subject: [PATCH 0140/1433] bpo-30017: Allowed calling the close() method of
the zip entry writer object (#1041) (#1092)
multiple times. Writing to closed zip entry writer object now always produce
a ValueError.
(cherry picked from commit 4c0d9ea995da595e90e08813b89510de59907802)
---
Lib/test/test_zipfile.py | 42 ++++++++++++++++++++++++++++++++++++++++
Lib/zipfile.py | 4 ++++
Misc/NEWS | 3 +++
3 files changed, 49 insertions(+)
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index d39f05fdb7..d09ad96fc8 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -734,6 +734,48 @@ class LzmaTestZip64InSmallFiles(AbstractTestZip64InSmallFiles,
compression = zipfile.ZIP_LZMA
+class AbstractWriterTests:
+
+ def tearDown(self):
+ unlink(TESTFN2)
+
+ def test_close_after_close(self):
+ data = b'content'
+ with zipfile.ZipFile(TESTFN2, "w", self.compression) as zipf:
+ w = zipf.open('test', 'w')
+ w.write(data)
+ w.close()
+ self.assertTrue(w.closed)
+ w.close()
+ self.assertTrue(w.closed)
+ self.assertEqual(zipf.read('test'), data)
+
+ def test_write_after_close(self):
+ data = b'content'
+ with zipfile.ZipFile(TESTFN2, "w", self.compression) as zipf:
+ w = zipf.open('test', 'w')
+ w.write(data)
+ w.close()
+ self.assertTrue(w.closed)
+ self.assertRaises(ValueError, w.write, b'')
+ self.assertEqual(zipf.read('test'), data)
+
+class StoredWriterTests(AbstractWriterTests, unittest.TestCase):
+ compression = zipfile.ZIP_STORED
+
+@requires_zlib
+class DeflateWriterTests(AbstractWriterTests, unittest.TestCase):
+ compression = zipfile.ZIP_DEFLATED
+
+@requires_bz2
+class Bzip2WriterTests(AbstractWriterTests, unittest.TestCase):
+ compression = zipfile.ZIP_BZIP2
+
+@requires_lzma
+class LzmaWriterTests(AbstractWriterTests, unittest.TestCase):
+ compression = zipfile.ZIP_LZMA
+
+
class PyZipFileTests(unittest.TestCase):
def assertCompiledIn(self, name, namelist):
if name + 'o' not in namelist:
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index d7f5beba99..06eedec340 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -981,6 +981,8 @@ class _ZipWriteFile(io.BufferedIOBase):
return True
def write(self, data):
+ if self.closed:
+ raise ValueError('I/O operation on closed file.')
nbytes = len(data)
self._file_size += nbytes
self._crc = crc32(data, self._crc)
@@ -991,6 +993,8 @@ class _ZipWriteFile(io.BufferedIOBase):
return nbytes
def close(self):
+ if self.closed:
+ return
super().close()
# Flush any data from the compressor, and update header info
if self._compressor:
diff --git a/Misc/NEWS b/Misc/NEWS
index 7628ed5cab..673211d72d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -32,6 +32,9 @@ Core and Builtins
Library
-------
+- bpo-30017: Allowed calling the close() method of the zip entry writer object
+ multiple times. Writing to a closed writer now always produces a ValueError.
+
- bpo-30068: _io._IOBase.readlines will check if it's closed first when
hint is present.
--
GitLab
From 680fea4067537a9b9c79aadd44a3a19e83cd2dbf Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Wed, 19 Apr 2017 21:22:49 +0300
Subject: [PATCH 0141/1433] bpo-30061: Check if
PyObject_Size()/PySequence_Size()/PyMapping_Size() (#1096) (#1180)
raised an error.
(cherry picked from commit bf623ae8843dc30b28c574bec8d29fc14be59d86)
---
Lib/test/test_io.py | 16 ++++++++
Misc/NEWS | 5 +++
Modules/_io/iobase.c | 13 +++++--
Modules/_winapi.c | 17 ++++++---
Modules/cjkcodecs/multibytecodec.c | 3 ++
Modules/posixmodule.c | 60 +++++++++++++++++++++---------
Objects/setobject.c | 12 ++++--
7 files changed, 95 insertions(+), 31 deletions(-)
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index e04baefef0..5a7617cd9f 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -543,6 +543,22 @@ class IOTest(unittest.TestCase):
with self.open(support.TESTFN, "r") as f:
self.assertRaises(TypeError, f.readline, 5.3)
+ def test_readline_nonsizeable(self):
+ # Issue #30061
+ # Crash when readline() returns an object without __len__
+ class R(self.IOBase):
+ def readline(self):
+ return None
+ self.assertRaises((TypeError, StopIteration), next, R())
+
+ def test_next_nonsizeable(self):
+ # Issue #30061
+ # Crash when __next__() returns an object without __len__
+ class R(self.IOBase):
+ def __next__(self):
+ return None
+ self.assertRaises(TypeError, R().readlines, 1)
+
def test_raw_bytes_io(self):
f = self.BytesIO()
self.write_ops(f)
diff --git a/Misc/NEWS b/Misc/NEWS
index 673211d72d..44a4b873b1 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -32,6 +32,11 @@ Core and Builtins
Library
-------
+- bpo-30061: Fixed crashes in IOBase methods __next__() and readlines() when
+ readline() or __next__() respectively return non-sizeable object.
+ Fixed possible other errors caused by not checking results of PyObject_Size(),
+ PySequence_Size(), or PyMapping_Size().
+
- bpo-30017: Allowed calling the close() method of the zip entry writer object
multiple times. Writing to a closed writer now always produces a ValueError.
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index f7986d7e52..c8642040ae 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -625,7 +625,8 @@ iobase_iternext(PyObject *self)
if (line == NULL)
return NULL;
- if (PyObject_Size(line) == 0) {
+ if (PyObject_Size(line) <= 0) {
+ /* Error or empty */
Py_DECREF(line);
return NULL;
}
@@ -676,6 +677,7 @@ _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint)
}
while (1) {
+ Py_ssize_t line_length;
PyObject *line = PyIter_Next(it);
if (line == NULL) {
if (PyErr_Occurred()) {
@@ -689,11 +691,14 @@ _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint)
Py_DECREF(line);
goto error;
}
- length += PyObject_Size(line);
+ line_length = PyObject_Size(line);
Py_DECREF(line);
-
- if (length > hint)
+ if (line_length < 0) {
+ goto error;
+ }
+ if (line_length > hint - length)
break;
+ length += line_length;
}
Py_DECREF(it);
diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index 91d4f0172c..248f4582c6 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -722,17 +722,22 @@ getenvironment(PyObject* environment)
return NULL;
}
- envsize = PyMapping_Length(environment);
-
keys = PyMapping_Keys(environment);
values = PyMapping_Values(environment);
if (!keys || !values)
goto error;
+ envsize = PySequence_Fast_GET_SIZE(keys);
+ if (PySequence_Fast_GET_SIZE(values) != envsize) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "environment changed size during iteration");
+ goto error;
+ }
+
totalsize = 1; /* trailing null character */
for (i = 0; i < envsize; i++) {
- PyObject* key = PyList_GET_ITEM(keys, i);
- PyObject* value = PyList_GET_ITEM(values, i);
+ PyObject* key = PySequence_Fast_GET_ITEM(keys, i);
+ PyObject* value = PySequence_Fast_GET_ITEM(values, i);
if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError,
@@ -760,8 +765,8 @@ getenvironment(PyObject* environment)
end = buffer + totalsize;
for (i = 0; i < envsize; i++) {
- PyObject* key = PyList_GET_ITEM(keys, i);
- PyObject* value = PyList_GET_ITEM(values, i);
+ PyObject* key = PySequence_Fast_GET_ITEM(keys, i);
+ PyObject* value = PySequence_Fast_GET_ITEM(values, i);
if (!PyUnicode_AsUCS4(key, p, end - p, 0))
goto error;
p += PyUnicode_GET_LENGTH(key);
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index d1da189ddd..d6efc77d20 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -1670,6 +1670,9 @@ _multibytecodec_MultibyteStreamWriter_writelines(MultibyteStreamWriterObject *se
if (r == -1)
return NULL;
}
+ /* PySequence_Length() can fail */
+ if (PyErr_Occurred())
+ return NULL;
Py_RETURN_NONE;
}
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 2ea5e2def9..f4bbc8931b 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -6650,7 +6650,7 @@ static PyObject *
os_setgroups(PyObject *module, PyObject *groups)
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
{
- int i, len;
+ Py_ssize_t i, len;
gid_t grouplist[MAX_GROUPS];
if (!PySequence_Check(groups)) {
@@ -6658,6 +6658,9 @@ os_setgroups(PyObject *module, PyObject *groups)
return NULL;
}
len = PySequence_Size(groups);
+ if (len < 0) {
+ return NULL;
+ }
if (len > MAX_GROUPS) {
PyErr_SetString(PyExc_ValueError, "too many groups");
return NULL;
@@ -7886,9 +7889,9 @@ os_read_impl(PyObject *module, int fd, Py_ssize_t length)
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
|| defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV)
static Py_ssize_t
-iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
+iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
{
- int i, j;
+ Py_ssize_t i, j;
Py_ssize_t blen, total = 0;
*iov = PyMem_New(struct iovec, cnt);
@@ -7965,8 +7968,7 @@ static Py_ssize_t
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
{
- int cnt;
- Py_ssize_t n;
+ Py_ssize_t cnt, n;
int async_err = 0;
struct iovec *iov;
Py_buffer *buf;
@@ -7978,6 +7980,8 @@ os_readv_impl(PyObject *module, int fd, PyObject *buffers)
}
cnt = PySequence_Size(buffers);
+ if (cnt < 0)
+ return -1;
if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
return -1;
@@ -8116,15 +8120,24 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
"sendfile() headers must be a sequence");
return NULL;
} else {
- Py_ssize_t i = 0; /* Avoid uninitialized warning */
- sf.hdr_cnt = PySequence_Size(headers);
- if (sf.hdr_cnt > 0 &&
- (i = iov_setup(&(sf.headers), &hbuf,
- headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0)
+ Py_ssize_t i = PySequence_Size(headers);
+ if (i < 0)
+ return NULL;
+ if (i > INT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "sendfile() header is too large");
return NULL;
+ }
+ if (i > 0) {
+ sf.hdr_cnt = (int)i;
+ i = iov_setup(&(sf.headers), &hbuf,
+ headers, sf.hdr_cnt, PyBUF_SIMPLE);
+ if (i < 0)
+ return NULL;
#ifdef __APPLE__
- sbytes += i;
+ sbytes += i;
#endif
+ }
}
}
if (trailers != NULL) {
@@ -8133,15 +8146,24 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
"sendfile() trailers must be a sequence");
return NULL;
} else {
- Py_ssize_t i = 0; /* Avoid uninitialized warning */
- sf.trl_cnt = PySequence_Size(trailers);
- if (sf.trl_cnt > 0 &&
- (i = iov_setup(&(sf.trailers), &tbuf,
- trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0)
+ Py_ssize_t i = PySequence_Size(trailers);
+ if (i < 0)
+ return NULL;
+ if (i > INT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "sendfile() trailer is too large");
return NULL;
+ }
+ if (i > 0) {
+ sf.trl_cnt = (int)i;
+ i = iov_setup(&(sf.trailers), &tbuf,
+ trailers, sf.trl_cnt, PyBUF_SIMPLE);
+ if (i < 0)
+ return NULL;
#ifdef __APPLE__
- sbytes += i;
+ sbytes += i;
#endif
+ }
}
}
@@ -8411,7 +8433,7 @@ static Py_ssize_t
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
/*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
{
- int cnt;
+ Py_ssize_t cnt;
Py_ssize_t result;
int async_err = 0;
struct iovec *iov;
@@ -8423,6 +8445,8 @@ os_writev_impl(PyObject *module, int fd, PyObject *buffers)
return -1;
}
cnt = PySequence_Size(buffers);
+ if (cnt < 0)
+ return -1;
if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
return -1;
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 9fe28138c0..c1bc1e1234 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -1550,20 +1550,26 @@ set_difference(PySetObject *so, PyObject *other)
PyObject *key;
Py_hash_t hash;
setentry *entry;
- Py_ssize_t pos = 0;
+ Py_ssize_t pos = 0, other_size;
int rv;
if (PySet_GET_SIZE(so) == 0) {
return set_copy(so);
}
- if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) {
+ if (PyAnySet_Check(other)) {
+ other_size = PySet_GET_SIZE(other);
+ }
+ else if (PyDict_CheckExact(other)) {
+ other_size = PyDict_Size(other);
+ }
+ else {
return set_copy_and_difference(so, other);
}
/* If len(so) much more than len(other), it's more efficient to simply copy
* so and then iterate other looking for common elements. */
- if ((PySet_GET_SIZE(so) >> 2) > PyObject_Size(other)) {
+ if ((PySet_GET_SIZE(so) >> 2) > other_size) {
return set_copy_and_difference(so, other);
}
--
GitLab
From 39dedb6e1a18069ce8f5c8e6076e9d9ef9d6d515 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Wed, 19 Apr 2017 23:22:19 +0300
Subject: [PATCH 0142/1433] [3.6] bpo-30070: Fixed leaks and crashes in errors
handling in the parser module. (GH-1131). (#1184)
(cherry picked from commit a79f4c219531c05fc8f670c1e4bbf12c081935d3)
---
Lib/test/test_parser.py | 81 +++++++++++++++++++++++++
Misc/NEWS | 2 +
Modules/parsermodule.c | 131 ++++++++++++++++++++++++----------------
3 files changed, 162 insertions(+), 52 deletions(-)
diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py
index d6e6f71577..70cabb2859 100644
--- a/Lib/test/test_parser.py
+++ b/Lib/test/test_parser.py
@@ -1,4 +1,6 @@
+import copy
import parser
+import pickle
import unittest
import operator
import struct
@@ -424,6 +426,52 @@ class IllegalSyntaxTestCase(unittest.TestCase):
# not even remotely valid:
self.check_bad_tree((1, 2, 3), "")
+ def test_illegal_terminal(self):
+ tree = \
+ (257,
+ (269,
+ (270,
+ (271,
+ (277,
+ (1,))),
+ (4, ''))),
+ (4, ''),
+ (0, ''))
+ self.check_bad_tree(tree, "too small items in terminal node")
+ tree = \
+ (257,
+ (269,
+ (270,
+ (271,
+ (277,
+ (1, b'pass'))),
+ (4, ''))),
+ (4, ''),
+ (0, ''))
+ self.check_bad_tree(tree, "non-string second item in terminal node")
+ tree = \
+ (257,
+ (269,
+ (270,
+ (271,
+ (277,
+ (1, 'pass', '0', 0))),
+ (4, ''))),
+ (4, ''),
+ (0, ''))
+ self.check_bad_tree(tree, "non-integer third item in terminal node")
+ tree = \
+ (257,
+ (269,
+ (270,
+ (271,
+ (277,
+ (1, 'pass', 0, 0))),
+ (4, ''))),
+ (4, ''),
+ (0, ''))
+ self.check_bad_tree(tree, "too many items in terminal node")
+
def test_illegal_yield_1(self):
# Illegal yield statement: def f(): return 1; yield 1
tree = \
@@ -628,6 +676,24 @@ class IllegalSyntaxTestCase(unittest.TestCase):
(4, ''), (0, ''))
self.check_bad_tree(tree, "from import fred")
+ def test_illegal_encoding(self):
+ # Illegal encoding declaration
+ tree = \
+ (339,
+ (257, (0, '')))
+ self.check_bad_tree(tree, "missed encoding")
+ tree = \
+ (339,
+ (257, (0, '')),
+ b'iso-8859-1')
+ self.check_bad_tree(tree, "non-string encoding")
+ tree = \
+ (339,
+ (257, (0, '')),
+ '\udcff')
+ with self.assertRaises(UnicodeEncodeError):
+ parser.sequence2st(tree)
+
class CompileTestCase(unittest.TestCase):
@@ -772,6 +838,21 @@ class STObjectTestCase(unittest.TestCase):
self.assertRaises(TypeError, operator.lt, st1, 1815)
self.assertRaises(TypeError, operator.gt, b'waterloo', st2)
+ def test_copy_pickle(self):
+ sts = [
+ parser.expr('2 + 3'),
+ parser.suite('x = 2; y = x + 3'),
+ parser.expr('list(x**3 for x in range(20))')
+ ]
+ for st in sts:
+ st_copy = copy.copy(st)
+ self.assertEqual(st_copy.totuple(), st.totuple())
+ st_copy = copy.deepcopy(st)
+ self.assertEqual(st_copy.totuple(), st.totuple())
+ for proto in range(pickle.HIGHEST_PROTOCOL+1):
+ st_copy = pickle.loads(pickle.dumps(st, proto))
+ self.assertEqual(st_copy.totuple(), st.totuple())
+
check_sizeof = support.check_sizeof
@support.cpython_only
diff --git a/Misc/NEWS b/Misc/NEWS
index 44a4b873b1..cb9fab656e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -32,6 +32,8 @@ Core and Builtins
Library
-------
+- bpo-30070: Fixed leaks and crashes in errors handling in the parser module.
+
- bpo-30061: Fixed crashes in IOBase methods __next__() and readlines() when
readline() or __next__() respectively return non-sizeable object.
Fixed possible other errors caused by not checking results of PyObject_Size(),
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c
index b2566951d0..a4443350ef 100644
--- a/Modules/parsermodule.c
+++ b/Modules/parsermodule.c
@@ -698,7 +698,7 @@ validate_node(node *tree)
short a_label = dfa_state->s_arc[arc].a_lbl;
assert(a_label < _PyParser_Grammar.g_ll.ll_nlabels);
if (_PyParser_Grammar.g_ll.ll_label[a_label].lb_type == ch_type) {
- /* The child is acceptable; if non-terminal, validate it recursively. */
+ /* The child is acceptable; if non-terminal, validate it recursively. */
if (ISNONTERMINAL(ch_type) && !validate_node(ch))
return 0;
@@ -776,32 +776,35 @@ parser_tuple2st(PyST_Object *self, PyObject *args, PyObject *kw)
*/
tree = build_node_tree(tuple);
if (tree != 0) {
- node *validation_root = tree;
+ node *validation_root = NULL;
int tree_type = 0;
switch (TYPE(tree)) {
case eval_input:
/* Might be an eval form. */
tree_type = PyST_EXPR;
+ validation_root = tree;
break;
case encoding_decl:
/* This looks like an encoding_decl so far. */
- if (NCH(tree) != 1)
+ if (NCH(tree) == 1) {
+ tree_type = PyST_SUITE;
+ validation_root = CHILD(tree, 0);
+ }
+ else {
err_string("Error Parsing encoding_decl");
- validation_root = CHILD(tree, 0);
- /* Fall through */
+ }
+ break;
case file_input:
/* This looks like an exec form so far. */
-
tree_type = PyST_SUITE;
+ validation_root = tree;
break;
default:
/* This is a fragment, at best. */
- PyNode_Free(tree);
err_string("parse tree does not use a valid start symbol");
- return (0);
}
- if (validate_node(validation_root))
+ if (validation_root != NULL && validate_node(validation_root))
st = parser_newstobject(tree, tree_type);
else
PyNode_Free(tree);
@@ -831,6 +834,9 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
Py_ssize_t i;
int err;
+ if (len < 0) {
+ return NULL;
+ }
for (i = 1; i < len; ++i) {
/* elem must always be a sequence, however simple */
PyObject* elem = PySequence_GetItem(tuple, i);
@@ -851,7 +857,7 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
if (type == -1 && PyErr_Occurred()) {
Py_DECREF(temp);
Py_DECREF(elem);
- return 0;
+ return NULL;
}
}
Py_DECREF(temp);
@@ -863,7 +869,7 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
PyErr_SetObject(parser_error, err);
Py_XDECREF(err);
Py_XDECREF(elem);
- return (0);
+ return NULL;
}
if (ISTERMINAL(type)) {
Py_ssize_t len = PyObject_Size(elem);
@@ -872,11 +878,14 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
if ((len != 2) && (len != 3)) {
err_string("terminal nodes must have 2 or 3 entries");
- return 0;
+ Py_DECREF(elem);
+ return NULL;
}
temp = PySequence_GetItem(elem, 1);
- if (temp == NULL)
- return 0;
+ if (temp == NULL) {
+ Py_DECREF(elem);
+ return NULL;
+ }
if (!PyUnicode_Check(temp)) {
PyErr_Format(parser_error,
"second item in terminal node must be a string,"
@@ -884,46 +893,49 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
Py_TYPE(temp)->tp_name);
Py_DECREF(temp);
Py_DECREF(elem);
- return 0;
+ return NULL;
}
if (len == 3) {
PyObject *o = PySequence_GetItem(elem, 2);
- if (o != NULL) {
- if (PyLong_Check(o)) {
- int num = _PyLong_AsInt(o);
- if (num == -1 && PyErr_Occurred()) {
- Py_DECREF(o);
- Py_DECREF(temp);
- Py_DECREF(elem);
- return 0;
- }
- *line_num = num;
- }
- else {
- PyErr_Format(parser_error,
- "third item in terminal node must be an"
- " integer, found %s",
- Py_TYPE(temp)->tp_name);
+ if (o == NULL) {
+ Py_DECREF(temp);
+ Py_DECREF(elem);
+ return NULL;
+ }
+ if (PyLong_Check(o)) {
+ int num = _PyLong_AsInt(o);
+ if (num == -1 && PyErr_Occurred()) {
Py_DECREF(o);
Py_DECREF(temp);
Py_DECREF(elem);
- return 0;
+ return NULL;
}
+ *line_num = num;
+ }
+ else {
+ PyErr_Format(parser_error,
+ "third item in terminal node must be an"
+ " integer, found %s",
+ Py_TYPE(temp)->tp_name);
Py_DECREF(o);
+ Py_DECREF(temp);
+ Py_DECREF(elem);
+ return NULL;
}
+ Py_DECREF(o);
}
temp_str = PyUnicode_AsUTF8AndSize(temp, &len);
if (temp_str == NULL) {
Py_DECREF(temp);
- Py_XDECREF(elem);
- return 0;
+ Py_DECREF(elem);
+ return NULL;
}
strn = (char *)PyObject_MALLOC(len + 1);
if (strn == NULL) {
Py_DECREF(temp);
- Py_XDECREF(elem);
+ Py_DECREF(elem);
PyErr_NoMemory();
- return 0;
+ return NULL;
}
(void) memcpy(strn, temp_str, len + 1);
Py_DECREF(temp);
@@ -933,20 +945,21 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
* It has to be one or the other; this is an error.
* Raise an exception.
*/
- PyObject *err = Py_BuildValue("os", elem, "unknown node type.");
+ PyObject *err = Py_BuildValue("Os", elem, "unknown node type.");
PyErr_SetObject(parser_error, err);
Py_XDECREF(err);
- Py_XDECREF(elem);
- return (0);
+ Py_DECREF(elem);
+ return NULL;
}
err = PyNode_AddChild(root, type, strn, *line_num, 0);
if (err == E_NOMEM) {
- Py_XDECREF(elem);
+ Py_DECREF(elem);
PyObject_FREE(strn);
- return (node *) PyErr_NoMemory();
+ PyErr_NoMemory();
+ return NULL;
}
if (err == E_OVERFLOW) {
- Py_XDECREF(elem);
+ Py_DECREF(elem);
PyObject_FREE(strn);
PyErr_SetString(PyExc_ValueError,
"unsupported number of child nodes");
@@ -957,14 +970,14 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
node* new_child = CHILD(root, i - 1);
if (new_child != build_node_children(elem, new_child, line_num)) {
- Py_XDECREF(elem);
- return (0);
+ Py_DECREF(elem);
+ return NULL;
}
}
else if (type == NEWLINE) { /* It's true: we increment the */
++(*line_num); /* line number *after* the newline! */
}
- Py_XDECREF(elem);
+ Py_DECREF(elem);
}
return root;
}
@@ -999,10 +1012,23 @@ build_node_tree(PyObject *tuple)
if (num == encoding_decl) {
encoding = PySequence_GetItem(tuple, 2);
+ if (encoding == NULL) {
+ PyErr_SetString(parser_error, "missed encoding");
+ return NULL;
+ }
+ if (!PyUnicode_Check(encoding)) {
+ PyErr_Format(parser_error,
+ "encoding must be a string, found %.200s",
+ Py_TYPE(encoding)->tp_name);
+ Py_DECREF(encoding);
+ return NULL;
+ }
/* tuple isn't borrowed anymore here, need to DECREF */
tuple = PySequence_GetSlice(tuple, 0, 2);
- if (tuple == NULL)
+ if (tuple == NULL) {
+ Py_DECREF(encoding);
return NULL;
+ }
}
res = PyNode_New(num);
if (res != NULL) {
@@ -1015,31 +1041,33 @@ build_node_tree(PyObject *tuple)
const char *temp;
temp = PyUnicode_AsUTF8AndSize(encoding, &len);
if (temp == NULL) {
- Py_DECREF(res);
+ PyNode_Free(res);
Py_DECREF(encoding);
Py_DECREF(tuple);
return NULL;
}
res->n_str = (char *)PyObject_MALLOC(len + 1);
if (res->n_str == NULL) {
- Py_DECREF(res);
+ PyNode_Free(res);
Py_DECREF(encoding);
Py_DECREF(tuple);
PyErr_NoMemory();
return NULL;
}
(void) memcpy(res->n_str, temp, len + 1);
- Py_DECREF(encoding);
- Py_DECREF(tuple);
}
}
+ if (encoding != NULL) {
+ Py_DECREF(encoding);
+ Py_DECREF(tuple);
+ }
}
else {
/* The tuple is illegal -- if the number is neither TERMINAL nor
* NONTERMINAL, we can't use it. Not sure the implementation
* allows this condition, but the API doesn't preclude it.
*/
- PyObject *err = Py_BuildValue("os", tuple,
+ PyObject *err = Py_BuildValue("Os", tuple,
"Illegal component tuple.");
PyErr_SetObject(parser_error, err);
Py_XDECREF(err);
@@ -1074,7 +1102,6 @@ parser__pickler(PyObject *self, PyObject *args)
result = Py_BuildValue("O(O)", pickle_constructor, tuple);
Py_DECREF(tuple);
}
- Py_DECREF(empty_dict);
Py_DECREF(newargs);
}
finally:
--
GitLab
From e2546172622dd52692cf0e26c2b931f942f345b6 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Wed, 19 Apr 2017 23:59:02 +0300
Subject: [PATCH 0143/1433] [3.6] bpo-30065: Fixed arguments validation in
_posixsubprocess.fork_exec(). (GH-1110) (#1186)
(cherry picked from commit 66bffd1)
---
Lib/multiprocessing/util.py | 2 +-
Lib/subprocess.py | 3 ++-
Lib/test/test_capi.py | 6 +++---
Lib/test/test_subprocess.py | 13 ++++++++++-
Modules/_posixsubprocess.c | 43 ++++++++++++++++++++-----------------
5 files changed, 41 insertions(+), 26 deletions(-)
diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py
index 1a2c0db40b..0ce274ceca 100644
--- a/Lib/multiprocessing/util.py
+++ b/Lib/multiprocessing/util.py
@@ -386,7 +386,7 @@ def _close_stdin():
def spawnv_passfds(path, args, passfds):
import _posixsubprocess
- passfds = sorted(passfds)
+ passfds = tuple(sorted(map(int, passfds)))
errpipe_read, errpipe_write = os.pipe()
try:
return _posixsubprocess.fork_exec(
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 0db6571f29..1721269291 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -1253,7 +1253,8 @@ class Popen(object):
fds_to_keep.add(errpipe_write)
self.pid = _posixsubprocess.fork_exec(
args, executable_list,
- close_fds, sorted(fds_to_keep), cwd, env_list,
+ close_fds, tuple(sorted(map(int, fds_to_keep))),
+ cwd, env_list,
p2cread, p2cwrite, c2pread, c2pwrite,
errread, errwrite,
errpipe_read, errpipe_write,
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index 6c3625d487..08aa3ffdf6 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -98,7 +98,7 @@ class CAPITest(unittest.TestCase):
def __len__(self):
return 1
self.assertRaises(TypeError, _posixsubprocess.fork_exec,
- 1,Z(),3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)
+ 1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17)
# Issue #15736: overflow in _PySequence_BytesToCharpArray()
class Z(object):
def __len__(self):
@@ -106,7 +106,7 @@ class CAPITest(unittest.TestCase):
def __getitem__(self, i):
return b'x'
self.assertRaises(MemoryError, _posixsubprocess.fork_exec,
- 1,Z(),3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)
+ 1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17)
@unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.')
def test_subprocess_fork_exec(self):
@@ -116,7 +116,7 @@ class CAPITest(unittest.TestCase):
# Issue #15738: crash in subprocess_fork_exec()
self.assertRaises(TypeError, _posixsubprocess.fork_exec,
- Z(),[b'1'],3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)
+ Z(),[b'1'],3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17)
@unittest.skipIf(MISSING_C_DOCSTRINGS,
"Signature information for builtins requires docstrings")
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
index 3c871dde5c..d8d6d82713 100644
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -2431,7 +2431,7 @@ class POSIXProcessTestCase(BaseTestCase):
with self.assertRaises(TypeError):
_posixsubprocess.fork_exec(
args, exe_list,
- True, [], cwd, env_list,
+ True, (), cwd, env_list,
-1, -1, -1, -1,
1, 2, 3, 4,
True, True, func)
@@ -2443,6 +2443,16 @@ class POSIXProcessTestCase(BaseTestCase):
def test_fork_exec_sorted_fd_sanity_check(self):
# Issue #23564: sanity check the fork_exec() fds_to_keep sanity check.
import _posixsubprocess
+ class BadInt:
+ first = True
+ def __init__(self, value):
+ self.value = value
+ def __int__(self):
+ if self.first:
+ self.first = False
+ return self.value
+ raise ValueError
+
gc_enabled = gc.isenabled()
try:
gc.enable()
@@ -2453,6 +2463,7 @@ class POSIXProcessTestCase(BaseTestCase):
(18, 23, 42, 2**63), # Out of range.
(5, 4), # Not sorted.
(6, 7, 7, 8), # Duplicate.
+ (BadInt(1), BadInt(2)),
):
with self.assertRaises(
ValueError,
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index 5007a39bc2..d1434d59f8 100644
--- a/Modules/_posixsubprocess.c
+++ b/Modules/_posixsubprocess.c
@@ -111,13 +111,17 @@ _is_fdescfs_mounted_on_dev_fd(void)
static int
_sanity_check_python_fd_sequence(PyObject *fd_sequence)
{
- Py_ssize_t seq_idx, seq_len = PySequence_Length(fd_sequence);
+ Py_ssize_t seq_idx;
long prev_fd = -1;
- for (seq_idx = 0; seq_idx < seq_len; ++seq_idx) {
- PyObject* py_fd = PySequence_Fast_GET_ITEM(fd_sequence, seq_idx);
- long iter_fd = PyLong_AsLong(py_fd);
+ for (seq_idx = 0; seq_idx < PyTuple_GET_SIZE(fd_sequence); ++seq_idx) {
+ PyObject* py_fd = PyTuple_GET_ITEM(fd_sequence, seq_idx);
+ long iter_fd;
+ if (!PyLong_Check(py_fd)) {
+ return 1;
+ }
+ iter_fd = PyLong_AsLong(py_fd);
if (iter_fd < 0 || iter_fd <= prev_fd || iter_fd > INT_MAX) {
- /* Negative, overflow, not a Long, unsorted, too big for a fd. */
+ /* Negative, overflow, unsorted, too big for a fd. */
return 1;
}
prev_fd = iter_fd;
@@ -132,13 +136,12 @@ _is_fd_in_sorted_fd_sequence(int fd, PyObject *fd_sequence)
{
/* Binary search. */
Py_ssize_t search_min = 0;
- Py_ssize_t search_max = PySequence_Length(fd_sequence) - 1;
+ Py_ssize_t search_max = PyTuple_GET_SIZE(fd_sequence) - 1;
if (search_max < 0)
return 0;
do {
long middle = (search_min + search_max) / 2;
- long middle_fd = PyLong_AsLong(
- PySequence_Fast_GET_ITEM(fd_sequence, middle));
+ long middle_fd = PyLong_AsLong(PyTuple_GET_ITEM(fd_sequence, middle));
if (fd == middle_fd)
return 1;
if (fd > middle_fd)
@@ -154,9 +157,9 @@ make_inheritable(PyObject *py_fds_to_keep, int errpipe_write)
{
Py_ssize_t i, len;
- len = PySequence_Length(py_fds_to_keep);
+ len = PyTuple_GET_SIZE(py_fds_to_keep);
for (i = 0; i < len; ++i) {
- PyObject* fdobj = PySequence_Fast_GET_ITEM(py_fds_to_keep, i);
+ PyObject* fdobj = PyTuple_GET_ITEM(py_fds_to_keep, i);
long fd = PyLong_AsLong(fdobj);
assert(!PyErr_Occurred());
assert(0 <= fd && fd <= INT_MAX);
@@ -213,14 +216,13 @@ static void
_close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep)
{
long end_fd = safe_get_max_fd();
- Py_ssize_t num_fds_to_keep = PySequence_Length(py_fds_to_keep);
+ Py_ssize_t num_fds_to_keep = PyTuple_GET_SIZE(py_fds_to_keep);
Py_ssize_t keep_seq_idx;
int fd_num;
/* As py_fds_to_keep is sorted we can loop through the list closing
* fds inbetween any in the keep list falling within our range. */
for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
- PyObject* py_keep_fd = PySequence_Fast_GET_ITEM(py_fds_to_keep,
- keep_seq_idx);
+ PyObject* py_keep_fd = PyTuple_GET_ITEM(py_fds_to_keep, keep_seq_idx);
int keep_fd = PyLong_AsLong(py_keep_fd);
if (keep_fd < start_fd)
continue;
@@ -306,7 +308,7 @@ _close_open_fds_safe(int start_fd, PyObject* py_fds_to_keep)
/* Close all open file descriptors from start_fd and higher.
- * Do not close any in the sorted py_fds_to_keep list.
+ * Do not close any in the sorted py_fds_to_keep tuple.
*
* This function violates the strict use of async signal safe functions. :(
* It calls opendir(), readdir() and closedir(). Of these, the one most
@@ -562,8 +564,9 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
#endif
if (!PyArg_ParseTuple(
- args, "OOpOOOiiiiiiiiiiO:fork_exec",
- &process_args, &executable_list, &close_fds, &py_fds_to_keep,
+ args, "OOpO!OOiiiiiiiiiiO:fork_exec",
+ &process_args, &executable_list,
+ &close_fds, &PyTuple_Type, &py_fds_to_keep,
&cwd_obj, &env_list,
&p2cread, &p2cwrite, &c2pread, &c2pwrite,
&errread, &errwrite, &errpipe_read, &errpipe_write,
@@ -574,10 +577,6 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3");
return NULL;
}
- if (PySequence_Length(py_fds_to_keep) < 0) {
- PyErr_SetString(PyExc_ValueError, "cannot get length of fds_to_keep");
- return NULL;
- }
if (_sanity_check_python_fd_sequence(py_fds_to_keep)) {
PyErr_SetString(PyExc_ValueError, "bad value(s) in fds_to_keep");
return NULL;
@@ -631,6 +630,10 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
goto cleanup;
for (arg_num = 0; arg_num < num_args; ++arg_num) {
PyObject *borrowed_arg, *converted_arg;
+ if (PySequence_Fast_GET_SIZE(fast_args) != num_args) {
+ PyErr_SetString(PyExc_RuntimeError, "args changed during iteration");
+ goto cleanup;
+ }
borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num);
if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0)
goto cleanup;
--
GitLab
From 5fb4bf91e78e128a22b5b58da179f09d0b307f2d Mon Sep 17 00:00:00 2001
From: cocoatomo
Date: Thu, 20 Apr 2017 12:54:06 +0900
Subject: [PATCH 0144/1433] bpo-19225: Remove duplicated description for
standard warning categories (GH-1068)
---
Doc/c-api/exceptions.rst | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst
index 3516a16903..c75408db77 100644
--- a/Doc/c-api/exceptions.rst
+++ b/Doc/c-api/exceptions.rst
@@ -291,16 +291,11 @@ an error value).
is the function calling :c:func:`PyErr_WarnEx`, 2 is the function above that,
and so forth.
- Warning categories must be subclasses of :c:data:`Warning`; the default warning
- category is :c:data:`RuntimeWarning`. The standard Python warning categories are
- available as global variables whose names are ``PyExc_`` followed by the Python
- exception name. These have the type :c:type:`PyObject\*`; they are all class
- objects. Their names are :c:data:`PyExc_Warning`, :c:data:`PyExc_UserWarning`,
- :c:data:`PyExc_UnicodeWarning`, :c:data:`PyExc_DeprecationWarning`,
- :c:data:`PyExc_SyntaxWarning`, :c:data:`PyExc_RuntimeWarning`, and
- :c:data:`PyExc_FutureWarning`. :c:data:`PyExc_Warning` is a subclass of
- :c:data:`PyExc_Exception`; the other warning categories are subclasses of
- :c:data:`PyExc_Warning`.
+ Warning categories must be subclasses of :c:data:`PyExc_Warning`;
+ :c:data:`PyExc_Warning` is a subclass of :c:data:`PyExc_Exception`;
+ the default warning category is :c:data:`PyExc_RuntimeWarning`. The standard
+ Python warning categories are available as global variables whose names are
+ enumerated at :ref:`standarwarningcategories`.
For information about warning control, see the documentation for the
:mod:`warnings` module and the :option:`-W` option in the command line
@@ -963,8 +958,10 @@ Notes:
Only defined on Windows; protect code that uses this by testing that the
preprocessor macro ``MS_WINDOWS`` is defined.
-Standard Warnings
-=================
+.. _standarwarningcategories:
+
+Standard Warning Categories
+===========================
All standard Python warning categories are available as global variables whose
names are ``PyExc_`` followed by the Python exception name. These have the type
--
GitLab
From 596e714d79a22d1d53f26ae1a579dcd43f15865a Mon Sep 17 00:00:00 2001
From: Berker Peksag
Date: Thu, 20 Apr 2017 07:36:57 +0300
Subject: [PATCH 0145/1433] bpo-30078: Add an example of passing a path to
unittest (GH-1178)
(cherry picked from commit f7e62cf8adfb8ab6a6a870903defe8ff218a0383)
---
Lib/unittest/main.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/Lib/unittest/main.py b/Lib/unittest/main.py
index 09fefe1164..807604f08d 100644
--- a/Lib/unittest/main.py
+++ b/Lib/unittest/main.py
@@ -14,6 +14,7 @@ Examples:
%(prog)s test_module - run tests from test_module
%(prog)s module.TestClass - run tests from module.TestClass
%(prog)s module.Class.test_method - run specified test method
+ %(prog)s path/to/test_file.py - run tests from test_file.py
"""
MODULE_EXAMPLES = """\
--
GitLab
From 83a90b9aeda3a4c10e8393893ed4ec8adc861e62 Mon Sep 17 00:00:00 2001
From: Berker Peksag
Date: Thu, 20 Apr 2017 07:42:32 +0300
Subject: [PATCH 0146/1433] Remove redundant comma in argparse HOWTO (GH-1141)
Reported by Sean Canavan on docs@p.o.
(cherry picked from commit 8526fb74edf5ac9ca175b7cdcb0d82bb8780d2cf)
---
Doc/howto/argparse.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/howto/argparse.rst b/Doc/howto/argparse.rst
index 7e161a59ad..9d770f5232 100644
--- a/Doc/howto/argparse.rst
+++ b/Doc/howto/argparse.rst
@@ -221,7 +221,7 @@ before proceeding.
Introducing Optional arguments
==============================
-So far we, have been playing with positional arguments. Let us
+So far we have been playing with positional arguments. Let us
have a look on how to add optional ones::
import argparse
--
GitLab
From df5df13fdc3a71bcf2295acc2cba7f22cfe2d669 Mon Sep 17 00:00:00 2001
From: Dong-hee Na
Date: Thu, 20 Apr 2017 17:26:25 +0900
Subject: [PATCH 0147/1433] [3.6] bpo-12414: Update code_sizeof() to take in
account co_extra memory. (#1168) (#1198)
---
Lib/test/test_sys.py | 8 +++++---
Misc/ACKS | 1 +
Misc/NEWS | 4 ++++
Objects/codeobject.c | 10 +++++++---
4 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index df9ebd4085..e151f493d4 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -913,13 +913,15 @@ class SizeofTest(unittest.TestCase):
return inner
check(get_cell().__closure__[0], size('P'))
# code
- check(get_cell().__code__, size('6i13P'))
- check(get_cell.__code__, size('6i13P'))
+ def check_code_size(a, expected_size):
+ self.assertGreaterEqual(sys.getsizeof(a), expected_size)
+ check_code_size(get_cell().__code__, size('6i13P'))
+ check_code_size(get_cell.__code__, size('6i13P'))
def get_cell2(x):
def inner():
return x
return inner
- check(get_cell2.__code__, size('6i13P') + 1)
+ check_code_size(get_cell2.__code__, size('6i13P') + calcsize('n'))
# complex
check(complex(0,1), size('2d'))
# method_descriptor (descriptor object)
diff --git a/Misc/ACKS b/Misc/ACKS
index 72070e19f6..ac2c4edc73 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1060,6 +1060,7 @@ R. David Murray
Matti Mäki
Jörg Müller
Kaushik N
+Dong-hee Na
Dale Nagata
John Nagle
Takahiro Nakayama
diff --git a/Misc/NEWS b/Misc/NEWS
index cb9fab656e..b1f79d6124 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,10 @@ What's New in Python 3.6.2 release candidate 1?
Core and Builtins
-----------------
+- bpo-12414: sys.getsizeof() on a code object now returns the sizes
+ which includes the code struct and sizes of objects which it references.
+ Patch by Dong-hee Na.
+
- bpo-29949: Fix memory usage regression of set and frozenset object.
- bpo-29935: Fixed error messages in the index() method of tuple, list and deque
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index df8b9538fe..22c4f856cd 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -446,11 +446,15 @@ code_dealloc(PyCodeObject *co)
static PyObject *
code_sizeof(PyCodeObject *co, void *unused)
{
- Py_ssize_t res;
+ Py_ssize_t res = _PyObject_SIZE(Py_TYPE(co));
+ _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) co->co_extra;
- res = _PyObject_SIZE(Py_TYPE(co));
if (co->co_cell2arg != NULL && co->co_cellvars != NULL)
- res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(unsigned char);
+ res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(Py_ssize_t);
+
+ if (co_extra != NULL)
+ res += co_extra->ce_size * sizeof(co_extra->ce_extras[0]);
+
return PyLong_FromSsize_t(res);
}
--
GitLab
From 430020500c56259d31e07d32771f017952bad4e0 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 20 Apr 2017 07:12:37 -0700
Subject: [PATCH 0148/1433] [3.6] bpo-30109: Fix reindent.py (GH-1207)
(GH-1208)
Skip the file if it has bad encoding.
(cherry picked from commit 58f3c9dc8f5626abe09ac9738c34f6ba99ce2972)
---
Lib/test/test_tools/test_reindent.py | 7 +++++++
Tools/scripts/reindent.py | 6 +++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/Lib/test/test_tools/test_reindent.py b/Lib/test/test_tools/test_reindent.py
index d7c20e1e5c..34df0c5d51 100644
--- a/Lib/test/test_tools/test_reindent.py
+++ b/Lib/test/test_tools/test_reindent.py
@@ -7,6 +7,7 @@ Tools directory of a Python checkout or tarball, such as reindent.py.
import os
import unittest
from test.support.script_helper import assert_python_ok
+from test.support import findfile
from test.test_tools import scriptsdir, skip_if_missing
@@ -23,6 +24,12 @@ class ReindentTests(unittest.TestCase):
self.assertEqual(out, b'')
self.assertGreater(err, b'')
+ def test_reindent_file_with_bad_encoding(self):
+ bad_coding_path = findfile('bad_coding.py')
+ rc, out, err = assert_python_ok(self.script, '-r', bad_coding_path)
+ self.assertEqual(out, b'')
+ self.assertNotEqual(err, b'')
+
if __name__ == '__main__':
unittest.main()
diff --git a/Tools/scripts/reindent.py b/Tools/scripts/reindent.py
index 18424dea14..f6dadaac5a 100755
--- a/Tools/scripts/reindent.py
+++ b/Tools/scripts/reindent.py
@@ -118,7 +118,11 @@ def check(file):
if verbose:
print("checking", file, "...", end=' ')
with open(file, 'rb') as f:
- encoding, _ = tokenize.detect_encoding(f.readline)
+ try:
+ encoding, _ = tokenize.detect_encoding(f.readline)
+ except SyntaxError as se:
+ errprint("%s: SyntaxError: %s" % (file, str(se)))
+ return
try:
with open(file, encoding=encoding) as f:
r = Reindenter(f)
--
GitLab
From 7a113a0cbf545588d61286fcc0e89141cf211735 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Thu, 20 Apr 2017 22:55:06 +0300
Subject: [PATCH 0149/1433] bpo-29802: Fix the cleaning up issue in
PyUnicode_FSDecoder(). (#1217)
---
Objects/unicodeobject.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 7871043681..4e0c663e33 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -3902,6 +3902,7 @@ PyUnicode_FSDecoder(PyObject* arg, void* addr)
PyObject *output = NULL;
if (arg == NULL) {
Py_DECREF(*(PyObject**)addr);
+ *(PyObject**)addr = NULL;
return 1;
}
--
GitLab
From 483729526e06cda0befc241190bb586d472a72e8 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Thu, 20 Apr 2017 20:55:59 -0700
Subject: [PATCH 0150/1433] [3.6] Add missing .gitignore entries for VS2015
IntelliSense DB (GH-1223) (#1225)
(cherry picked from commit 8e675286a92f33837cfffac5914b5175dac5d573)
---
.gitignore | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.gitignore b/.gitignore
index db27597aac..9392fe5def 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,6 +52,8 @@ PCbuild/*.suo
PCbuild/*.*sdf
PCbuild/*-pgi
PCbuild/*-pgo
+PCbuild/*.VC.db
+PCbuild/*.VC.opendb
PCbuild/.vs/
PCbuild/amd64/
PCbuild/obj/
--
GitLab
From b984a05d557e78b928f38098d0b6c0e95f737b9a Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Fri, 21 Apr 2017 18:27:29 +0200
Subject: [PATCH 0151/1433] bpo-30107: don't dump core on expected test_io
crash (#1235) (#1241)
test_io has two unit tests which trigger a deadlock:
* test_daemon_threads_shutdown_stdout_deadlock()
* test_daemon_threads_shutdown_stderr_deadlock()
These tests call Py_FatalError() if the expected bug is triggered
which calls abort(). Use test.support.SuppressCrashReport to prevent
the creation on a core dump, to fix the warning:
Warning -- files was modified by test_io
Before: []
After: ['python.core']
(cherry picked from commit 2a1aed04b0943636f605543522e16cca1dc23e70)
---
Lib/test/test_io.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index 5a7617cd9f..8c91ad2ad8 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -3720,6 +3720,7 @@ class CMiscIOTest(MiscIOTest):
import sys
import time
import threading
+ from test.support import SuppressCrashReport
file = sys.{stream_name}
@@ -3728,6 +3729,10 @@ class CMiscIOTest(MiscIOTest):
file.write('.')
file.flush()
+ crash = SuppressCrashReport()
+ crash.__enter__()
+ # don't call __exit__(): the crash occurs at Python shutdown
+
thread = threading.Thread(target=run)
thread.daemon = True
thread.start()
--
GitLab
From 1ccbe6007e5569ab25170f8ecddd5fbbc2ef36b0 Mon Sep 17 00:00:00 2001
From: Steve Dower
Date: Fri, 21 Apr 2017 11:28:46 -0700
Subject: [PATCH 0152/1433] bpo-29191: Add liblzma.vcxproj to pcbuild.sln and
other missing entries (GH-1222) (GH-1244)
liblzma is missing from pcbuild.sln. This causes the build of _lzma to fail when building the solution and not using build.bat.
---
PCbuild/pcbuild.sln | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln
index 0e65811ae7..580879930a 100644
--- a/PCbuild/pcbuild.sln
+++ b/PCbuild/pcbuild.sln
@@ -96,6 +96,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testconsole", "_testconsol
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_asyncio", "_asyncio.vcxproj", "{384C224A-7474-476E-A01B-750EA7DE918C}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblzma", "liblzma.vcxproj", "{12728250-16EC-4DC6-94D7-E21DD88947F8}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -728,6 +730,38 @@ Global
{B244E787-C445-441C-BDF4-5A4F1A3A1E51}.Release|Win32.Build.0 = Release|Win32
{B244E787-C445-441C-BDF4-5A4F1A3A1E51}.Release|x64.ActiveCfg = Release|x64
{B244E787-C445-441C-BDF4-5A4F1A3A1E51}.Release|x64.Build.0 = Release|x64
+ {384C224A-7474-476E-A01B-750EA7DE918C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {384C224A-7474-476E-A01B-750EA7DE918C}.Debug|Win32.Build.0 = Debug|Win32
+ {384C224A-7474-476E-A01B-750EA7DE918C}.Debug|x64.ActiveCfg = Debug|x64
+ {384C224A-7474-476E-A01B-750EA7DE918C}.Debug|x64.Build.0 = Debug|x64
+ {384C224A-7474-476E-A01B-750EA7DE918C}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32
+ {384C224A-7474-476E-A01B-750EA7DE918C}.PGInstrument|Win32.Build.0 = PGInstrument|Win32
+ {384C224A-7474-476E-A01B-750EA7DE918C}.PGInstrument|x64.ActiveCfg = PGInstrument|x64
+ {384C224A-7474-476E-A01B-750EA7DE918C}.PGInstrument|x64.Build.0 = PGInstrument|x64
+ {384C224A-7474-476E-A01B-750EA7DE918C}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32
+ {384C224A-7474-476E-A01B-750EA7DE918C}.PGUpdate|Win32.Build.0 = PGUpdate|Win32
+ {384C224A-7474-476E-A01B-750EA7DE918C}.PGUpdate|x64.ActiveCfg = PGUpdate|x64
+ {384C224A-7474-476E-A01B-750EA7DE918C}.PGUpdate|x64.Build.0 = PGUpdate|x64
+ {384C224A-7474-476E-A01B-750EA7DE918C}.Release|Win32.ActiveCfg = Release|Win32
+ {384C224A-7474-476E-A01B-750EA7DE918C}.Release|Win32.Build.0 = Release|Win32
+ {384C224A-7474-476E-A01B-750EA7DE918C}.Release|x64.ActiveCfg = Release|x64
+ {384C224A-7474-476E-A01B-750EA7DE918C}.Release|x64.Build.0 = Release|x64
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.Debug|Win32.Build.0 = Debug|Win32
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.Debug|x64.ActiveCfg = Debug|x64
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.Debug|x64.Build.0 = Debug|x64
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.PGInstrument|Win32.Build.0 = PGInstrument|Win32
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.PGInstrument|x64.ActiveCfg = PGInstrument|x64
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.PGInstrument|x64.Build.0 = PGInstrument|x64
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.PGUpdate|Win32.Build.0 = PGUpdate|Win32
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.PGUpdate|x64.ActiveCfg = PGUpdate|x64
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.PGUpdate|x64.Build.0 = PGUpdate|x64
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.Release|Win32.ActiveCfg = Release|Win32
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.Release|Win32.Build.0 = Release|Win32
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.Release|x64.ActiveCfg = Release|x64
+ {12728250-16EC-4DC6-94D7-E21DD88947F8}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
--
GitLab
From 3a8f8ea2aca46f9ef1e715f2c924357b6719525f Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Fri, 21 Apr 2017 23:17:33 +0200
Subject: [PATCH 0153/1433] bpo-30125: Fix faulthandler.disable() on Windows
(#1243)
On Windows, faulthandler.disable() now removes the exception handler
installed by faulthandler.enable().
---
Lib/test/test_faulthandler.py | 12 ++++++++++++
Modules/faulthandler.c | 13 +++++++++++--
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py
index bdd8d1a2a6..01cbae3f20 100644
--- a/Lib/test/test_faulthandler.py
+++ b/Lib/test/test_faulthandler.py
@@ -755,6 +755,18 @@ class FaultHandlerTests(unittest.TestCase):
3,
name)
+ @unittest.skipUnless(MS_WINDOWS, 'specific to Windows')
+ def test_disable_windows_exc_handler(self):
+ code = dedent("""
+ import faulthandler
+ faulthandler.enable()
+ faulthandler.disable()
+ code = faulthandler._EXCEPTION_ACCESS_VIOLATION
+ faulthandler._raise_exception(code)
+ """)
+ output, exitcode = self.get_output(code)
+ self.assertEqual(output, [])
+ self.assertEqual(exitcode, 0xC0000005)
if __name__ == "__main__":
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 2f8b624fd1..61fc4908b0 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -55,6 +55,9 @@ static struct {
int fd;
int all_threads;
PyInterpreterState *interp;
+#ifdef MS_WINDOWS
+ void *exc_handler;
+#endif
} fatal_error = {0, NULL, -1, 0};
#ifdef FAULTHANDLER_LATER
@@ -462,7 +465,8 @@ faulthandler_enable(void)
}
#ifdef MS_WINDOWS
- AddVectoredExceptionHandler(1, faulthandler_exc_handler);
+ assert(fatal_error.exc_handler == NULL);
+ fatal_error.exc_handler = AddVectoredExceptionHandler(1, faulthandler_exc_handler);
#endif
return 0;
}
@@ -514,7 +518,12 @@ faulthandler_disable(void)
faulthandler_disable_fatal_handler(handler);
}
}
-
+#ifdef MS_WINDOWS
+ if (fatal_error.exc_handler != NULL) {
+ RemoveVectoredExceptionHandler(fatal_error.exc_handler);
+ fatal_error.exc_handler = NULL;
+ }
+#endif
Py_CLEAR(fatal_error.file);
}
--
GitLab
From 414e0283a351e7b070c3f13aa24cadc5fdd9a230 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Fri, 21 Apr 2017 19:28:29 -0700
Subject: [PATCH 0154/1433] [3.6] Correct the README link in Unix install docs
(GH-1245) (GH-1248)
(cherry picked from commit d1ae24e8880fe00d006eb2996af815c35fbcfb33)
---
Doc/using/unix.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/using/unix.rst b/Doc/using/unix.rst
index 97f0a49ca7..604688ce94 100644
--- a/Doc/using/unix.rst
+++ b/Doc/using/unix.rst
@@ -77,7 +77,7 @@ The build process consists in the usual ::
make install
invocations. Configuration options and caveats for specific Unix platforms are
-extensively documented in the :source:`README` file in the root of the Python
+extensively documented in the :source:`README.rst` file in the root of the Python
source tree.
.. warning::
--
GitLab
From a3d8dda7d899bf41ab7eb2c6148459ad276fe295 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Fri, 21 Apr 2017 19:58:28 -0700
Subject: [PATCH 0155/1433] bpo-30098: Clarify that run_coroutine_threadsafe
expects asyncio.Future (GH-1170) (#1247)
(cherry picked from commit ae5b3260dd459845aad8a30491b76d471577785d)
---
Lib/asyncio/tasks.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 4d79367d5c..f91e70aecb 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -517,7 +517,8 @@ def ensure_future(coro_or_future, *, loop=None):
elif compat.PY35 and inspect.isawaitable(coro_or_future):
return ensure_future(_wrap_awaitable(coro_or_future), loop=loop)
else:
- raise TypeError('A Future, a coroutine or an awaitable is required')
+ raise TypeError('An asyncio.Future, a coroutine or an awaitable is '
+ 'required')
@coroutine
--
GitLab
From 9d022f169ec64987b29359ae0e904026aab07a64 Mon Sep 17 00:00:00 2001
From: Louie Lu
Date: Sat, 22 Apr 2017 19:48:53 +0800
Subject: [PATCH 0156/1433] [3.6] Fix trailing colon and newline in test.rst
(GH-1250) (#1254)
(cherry picked from commit 7fae81e1672d0b4110d31ea6a765b54f63a2e54b)
---
Doc/library/test.rst | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Doc/library/test.rst b/Doc/library/test.rst
index fab3e1fe4c..9d4ff7ad8b 100644
--- a/Doc/library/test.rst
+++ b/Doc/library/test.rst
@@ -570,7 +570,8 @@ The :mod:`test.support` module defines the following functions:
def load_tests(*args):
return load_package_tests(os.path.dirname(__file__), *args)
-.. function:: detect_api_mismatch(ref_api, other_api, *, ignore=()):
+
+.. function:: detect_api_mismatch(ref_api, other_api, *, ignore=())
Returns the set of attributes, functions or methods of *ref_api* not
found on *other_api*, except for a defined list of items to be
--
GitLab
From f2ed2858eea7569c8915b3611ca5ec92ae10b17f Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sun, 23 Apr 2017 08:50:14 +0300
Subject: [PATCH 0157/1433] [3.6] bpo-15718: Document the upper bound constrain
on the __len__ return value. (GH-1256) (#1259)
(cherry picked from commit 85157cd)
---
Doc/reference/datamodel.rst | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst
index 095a2380b3..35925a065f 100644
--- a/Doc/reference/datamodel.rst
+++ b/Doc/reference/datamodel.rst
@@ -2011,6 +2011,14 @@ through the container; for mappings, :meth:`__iter__` should be the same as
:meth:`__bool__` method and whose :meth:`__len__` method returns zero is
considered to be false in a Boolean context.
+ .. impl-detail::
+
+ In CPython, the length is required to be at most :attr:`sys.maxsize`.
+ If the length is larger than :attr:`!sys.maxsize` some features (such as
+ :func:`len`) may raise :exc:`OverflowError`. To prevent raising
+ :exc:`!OverflowError` by truth value testing, an object must define a
+ :meth:`__bool__` method.
+
.. method:: object.__length_hint__(self)
@@ -2021,6 +2029,7 @@ through the container; for mappings, :meth:`__iter__` should be the same as
.. versionadded:: 3.4
+
.. note::
Slicing is done exclusively with the following three methods. A call like ::
--
GitLab
From ea0efa3bc1d0b832da75519c6f85d767ae44feda Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sun, 23 Apr 2017 21:05:01 -0700
Subject: [PATCH 0158/1433] [3.6] bpo-29751: Improve PyLong_FromString
documentation (GH-915) (#1266)
(cherry picked from commit 26896f2832324dde85cdd63d525571ca669f6f0b)
---
Doc/c-api/long.rst | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst
index f592cb65c3..f50680b3d2 100644
--- a/Doc/c-api/long.rst
+++ b/Doc/c-api/long.rst
@@ -85,13 +85,12 @@ All integers are implemented as "long" integer objects of arbitrary size.
Return a new :c:type:`PyLongObject` based on the string value in *str*, which
is interpreted according to the radix in *base*. If *pend* is non-*NULL*,
*\*pend* will point to the first character in *str* which follows the
- representation of the number. If *base* is ``0``, the radix will be
- determined based on the leading characters of *str*: if *str* starts with
- ``'0x'`` or ``'0X'``, radix 16 will be used; if *str* starts with ``'0o'`` or
- ``'0O'``, radix 8 will be used; if *str* starts with ``'0b'`` or ``'0B'``,
- radix 2 will be used; otherwise radix 10 will be used. If *base* is not
- ``0``, it must be between ``2`` and ``36``, inclusive. Leading spaces are
- ignored. If there are no digits, :exc:`ValueError` will be raised.
+ representation of the number. If *base* is ``0``, *str* is interpreted using
+ the :ref:`integers` definition; in this case, leading zeros in a
+ non-zero decimal number raises a :exc:`ValueError`. If *base* is not ``0``,
+ it must be between ``2`` and ``36``, inclusive. Leading spaces and single
+ underscores after a base specifier and between digits are ignored. If there
+ are no digits, :exc:`ValueError` will be raised.
.. c:function:: PyObject* PyLong_FromUnicode(Py_UNICODE *u, Py_ssize_t length, int base)
--
GitLab
From 16b6f971bd8afc72b439b83324eba744460adb67 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Tue, 25 Apr 2017 18:23:05 -0700
Subject: [PATCH 0159/1433] [3.6] bpo-28851: Improve namedtuple documentation
(GH-1274) (GH-1286)
Clarify that a sequence of strings is the preferred value for 'field_names'.
(cherry picked from commit 97bf722fcd1de1236824377e052369dc7686b644)
---
Doc/library/collections.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst
index 8e2eb4d9b0..2d51f0cfdc 100644
--- a/Doc/library/collections.rst
+++ b/Doc/library/collections.rst
@@ -771,9 +771,9 @@ they add the ability to access fields by name instead of position index.
helpful docstring (with typename and field_names) and a helpful :meth:`__repr__`
method which lists the tuple contents in a ``name=value`` format.
- The *field_names* are a single string with each fieldname separated by whitespace
- and/or commas, for example ``'x y'`` or ``'x, y'``. Alternatively, *field_names*
- can be a sequence of strings such as ``['x', 'y']``.
+ The *field_names* are a sequence of strings such as ``['x', 'y']``.
+ Alternatively, *field_names* can be a single string with each fieldname
+ separated by whitespace and/or commas, for example ``'x y'`` or ``'x, y'``.
Any valid Python identifier may be used for a fieldname except for names
starting with an underscore. Valid identifiers consist of letters, digits,
--
GitLab
From 9f6828119df23fca9e799f47e02baabe87adca2a Mon Sep 17 00:00:00 2001
From: Louie Lu
Date: Wed, 26 Apr 2017 16:45:31 +0800
Subject: [PATCH 0160/1433] bpo-28698: Fix c_wchar_p doc example (GH-1160)
(cherry picked from commit 0d637e236d7099f7b724026c8cb7bd83d8e12e6b)
---
Doc/library/ctypes.rst | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst
index 3840935ce0..51a3a360fa 100644
--- a/Doc/library/ctypes.rst
+++ b/Doc/library/ctypes.rst
@@ -284,7 +284,7 @@ the correct type and value::
>>> c_int()
c_long(0)
>>> c_wchar_p("Hello, World")
- c_wchar_p('Hello, World')
+ c_wchar_p(140018365411392)
>>> c_ushort(-3)
c_ushort(65533)
>>>
@@ -309,11 +309,15 @@ bytes objects are immutable)::
>>> s = "Hello, World"
>>> c_s = c_wchar_p(s)
>>> print(c_s)
- c_wchar_p('Hello, World')
+ c_wchar_p(139966785747344)
+ >>> print(c_s.value)
+ Hello World
>>> c_s.value = "Hi, there"
- >>> print(c_s)
- c_wchar_p('Hi, there')
- >>> print(s) # first object is unchanged
+ >>> print(c_s) # the memory location has changed
+ c_wchar_p(139966783348904)
+ >>> print(c_s.value)
+ Hi, there
+ >>> print(s) # first object is unchanged
Hello, World
>>>
--
GitLab
From 04f389b8b357c8507b6c9642adcb8b956489e034 Mon Sep 17 00:00:00 2001
From: Berker Peksag
Date: Wed, 26 Apr 2017 17:25:37 +0300
Subject: [PATCH 0161/1433] bpo-29974: Improve typing.TYPE_CHECKING example
(GH-982)
* Fix PEP 8 (SomeType instead of some_type)
* Add a function parameter annotation
* Explain, using wording from PEP 484 and PEP 526,
why one annotation is in quotes and another is not.
Suggested by Ivan Levkevskyi.
(cherry picked from commit 87c07fe9d908d0a2143fcc8369255c6ff3241503)
---
Doc/library/typing.rst | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst
index 2cfc37f695..1780739ad1 100644
--- a/Doc/library/typing.rst
+++ b/Doc/library/typing.rst
@@ -1041,5 +1041,10 @@ The module defines the following classes, functions and decorators:
if TYPE_CHECKING:
import expensive_mod
- def fun():
- local_var: expensive_mod.some_type = other_fun()
+ def fun(arg: 'expensive_mod.SomeType') -> None:
+ local_var: expensive_mod.AnotherType = other_fun()
+
+ Note that the first type annotation must be enclosed in quotes, making it a
+ "forward reference", to hide the ``expensive_mod`` reference from the
+ interpreter runtime. Type annotations for local variables are not
+ evaluated, so the second annotation does not need to be enclosed in quotes.
--
GitLab
From 2fc3c543fc93d6211de8dcfaeac3a0fd10a356e0 Mon Sep 17 00:00:00 2001
From: Dong-hee Na
Date: Thu, 27 Apr 2017 01:55:55 +0900
Subject: [PATCH 0162/1433] [3.6] bpo-30142: Remove "callable" from the
2to3fixer documentation. (GH-1303)
---
Doc/library/2to3.rst | 7 -------
1 file changed, 7 deletions(-)
diff --git a/Doc/library/2to3.rst b/Doc/library/2to3.rst
index ace1bfaf8c..4c9a528d42 100644
--- a/Doc/library/2to3.rst
+++ b/Doc/library/2to3.rst
@@ -199,13 +199,6 @@ and off individually. They are described here in more detail.
because the :class:`memoryview` API is similar but not exactly the same as
that of :class:`buffer`.
-.. 2to3fixer:: callable
-
- Converts ``callable(x)`` to ``isinstance(x, collections.Callable)``, adding
- 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
Fixes dictionary iteration methods. :meth:`dict.iteritems` is converted to
--
GitLab
From 33a5568f69301562d536852d12b9e03cd8dfc3a4 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Wed, 26 Apr 2017 22:18:53 -0700
Subject: [PATCH 0163/1433] [3.6] bpo-30182: Use the correct name for ISO in
Unicode HOWTO. (GH-1312) (GH-1313)
(cherry picked from commit 6fde770e4e940c19cd62de0b6aeb77840690843e)
---
Doc/howto/unicode.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst
index a48ae1f5fa..9649b9c609 100644
--- a/Doc/howto/unicode.rst
+++ b/Doc/howto/unicode.rst
@@ -43,9 +43,9 @@ hold values ranging from 0 to 255. ASCII codes only went up to 127, so some
machines assigned values between 128 and 255 to accented characters. Different
machines had different codes, however, which led to problems exchanging files.
Eventually various commonly used sets of values for the 128--255 range emerged.
-Some were true standards, defined by the International Standards Organization,
-and some were *de facto* conventions that were invented by one company or
-another and managed to catch on.
+Some were true standards, defined by the International Organization for
+Standardization, and some were *de facto* conventions that were invented by one
+company or another and managed to catch on.
255 characters aren't very many. For example, you can't fit both the accented
characters used in Western Europe and the Cyrillic alphabet used for Russian
--
GitLab
From 4dc3b9cf2a868a8378ecbc2221a15e7b59e8e944 Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Thu, 27 Apr 2017 18:25:03 +0200
Subject: [PATCH 0164/1433] bpo-30175: Skip client cert tests of test_imaplib
(#1320) (#1323)
* bpo-30175: Skip client cert tests of test_imaplib
The IMAP server cyrus.andrew.cmu.edu doesn't accept our randomly
generated client x509 certificate anymore.
* bpo-30188: Catch EOFError in NetworkedNNTPTests
test_nntplib fails randomly with EOFError in
NetworkedNNTPTests.setUpClass(). Catch EOFError to skip tests in that
case.
(cherry picked from commit 5bccca58b9b2b3a925b16750bedbd907695ea8d7)
---
Lib/test/test_imaplib.py | 6 ++++++
Lib/test/test_nntplib.py | 7 ++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py
index fac6b57081..9df37b1de5 100644
--- a/Lib/test/test_imaplib.py
+++ b/Lib/test/test_imaplib.py
@@ -966,6 +966,9 @@ class RemoteIMAP_SSLTest(RemoteIMAPTest):
_server = self.imap_class(self.host, self.port)
self.check_logincapa(_server)
+ @unittest.skipIf(True,
+ "bpo-30175: FIXME: cyrus.andrew.cmu.edu doesn't accept "
+ "our randomly generated client x509 certificate anymore")
def test_logincapa_with_client_certfile(self):
with transient_internet(self.host):
with support.check_warnings(('', DeprecationWarning)):
@@ -973,6 +976,9 @@ class RemoteIMAP_SSLTest(RemoteIMAPTest):
certfile=CERTFILE)
self.check_logincapa(_server)
+ @unittest.skipIf(True,
+ "bpo-30175: FIXME: cyrus.andrew.cmu.edu doesn't accept "
+ "our randomly generated client x509 certificate anymore")
def test_logincapa_with_client_ssl_context(self):
with transient_internet(self.host):
_server = self.imap_class(
diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py
index c46ded1186..3e84f3429e 100644
--- a/Lib/test/test_nntplib.py
+++ b/Lib/test/test_nntplib.py
@@ -286,7 +286,12 @@ class NetworkedNNTPTests(NetworkedNNTPTestsMixin, unittest.TestCase):
def setUpClass(cls):
support.requires("network")
with support.transient_internet(cls.NNTP_HOST):
- cls.server = cls.NNTP_CLASS(cls.NNTP_HOST, timeout=TIMEOUT, usenetrc=False)
+ try:
+ cls.server = cls.NNTP_CLASS(cls.NNTP_HOST, timeout=TIMEOUT,
+ usenetrc=False)
+ except EOFError:
+ raise unittest.SkipTest(f"{cls} got EOF error on connecting "
+ f"to {cls.NNTP_HOST!r}")
@classmethod
def tearDownClass(cls):
--
GitLab
From c9ca57eeea4d9da748d84281506c5803512b79ac Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Fri, 28 Apr 2017 03:27:51 +0200
Subject: [PATCH 0165/1433] bpo-30107: Make SuppressCrashReport quiet on macOS
(#1279) (#1335)
On macOS, SuppressCrashReport now redirects /usr/bin/defaults command
stderr into a pipe to not pollute stderr. It fixes a
test_io.test_daemon_threads_shutdown_stderr_deadlock() failure when
the CrashReporter domain doesn't exists. Message logged into stderr:
2017-04-24 16:57:21.432 defaults[41046:2462851]
The domain/default pair of (com.apple.CrashReporter, DialogType) does not exist
(cherry picked from commit d819ad9832292d854e9710493ecdf959b69802e3)
---
Lib/test/support/__init__.py | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 15d8fc849b..1621e3de40 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -2433,6 +2433,7 @@ class SuppressCrashReport:
(0, self.old_value[1]))
except (ValueError, OSError):
pass
+
if sys.platform == 'darwin':
# Check if the 'Crash Reporter' on OSX was configured
# in 'Developer' mode and warn that it will get triggered
@@ -2440,10 +2441,14 @@ class SuppressCrashReport:
#
# This assumes that this context manager is used in tests
# that might trigger the next manager.
- value = subprocess.Popen(['/usr/bin/defaults', 'read',
- 'com.apple.CrashReporter', 'DialogType'],
- stdout=subprocess.PIPE).communicate()[0]
- if value.strip() == b'developer':
+ cmd = ['/usr/bin/defaults', 'read',
+ 'com.apple.CrashReporter', 'DialogType']
+ proc = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ with proc:
+ stdout = proc.communicate()[0]
+ if stdout.strip() == b'developer':
print("this test triggers the Crash Reporter, "
"that is intentional", end='', flush=True)
--
GitLab
From caa59c156d1e6ff3d005e0112bb27c5bed4afb71 Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Fri, 28 Apr 2017 04:13:37 +0200
Subject: [PATCH 0166/1433] [3.6] bpo-30106: Fix
test_asyncore.test_quick_connect() (#1336)
* Fix/optimize test_asyncore.test_quick_connect() (#1188)
Don't use addCleanup() in test_quick_connect() because it keeps the
Thread object alive and so @reap_threads fails on its timeout of 1
second. "./python -m test -v test_asyncore -m test_quick_connect"
now takes 185 ms, instead of 11 seconds.
Other minor changes:
* Use "with sock:" to close the socket instead of
try/finally: sock.close()
* Use self.skipTest() in test_quick_connect() to remove one
indentation level and notice user that the test is specific to
AF_INET and AF_INET6
* bpo-30106: Fix tearDown() of test_asyncore (#1194)
Call asyncore.close_all() with ignore_all=True in the tearDown()
method of the test_asyncore base test case. It should prevent keeping
alive sockets in asyncore.socket_map if close() fails with an
unexpected error.
Revert also an unwanted change of my previous commit: remove name
parameter of Thread in test_quick_connect().
* bpo-30106: Fix test_asyncore.test_quick_connect() (#1234)
test_quick_connect() runs a thread up to 50 seconds, whereas the
socket is connected in 0.2 second and then the thread is expected to
end in less than 3 second. On Linux, the thread ends quickly because
select() seems to always return quickly. On FreeBSD, sometimes
select() fails with timeout and so the thread runs much longer than
expected.
Fix the thread timeout to fix a race condition in the test.
---
Lib/test/test_asyncore.py | 80 +++++++++++++++++++--------------------
1 file changed, 40 insertions(+), 40 deletions(-)
diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py
index d05462b7ef..dc2f716e0b 100644
--- a/Lib/test/test_asyncore.py
+++ b/Lib/test/test_asyncore.py
@@ -502,7 +502,7 @@ class BaseClient(BaseTestHandler):
class BaseTestAPI:
def tearDown(self):
- asyncore.close_all()
+ asyncore.close_all(ignore_all=True)
def loop_waiting_for_flag(self, instance, timeout=5):
timeout = float(timeout) / 100
@@ -755,50 +755,50 @@ class BaseTestAPI:
def test_set_reuse_addr(self):
if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX:
self.skipTest("Not applicable to AF_UNIX sockets.")
- sock = socket.socket(self.family)
- try:
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- except OSError:
- unittest.skip("SO_REUSEADDR not supported on this platform")
- else:
- # if SO_REUSEADDR succeeded for sock we expect asyncore
- # to do the same
- s = asyncore.dispatcher(socket.socket(self.family))
- self.assertFalse(s.socket.getsockopt(socket.SOL_SOCKET,
- socket.SO_REUSEADDR))
- s.socket.close()
- s.create_socket(self.family)
- s.set_reuse_addr()
- self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET,
- socket.SO_REUSEADDR))
- finally:
- sock.close()
+
+ with socket.socket(self.family) as sock:
+ try:
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ except OSError:
+ unittest.skip("SO_REUSEADDR not supported on this platform")
+ else:
+ # if SO_REUSEADDR succeeded for sock we expect asyncore
+ # to do the same
+ s = asyncore.dispatcher(socket.socket(self.family))
+ self.assertFalse(s.socket.getsockopt(socket.SOL_SOCKET,
+ socket.SO_REUSEADDR))
+ s.socket.close()
+ s.create_socket(self.family)
+ s.set_reuse_addr()
+ self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET,
+ socket.SO_REUSEADDR))
@unittest.skipUnless(threading, 'Threading required for this test.')
@support.reap_threads
def test_quick_connect(self):
# see: http://bugs.python.org/issue10340
- if self.family in (socket.AF_INET, getattr(socket, "AF_INET6", object())):
- server = BaseServer(self.family, self.addr)
- t = threading.Thread(target=lambda: asyncore.loop(timeout=0.1,
- count=500))
- t.start()
- def cleanup():
- t.join(timeout=TIMEOUT)
- if t.is_alive():
- self.fail("join() timed out")
- self.addCleanup(cleanup)
-
- s = socket.socket(self.family, socket.SOCK_STREAM)
- s.settimeout(.2)
- s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
- struct.pack('ii', 1, 0))
- try:
- s.connect(server.address)
- except OSError:
- pass
- finally:
- s.close()
+ if self.family not in (socket.AF_INET, getattr(socket, "AF_INET6", object())):
+ self.skipTest("test specific to AF_INET and AF_INET6")
+
+ server = BaseServer(self.family, self.addr)
+ # run the thread 500 ms: the socket should be connected in 200 ms
+ t = threading.Thread(target=lambda: asyncore.loop(timeout=0.1,
+ count=5))
+ t.start()
+ try:
+ with socket.socket(self.family, socket.SOCK_STREAM) as s:
+ s.settimeout(.2)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
+ struct.pack('ii', 1, 0))
+
+ try:
+ s.connect(server.address)
+ except OSError:
+ pass
+ finally:
+ t.join(timeout=TIMEOUT)
+ if t.is_alive():
+ self.fail("join() timed out")
class TestAPI_UseIPv4Sockets(BaseTestAPI):
family = socket.AF_INET
--
GitLab
From cb21f5f3d2005b891df0b76e3fc4d4676e285f21 Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Fri, 28 Apr 2017 04:13:53 +0200
Subject: [PATCH 0167/1433] bpo-30131: test_logging now joins queue threads
(#1298) (#1317)
QueueListenerTest of test_logging now closes the multiprocessing
Queue and joins its thread to prevent leaking dangling threads to
following tests.
Add also @support.reap_threads to detect earlier if a test leaks
threads (and try to "cleanup" these threads).
(cherry picked from commit 8ca2f2faefa8dba323a2e4c4b86efb633d7a53cf)
---
Lib/test/test_logging.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 9dedc098ba..0a2584c610 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -3163,6 +3163,7 @@ if hasattr(logging.handlers, 'QueueListener'):
handler.close()
@patch.object(logging.handlers.QueueListener, 'handle')
+ @support.reap_threads
def test_handle_called_with_queue_queue(self, mock_handle):
for i in range(self.repeat):
log_queue = queue.Queue()
@@ -3172,10 +3173,13 @@ if hasattr(logging.handlers, 'QueueListener'):
@support.requires_multiprocessing_queue
@patch.object(logging.handlers.QueueListener, 'handle')
+ @support.reap_threads
def test_handle_called_with_mp_queue(self, mock_handle):
for i in range(self.repeat):
log_queue = multiprocessing.Queue()
self.setup_and_log(log_queue, '%s_%s' % (self.id(), i))
+ log_queue.close()
+ log_queue.join_thread()
self.assertEqual(mock_handle.call_count, 5 * self.repeat,
'correct number of handled log messages')
@@ -3188,6 +3192,7 @@ if hasattr(logging.handlers, 'QueueListener'):
return []
@support.requires_multiprocessing_queue
+ @support.reap_threads
def test_no_messages_in_queue_after_stop(self):
"""
Five messages are logged then the QueueListener is stopped. This
@@ -3200,6 +3205,9 @@ if hasattr(logging.handlers, 'QueueListener'):
self.setup_and_log(queue, '%s_%s' %(self.id(), i))
# time.sleep(1)
items = list(self.get_all_from_queue(queue))
+ queue.close()
+ queue.join_thread()
+
expected = [[], [logging.handlers.QueueListener._sentinel]]
self.assertIn(items, expected,
'Found unexpected messages in queue: %s' % (
--
GitLab
From e005dd9a6da7dfa34f47a6989a7e0a6b1ad04949 Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Fri, 28 Apr 2017 16:06:48 +0200
Subject: [PATCH 0168/1433] bpo-30125: disable faulthandler in ctypes test_SEH
(#1237) (#1343)
Disable faulthandler to run test_SEH() of test_ctypes to prevent the
following log with a traceback:
Windows fatal exception: access violation
Add support.disable_faulthandler() context manager.
(cherry picked from commit a36e939aeb3b5a2c56561eb24f0e339eee9f3f9d)
---
Lib/ctypes/test/test_win32.py | 12 ++++++++----
Lib/test/support/__init__.py | 16 ++++++++++++++++
2 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/Lib/ctypes/test/test_win32.py b/Lib/ctypes/test/test_win32.py
index da1624015e..5d85ad6200 100644
--- a/Lib/ctypes/test/test_win32.py
+++ b/Lib/ctypes/test/test_win32.py
@@ -41,15 +41,19 @@ class FunctionCallTestCase(unittest.TestCase):
@unittest.skipIf(sys.executable.lower().endswith('_d.exe'),
"SEH not enabled in debug builds")
def test_SEH(self):
- # Call functions with invalid arguments, and make sure
- # that access violations are trapped and raise an
- # exception.
- self.assertRaises(OSError, windll.kernel32.GetModuleHandleA, 32)
+ # Disable faulthandler to prevent logging the warning:
+ # "Windows fatal exception: access violation"
+ with support.disable_faulthandler():
+ # Call functions with invalid arguments, and make sure
+ # that access violations are trapped and raise an
+ # exception.
+ self.assertRaises(OSError, windll.kernel32.GetModuleHandleA, 32)
def test_noargs(self):
# This is a special case on win32 x64
windll.user32.GetDesktopWindow()
+
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
class TestWintypes(unittest.TestCase):
def test_HWND(self):
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 1621e3de40..2d60adc3dc 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -2586,3 +2586,19 @@ def setswitchinterval(interval):
if _is_android_emulator:
interval = minimum_interval
return sys.setswitchinterval(interval)
+
+
+@contextlib.contextmanager
+def disable_faulthandler():
+ # use sys.__stderr__ instead of sys.stderr, since regrtest replaces
+ # sys.stderr with a StringIO which has no file descriptor when a test
+ # is run with -W/--verbose3.
+ fd = sys.__stderr__.fileno()
+
+ is_enabled = faulthandler.is_enabled()
+ try:
+ faulthandler.disable()
+ yield
+ finally:
+ if is_enabled:
+ faulthandler.enable(file=fd, all_threads=True)
--
GitLab
From 712114b3f9f5f98f03c66a80607b6f7101c5cc90 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Fri, 28 Apr 2017 20:05:05 +0300
Subject: [PATCH 0169/1433] [3.6] bpo-30197: Enhance functions swap_attr() and
swap_item() in test.support. (GH-1341) (#1345)
They now work when delete replaced attribute or item inside the with
statement. The old value of the attribute or item (or None if it doesn't
exist) now will be assigned to the target of the "as" clause, if there is
one.
(cherry picked from commit d1a1def7bf221b04dcf3fc3a67aa19aa2f622f83)
---
Lib/test/support/__init__.py | 16 ++++++++++++----
Lib/test/test_support.py | 29 +++++++++++++++++++++++------
Lib/test/test_tempfile.py | 5 ++---
Misc/NEWS | 9 +++++++++
4 files changed, 46 insertions(+), 13 deletions(-)
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 2d60adc3dc..f8d177990b 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -2105,12 +2105,15 @@ def swap_attr(obj, attr, new_val):
restoring the old value at the end of the block. If `attr` doesn't
exist on `obj`, it will be created and then deleted at the end of the
block.
+
+ The old value (or None if it doesn't exist) will be assigned to the
+ target of the "as" clause, if there is one.
"""
if hasattr(obj, attr):
real_val = getattr(obj, attr)
setattr(obj, attr, new_val)
try:
- yield
+ yield real_val
finally:
setattr(obj, attr, real_val)
else:
@@ -2118,7 +2121,8 @@ def swap_attr(obj, attr, new_val):
try:
yield
finally:
- delattr(obj, attr)
+ if hasattr(obj, attr):
+ delattr(obj, attr)
@contextlib.contextmanager
def swap_item(obj, item, new_val):
@@ -2132,12 +2136,15 @@ def swap_item(obj, item, new_val):
restoring the old value at the end of the block. If `item` doesn't
exist on `obj`, it will be created and then deleted at the end of the
block.
+
+ The old value (or None if it doesn't exist) will be assigned to the
+ target of the "as" clause, if there is one.
"""
if item in obj:
real_val = obj[item]
obj[item] = new_val
try:
- yield
+ yield real_val
finally:
obj[item] = real_val
else:
@@ -2145,7 +2152,8 @@ def swap_item(obj, item, new_val):
try:
yield
finally:
- del obj[item]
+ if item in obj:
+ del obj[item]
def strip_python_stderr(stderr):
"""Strip the stderr of a Python process from potential debug output
diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
index e83a4d6426..ddd6509231 100644
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -282,17 +282,34 @@ class TestSupport(unittest.TestCase):
def test_swap_attr(self):
class Obj:
- x = 1
+ pass
obj = Obj()
- with support.swap_attr(obj, "x", 5):
+ obj.x = 1
+ with support.swap_attr(obj, "x", 5) as x:
self.assertEqual(obj.x, 5)
+ self.assertEqual(x, 1)
self.assertEqual(obj.x, 1)
+ with support.swap_attr(obj, "y", 5) as y:
+ self.assertEqual(obj.y, 5)
+ self.assertIsNone(y)
+ self.assertFalse(hasattr(obj, 'y'))
+ with support.swap_attr(obj, "y", 5):
+ del obj.y
+ self.assertFalse(hasattr(obj, 'y'))
def test_swap_item(self):
- D = {"item":1}
- with support.swap_item(D, "item", 5):
- self.assertEqual(D["item"], 5)
- self.assertEqual(D["item"], 1)
+ D = {"x":1}
+ with support.swap_item(D, "x", 5) as x:
+ self.assertEqual(D["x"], 5)
+ self.assertEqual(x, 1)
+ self.assertEqual(D["x"], 1)
+ with support.swap_item(D, "y", 5) as y:
+ self.assertEqual(D["y"], 5)
+ self.assertIsNone(y)
+ self.assertNotIn("y", D)
+ with support.swap_item(D, "y", 5):
+ del D["y"]
+ self.assertNotIn("y", D)
class RefClass:
attribute1 = None
diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py
index 51df1ecd7d..d0cf04b0cb 100644
--- a/Lib/test/test_tempfile.py
+++ b/Lib/test/test_tempfile.py
@@ -273,13 +273,12 @@ class TestGetDefaultTempdir(BaseTestCase):
tempfile._get_default_tempdir()
self.assertEqual(os.listdir(our_temp_directory), [])
- open = io.open
def bad_writer(*args, **kwargs):
- fp = open(*args, **kwargs)
+ fp = orig_open(*args, **kwargs)
fp.write = raise_OSError
return fp
- with support.swap_attr(io, "open", bad_writer):
+ with support.swap_attr(io, "open", bad_writer) as orig_open:
# test again with failing write()
with self.assertRaises(FileNotFoundError):
tempfile._get_default_tempdir()
diff --git a/Misc/NEWS b/Misc/NEWS
index b1f79d6124..936e2b0201 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -114,6 +114,15 @@ Documentation
- bpo-26985: Add missing info of code object in inspect documentation.
+Tests
+-----
+
+- bpo-30197: Enhanced functions swap_attr() and swap_item() in the
+ test.support module. They now work when delete replaced attribute or item
+ inside the with statement. The old value of the attribute or item (or None
+ if it doesn't exist) now will be assigned to the target of the "as" clause,
+ if there is one.
+
What's New in Python 3.6.1?
===========================
--
GitLab
From 5a8dcec93936de816cef5c17522e48fca9c30b43 Mon Sep 17 00:00:00 2001
From: csabella
Date: Sat, 29 Apr 2017 20:42:03 -0400
Subject: [PATCH 0170/1433] [3.6] bpo-30208: DOC: fix small typos in IDLE
(#1356)
(cherry picked from commit d9af73330f46d79cc0c56d369f65ebeec3cb5334)
---
Doc/library/idle.rst | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst
index 07c2a25d6a..1a2dac0233 100644
--- a/Doc/library/idle.rst
+++ b/Doc/library/idle.rst
@@ -244,7 +244,7 @@ Go to File/Line
single: stack viewer
Debugger (toggle)
- When actived, code entered in the Shell or run from an Editor will run
+ When activated, code entered in the Shell or run from an Editor will run
under the debugger. In the Editor, breakpoints can be set with the context
menu. This feature is still incomplete and somewhat experimental.
@@ -372,7 +372,7 @@ the :kbd:`Command` key on Mac OSX.
* :kbd:`C-l` center window around the insertion point
- * :kbd:`C-b` go backwards one character without deleting (usually you can
+ * :kbd:`C-b` go backward one character without deleting (usually you can
also use the cursor key for this)
* :kbd:`C-f` go forward one character without deleting (usually you can
@@ -394,7 +394,7 @@ After a block-opening statement, the next line is indented by 4 spaces (in the
Python Shell window by one tab). After certain keywords (break, return etc.)
the next line is dedented. In leading indentation, :kbd:`Backspace` deletes up
to 4 spaces if they are there. :kbd:`Tab` inserts spaces (in the Python
-Shell window one tab), number depends on Indent width. Currently tabs
+Shell window one tab), number depends on Indent width. Currently, tabs
are restricted to four spaces due to Tcl/Tk limitations.
See also the indent/dedent region commands in the edit menu.
@@ -418,7 +418,7 @@ If there is only one possible completion for the characters entered, a
:kbd:`C-space` will open a completions window. In an empty
string, this will contain the files in the current directory. On a
blank line, it will contain the built-in and user-defined functions and
-classes in the current name spaces, plus any modules imported. If some
+classes in the current namespaces, plus any modules imported. If some
characters have been entered, the ACW will attempt to be more specific.
If a string of characters is typed, the ACW selection will jump to the
@@ -557,7 +557,7 @@ IDLE-console differences
As much as possible, the result of executing Python code with IDLE is the
same as executing the same code in a console window. However, the different
-interface and operation occasionally affects visible results. For instance,
+interface and operation occasionally affect visible results. For instance,
``sys.modules`` starts with more entries.
IDLE also replaces ``sys.stdin``, ``sys.stdout``, and ``sys.stderr`` with
@@ -583,7 +583,7 @@ If firewall software complains anyway, you can ignore it.
If the attempt to make the socket connection fails, Idle will notify you.
Such failures are sometimes transient, but if persistent, the problem
-may be either a firewall blocking the connecton or misconfiguration of
+may be either a firewall blocking the connection or misconfiguration of
a particular system. Until the problem is fixed, one can run Idle with
the -n command line switch.
@@ -619,14 +619,14 @@ Setting preferences
The font preferences, highlighting, keys, and general preferences can be
changed via Configure IDLE on the Option menu. Keys can be user defined;
-IDLE ships with four built in key sets. In addition a user can create a
+IDLE ships with four built-in key sets. In addition, a user can create a
custom key set in the Configure IDLE dialog under the keys tab.
Extensions
^^^^^^^^^^
-IDLE contains an extension facility. Peferences for extensions can be
+IDLE contains an extension facility. Preferences for extensions can be
changed with Configure Extensions. See the beginning of config-extensions.def
in the idlelib directory for further information. The default extensions
are currently:
--
GitLab
From 750ff5f8df8faef842470518c58dae2a251114c9 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sat, 29 Apr 2017 22:18:40 -0700
Subject: [PATCH 0171/1433] [3.6] Improve the grammar in windows.rst (GH-1330)
(GH-1360)
(cherry picked from commit 80a3da4d4aad0b51893e1e2f696b6252eca80e07)
---
Doc/using/windows.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst
index 3e4b70e8a1..68687e9f3e 100644
--- a/Doc/using/windows.rst
+++ b/Doc/using/windows.rst
@@ -550,9 +550,9 @@ Shebang Lines
If the first line of a script file starts with ``#!``, it is known as a
"shebang" line. Linux and other Unix like operating systems have native
-support for such lines and are commonly used on such systems to indicate how
-a script should be executed. This launcher allows the same facilities to be
-using with Python scripts on Windows and the examples above demonstrate their
+support for such lines and they are commonly used on such systems to indicate
+how a script should be executed. This launcher allows the same facilities to
+be used with Python scripts on Windows and the examples above demonstrate their
use.
To allow shebang lines in Python scripts to be portable between Unix and
--
GitLab
From 78b23ab6827410960577c01a33df8afc8fd4496e Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Mon, 1 May 2017 22:55:53 -0700
Subject: [PATCH 0172/1433] [3.6] Clean up some confusing text left by
PROTOCOL_SSLv23 -> PROTOCOL_TLS transition (GH-1355) (#1371)
(cherry picked from commit d4069de5112f0408801ff2479476827bb3e0e8fc)
---
Doc/library/ssl.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index bbb13745b2..0ce73c1409 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -610,13 +610,13 @@ Constants
.. data:: PROTOCOL_TLS
Selects the highest protocol version that both the client and server support.
- Despite the name, this option can select "TLS" protocols as well as "SSL".
+ Despite the name, this option can select both "SSL" and "TLS" protocols.
.. versionadded:: 3.6
.. data:: PROTOCOL_TLS_CLIENT
- Auto-negotiate the highest protocol version like :data:`PROTOCOL_SSLv23`,
+ Auto-negotiate the highest protocol version like :data:`PROTOCOL_TLS`,
but only support client-side :class:`SSLSocket` connections. The protocol
enables :data:`CERT_REQUIRED` and :attr:`~SSLContext.check_hostname` by
default.
@@ -625,7 +625,7 @@ Constants
.. data:: PROTOCOL_TLS_SERVER
- Auto-negotiate the highest protocol version like :data:`PROTOCOL_SSLv23`,
+ Auto-negotiate the highest protocol version like :data:`PROTOCOL_TLS`,
but only support server-side :class:`SSLSocket` connections.
.. versionadded:: 3.6
--
GitLab
From 809101f14f27ddb394cd77c477470761ecf99f41 Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Tue, 2 May 2017 10:47:37 +0200
Subject: [PATCH 0173/1433] bpo-30104: Use -fno-strict-aliasing on clang
(#1376)
Python/dtoa.c is not compiled correctly with clang 4.0 and
optimization level -O2 or higher, because of an aliasing issue on the
double/ULong[2] union. Only compile dtoa.c with -fno-strict-aliasing.
LLVM bug report:
https://bugs.llvm.org//show_bug.cgi?id=31928
---
Makefile.pre.in | 9 +++++++++
configure | 35 ++++++++++++++++++++++++++++-------
configure.ac | 34 +++++++++++++++++++++++++++-------
3 files changed, 64 insertions(+), 14 deletions(-)
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 8f27d7320c..3eef424b30 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -107,6 +107,8 @@ ARFLAGS= @ARFLAGS@
CFLAGSFORSHARED=@CFLAGSFORSHARED@
# C flags used for building the interpreter object files
PY_CORE_CFLAGS= $(PY_CFLAGS) $(PY_CFLAGS_NODIST) $(PY_CPPFLAGS) $(CFLAGSFORSHARED) -DPy_BUILD_CORE
+# Strict or non-strict aliasing flags used to compile dtoa.c, see above
+CFLAGS_ALIASING=@CFLAGS_ALIASING@
# Machine-dependent subdirectories
@@ -1535,6 +1537,13 @@ config.status: $(srcdir)/configure
.c.o:
$(CC) -c $(PY_CORE_CFLAGS) -o $@ $<
+# bpo-30104: dtoa.c uses union to cast double to unsigned long[2]. clang 4.0
+# with -O2 or higher and strict aliasing miscompiles the ratio() function
+# causing rounding issues. Compile dtoa.c using -fno-strict-aliasing on clang.
+# https://bugs.llvm.org//show_bug.cgi?id=31928
+Python/dtoa.o: Python/dtoa.c
+ $(CC) -c $(PY_CORE_CFLAGS) $(CFLAGS_ALIASING) -o $@ $<
+
# Run reindent on the library
reindent:
./$(BUILDPYTHON) $(srcdir)/Tools/scripts/reindent.py -r $(srcdir)/Lib
diff --git a/configure b/configure
index 6a1b9e4edc..227d1d24b3 100755
--- a/configure
+++ b/configure
@@ -668,6 +668,7 @@ OTHER_LIBTOOL_OPT
UNIVERSAL_ARCH_FLAGS
CFLAGS_NODIST
BASECFLAGS
+CFLAGS_ALIASING
OPT
LLVM_PROF_FOUND
target_os
@@ -6851,6 +6852,7 @@ esac
# tweak OPT based on compiler and platform, only if the user didn't set
# it on the command line
+
if test "${OPT-unset}" = "unset"
then
case $GCC in
@@ -6863,30 +6865,49 @@ then
WRAP="-fwrapv"
fi
- # Clang also needs -fwrapv
case $CC in
- *clang*) WRAP="-fwrapv"
- ;;
+ *clang*)
+ cc_is_clang=1
+ ;;
+ *)
+ if $CC --version 2>&1 | grep -q clang
+ then
+ cc_is_clang=1
+ else
+ cc_is_clang=
+ fi
esac
+ if test -n "${cc_is_clang}"
+ then
+ # Clang also needs -fwrapv
+ WRAP="-fwrapv"
+ # bpo-30104: disable strict aliasing to compile correctly dtoa.c,
+ # see Makefile.pre.in for more information
+ CFLAGS_ALIASING="-fno-strict-aliasing"
+ fi
+
case $ac_cv_prog_cc_g in
yes)
if test "$Py_DEBUG" = 'true' ; then
# Optimization messes up debuggers, so turn it off for
# debug builds.
if "$CC" -v --help 2>/dev/null |grep -- -Og > /dev/null; then
- OPT="-g -Og -Wall $STRICT_PROTO"
+ OPT="-g -Og -Wall"
else
- OPT="-g -O0 -Wall $STRICT_PROTO"
+ OPT="-g -O0 -Wall"
fi
else
- OPT="-g $WRAP -O3 -Wall $STRICT_PROTO"
+ OPT="-g $WRAP -O3 -Wall"
fi
;;
*)
- OPT="-O3 -Wall $STRICT_PROTO"
+ OPT="-O3 -Wall"
;;
esac
+
+ OPT="$OPT $STRICT_PROTO"
+
case $ac_sys_system in
SCO_SV*) OPT="$OPT -m486 -DSCO5"
;;
diff --git a/configure.ac b/configure.ac
index 2c8e246f22..6978b9090d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1447,6 +1447,7 @@ esac
# tweak OPT based on compiler and platform, only if the user didn't set
# it on the command line
AC_SUBST(OPT)
+AC_SUBST(CFLAGS_ALIASING)
if test "${OPT-unset}" = "unset"
then
case $GCC in
@@ -1459,30 +1460,49 @@ then
WRAP="-fwrapv"
fi
- # Clang also needs -fwrapv
case $CC in
- *clang*) WRAP="-fwrapv"
- ;;
+ *clang*)
+ cc_is_clang=1
+ ;;
+ *)
+ if $CC --version 2>&1 | grep -q clang
+ then
+ cc_is_clang=1
+ else
+ cc_is_clang=
+ fi
esac
+ if test -n "${cc_is_clang}"
+ then
+ # Clang also needs -fwrapv
+ WRAP="-fwrapv"
+ # bpo-30104: disable strict aliasing to compile correctly dtoa.c,
+ # see Makefile.pre.in for more information
+ CFLAGS_ALIASING="-fno-strict-aliasing"
+ fi
+
case $ac_cv_prog_cc_g in
yes)
if test "$Py_DEBUG" = 'true' ; then
# Optimization messes up debuggers, so turn it off for
# debug builds.
if "$CC" -v --help 2>/dev/null |grep -- -Og > /dev/null; then
- OPT="-g -Og -Wall $STRICT_PROTO"
+ OPT="-g -Og -Wall"
else
- OPT="-g -O0 -Wall $STRICT_PROTO"
+ OPT="-g -O0 -Wall"
fi
else
- OPT="-g $WRAP -O3 -Wall $STRICT_PROTO"
+ OPT="-g $WRAP -O3 -Wall"
fi
;;
*)
- OPT="-O3 -Wall $STRICT_PROTO"
+ OPT="-O3 -Wall"
;;
esac
+
+ OPT="$OPT $STRICT_PROTO"
+
case $ac_sys_system in
SCO_SV*) OPT="$OPT -m486 -DSCO5"
;;
--
GitLab
From 33a5d40de997fff5b60157c546a3bf711e083bcc Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Tue, 2 May 2017 11:45:42 +0200
Subject: [PATCH 0174/1433] bpo-30108: Restore sys.path in test_site (#1197)
(#1378)
Add setUpModule() and tearDownModule() functions to test_site to
save/restore sys.path at the module level to prevent warning if the
user site directory is created, since site.addsitedir() modifies
sys.path.
(cherry picked from commit b85c136903c6d2368162f7c4a58f258c9c69ead0)
---
Lib/test/test_site.py | 29 +++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py
index 342ec9e43d..4029617aa1 100644
--- a/Lib/test/test_site.py
+++ b/Lib/test/test_site.py
@@ -27,14 +27,27 @@ if sys.flags.no_site:
import site
-if site.ENABLE_USER_SITE and not os.path.isdir(site.USER_SITE):
- # need to add user site directory for tests
- try:
- os.makedirs(site.USER_SITE)
- site.addsitedir(site.USER_SITE)
- except PermissionError as exc:
- raise unittest.SkipTest('unable to create user site directory (%r): %s'
- % (site.USER_SITE, exc))
+
+OLD_SYS_PATH = None
+
+
+def setUpModule():
+ global OLD_SYS_PATH
+ OLD_SYS_PATH = sys.path[:]
+
+ if site.ENABLE_USER_SITE and not os.path.isdir(site.USER_SITE):
+ # need to add user site directory for tests
+ try:
+ os.makedirs(site.USER_SITE)
+ # modify sys.path: will be restored by tearDownModule()
+ site.addsitedir(site.USER_SITE)
+ except PermissionError as exc:
+ raise unittest.SkipTest('unable to create user site directory (%r): %s'
+ % (site.USER_SITE, exc))
+
+
+def tearDownModule():
+ sys.path[:] = OLD_SYS_PATH
class HelperFunctionsTests(unittest.TestCase):
--
GitLab
From 30768958490c658fba0fe24f1cabbdad44be22ff Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Tue, 2 May 2017 15:50:42 +0200
Subject: [PATCH 0175/1433] bpo-30132: distutils BuildExtTestCase use temp_cwd
(#1387)
BuildExtTestCase of test_distutils now uses support.temp_cwd() in
setUp() to remove files created in the current working in all
BuildExtTestCase unit tests, not only test_build_ext().
Fix the following warning:
Warning -- files was modified by test_distutils
Before: []
After: ['vc140.pdb']
---
Lib/distutils/tests/test_build_ext.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Lib/distutils/tests/test_build_ext.py b/Lib/distutils/tests/test_build_ext.py
index be7f5f38aa..c6502d61d5 100644
--- a/Lib/distutils/tests/test_build_ext.py
+++ b/Lib/distutils/tests/test_build_ext.py
@@ -37,6 +37,13 @@ class BuildExtTestCase(TempdirManager,
from distutils.command import build_ext
build_ext.USER_BASE = site.USER_BASE
+ # bpo-30132: On Windows, a .pdb file may be created in the current
+ # working directory. Create a temporary working directory to cleanup
+ # everything at the end of the test.
+ self.temp_cwd = support.temp_cwd()
+ self.temp_cwd.__enter__()
+ self.addCleanup(self.temp_cwd.__exit__, None, None, None)
+
def build_ext(self, *args, **kwargs):
return build_ext(*args, **kwargs)
--
GitLab
From 3c422b92653df05c7034136b77f76376aa5aec4f Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Tue, 2 May 2017 16:49:10 +0200
Subject: [PATCH 0176/1433] bpo-30199: test_ssl closes all asyncore channels
(#1381) (#1390)
AsyncoreEchoServer of test_ssl now calls
asyncore.close_all(ignore_all=True) to ensure that
asyncore.socket_map is cleared once the test completes, even if
ConnectionHandler was not correctly unregistered.
Fix the following warning:
Warning -- asyncore.socket_map was modified by test_ssl
Before: {}
After: {6: }
(cherry picked from commit 1dae7450c68bad498e57800387b24cb103c461fa)
---
Lib/test/test_ssl.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index d203cddbdf..85c59a618c 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -2065,7 +2065,7 @@ if _have_threads:
class EchoServer (asyncore.dispatcher):
- class ConnectionHandler (asyncore.dispatcher_with_send):
+ class ConnectionHandler(asyncore.dispatcher_with_send):
def __init__(self, conn, certfile):
self.socket = test_wrap_socket(conn, server_side=True,
@@ -2156,6 +2156,8 @@ if _have_threads:
self.join()
if support.verbose:
sys.stdout.write(" cleanup: successfully joined.\n")
+ # make sure that ConnectionHandler is removed from socket_map
+ asyncore.close_all(ignore_all=True)
def start (self, flag=None):
self.flag = flag
--
GitLab
From 4dae0d111dd7bb34ec730eea2327a3219acff211 Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Tue, 2 May 2017 23:46:06 +0200
Subject: [PATCH 0177/1433] [3.6] bpo-30232: Support Git worktree in
configure.ac (#1398)
* bpo-30232: Support Git worktree in configure.ac (#1391)
Don't test if .git/HEAD file exists, but only if the .git file (or
directory) exists.
(cherry picked from commit 5facdbb29169c2799c42f887cef4cd9d087b0167)
* bpo-30232: Regenerate configure (#1396)
Run autoconf.
(cherry picked from commit 9ed34a89532763cf89f5e11fffb91ef7dee29fed)
---
configure | 2 +-
configure.ac | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/configure b/configure
index 227d1d24b3..3c611d6afa 100755
--- a/configure
+++ b/configure
@@ -2711,7 +2711,7 @@ fi
-if test -e $srcdir/.git/HEAD
+if test -e $srcdir/.git
then
# Extract the first word of "git", so it can be a program name with args.
set dummy git; ac_word=$2
diff --git a/configure.ac b/configure.ac
index 6978b9090d..eda075dc75 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,7 +29,7 @@ AC_SUBST(GITVERSION)
AC_SUBST(GITTAG)
AC_SUBST(GITBRANCH)
-if test -e $srcdir/.git/HEAD
+if test -e $srcdir/.git
then
AC_CHECK_PROG(HAS_GIT, git, found, not-found)
else
--
GitLab
From 0c2ff0898db2db9cd9c643dfadbff11761bacf5f Mon Sep 17 00:00:00 2001
From: Antoine Pitrou
Date: Wed, 3 May 2017 00:14:29 +0200
Subject: [PATCH 0178/1433] Backport bpo-30205 to 3.6 (#1403)
---
Lib/test/test_socket.py | 4 ++++
Misc/NEWS | 2 ++
Modules/socketmodule.c | 6 +++---
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 2497e47c66..80dfc405c7 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -4660,6 +4660,10 @@ class TestUnixDomain(unittest.TestCase):
else:
raise
+ def testUnbound(self):
+ # Issue #30205
+ self.assertIn(self.sock.getsockname(), ('', None))
+
def testStrAddr(self):
# Test binding to and retrieving a normal string pathname.
path = os.path.abspath(support.TESTFN)
diff --git a/Misc/NEWS b/Misc/NEWS
index 936e2b0201..3b61543469 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,8 @@ Core and Builtins
Library
-------
+- bpo-30205: Fix getsockname() for unbound AF_UNIX sockets on Linux.
+
- bpo-30070: Fixed leaks and crashes in errors handling in the parser module.
- bpo-30061: Fixed crashes in IOBase methods __next__() and readlines() when
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index f3654c97e7..42aec59ca7 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -1212,9 +1212,9 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
{
struct sockaddr_un *a = (struct sockaddr_un *) addr;
#ifdef __linux__
- if (a->sun_path[0] == 0) { /* Linux abstract namespace */
- addrlen -= offsetof(struct sockaddr_un, sun_path);
- return PyBytes_FromStringAndSize(a->sun_path, addrlen);
+ size_t linuxaddrlen = addrlen - offsetof(struct sockaddr_un, sun_path);
+ if (linuxaddrlen > 0 && a->sun_path[0] == 0) { /* Linux abstract namespace */
+ return PyBytes_FromStringAndSize(a->sun_path, linuxaddrlen);
}
else
#endif /* linux */
--
GitLab
From 564e89f43b8d64c165755e3c7a94e4daecfde5a3 Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Wed, 3 May 2017 02:12:22 +0200
Subject: [PATCH 0179/1433] regrtest: always show before/after of modified env
(#1192) (#1406)
Buildbots don't run tests with -vv and so only log "xxx was modified
by test_xxx" which is not enough to debug such random issue. In many
cases, I'm unable to reproduce the warning and so unable to fix it.
Always logging the value before and value after should help to debug
such warning on buildbots.
(cherry picked from commit ec4b17239d899550be4ee6104b61751bb3c70382)
---
Lib/test/libregrtest/save_env.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/Lib/test/libregrtest/save_env.py b/Lib/test/libregrtest/save_env.py
index 96ad3af8df..8309f266bf 100644
--- a/Lib/test/libregrtest/save_env.py
+++ b/Lib/test/libregrtest/save_env.py
@@ -279,7 +279,6 @@ class saved_test_environment:
if not self.quiet and not self.pgo:
print(f"Warning -- {name} was modified by {self.testname}",
file=sys.stderr, flush=True)
- if self.verbose > 1:
- print(f" Before: {original}\n After: {current} ",
- file=sys.stderr, flush=True)
+ print(f" Before: {original}\n After: {current} ",
+ file=sys.stderr, flush=True)
return False
--
GitLab
From 5bcf01d4cdc78f6b01e5017ff60da7dbfc34c36b Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Tue, 2 May 2017 21:35:43 -0700
Subject: [PATCH 0180/1433] [3.6] Fix typo in selectors.rst (GH-1383) (#1414)
decriptor -> descriptor
(cherry picked from commit b0d82036549074357717d130a772d1e2ebc8ea01)
---
Doc/library/selectors.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/library/selectors.rst b/Doc/library/selectors.rst
index 1624d88aae..6d864a836d 100644
--- a/Doc/library/selectors.rst
+++ b/Doc/library/selectors.rst
@@ -68,7 +68,7 @@ constants below:
.. class:: SelectorKey
A :class:`SelectorKey` is a :class:`~collections.namedtuple` used to
- associate a file object to its underlying file decriptor, selected event
+ associate a file object to its underlying file descriptor, selected event
mask and attached data. It is returned by several :class:`BaseSelector`
methods.
--
GitLab
From e612c28513b406779d187e5f816445c7d40d292b Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Wed, 3 May 2017 09:38:01 -0700
Subject: [PATCH 0181/1433] [3.6] bpo-28556: Routine updates to typing
(GH-1366) (#1416)
- Add NoReturn type
- Use WrapperDescriptorType (original PR by Jim Fasarakis-Hilliard)
- Minor bug-fixes
(cherry picked from commit f06e0218ef6007667f5d61184b85a81a0466d3ae)
---
Lib/test/test_typing.py | 51 +++++++++++++++++++++++++++++++++++++----
Lib/typing.py | 35 ++++++++++++++++++++++++----
Misc/NEWS | 4 ++++
3 files changed, 81 insertions(+), 9 deletions(-)
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index f0070ec975..b3cabda394 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -6,7 +6,7 @@ import sys
from unittest import TestCase, main, skipUnless, SkipTest
from copy import copy, deepcopy
-from typing import Any
+from typing import Any, NoReturn
from typing import TypeVar, AnyStr
from typing import T, KT, VT # Not in __all__.
from typing import Union, Optional
@@ -102,10 +102,6 @@ class AnyTests(BaseTestCase):
with self.assertRaises(TypeError):
type(Any)()
- def test_cannot_subscript(self):
- with self.assertRaises(TypeError):
- Any[int]
-
def test_any_works_with_alias(self):
# These expressions must simply not fail.
typing.Match[Any]
@@ -113,6 +109,40 @@ class AnyTests(BaseTestCase):
typing.IO[Any]
+class NoReturnTests(BaseTestCase):
+
+ def test_noreturn_instance_type_error(self):
+ with self.assertRaises(TypeError):
+ isinstance(42, NoReturn)
+
+ def test_noreturn_subclass_type_error(self):
+ with self.assertRaises(TypeError):
+ issubclass(Employee, NoReturn)
+ with self.assertRaises(TypeError):
+ issubclass(NoReturn, Employee)
+
+ def test_repr(self):
+ self.assertEqual(repr(NoReturn), 'typing.NoReturn')
+
+ def test_not_generic(self):
+ with self.assertRaises(TypeError):
+ NoReturn[int]
+
+ def test_cannot_subclass(self):
+ with self.assertRaises(TypeError):
+ class A(NoReturn):
+ pass
+ with self.assertRaises(TypeError):
+ class A(type(NoReturn)):
+ pass
+
+ def test_cannot_instantiate(self):
+ with self.assertRaises(TypeError):
+ NoReturn()
+ with self.assertRaises(TypeError):
+ type(NoReturn)()
+
+
class TypeVarTests(BaseTestCase):
def test_basic_plain(self):
@@ -2273,6 +2303,14 @@ class XMethBad(NamedTuple):
return 'no chance for this'
""")
+ with self.assertRaises(AttributeError):
+ exec("""
+class XMethBad2(NamedTuple):
+ x: int
+ def _source(self):
+ return 'no chance for this as well'
+""")
+
@skipUnless(PY36, 'Python 3.6 required')
def test_namedtuple_keyword_usage(self):
LocalEmployee = NamedTuple("LocalEmployee", name=str, age=int)
@@ -2420,6 +2458,9 @@ class AllTests(BaseTestCase):
self.assertNotIn('sys', a)
# Check that Text is defined.
self.assertIn('Text', a)
+ # Check previously missing classes.
+ self.assertIn('SupportsBytes', a)
+ self.assertIn('SupportsComplex', a)
if __name__ == '__main__':
diff --git a/Lib/typing.py b/Lib/typing.py
index 9a0f49099a..645bc6f8ae 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -11,9 +11,9 @@ try:
except ImportError:
import collections as collections_abc # Fallback for PY3.2.
try:
- from types import SlotWrapperType, MethodWrapperType, MethodDescriptorType
+ from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType
except ImportError:
- SlotWrapperType = type(object.__init__)
+ WrapperDescriptorType = type(object.__init__)
MethodWrapperType = type(object().__str__)
MethodDescriptorType = type(str.join)
@@ -63,6 +63,8 @@ __all__ = [
# Structural checks, a.k.a. protocols.
'Reversible',
'SupportsAbs',
+ 'SupportsBytes',
+ 'SupportsComplex',
'SupportsFloat',
'SupportsInt',
'SupportsRound',
@@ -420,6 +422,31 @@ class _Any(_FinalTypingBase, _root=True):
Any = _Any(_root=True)
+class _NoReturn(_FinalTypingBase, _root=True):
+ """Special type indicating functions that never return.
+ Example::
+
+ from typing import NoReturn
+
+ def stop() -> NoReturn:
+ raise Exception('no way')
+
+ This type is invalid in other positions, e.g., ``List[NoReturn]``
+ will fail in static type checkers.
+ """
+
+ __slots__ = ()
+
+ def __instancecheck__(self, obj):
+ raise TypeError("NoReturn cannot be used with isinstance().")
+
+ def __subclasscheck__(self, cls):
+ raise TypeError("NoReturn cannot be used with issubclass().")
+
+
+NoReturn = _NoReturn(_root=True)
+
+
class TypeVar(_TypingBase, _root=True):
"""Type variable.
@@ -1450,7 +1477,7 @@ def _get_defaults(func):
_allowed_types = (types.FunctionType, types.BuiltinFunctionType,
types.MethodType, types.ModuleType,
- SlotWrapperType, MethodWrapperType, MethodDescriptorType)
+ WrapperDescriptorType, MethodWrapperType, MethodDescriptorType)
def get_type_hints(obj, globalns=None, localns=None):
@@ -2051,7 +2078,7 @@ _PY36 = sys.version_info[:2] >= (3, 6)
# attributes prohibited to set in NamedTuple class syntax
_prohibited = ('__new__', '__init__', '__slots__', '__getnewargs__',
'_fields', '_field_defaults', '_field_types',
- '_make', '_replace', '_asdict')
+ '_make', '_replace', '_asdict', '_source')
_special = ('__module__', '__name__', '__qualname__', '__annotations__')
diff --git a/Misc/NEWS b/Misc/NEWS
index 3b61543469..1c9026e77f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,10 @@ Core and Builtins
Library
-------
+- bpo-28556: Various updates to typing module: add typing.NoReturn type, use
+ WrapperDescriptorType, minor bug-fixes. Original PRs by
+ Jim Fasarakis-Hilliard and Ivan Levkivskyi.
+
- bpo-30205: Fix getsockname() for unbound AF_UNIX sockets on Linux.
- bpo-30070: Fixed leaks and crashes in errors handling in the parser module.
--
GitLab
From 833dcb62594cc7a834f63ac8f1c312f2ac24d393 Mon Sep 17 00:00:00 2001
From: Zachary Ware
Date: Wed, 3 May 2017 11:56:44 -0500
Subject: [PATCH 0182/1433] Bump version in AppVeyor config (GH-1436)
---
.github/appveyor.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/appveyor.yml b/.github/appveyor.yml
index a369e52415..a870e5b57d 100644
--- a/.github/appveyor.yml
+++ b/.github/appveyor.yml
@@ -1,4 +1,4 @@
-version: 3.6.1rc1+.{build}
+version: 3.6.1+.{build}
clone_depth: 5
build_script:
- cmd: PCbuild\build.bat -e
--
GitLab
From af71364c3f0e9cd6cb9d83194315af0ee3c783d2 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Wed, 3 May 2017 18:41:20 -0700
Subject: [PATCH 0183/1433] [3.6] bpo-28315: Improve code examples in docs
(GH-1372) (#1445)
Replace
File "", line 1, in ?
with
File "", line 1, in
(cherry picked from commit 8856940cf2e82cb17db2b684cd5732fe658605ca)
---
Doc/extending/newtypes.rst | 2 +-
Doc/howto/functional.rst | 6 +++---
Doc/library/ctypes.rst | 30 +++++++++++++++---------------
Doc/library/doctest.rst | 6 +++---
Doc/library/fpectl.rst | 2 +-
Doc/library/pdb.rst | 2 +-
Doc/library/unicodedata.rst | 2 +-
Doc/reference/expressions.rst | 2 +-
Doc/tutorial/classes.rst | 2 +-
Doc/tutorial/controlflow.rst | 2 +-
Doc/tutorial/datastructures.rst | 2 +-
Doc/tutorial/inputoutput.rst | 2 +-
12 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst
index b8ce437787..003b4e505d 100644
--- a/Doc/extending/newtypes.rst
+++ b/Doc/extending/newtypes.rst
@@ -124,7 +124,7 @@ our objects and in some error messages, for example::
>>> "" + noddy.new_noddy()
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
TypeError: cannot add type "noddy.Noddy" to string
Note that the name is a dotted name that includes both the module name and the
diff --git a/Doc/howto/functional.rst b/Doc/howto/functional.rst
index 8ae9679894..a82dca7077 100644
--- a/Doc/howto/functional.rst
+++ b/Doc/howto/functional.rst
@@ -210,7 +210,7 @@ You can experiment with the iteration interface manually:
3
>>> next(it)
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
StopIteration
>>>
@@ -474,7 +474,7 @@ Here's a sample usage of the ``generate_ints()`` generator:
2
>>> next(gen)
Traceback (most recent call last):
- File "stdin", line 1, in ?
+ File "stdin", line 1, in
File "stdin", line 2, in generate_ints
StopIteration
@@ -577,7 +577,7 @@ And here's an example of changing the counter:
9
>>> next(it) #doctest: +SKIP
Traceback (most recent call last):
- File "t.py", line 15, in ?
+ File "t.py", line 15, in
it.next()
StopIteration
diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst
index 51a3a360fa..47bf89f59a 100644
--- a/Doc/library/ctypes.rst
+++ b/Doc/library/ctypes.rst
@@ -97,7 +97,7 @@ Functions are accessed as attributes of dll objects::
<_FuncPtr object at 0x...>
>>> print(windll.kernel32.MyOwnFunction) # doctest: +WINDOWS
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
File "ctypes.py", line 239, in __getattr__
func = _StdcallFuncPtr(name, self)
AttributeError: function 'MyOwnFunction' not found
@@ -135,7 +135,7 @@ functions can be accessed by indexing the dll object with the ordinal number::
<_FuncPtr object at 0x...>
>>> cdll.kernel32[0] # doctest: +WINDOWS
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
File "ctypes.py", line 310, in __getitem__
func = _StdcallFuncPtr(name, self)
AttributeError: function ordinal 0 not found
@@ -168,11 +168,11 @@ although an error is raised the function *has* been called::
>>> windll.kernel32.GetModuleHandleA() # doctest: +WINDOWS
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
>>> windll.kernel32.GetModuleHandleA(0, 0) # doctest: +WINDOWS
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
>>>
@@ -181,13 +181,13 @@ The same exception is raised when you call an ``stdcall`` function with the
>>> cdll.kernel32.GetModuleHandleA(None) # doctest: +WINDOWS
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
>>>
>>> windll.msvcrt.printf(b"spam") # doctest: +WINDOWS
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
>>>
@@ -200,7 +200,7 @@ argument values::
>>> windll.kernel32.GetModuleHandleA(32) # doctest: +WINDOWS
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
OSError: exception: access violation reading 0x00000020
>>>
@@ -373,7 +373,7 @@ from within *IDLE* or *PythonWin*::
19
>>> printf(b"%f bottles of beer\n", 42.5)
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ArgumentError: argument 2: exceptions.TypeError: Don't know how to convert parameter 2
>>>
@@ -436,7 +436,7 @@ prototype for a C function), and tries to convert the arguments to valid types::
>>> printf(b"%d %d %d", 1, 2, 3)
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ArgumentError: argument 2: exceptions.TypeError: wrong type
>>> printf(b"%s %d %f\n", b"X", 2, 3)
X 2 3.000000
@@ -486,7 +486,7 @@ single character Python bytes object into a C char::
'def'
>>> strchr(b"abcdef", b"def")
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ArgumentError: argument 2: exceptions.TypeError: one character string expected
>>> print(strchr(b"abcdef", b"x"))
None
@@ -512,7 +512,7 @@ useful to check for error return values and automatically raise an exception::
486539264
>>> GetModuleHandle("something silly") # doctest: +WINDOWS
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
File "", line 3, in ValidHandle
OSError: [Errno 126] The specified module could not be found.
>>>
@@ -583,7 +583,7 @@ Here is a simple example of a POINT structure, which contains two integers named
0 5
>>> POINT(1, 2, 3)
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ValueError: too many initializers
>>>
@@ -786,7 +786,7 @@ new type::
>>> PI(42)
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
TypeError: expected c_long instead of int
>>> PI(c_int(42))
@@ -862,7 +862,7 @@ but not instances of other types::
>>> bar.values = (c_byte * 4)()
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance
>>>
@@ -913,7 +913,7 @@ work::
... ("next", POINTER(cell))]
...
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
File "", line 2, in cell
NameError: name 'cell' is not defined
>>>
diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst
index 15b12f7aa7..587a0a09a9 100644
--- a/Doc/library/doctest.rst
+++ b/Doc/library/doctest.rst
@@ -408,7 +408,7 @@ Simple example::
>>> [1, 2, 3].remove(42)
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ValueError: list.remove(x): x not in list
That doctest succeeds if :exc:`ValueError` is raised, with the ``list.remove(x):
@@ -432,7 +432,7 @@ multi-line detail::
>>> raise ValueError('multi\n line\ndetail')
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ValueError: multi
line
detail
@@ -591,7 +591,7 @@ doctest decides whether actual output matches an example's expected output:
>>> (1, 2)[3] = 'moo'
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
TypeError: object doesn't support item assignment
passes under Python 2.3 and later Python versions with the flag specified,
diff --git a/Doc/library/fpectl.rst b/Doc/library/fpectl.rst
index e4b528cf0b..96607165ba 100644
--- a/Doc/library/fpectl.rst
+++ b/Doc/library/fpectl.rst
@@ -89,7 +89,7 @@ The following example demonstrates how to start up and test operation of the
>>> import math
>>> math.exp(1000)
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
FloatingPointError: in math_1
diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst
index 7c37bb7d24..6225a3a1f0 100644
--- a/Doc/library/pdb.rst
+++ b/Doc/library/pdb.rst
@@ -76,7 +76,7 @@ The typical usage to inspect a crashed program is::
>>> import mymodule
>>> mymodule.test()
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
File "./mymodule.py", line 4, in test
test2()
File "./mymodule.py", line 3, in test2
diff --git a/Doc/library/unicodedata.rst b/Doc/library/unicodedata.rst
index 643180953f..2a97776095 100644
--- a/Doc/library/unicodedata.rst
+++ b/Doc/library/unicodedata.rst
@@ -158,7 +158,7 @@ Examples:
9
>>> unicodedata.decimal('a')
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ValueError: not a decimal
>>> unicodedata.category('A') # 'L'etter, 'u'ppercase
'Lu'
diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst
index c4f6c55c7c..43d2690cbb 100644
--- a/Doc/reference/expressions.rst
+++ b/Doc/reference/expressions.rst
@@ -905,7 +905,7 @@ keyword arguments (and any ``**expression`` arguments -- see below). So::
2 1
>>> f(a=1, *(2,))
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
TypeError: f() got multiple values for keyword argument 'a'
>>> f(1, *(2,))
1 2
diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst
index e134d5d62e..073444cf8b 100644
--- a/Doc/tutorial/classes.rst
+++ b/Doc/tutorial/classes.rst
@@ -784,7 +784,7 @@ using the :func:`next` built-in function; this example shows how it all works::
'c'
>>> next(it)
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
next(it)
StopIteration
diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst
index 6a9bb4889f..54171bc96f 100644
--- a/Doc/tutorial/controlflow.rst
+++ b/Doc/tutorial/controlflow.rst
@@ -475,7 +475,7 @@ Here's an example that fails due to this restriction::
...
>>> function(0, a=0)
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
TypeError: function() got multiple values for keyword argument 'a'
When a final formal parameter of the form ``**name`` is present, it receives a
diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst
index 6140ece046..1a73ac9d05 100644
--- a/Doc/tutorial/datastructures.rst
+++ b/Doc/tutorial/datastructures.rst
@@ -261,7 +261,7 @@ it must be parenthesized. ::
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # the tuple must be parenthesized, otherwise an error is raised
>>> [x, x**2 for x in range(6)]
- File "", line 1, in ?
+ File "", line 1, in
[x, x**2 for x in range(6)]
^
SyntaxError: invalid syntax
diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst
index beeaac36b9..bad0302b03 100644
--- a/Doc/tutorial/inputoutput.rst
+++ b/Doc/tutorial/inputoutput.rst
@@ -362,7 +362,7 @@ attempts to use the file object will automatically fail. ::
>>> f.close()
>>> f.read()
Traceback (most recent call last):
- File "", line 1, in ?
+ File "", line 1, in
ValueError: I/O operation on closed file
It is good practice to use the :keyword:`with` keyword when dealing with file
--
GitLab
From 1bebd8a21948652a5f941c550dec06ea84d1d979 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Thu, 4 May 2017 06:50:28 +0300
Subject: [PATCH 0184/1433] [3.6] bpo-30184: Add tests for invalid use of
PyArg_ParseTupleAndKeywords. (GH-1316). (#1441)
(cherry picked from commit 5f161fd86dd5bb936a1a2a13391b13b7e59ec201)
---
Lib/test/test_capi.py | 59 +++++++++++++++++++++++++++------------
Modules/_testcapimodule.c | 4 +--
2 files changed, 43 insertions(+), 20 deletions(-)
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index 08aa3ffdf6..216851c2d3 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -490,9 +490,8 @@ class SkipitemTest(unittest.TestCase):
# test the format unit when not skipped
format = c + "i"
try:
- # (note: the format string must be bytes!)
_testcapi.parse_tuple_and_keywords(tuple_1, dict_b,
- format.encode("ascii"), keywords)
+ format, keywords)
when_not_skipped = False
except SystemError as e:
s = "argument 1 (impossible)"
@@ -504,7 +503,7 @@ class SkipitemTest(unittest.TestCase):
optional_format = "|" + format
try:
_testcapi.parse_tuple_and_keywords(empty_tuple, dict_b,
- optional_format.encode("ascii"), keywords)
+ optional_format, keywords)
when_skipped = False
except SystemError as e:
s = "impossible: '{}'".format(format)
@@ -517,40 +516,64 @@ class SkipitemTest(unittest.TestCase):
self.assertIs(when_skipped, when_not_skipped, message)
def test_parse_tuple_and_keywords(self):
- # parse_tuple_and_keywords error handling tests
+ # Test handling errors in the parse_tuple_and_keywords helper itself
self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords,
(), {}, 42, [])
self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
- (), {}, b'', 42)
+ (), {}, '', 42)
self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
- (), {}, b'', [''] * 42)
+ (), {}, '', [''] * 42)
self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
- (), {}, b'', [42])
+ (), {}, '', [42])
+
+ def test_bad_use(self):
+ # Test handling invalid format and keywords in
+ # PyArg_ParseTupleAndKeywords()
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (1,), {}, '||O', ['a'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (1, 2), {}, '|O|O', ['a', 'b'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {'a': 1}, '$$O', ['a'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {'a': 1, 'b': 2}, '$O$O', ['a', 'b'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {'a': 1}, '$|O', ['a'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {'a': 1, 'b': 2}, '$O|O', ['a', 'b'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (1,), {}, '|O', ['a', 'b'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (1,), {}, '|OO', ['a'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {}, '|$O', [''])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {}, '|OO', ['a', ''])
def test_positional_only(self):
parse = _testcapi.parse_tuple_and_keywords
- parse((1, 2, 3), {}, b'OOO', ['', '', 'a'])
- parse((1, 2), {'a': 3}, b'OOO', ['', '', 'a'])
+ parse((1, 2, 3), {}, 'OOO', ['', '', 'a'])
+ parse((1, 2), {'a': 3}, 'OOO', ['', '', 'a'])
with self.assertRaisesRegex(TypeError,
r'Function takes at least 2 positional arguments \(1 given\)'):
- parse((1,), {'a': 3}, b'OOO', ['', '', 'a'])
- parse((1,), {}, b'O|OO', ['', '', 'a'])
+ parse((1,), {'a': 3}, 'OOO', ['', '', 'a'])
+ parse((1,), {}, 'O|OO', ['', '', 'a'])
with self.assertRaisesRegex(TypeError,
r'Function takes at least 1 positional arguments \(0 given\)'):
- parse((), {}, b'O|OO', ['', '', 'a'])
- parse((1, 2), {'a': 3}, b'OO$O', ['', '', 'a'])
+ parse((), {}, 'O|OO', ['', '', 'a'])
+ parse((1, 2), {'a': 3}, 'OO$O', ['', '', 'a'])
with self.assertRaisesRegex(TypeError,
r'Function takes exactly 2 positional arguments \(1 given\)'):
- parse((1,), {'a': 3}, b'OO$O', ['', '', 'a'])
- parse((1,), {}, b'O|O$O', ['', '', 'a'])
+ parse((1,), {'a': 3}, 'OO$O', ['', '', 'a'])
+ parse((1,), {}, 'O|O$O', ['', '', 'a'])
with self.assertRaisesRegex(TypeError,
r'Function takes at least 1 positional arguments \(0 given\)'):
- parse((), {}, b'O|O$O', ['', '', 'a'])
+ parse((), {}, 'O|O$O', ['', '', 'a'])
with self.assertRaisesRegex(SystemError, r'Empty parameter name after \$'):
- parse((1,), {}, b'O|$OO', ['', '', 'a'])
+ parse((1,), {}, 'O|$OO', ['', '', 'a'])
with self.assertRaisesRegex(SystemError, 'Empty keyword'):
- parse((1,), {}, b'O|OO', ['', 'a', ''])
+ parse((1,), {}, 'O|OO', ['', 'a', ''])
@unittest.skipUnless(threading, 'Threading required for this test.')
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index b25f4434ff..c76eefab4e 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -1571,7 +1571,7 @@ parse_tuple_and_keywords(PyObject *self, PyObject *args)
{
PyObject *sub_args;
PyObject *sub_kwargs;
- char *sub_format;
+ const char *sub_format;
PyObject *sub_keywords;
Py_ssize_t i, size;
@@ -1584,7 +1584,7 @@ parse_tuple_and_keywords(PyObject *self, PyObject *args)
double buffers[8][4]; /* double ensures alignment where necessary */
- if (!PyArg_ParseTuple(args, "OOyO:parse_tuple_and_keywords",
+ if (!PyArg_ParseTuple(args, "OOsO:parse_tuple_and_keywords",
&sub_args, &sub_kwargs,
&sub_format, &sub_keywords))
return NULL;
--
GitLab
From 31906b42fd71c6baaf80429005c720b40dfe8fae Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Thu, 4 May 2017 13:21:10 +0200
Subject: [PATCH 0185/1433] bpo-30225: Fix is_valid_fd() on macOS Tiger (#1443)
(#1449)
is_valid_fd() now uses fstat() instead of dup() on macOS to return 0
on a pipe when the other side of the pipe is closed. fstat() fails
with EBADF in that case, whereas dup() succeed.
(cherry picked from commit 1c4670ea0cc3d208121af11b9b973e6bb268e570)
---
Python/pylifecycle.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index af96d6d5fc..640271fd20 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -1044,6 +1044,14 @@ initsite(void)
static int
is_valid_fd(int fd)
{
+#ifdef __APPLE__
+ /* bpo-30225: On macOS Tiger, when stdout is redirected to a pipe
+ and the other side of the pipe is closed, dup(1) succeed, whereas
+ fstat(1, &st) fails with EBADF. Prefer fstat() over dup() to detect
+ such error. */
+ struct stat st;
+ return (fstat(fd, &st) == 0);
+#else
int fd2;
if (fd < 0)
return 0;
@@ -1056,6 +1064,7 @@ is_valid_fd(int fd)
close(fd2);
_Py_END_SUPPRESS_IPH
return fd2 >= 0;
+#endif
}
/* returns Py_None if the fd is not valid */
--
GitLab
From a7e48b544becc01dbf9059ed01f38997c6d0156c Mon Sep 17 00:00:00 2001
From: Antoine Pitrou
Date: Thu, 4 May 2017 17:12:35 +0200
Subject: [PATCH 0186/1433] [3.6] bpo-30185: avoid KeyboardInterrupt tracebacks
in forkserver (GH-1319) (#1454)
* bpo-30185: avoid KeyboardInterrupt tracebacks in forkserver
* Tweak comment.
(cherry picked from commit 6dd4d734ed207ba16b017e38f8909de7ef187e29)
---
Lib/multiprocessing/forkserver.py | 20 ++++++++++++++------
Misc/NEWS | 3 +++
2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/Lib/multiprocessing/forkserver.py b/Lib/multiprocessing/forkserver.py
index f2c179e4e0..d5ce625745 100644
--- a/Lib/multiprocessing/forkserver.py
+++ b/Lib/multiprocessing/forkserver.py
@@ -149,8 +149,15 @@ def main(listener_fd, alive_r, preload, main_path=None, sys_path=None):
util._close_stdin()
- # ignoring SIGCHLD means no need to reap zombie processes
- handler = signal.signal(signal.SIGCHLD, signal.SIG_IGN)
+ # ignoring SIGCHLD means no need to reap zombie processes;
+ # letting SIGINT through avoids KeyboardInterrupt tracebacks
+ handlers = {
+ signal.SIGCHLD: signal.SIG_IGN,
+ signal.SIGINT: signal.SIG_DFL,
+ }
+ old_handlers = {sig: signal.signal(sig, val)
+ for (sig, val) in handlers.items()}
+
with socket.socket(socket.AF_UNIX, fileno=listener_fd) as listener, \
selectors.DefaultSelector() as selector:
_forkserver._forkserver_address = listener.getsockname()
@@ -175,7 +182,7 @@ def main(listener_fd, alive_r, preload, main_path=None, sys_path=None):
code = 1
if os.fork() == 0:
try:
- _serve_one(s, listener, alive_r, handler)
+ _serve_one(s, listener, alive_r, old_handlers)
except Exception:
sys.excepthook(*sys.exc_info())
sys.stderr.flush()
@@ -186,11 +193,12 @@ def main(listener_fd, alive_r, preload, main_path=None, sys_path=None):
if e.errno != errno.ECONNABORTED:
raise
-def _serve_one(s, listener, alive_r, handler):
- # close unnecessary stuff and reset SIGCHLD handler
+def _serve_one(s, listener, alive_r, handlers):
+ # close unnecessary stuff and reset signal handlers
listener.close()
os.close(alive_r)
- signal.signal(signal.SIGCHLD, handler)
+ for sig, val in handlers.items():
+ signal.signal(sig, val)
# receive fds from parent process
fds = reduction.recvfds(s, MAXFDS_TO_SEND + 1)
diff --git a/Misc/NEWS b/Misc/NEWS
index 1c9026e77f..f0d5a3ba20 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,9 @@ Core and Builtins
Library
-------
+- bpo-30185: Avoid KeyboardInterrupt tracebacks in forkserver helper process
+ when Ctrl-C is received.
+
- bpo-28556: Various updates to typing module: add typing.NoReturn type, use
WrapperDescriptorType, minor bug-fixes. Original PRs by
Jim Fasarakis-Hilliard and Ivan Levkivskyi.
--
GitLab
From 9d02f562961efd12d3c8317a10916db7f77330cc Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Fri, 5 May 2017 00:46:56 +0200
Subject: [PATCH 0187/1433] [3.6] bpo-23404: make touch becomes make regen-all
(#1405) (#1461)
* bpo-23404: make touch becomes make regen-all (#1405)
Don't rebuild generated files based on file modification time
anymore, the action is now explicit. Replace "make touch"
with "make regen-all".
Changes:
* Remove "make touch", Tools/hg/hgtouch.py and .hgtouch
* Add a new "make regen-all" command to rebuild all generated files
* Add subcommands to only generate specific files:
- regen-ast: Include/Python-ast.h and Python/Python-ast.c
- regen-grammar: Include/graminit.h and Python/graminit.c
- regen-importlib: Python/importlib_external.h and Python/importlib.h
- regen-opcode: Include/opcode.h
- regen-opcode-targets: Python/opcode_targets.h
- regen-typeslots: Objects/typeslots.inc
* Rename PYTHON_FOR_GEN to PYTHON_FOR_REGEN
* pgen is now only built by by "make regen-grammar"
* Add $(srcdir)/ prefix to paths to source files to handle correctly
compilation outside the source directory
Note: $(PYTHON_FOR_REGEN) is no more used nor needed by "make"
default target building Python.
(cherry picked from commit a5c62a8e9f0de6c4133825a5710984a3cd5e102b)
* bpo-30273: Update sysconfig (#1464)
The AST_H_DIR variable was removed from Makefile.pre.in by the commit
a5c62a8e9f0de6c4133825a5710984a3cd5e102b (bpo-23404).
AST_H_DIR was hardcoded to "Include", so replace the removed variable
by its content.
Remove also ASDLGEN variable from sysconfig example since this
variable was also removed.
(cherry picked from commit b109a1d3360fc4bb87b9887264e3634632d392ca)
---
.hgtouch | 17 ----
Doc/library/sysconfig.rst | 1 -
Lib/distutils/sysconfig.py | 2 +-
Mac/BuildScript/build-installer.py | 4 -
Makefile.pre.in | 149 ++++++++++++++---------------
Misc/NEWS | 6 +-
Tools/hg/hgtouch.py | 129 -------------------------
configure | 32 +++----
configure.ac | 13 +--
9 files changed, 91 insertions(+), 262 deletions(-)
delete mode 100644 .hgtouch
delete mode 100644 Tools/hg/hgtouch.py
diff --git a/.hgtouch b/.hgtouch
deleted file mode 100644
index b9be0f11fd..0000000000
--- a/.hgtouch
+++ /dev/null
@@ -1,17 +0,0 @@
-# -*- Makefile -*-
-# Define dependencies of generated files that are checked into hg.
-# The syntax of this file uses make rule dependencies, without actions
-
-Python/importlib.h: Lib/importlib/_bootstrap.py Programs/_freeze_importlib.c
-
-Include/opcode.h: Lib/opcode.py Tools/scripts/generate_opcode_h.py
-
-Include/Python-ast.h: Parser/Python.asdl Parser/asdl.py Parser/asdl_c.py
-Python/Python-ast.c: Include/Python-ast.h
-
-Python/opcode_targets.h: Python/makeopcodetargets.py Lib/opcode.py
-
-Objects/typeslots.inc: Include/typeslots.h Objects/typeslots.py
-
-Include/graminit.h: Grammar/Grammar Parser/acceler.c Parser/grammar1.c Parser/listnode.c Parser/node.c Parser/parser.c Parser/bitset.c Parser/metagrammar.c Parser/firstsets.c Parser/grammar.c Parser/pgen.c Objects/obmalloc.c Python/dynamic_annotations.c Python/mysnprintf.c Python/pyctype.c Parser/tokenizer_pgen.c Parser/printgrammar.c Parser/parsetok_pgen.c Parser/pgenmain.c
-Python/graminit.c: Include/graminit.h Grammar/Grammar Parser/acceler.c Parser/grammar1.c Parser/listnode.c Parser/node.c Parser/parser.c Parser/bitset.c Parser/metagrammar.c Parser/firstsets.c Parser/grammar.c Parser/pgen.c Objects/obmalloc.c Python/dynamic_annotations.c Python/mysnprintf.c Python/pyctype.c Parser/tokenizer_pgen.c Parser/printgrammar.c Parser/parsetok_pgen.c Parser/pgenmain.c
diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst
index 08b74a9aff..f066a765d0 100644
--- a/Doc/library/sysconfig.rst
+++ b/Doc/library/sysconfig.rst
@@ -255,7 +255,6 @@ You can use :mod:`sysconfig` as a script with Python's *-m* option:
AIX_GENUINE_CPLUSPLUS = "0"
AR = "ar"
ARFLAGS = "rc"
- ASDLGEN = "./Parser/asdl_c.py"
...
This call will print in the standard output the information returned by
diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
index 8bf1a7016b..90004acea8 100644
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -97,7 +97,7 @@ def get_python_inc(plat_specific=0, prefix=None):
if plat_specific:
return base
if _sys_home:
- incdir = os.path.join(_sys_home, get_config_var('AST_H_DIR'))
+ incdir = os.path.join(_sys_home, 'Include')
else:
incdir = os.path.join(get_config_var('srcdir'), 'Include')
return os.path.normpath(incdir)
diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py
index f59ae34df2..7b4376f42b 100755
--- a/Mac/BuildScript/build-installer.py
+++ b/Mac/BuildScript/build-installer.py
@@ -1142,10 +1142,6 @@ def buildPython():
shellQuote(WORKDIR)[1:-1],
shellQuote(WORKDIR)[1:-1]))
- # bpo-29550: avoid using make touch until it is fixed for git
- # print("Running make touch")
- # runCommand("make touch")
-
print("Running make")
runCommand("make")
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 3eef424b30..6e3a82f95d 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -229,7 +229,7 @@ LIBOBJS= @LIBOBJS@
PYTHON= python$(EXE)
BUILDPYTHON= python$(BUILDEXE)
-PYTHON_FOR_GEN=@PYTHON_FOR_GEN@
+PYTHON_FOR_REGEN=@PYTHON_FOR_REGEN@
PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@
_PYTHON_HOST_PLATFORM=@_PYTHON_HOST_PLATFORM@
BUILD_GNU_TYPE= @build@
@@ -273,11 +273,6 @@ IO_OBJS= \
Modules/_io/stringio.o
##########################################################################
-# Grammar
-GRAMMAR_H= Include/graminit.h
-GRAMMAR_C= Python/graminit.c
-GRAMMAR_INPUT= $(srcdir)/Grammar/Grammar
-
LIBFFI_INCLUDEDIR= @LIBFFI_INCLUDEDIR@
@@ -316,38 +311,9 @@ PARSER_HEADERS= \
PGENOBJS= $(POBJS) $(PGOBJS)
-##########################################################################
-# opcode.h generation
-OPCODE_H_DIR= $(srcdir)/Include
-OPCODE_H_SCRIPT= $(srcdir)/Tools/scripts/generate_opcode_h.py
-OPCODE_H= $(OPCODE_H_DIR)/opcode.h
-OPCODE_H_GEN= $(PYTHON_FOR_GEN) $(OPCODE_H_SCRIPT) $(srcdir)/Lib/opcode.py $(OPCODE_H)
-
-##########################################################################
-# AST
-AST_H_DIR= Include
-AST_H= $(AST_H_DIR)/Python-ast.h
-AST_C_DIR= Python
-AST_C= $(AST_C_DIR)/Python-ast.c
-AST_ASDL= $(srcdir)/Parser/Python.asdl
-
-ASDLGEN_FILES= $(srcdir)/Parser/asdl.py $(srcdir)/Parser/asdl_c.py
-# Note that a build now requires Python to exist before the build starts.
-# Use "hg touch" to fix up screwed up file mtimes in a checkout.
-ASDLGEN= $(PYTHON_FOR_GEN) $(srcdir)/Parser/asdl_c.py
-
##########################################################################
# Python
-OPCODETARGETS_H= \
- Python/opcode_targets.h
-
-OPCODETARGETGEN= \
- $(srcdir)/Python/makeopcodetargets.py
-
-OPCODETARGETGEN_FILES= \
- $(OPCODETARGETGEN) $(srcdir)/Lib/opcode.py
-
PYTHON_OBJS= \
Python/_warnings.o \
Python/Python-ast.o \
@@ -547,7 +513,8 @@ coverage-lcov:
@echo "lcov report at $(COVERAGE_REPORT)/index.html"
@echo
-coverage-report:
+# Force regeneration of parser and importlib
+coverage-report: regen-grammar regen-importlib
: # force rebuilding of parser and importlib
@touch $(GRAMMAR_INPUT)
@touch $(srcdir)/Lib/importlib/_bootstrap.py
@@ -723,14 +690,24 @@ Programs/_freeze_importlib.o: Programs/_freeze_importlib.c Makefile
Programs/_freeze_importlib: Programs/_freeze_importlib.o $(LIBRARY_OBJS_OMIT_FROZEN)
$(LINKCC) $(PY_LDFLAGS) -o $@ Programs/_freeze_importlib.o $(LIBRARY_OBJS_OMIT_FROZEN) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
-Python/importlib_external.h: @GENERATED_COMMENT@ $(srcdir)/Lib/importlib/_bootstrap_external.py Programs/_freeze_importlib Python/marshal.c
+.PHONY: regen-importlib
+regen-importlib: Programs/_freeze_importlib
+ # Regenerate Python/importlib_external.h
+ # from Lib/importlib/_bootstrap_external.py using _freeze_importlib
./Programs/_freeze_importlib \
- $(srcdir)/Lib/importlib/_bootstrap_external.py Python/importlib_external.h
-
-Python/importlib.h: @GENERATED_COMMENT@ $(srcdir)/Lib/importlib/_bootstrap.py Programs/_freeze_importlib Python/marshal.c
+ $(srcdir)/Lib/importlib/_bootstrap_external.py \
+ $(srcdir)/Python/importlib_external.h
+ # Regenerate Python/importlib.h from Lib/importlib/_bootstrap.py
+ # using _freeze_importlib
./Programs/_freeze_importlib \
- $(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h
+ $(srcdir)/Lib/importlib/_bootstrap.py \
+ $(srcdir)/Python/importlib.h
+
+
+############################################################################
+# Regenerate all generated files
+regen-all: regen-opcode regen-opcode-targets regen-typeslots regen-grammar regen-ast regen-importlib
############################################################################
# Special rules for object files
@@ -789,15 +766,18 @@ Python/sysmodule.o: $(srcdir)/Python/sysmodule.c Makefile
$(IO_OBJS): $(IO_H)
-$(GRAMMAR_H): @GENERATED_COMMENT@ $(GRAMMAR_INPUT) $(PGEN)
- @$(MKDIR_P) Include
- $(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C)
-$(GRAMMAR_C): @GENERATED_COMMENT@ $(GRAMMAR_H)
- touch $(GRAMMAR_C)
-
$(PGEN): $(PGENOBJS)
$(CC) $(OPT) $(PY_LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN)
+.PHONY: regen-grammar
+regen-grammar: $(PGEN)
+ # Regenerate Include/graminit.h and Python/graminit.c
+ # from Grammar/Grammar using pgen
+ @$(MKDIR_P) Include
+ $(PGEN) $(srcdir)/Grammar/Grammar \
+ $(srcdir)/Include/graminit.h \
+ $(srcdir)/Python/graminit.c
+
Parser/grammar.o: $(srcdir)/Parser/grammar.c \
$(srcdir)/Include/token.h \
$(srcdir)/Include/grammar.h
@@ -809,18 +789,28 @@ Parser/printgrammar.o: $(srcdir)/Parser/printgrammar.c
Parser/pgenmain.o: $(srcdir)/Include/parsetok.h
-$(AST_H): $(AST_ASDL) $(ASDLGEN_FILES)
- $(MKDIR_P) $(AST_H_DIR)
- $(ASDLGEN) -h $(AST_H_DIR) $(AST_ASDL)
-
-$(AST_C): $(AST_H) $(AST_ASDL) $(ASDLGEN_FILES)
- $(MKDIR_P) $(AST_C_DIR)
- $(ASDLGEN) -c $(AST_C_DIR) $(AST_ASDL)
-
-$(OPCODE_H): $(srcdir)/Lib/opcode.py $(OPCODE_H_SCRIPT)
- $(OPCODE_H_GEN)
-
-Python/compile.o Python/symtable.o Python/ast.o: $(GRAMMAR_H) $(AST_H)
+.PHONY=regen-ast
+regen-ast:
+ # Regenerate Include/Python-ast.h using Parser/asdl_c.py -h
+ $(MKDIR_P) $(srcdir)/Include
+ $(PYTHON_FOR_REGEN) $(srcdir)/Parser/asdl_c.py \
+ -h $(srcdir)/Include \
+ $(srcdir)/Parser/Python.asdl
+ # Regenerate Python/Python-ast.c using Parser/asdl_c.py -c
+ $(MKDIR_P) $(srcdir)/Python
+ $(PYTHON_FOR_REGEN) $(srcdir)/Parser/asdl_c.py \
+ -c $(srcdir)/Python \
+ $(srcdir)/Parser/Python.asdl
+
+.PHONY: regen-opcode
+regen-opcode:
+ # Regenerate Include/opcode.h from Lib/opcode.py
+ # using Tools/scripts/generate_opcode_h.py
+ $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/generate_opcode_h.py \
+ $(srcdir)/Lib/opcode.py \
+ $(srcdir)/Include/opcode.h
+
+Python/compile.o Python/symtable.o Python/ast.o: $(srcdir)/Include/graminit.h $(srcdir)/Include/Python-ast.h
Python/getplatform.o: $(srcdir)/Python/getplatform.c
$(CC) -c $(PY_CORE_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c
@@ -870,12 +860,16 @@ Objects/odictobject.o: $(srcdir)/Objects/dict-common.h
Objects/dictobject.o: $(srcdir)/Objects/stringlib/eq.h $(srcdir)/Objects/dict-common.h
Objects/setobject.o: $(srcdir)/Objects/stringlib/eq.h
-$(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)
- $(PYTHON_FOR_GEN) $(OPCODETARGETGEN) $(OPCODETARGETS_H)
+.PHONY: regen-opcode-targets
+regen-opcode-targets:
+ # Regenerate Python/opcode_targets.h from Lib/opcode.py
+ # using Python/makeopcodetargets.py
+ $(PYTHON_FOR_REGEN) $(srcdir)/Python/makeopcodetargets.py \
+ $(srcdir)/Python/opcode_targets.h
-Python/ceval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h
+Python/ceval.o: $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/ceval_gil.h
-Python/frozen.o: Python/importlib.h Python/importlib_external.h
+Python/frozen.o: $(srcdir)/Python/importlib.h $(srcdir)/Python/importlib_external.h
# Generate DTrace probe macros, then rename them (PYTHON_ -> PyDTrace_) to
# follow our naming conventions. dtrace(1) uses the output filename to generate
@@ -890,8 +884,14 @@ Python/pydtrace.o: $(srcdir)/Include/pydtrace.d $(DTRACE_DEPS)
$(DTRACE) $(DFLAGS) -o $@ -G -s $< $(DTRACE_DEPS)
Objects/typeobject.o: Objects/typeslots.inc
-Objects/typeslots.inc: $(srcdir)/Include/typeslots.h $(srcdir)/Objects/typeslots.py
- $(PYTHON_FOR_GEN) $(srcdir)/Objects/typeslots.py < $(srcdir)/Include/typeslots.h Objects/typeslots.inc
+
+.PHONY: regen-typeslots
+regen-typeslots:
+ # Regenerate Objects/typeslots.inc from Include/typeslotsh
+ # using Objects/typeslots.py
+ $(PYTHON_FOR_REGEN) $(srcdir)/Objects/typeslots.py \
+ < $(srcdir)/Include/typeslots.h \
+ $(srcdir)/Objects/typeslots.inc
############################################################################
# Header files
@@ -944,7 +944,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/node.h \
$(srcdir)/Include/object.h \
$(srcdir)/Include/objimpl.h \
- $(OPCODE_H) \
+ $(srcdir)/Include/opcode.h \
$(srcdir)/Include/osdefs.h \
$(srcdir)/Include/osmodule.h \
$(srcdir)/Include/patchlevel.h \
@@ -987,7 +987,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/weakrefobject.h \
pyconfig.h \
$(PARSER_HEADERS) \
- $(AST_H) \
+ $(srcdir)/Include/Python-ast.h \
$(DTRACE_HEADERS)
$(LIBRARY_OBJS) $(MODOBJS) Programs/python.o: $(PYTHON_HEADERS)
@@ -1554,9 +1554,12 @@ recheck:
$(SHELL) config.status --recheck
$(SHELL) config.status
-# Rebuild the configure script from configure.ac; also rebuild pyconfig.h.in
+# Regenerate configure and pyconfig.h.in
+.PHONY: autoconf
autoconf:
+ # Regenerate the configure script from configure.ac using autoconf
(cd $(srcdir); autoconf -Wall)
+ # Regenerate pyconfig.h.in from configure.ac using autoheader
(cd $(srcdir); autoheader -Wall)
# Create a tags file for vi
@@ -1573,14 +1576,6 @@ TAGS::
etags Include/*.h; \
for i in $(SRCDIRS); do etags -a $$i/*.[ch]; done
-# This fixes up the mtimes of checked-in generated files, assuming that they
-# only *appear* to be outdated because of checkout order.
-# This is run while preparing a source release tarball, and can be run manually
-# to avoid bootstrap issues.
-touch:
- cd $(srcdir); \
- hg --config extensions.touch=Tools/hg/hgtouch.py touch -v
-
# Sanitation targets -- clean leaves libraries, executables and tags
# files, which clobber removes as well
pycremoval:
@@ -1698,7 +1693,7 @@ Python/thread.o: @THREADHEADERS@
.PHONY: maninstall libinstall inclinstall libainstall sharedinstall
.PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure
.PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools
-.PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean
+.PHONY: frameworkaltinstallunixtools recheck clean clobber distclean
.PHONY: smelly funny patchcheck touch altmaninstall commoninstall
.PHONY: gdbhooks
diff --git a/Misc/NEWS b/Misc/NEWS
index f0d5a3ba20..6913bfc8b7 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,7 +10,7 @@ What's New in Python 3.6.2 release candidate 1?
Core and Builtins
-----------------
-- bpo-12414: sys.getsizeof() on a code object now returns the sizes
+- bpo-12414: sys.getsizeof() on a code object now returns the sizes
which includes the code struct and sizes of objects which it references.
Patch by Dong-hee Na.
@@ -116,6 +116,10 @@ Library
Build
-----
+- bpo-23404: Don't regenerate generated files based on file modification time
+ anymore: the action is now explicit. Replace ``make touch`` with
+ ``make regen-all``.
+
- bpo-29643: Fix ``--enable-optimization`` didn't work.
Documentation
diff --git a/Tools/hg/hgtouch.py b/Tools/hg/hgtouch.py
deleted file mode 100644
index fbca469ba9..0000000000
--- a/Tools/hg/hgtouch.py
+++ /dev/null
@@ -1,129 +0,0 @@
-"""Bring time stamps of generated checked-in files into the right order
-
-A versioned configuration file .hgtouch specifies generated files, in the
-syntax of make rules.
-
- output: input1 input2
-
-In addition to the dependency syntax, #-comments are supported.
-"""
-import errno
-import os
-import time
-
-def parse_config(repo):
- try:
- fp = repo.wfile(".hgtouch")
- except IOError, e:
- if e.errno != errno.ENOENT:
- raise
- return {}
- result = {}
- with fp:
- for line in fp:
- # strip comments
- line = line.split('#')[0].strip()
- if ':' not in line:
- continue
- outputs, inputs = line.split(':', 1)
- outputs = outputs.split()
- inputs = inputs.split()
- for o in outputs:
- try:
- result[o].extend(inputs)
- except KeyError:
- result[o] = inputs
- return result
-
-def check_rule(ui, repo, modified, basedir, output, inputs):
- """Verify that the output is newer than any of the inputs.
- Return (status, stamp), where status is True if the update succeeded,
- and stamp is the newest time stamp assigned to any file (might be in
- the future).
-
- If basedir is nonempty, it gives a directory in which the tree is to
- be checked.
- """
- f_output = repo.wjoin(os.path.join(basedir, output))
- try:
- o_time = os.stat(f_output).st_mtime
- except OSError:
- ui.warn("Generated file %s does not exist\n" % output)
- return False, 0
- youngest = 0 # youngest dependency
- backdate = None
- backdate_source = None
- for i in inputs:
- f_i = repo.wjoin(os.path.join(basedir, i))
- try:
- i_time = os.stat(f_i).st_mtime
- except OSError:
- ui.warn(".hgtouch input file %s does not exist\n" % i)
- return False, 0
- if i in modified:
- # input is modified. Need to backdate at least to i_time
- if backdate is None or backdate > i_time:
- backdate = i_time
- backdate_source = i
- continue
- youngest = max(i_time, youngest)
- if backdate is not None:
- ui.warn("Input %s for file %s locally modified\n" % (backdate_source, output))
- # set to 1s before oldest modified input
- backdate -= 1
- os.utime(f_output, (backdate, backdate))
- return False, 0
- if youngest >= o_time:
- ui.note("Touching %s\n" % output)
- youngest += 1
- os.utime(f_output, (youngest, youngest))
- return True, youngest
- else:
- # Nothing to update
- return True, 0
-
-def do_touch(ui, repo, basedir):
- if basedir:
- if not os.path.isdir(repo.wjoin(basedir)):
- ui.warn("Abort: basedir %r does not exist\n" % basedir)
- return
- modified = []
- else:
- modified = repo.status()[0]
- dependencies = parse_config(repo)
- success = True
- tstamp = 0 # newest time stamp assigned
- # try processing all rules in topological order
- hold_back = {}
- while dependencies:
- output, inputs = dependencies.popitem()
- # check whether any of the inputs is generated
- for i in inputs:
- if i in dependencies:
- hold_back[output] = inputs
- continue
- _success, _tstamp = check_rule(ui, repo, modified, basedir, output, inputs)
- success = success and _success
- tstamp = max(tstamp, _tstamp)
- # put back held back rules
- dependencies.update(hold_back)
- hold_back = {}
- now = time.time()
- if tstamp > now:
- # wait until real time has passed the newest time stamp, to
- # avoid having files dated in the future
- time.sleep(tstamp-now)
- if hold_back:
- ui.warn("Cyclic dependency involving %s\n" % (' '.join(hold_back.keys())))
- return False
- return success
-
-def touch(ui, repo, basedir):
- "touch generated files that are older than their sources after an update."
- do_touch(ui, repo, basedir)
-
-cmdtable = {
- "touch": (touch,
- [('b', 'basedir', '', 'base dir of the tree to apply touching')],
- "hg touch [-b BASEDIR]")
-}
diff --git a/configure b/configure
index 3c611d6afa..97d3301f8e 100755
--- a/configure
+++ b/configure
@@ -750,9 +750,8 @@ UNIVERSALSDK
CONFIG_ARGS
SOVERSION
VERSION
-GENERATED_COMMENT
PYTHON_FOR_BUILD
-PYTHON_FOR_GEN
+PYTHON_FOR_REGEN
host_os
host_vendor
host_cpu
@@ -2881,11 +2880,11 @@ do
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_PYTHON_FOR_GEN+:} false; then :
+if ${ac_cv_prog_PYTHON_FOR_REGEN+:} false; then :
$as_echo_n "(cached) " >&6
else
- if test -n "$PYTHON_FOR_GEN"; then
- ac_cv_prog_PYTHON_FOR_GEN="$PYTHON_FOR_GEN" # Let the user override the test.
+ if test -n "$PYTHON_FOR_REGEN"; then
+ ac_cv_prog_PYTHON_FOR_REGEN="$PYTHON_FOR_REGEN" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
@@ -2894,7 +2893,7 @@ do
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_PYTHON_FOR_GEN="$ac_prog"
+ ac_cv_prog_PYTHON_FOR_REGEN="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
@@ -2904,25 +2903,20 @@ IFS=$as_save_IFS
fi
fi
-PYTHON_FOR_GEN=$ac_cv_prog_PYTHON_FOR_GEN
-if test -n "$PYTHON_FOR_GEN"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_FOR_GEN" >&5
-$as_echo "$PYTHON_FOR_GEN" >&6; }
+PYTHON_FOR_REGEN=$ac_cv_prog_PYTHON_FOR_REGEN
+if test -n "$PYTHON_FOR_REGEN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_FOR_REGEN" >&5
+$as_echo "$PYTHON_FOR_REGEN" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
- test -n "$PYTHON_FOR_GEN" && break
+ test -n "$PYTHON_FOR_REGEN" && break
done
-test -n "$PYTHON_FOR_GEN" || PYTHON_FOR_GEN="not-found"
+test -n "$PYTHON_FOR_REGEN" || PYTHON_FOR_REGEN="python3"
-if test "$PYTHON_FOR_GEN" = not-found; then
- PYTHON_FOR_GEN='@echo "Cannot generate $@, python not found !" && \
- echo "To skip re-generation of $@ run or ." && \
- echo "Otherwise, set python in PATH and run configure or run ." && false &&'
-fi
if test "$cross_compiling" = yes; then
@@ -2943,18 +2937,14 @@ $as_echo_n "checking for python interpreter for cross build... " >&6; }
$as_echo "$interp" >&6; }
PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$interp
fi
- # Used to comment out stuff for rebuilding generated files
- GENERATED_COMMENT='#'
elif test "$cross_compiling" = maybe; then
as_fn_error $? "Cross compiling required --host=HOST-TUPLE and --build=ARCH" "$LINENO" 5
else
PYTHON_FOR_BUILD='./$(BUILDPYTHON) -E'
- GENERATED_COMMENT=''
fi
-
if test "$prefix" != "/"; then
prefix=`echo "$prefix" | sed -e 's/\/$//g'`
fi
diff --git a/configure.ac b/configure.ac
index eda075dc75..8abf2f96cc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -56,13 +56,8 @@ AC_SUBST(host)
# pybuilddir.txt will be created by --generate-posix-vars in the Makefile
rm -f pybuilddir.txt
-AC_CHECK_PROGS(PYTHON_FOR_GEN, python$PACKAGE_VERSION python3 python, not-found)
-if test "$PYTHON_FOR_GEN" = not-found; then
- PYTHON_FOR_GEN='@echo "Cannot generate $@, python not found !" && \
- echo "To skip re-generation of $@ run or ." && \
- echo "Otherwise, set python in PATH and run configure or run ." && false &&'
-fi
-AC_SUBST(PYTHON_FOR_GEN)
+AC_CHECK_PROGS(PYTHON_FOR_REGEN, python$PACKAGE_VERSION python3 python, python3)
+AC_SUBST(PYTHON_FOR_REGEN)
if test "$cross_compiling" = yes; then
AC_MSG_CHECKING([for python interpreter for cross build])
@@ -80,16 +75,12 @@ if test "$cross_compiling" = yes; then
AC_MSG_RESULT($interp)
PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$interp
fi
- # Used to comment out stuff for rebuilding generated files
- GENERATED_COMMENT='#'
elif test "$cross_compiling" = maybe; then
AC_MSG_ERROR([Cross compiling required --host=HOST-TUPLE and --build=ARCH])
else
PYTHON_FOR_BUILD='./$(BUILDPYTHON) -E'
- GENERATED_COMMENT=''
fi
AC_SUBST(PYTHON_FOR_BUILD)
-AC_SUBST(GENERATED_COMMENT)
dnl Ensure that if prefix is specified, it does not end in a slash. If
dnl it does, we get path names containing '//' which is both ugly and
--
GitLab
From 39b73dd5131ce205dcee3b9e24ba0fc28934d79c Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Fri, 5 May 2017 10:40:30 +0300
Subject: [PATCH 0188/1433] [3.6] bpo-30243: Fixed the possibility of a crash
in _json. (GH-1420) (#1469)
It was possible to get a core dump by using uninitialized
_json objects. Now __new__ methods create initialized objects.
__init__ methods are removed..
(cherry picked from commit 76a3e51a403bc84ed536921866c86dd7d07aaa7e)
---
Misc/NEWS | 4 +++
Modules/_json.c | 86 ++++++++++++-------------------------------------
2 files changed, 24 insertions(+), 66 deletions(-)
diff --git a/Misc/NEWS b/Misc/NEWS
index 6913bfc8b7..0a2e5eb397 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,10 @@ Core and Builtins
Library
-------
+- bpo-30243: Removed the __init__ methods of _json's scanner and encoder.
+ Misusing them could cause memory leaks or crashes. Now scanner and encoder
+ objects are completely initialized in the __new__ methods.
+
- bpo-30185: Avoid KeyboardInterrupt tracebacks in forkserver helper process
when Ctrl-C is received.
diff --git a/Modules/_json.c b/Modules/_json.c
index faa213491b..a84b085109 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -89,16 +89,12 @@ static PyObject *
_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
static PyObject *
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-static int
-scanner_init(PyObject *self, PyObject *args, PyObject *kwds);
static void
scanner_dealloc(PyObject *self);
static int
scanner_clear(PyObject *self);
static PyObject *
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-static int
-encoder_init(PyObject *self, PyObject *args, PyObject *kwds);
static void
encoder_dealloc(PyObject *self);
static int
@@ -1203,38 +1199,21 @@ static PyObject *
scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyScannerObject *s;
- s = (PyScannerObject *)type->tp_alloc(type, 0);
- if (s != NULL) {
- s->strict = NULL;
- s->object_hook = NULL;
- s->object_pairs_hook = NULL;
- s->parse_float = NULL;
- s->parse_int = NULL;
- s->parse_constant = NULL;
- }
- return (PyObject *)s;
-}
-
-static int
-scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- /* Initialize Scanner object */
PyObject *ctx;
static char *kwlist[] = {"context", NULL};
- PyScannerObject *s;
-
- assert(PyScanner_Check(self));
- s = (PyScannerObject *)self;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
- return -1;
+ return NULL;
- if (s->memo == NULL) {
- s->memo = PyDict_New();
- if (s->memo == NULL)
- goto bail;
+ s = (PyScannerObject *)type->tp_alloc(type, 0);
+ if (s == NULL) {
+ return NULL;
}
+ s->memo = PyDict_New();
+ if (s->memo == NULL)
+ goto bail;
+
/* All of these will fail "gracefully" so we don't need to verify them */
s->strict = PyObject_GetAttrString(ctx, "strict");
if (s->strict == NULL)
@@ -1255,16 +1234,11 @@ scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
if (s->parse_constant == NULL)
goto bail;
- return 0;
+ return (PyObject *)s;
bail:
- Py_CLEAR(s->strict);
- Py_CLEAR(s->object_hook);
- Py_CLEAR(s->object_pairs_hook);
- Py_CLEAR(s->parse_float);
- Py_CLEAR(s->parse_int);
- Py_CLEAR(s->parse_constant);
- return -1;
+ Py_DECREF(s);
+ return NULL;
}
PyDoc_STRVAR(scanner_doc, "JSON scanner object");
@@ -1306,7 +1280,7 @@ PyTypeObject PyScannerType = {
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
- scanner_init, /* tp_init */
+ 0, /* tp_init */
0,/* PyType_GenericAlloc, */ /* tp_alloc */
scanner_new, /* tp_new */
0,/* PyObject_GC_Del, */ /* tp_free */
@@ -1315,25 +1289,6 @@ PyTypeObject PyScannerType = {
static PyObject *
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- PyEncoderObject *s;
- s = (PyEncoderObject *)type->tp_alloc(type, 0);
- if (s != NULL) {
- s->markers = NULL;
- s->defaultfn = NULL;
- s->encoder = NULL;
- s->indent = NULL;
- s->key_separator = NULL;
- s->item_separator = NULL;
- s->sort_keys = NULL;
- s->skipkeys = NULL;
- }
- return (PyObject *)s;
-}
-
-static int
-encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- /* initialize Encoder object */
static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL};
PyEncoderObject *s;
@@ -1341,22 +1296,23 @@ encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
PyObject *item_separator, *sort_keys, *skipkeys;
int allow_nan;
- assert(PyEncoder_Check(self));
- s = (PyEncoderObject *)self;
-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist,
&markers, &defaultfn, &encoder, &indent,
&key_separator, &item_separator,
&sort_keys, &skipkeys, &allow_nan))
- return -1;
+ return NULL;
if (markers != Py_None && !PyDict_Check(markers)) {
PyErr_Format(PyExc_TypeError,
"make_encoder() argument 1 must be dict or None, "
"not %.200s", Py_TYPE(markers)->tp_name);
- return -1;
+ return NULL;
}
+ s = (PyEncoderObject *)type->tp_alloc(type, 0);
+ if (s == NULL)
+ return NULL;
+
s->markers = markers;
s->defaultfn = defaultfn;
s->encoder = encoder;
@@ -1383,7 +1339,7 @@ encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
Py_INCREF(s->item_separator);
Py_INCREF(s->sort_keys);
Py_INCREF(s->skipkeys);
- return 0;
+ return (PyObject *)s;
}
static PyObject *
@@ -1914,7 +1870,7 @@ PyTypeObject PyEncoderType = {
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
- encoder_init, /* tp_init */
+ 0, /* tp_init */
0, /* tp_alloc */
encoder_new, /* tp_new */
0, /* tp_free */
@@ -1957,10 +1913,8 @@ PyInit__json(void)
PyObject *m = PyModule_Create(&jsonmodule);
if (!m)
return NULL;
- PyScannerType.tp_new = PyType_GenericNew;
if (PyType_Ready(&PyScannerType) < 0)
goto fail;
- PyEncoderType.tp_new = PyType_GenericNew;
if (PyType_Ready(&PyEncoderType) < 0)
goto fail;
Py_INCREF((PyObject*)&PyScannerType);
--
GitLab
From 0fe870f3f95ba883b2b06bc0d814bdab8d53df98 Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Fri, 5 May 2017 10:04:57 +0200
Subject: [PATCH 0189/1433] bpo-30264: ExpatParser closes the source on error
(#1451) (#1474)
ExpatParser.parse() of xml.sax.xmlreader now always closes the
source: close the file object or the urllib object if source is a
string (not an open file-like object). The change fixes a
ResourceWarning on parsing error.
Add test_parse_close_source() unit test.
(cherry picked from commit ef9c0e732fc50aefbdd7c5a80e04e14b31684e66)
---
Lib/test/test_sax.py | 24 ++++++++++++++++++------
Lib/xml/sax/expatreader.py | 33 ++++++++++++++++++++++-----------
2 files changed, 40 insertions(+), 17 deletions(-)
diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py
index 2411895d9d..2eb62905ff 100644
--- a/Lib/test/test_sax.py
+++ b/Lib/test/test_sax.py
@@ -4,6 +4,7 @@
from xml.sax import make_parser, ContentHandler, \
SAXException, SAXReaderNotAvailable, SAXParseException
import unittest
+from unittest import mock
try:
make_parser()
except SAXReaderNotAvailable:
@@ -175,12 +176,8 @@ class ParseTest(unittest.TestCase):
with self.assertRaises(SAXException):
self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1', None)))
make_xml_file(self.data, 'iso-8859-1', None)
- with support.check_warnings(('unclosed file', ResourceWarning)):
- # XXX Failed parser leaks an opened file.
- with self.assertRaises(SAXException):
- self.check_parse(TESTFN)
- # Collect leaked file.
- gc.collect()
+ with self.assertRaises(SAXException):
+ self.check_parse(TESTFN)
with open(TESTFN, 'rb') as f:
with self.assertRaises(SAXException):
self.check_parse(f)
@@ -194,6 +191,21 @@ class ParseTest(unittest.TestCase):
input.setEncoding('iso-8859-1')
self.check_parse(input)
+ def test_parse_close_source(self):
+ builtin_open = open
+ fileobj = None
+
+ def mock_open(*args):
+ nonlocal fileobj
+ fileobj = builtin_open(*args)
+ return fileobj
+
+ with mock.patch('xml.sax.saxutils.open', side_effect=mock_open):
+ make_xml_file(self.data, 'iso-8859-1', None)
+ with self.assertRaises(SAXException):
+ self.check_parse(TESTFN)
+ self.assertTrue(fileobj.closed)
+
def check_parseString(self, s):
from xml.sax import parseString
result = StringIO()
diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py
index 98b5ca9539..421358fa5b 100644
--- a/Lib/xml/sax/expatreader.py
+++ b/Lib/xml/sax/expatreader.py
@@ -105,9 +105,16 @@ class ExpatParser(xmlreader.IncrementalParser, xmlreader.Locator):
source = saxutils.prepare_input_source(source)
self._source = source
- self.reset()
- self._cont_handler.setDocumentLocator(ExpatLocator(self))
- xmlreader.IncrementalParser.parse(self, source)
+ try:
+ self.reset()
+ self._cont_handler.setDocumentLocator(ExpatLocator(self))
+ xmlreader.IncrementalParser.parse(self, source)
+ except:
+ # bpo-30264: Close the source on error to not leak resources:
+ # xml.sax.parse() doesn't give access to the underlying parser
+ # to the caller
+ self._close_source()
+ raise
def prepareParser(self, source):
if source.getSystemId() is not None:
@@ -213,6 +220,17 @@ class ExpatParser(xmlreader.IncrementalParser, xmlreader.Locator):
# FIXME: when to invoke error()?
self._err_handler.fatalError(exc)
+ def _close_source(self):
+ source = self._source
+ try:
+ file = source.getCharacterStream()
+ if file is not None:
+ file.close()
+ finally:
+ file = source.getByteStream()
+ if file is not None:
+ file.close()
+
def close(self):
if (self._entity_stack or self._parser is None or
isinstance(self._parser, _ClosedParser)):
@@ -232,14 +250,7 @@ class ExpatParser(xmlreader.IncrementalParser, xmlreader.Locator):
parser.ErrorColumnNumber = self._parser.ErrorColumnNumber
parser.ErrorLineNumber = self._parser.ErrorLineNumber
self._parser = parser
- try:
- file = self._source.getCharacterStream()
- if file is not None:
- file.close()
- finally:
- file = self._source.getByteStream()
- if file is not None:
- file.close()
+ self._close_source()
def _reset_cont_handler(self):
self._parser.ProcessingInstructionHandler = \
--
GitLab
From 70dc6a7a0b7f104d87512556fca242c2ca96a010 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Sat, 6 May 2017 15:10:50 +0300
Subject: [PATCH 0190/1433] [3.6] Revert bpo-26293 for zipfile breakage. See
also bpo-29094. (GH-1484). (#1485)
(cherry picked from commit 3763ea865cee5bbabcce11cd577811135e0fc747)
---
Lib/zipfile.py | 27 +++++++++++++--------------
Misc/NEWS | 2 ++
2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index 06eedec340..9164f8ab08 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -1110,7 +1110,6 @@ class ZipFile:
# set the modified flag so central directory gets written
# even if no files are added to the archive
self._didModify = True
- self._start_disk = 0
try:
self.start_dir = self.fp.tell()
except (AttributeError, OSError):
@@ -1136,7 +1135,7 @@ class ZipFile:
# set the modified flag so central directory gets written
# even if no files are added to the archive
self._didModify = True
- self.start_dir = self._start_disk = self.fp.tell()
+ self.start_dir = self.fp.tell()
else:
raise ValueError("Mode must be 'r', 'w', 'x', or 'a'")
except:
@@ -1180,18 +1179,17 @@ class ZipFile:
offset_cd = endrec[_ECD_OFFSET] # offset of central directory
self._comment = endrec[_ECD_COMMENT] # archive comment
- # self._start_disk: Position of the start of ZIP archive
- # It is zero, unless ZIP was concatenated to another file
- self._start_disk = endrec[_ECD_LOCATION] - size_cd - offset_cd
+ # "concat" is zero, unless zip was concatenated to another file
+ concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
if endrec[_ECD_SIGNATURE] == stringEndArchive64:
# If Zip64 extension structures are present, account for them
- self._start_disk -= (sizeEndCentDir64 + sizeEndCentDir64Locator)
+ concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator)
if self.debug > 2:
- inferred = self._start_disk + offset_cd
- print("given, inferred, offset", offset_cd, inferred, self._start_disk)
+ inferred = concat + offset_cd
+ print("given, inferred, offset", offset_cd, inferred, concat)
# self.start_dir: Position of start of central directory
- self.start_dir = offset_cd + self._start_disk
+ self.start_dir = offset_cd + concat
fp.seek(self.start_dir, 0)
data = fp.read(size_cd)
fp = io.BytesIO(data)
@@ -1231,7 +1229,7 @@ class ZipFile:
t>>11, (t>>5)&0x3F, (t&0x1F) * 2 )
x._decodeExtra()
- x.header_offset = x.header_offset + self._start_disk
+ x.header_offset = x.header_offset + concat
self.filelist.append(x)
self.NameToInfo[x.filename] = x
@@ -1702,10 +1700,11 @@ class ZipFile:
file_size = zinfo.file_size
compress_size = zinfo.compress_size
- header_offset = zinfo.header_offset - self._start_disk
- if header_offset > ZIP64_LIMIT:
- extra.append(header_offset)
+ if zinfo.header_offset > ZIP64_LIMIT:
+ extra.append(zinfo.header_offset)
header_offset = 0xffffffff
+ else:
+ header_offset = zinfo.header_offset
extra_data = zinfo.extra
min_version = 0
@@ -1752,7 +1751,7 @@ class ZipFile:
# Write end-of-zip-archive record
centDirCount = len(self.filelist)
centDirSize = pos2 - self.start_dir
- centDirOffset = self.start_dir - self._start_disk
+ centDirOffset = self.start_dir
requires_zip64 = None
if centDirCount > ZIP_FILECOUNT_LIMIT:
requires_zip64 = "Files count"
diff --git a/Misc/NEWS b/Misc/NEWS
index 0a2e5eb397..6d6bdee088 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,8 @@ Core and Builtins
Library
-------
+- Revert bpo-26293 for zipfile breakage. See also bpo-29094.
+
- bpo-30243: Removed the __init__ methods of _json's scanner and encoder.
Misusing them could cause memory leaks or crashes. Now scanner and encoder
objects are completely initialized in the __new__ methods.
--
GitLab
From 410d75ab71e2db0fdc8b2016600a3d3d4830f38e Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Tue, 9 May 2017 10:56:30 +0800
Subject: [PATCH 0191/1433] bpo-30289: remove Misc/python-config.sh when make
distclean (#1498) (#1506)
---
Makefile.pre.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 6e3a82f95d..2e4dd3b3ce 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1630,7 +1630,8 @@ distclean: clobber
done
-rm -f core Makefile Makefile.pre config.status \
Modules/Setup Modules/Setup.local Modules/Setup.config \
- Modules/ld_so_aix Modules/python.exp Misc/python.pc
+ Modules/ld_so_aix Modules/python.exp Misc/python.pc \
+ Misc/python-config.sh
-rm -f python*-gdb.py
# Issue #28258: set LC_ALL to avoid issues with Estonian locale.
# Expansion is performed here by shell (spawned by make) itself before
--
GitLab
From 72e1b61da0920c5607481304879e039b63e2a3d5 Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Tue, 9 May 2017 12:16:50 +0800
Subject: [PATCH 0192/1433] bpo-29990: Fix range checking in GB18030 decoder
(#1495) (#1507)
When decoding a 4-byte GB18030 sequence, the first and third byte cannot exceed 0xFE.
---
Lib/test/test_codecencodings_cn.py | 6 ++++++
Misc/NEWS | 2 ++
Modules/cjkcodecs/_codecs_cn.c | 4 +++-
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/Lib/test/test_codecencodings_cn.py b/Lib/test/test_codecencodings_cn.py
index 3bdf7d0e14..c8a410c2e0 100644
--- a/Lib/test/test_codecencodings_cn.py
+++ b/Lib/test/test_codecencodings_cn.py
@@ -48,6 +48,12 @@ class Test_GB18030(multibytecodec_support.TestBase, unittest.TestCase):
(b"abc\x84\x32\x80\x80def", "replace", 'abc\ufffd2\ufffd\ufffddef'),
(b"abc\x81\x30\x81\x30def", "strict", 'abc\x80def'),
(b"abc\x86\x30\x81\x30def", "replace", 'abc\ufffd0\ufffd0def'),
+ # issue29990
+ (b"\xff\x30\x81\x30", "strict", None),
+ (b"\x81\x30\xff\x30", "strict", None),
+ (b"abc\x81\x39\xff\x39\xc1\xc4", "replace", "abc\ufffd\x39\ufffd\x39\u804a"),
+ (b"abc\xab\x36\xff\x30def", "replace", 'abc\ufffd\x36\ufffd\x30def'),
+ (b"abc\xbf\x38\xff\x32\xc1\xc4", "ignore", "abc\x38\x32\u804a"),
)
has_iso10646 = True
diff --git a/Misc/NEWS b/Misc/NEWS
index 6d6bdee088..255942d7ca 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,8 @@ Core and Builtins
Library
-------
+- bpo-29990: Fix range checking in GB18030 decoder. Original patch by Ma Lin.
+
- Revert bpo-26293 for zipfile breakage. See also bpo-29094.
- bpo-30243: Removed the __init__ methods of _json's scanner and encoder.
diff --git a/Modules/cjkcodecs/_codecs_cn.c b/Modules/cjkcodecs/_codecs_cn.c
index 1a070f2f39..bda175c55d 100644
--- a/Modules/cjkcodecs/_codecs_cn.c
+++ b/Modules/cjkcodecs/_codecs_cn.c
@@ -279,7 +279,9 @@ DECODER(gb18030)
REQUIRE_INBUF(4);
c3 = INBYTE3;
c4 = INBYTE4;
- if (c < 0x81 || c3 < 0x81 || c4 < 0x30 || c4 > 0x39)
+ if (c < 0x81 || c > 0xFE ||
+ c3 < 0x81 || c3 > 0xFE ||
+ c4 < 0x30 || c4 > 0x39)
return 1;
c -= 0x81; c2 -= 0x30;
c3 -= 0x81; c4 -= 0x30;
--
GitLab
From 03b8a378dfa46372b96790f82c85e9b72518f1bf Mon Sep 17 00:00:00 2001
From: torsava
Date: Tue, 9 May 2017 16:05:10 +0200
Subject: [PATCH 0193/1433] [3.6] bpo-29243: Fix Makefile with respect to
--enable-optimizations (GH-1478) (#1518)
* bpo-29243: Fix Makefile with respect to --enable-optimizations (#1478)
* bpo-29243: Fix Makefile with respect to --enable-optimizations
When using the Profile Guided Optimization (./configure --enable-optimizations)
Python is built not only during `make` but rebuilt again during `make test`,
`make install` and others. This patch fixes the issue.
Note that this fix produces no change at all in the Makefile if configure is
run witout --enable-optimizations.
* !squash
(cherry picked from commit a1054c3b0037d4c2a5492e79fc193f36245366c7)
* [3.6] bpo-29243: Fix Makefile with respect to --enable-optimizations (GH-1478)
* bpo-29243: Fix Makefile with respect to --enable-optimizations
When using the Profile Guided Optimization (./configure --enable-optimizations)
Python is built not only during `make` but rebuilt again during `make test`,
`make install` and others. This patch fixes the issue.
Note that this fix produces no change at all in the Makefile if configure is
run witout --enable-optimizations.
* !squash.
(cherry picked from commit a1054c3b0037d4c2a5492e79fc193f36245366c7)
---
Makefile.pre.in | 14 +++++++-------
Misc/ACKS | 1 +
Misc/NEWS | 4 ++++
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 2e4dd3b3ce..076fb44631 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1002,7 +1002,7 @@ TESTTIMEOUT= 1200
# Run a basic set of regression tests.
# This excludes some tests that are particularly resource-intensive.
-test: all platform
+test: @DEF_MAKE_RULE@ platform
$(TESTRUNNER) $(TESTOPTS)
# Run the full test suite twice - once without .pyc files, and once with.
@@ -1012,7 +1012,7 @@ test: all platform
# the bytecode read from a .pyc file had the bug, sometimes the directly
# generated bytecode. This is sometimes a very shy bug needing a lot of
# sample data.
-testall: all platform
+testall: @DEF_MAKE_RULE@ platform
-find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f
$(TESTPYTHON) -E $(srcdir)/Lib/compileall.py
-find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f
@@ -1021,7 +1021,7 @@ testall: all platform
# Run the test suite for both architectures in a Universal build on OSX.
# Must be run on an Intel box.
-testuniversal: all platform
+testuniversal: @DEF_MAKE_RULE@ platform
if [ `arch` != 'i386' ];then \
echo "This can only be used on OSX/i386" ;\
exit 1 ;\
@@ -1044,7 +1044,7 @@ QUICKTESTOPTS= $(TESTOPTS) -x test_subprocess test_io test_lib2to3 \
test_multiprocessing_forkserver \
test_mailbox test_socket test_poll \
test_select test_zipfile test_concurrent_futures
-quicktest: all platform
+quicktest: @DEF_MAKE_RULE@ platform
$(TESTRUNNER) $(QUICKTESTOPTS)
@@ -1381,7 +1381,7 @@ LIBPL= @LIBPL@
# pkgconfig directory
LIBPC= $(LIBDIR)/pkgconfig
-libainstall: all python-config
+libainstall: @DEF_MAKE_RULE@ python-config
@for i in $(LIBDIR) $(LIBPL) $(LIBPC); \
do \
if test ! -d $(DESTDIR)$$i; then \
@@ -1644,7 +1644,7 @@ distclean: clobber
-exec rm -f {} ';'
# Check for smelly exported symbols (not starting with Py/_Py)
-smelly: all
+smelly: @DEF_MAKE_RULE@
nm -p $(LIBRARY) | \
sed -n "/ [TDB] /s/.* //p" | grep -v "^_*Py" | sort -u; \
@@ -1681,7 +1681,7 @@ funny:
-o -print
# Perform some verification checks on any modified files.
-patchcheck: all
+patchcheck: @DEF_MAKE_RULE@
$(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/patchcheck.py
# Dependencies
diff --git a/Misc/ACKS b/Misc/ACKS
index ac2c4edc73..b38a1fe05f 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1114,6 +1114,7 @@ Jason Orendorff
Douglas Orr
William Orr
Michele Orrù
+Tomáš Orsava
Oleg Oshmyan
Denis S. Otkidach
Peter Otten
diff --git a/Misc/NEWS b/Misc/NEWS
index 255942d7ca..64974ef2eb 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -124,6 +124,10 @@ Library
Build
-----
+- bpo-29243: Prevent unnecessary rebuilding of Python during ``make test``,
+ ``make install`` and some other make targets when configured with
+ ``--enable-optimizations``.
+
- bpo-23404: Don't regenerate generated files based on file modification time
anymore: the action is now explicit. Replace ``make touch`` with
``make regen-all``.
--
GitLab
From 418d60a52579b6847776db3e354a8660b26dc752 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Wed, 10 May 2017 06:44:02 +0300
Subject: [PATCH 0194/1433] [3.6] bpo-30298: Weaken the condition of
deprecation warnings for inline modifiers. (GH-1490) (#1525)
Now allowed several subsequential inline modifiers at the start of the
pattern (e.g. '(?i)(?s)...'). In verbose mode whitespaces and comments
now are allowed before and between inline modifiers (e.g.
'(?x) (?i) (?s)...')..
(cherry picked from commit 305ccbe27ea5ba82fd2d8c32ec739f980e524330)
---
Lib/sre_parse.py | 12 ++++-----
Lib/test/test_re.py | 59 ++++++++++++++++++++++++++++++++++-----------
Misc/NEWS | 6 +++++
3 files changed, 56 insertions(+), 21 deletions(-)
diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py
index 6aa49c3bf6..e1c749634b 100644
--- a/Lib/sre_parse.py
+++ b/Lib/sre_parse.py
@@ -412,7 +412,7 @@ def _parse_sub(source, state, verbose, nested=True):
sourcematch = source.match
start = source.tell()
while True:
- itemsappend(_parse(source, state, verbose))
+ itemsappend(_parse(source, state, verbose, not nested and not items))
if not sourcematch("|"):
break
@@ -466,7 +466,7 @@ def _parse_sub_cond(source, state, condgroup, verbose):
subpattern.append((GROUPREF_EXISTS, (condgroup, item_yes, item_no)))
return subpattern
-def _parse(source, state, verbose):
+def _parse(source, state, verbose, first=False):
# parse a simple pattern
subpattern = SubPattern(state)
@@ -730,10 +730,9 @@ def _parse(source, state, verbose):
state.checklookbehindgroup(condgroup, source)
elif char in FLAGS or char == "-":
# flags
- pos = source.pos
flags = _parse_flags(source, state, char)
if flags is None: # global flags
- if pos != 3: # "(?x"
+ if not first or subpattern:
import warnings
warnings.warn(
'Flags not at the start of the expression %s%s' % (
@@ -742,6 +741,8 @@ def _parse(source, state, verbose):
),
DeprecationWarning, stacklevel=7
)
+ if (state.flags & SRE_FLAG_VERBOSE) and not verbose:
+ raise Verbose
continue
add_flags, del_flags = flags
group = None
@@ -795,9 +796,6 @@ def _parse_flags(source, state, char):
msg = "unknown flag" if char.isalpha() else "missing -, : or )"
raise source.error(msg, len(char))
if char == ")":
- if ((add_flags & SRE_FLAG_VERBOSE) and
- not (state.flags & SRE_FLAG_VERBOSE)):
- raise Verbose
state.flags |= add_flags
return None
if add_flags & GLOBAL_FLAGS:
diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py
index b945cf094e..c52417ba00 100644
--- a/Lib/test/test_re.py
+++ b/Lib/test/test_re.py
@@ -1303,32 +1303,43 @@ class ReTests(unittest.TestCase):
upper_char = '\u1ea0' # Latin Capital Letter A with Dot Below
lower_char = '\u1ea1' # Latin Small Letter A with Dot Below
- p = re.compile(upper_char, re.I | re.U)
- q = p.match(lower_char)
+ p = re.compile('.' + upper_char, re.I | re.S)
+ q = p.match('\n' + lower_char)
self.assertTrue(q)
- p = re.compile(lower_char, re.I | re.U)
- q = p.match(upper_char)
+ p = re.compile('.' + lower_char, re.I | re.S)
+ q = p.match('\n' + upper_char)
self.assertTrue(q)
- p = re.compile('(?i)' + upper_char, re.U)
- q = p.match(lower_char)
+ p = re.compile('(?i).' + upper_char, re.S)
+ q = p.match('\n' + lower_char)
self.assertTrue(q)
- p = re.compile('(?i)' + lower_char, re.U)
- q = p.match(upper_char)
+ p = re.compile('(?i).' + lower_char, re.S)
+ q = p.match('\n' + upper_char)
self.assertTrue(q)
- p = re.compile('(?iu)' + upper_char)
- q = p.match(lower_char)
+ p = re.compile('(?is).' + upper_char)
+ q = p.match('\n' + lower_char)
self.assertTrue(q)
- p = re.compile('(?iu)' + lower_char)
- q = p.match(upper_char)
+ p = re.compile('(?is).' + lower_char)
+ q = p.match('\n' + upper_char)
self.assertTrue(q)
- self.assertTrue(re.match('(?ixu) ' + upper_char, lower_char))
- self.assertTrue(re.match('(?ixu) ' + lower_char, upper_char))
+ p = re.compile('(?s)(?i).' + upper_char)
+ q = p.match('\n' + lower_char)
+ self.assertTrue(q)
+
+ p = re.compile('(?s)(?i).' + lower_char)
+ q = p.match('\n' + upper_char)
+ self.assertTrue(q)
+
+ self.assertTrue(re.match('(?ix) ' + upper_char, lower_char))
+ self.assertTrue(re.match('(?ix) ' + lower_char, upper_char))
+ self.assertTrue(re.match(' (?i) ' + upper_char, lower_char, re.X))
+ self.assertTrue(re.match('(?x) (?i) ' + upper_char, lower_char))
+ self.assertTrue(re.match(' (?x) (?i) ' + upper_char, lower_char, re.X))
p = upper_char + '(?i)'
with self.assertWarns(DeprecationWarning) as warns:
@@ -1346,6 +1357,26 @@ class ReTests(unittest.TestCase):
'Flags not at the start of the expression %s (truncated)' % p[:20]
)
+ with self.assertWarns(DeprecationWarning):
+ self.assertTrue(re.match('(?s).(?i)' + upper_char, '\n' + lower_char))
+ with self.assertWarns(DeprecationWarning):
+ self.assertTrue(re.match('(?i) ' + upper_char + ' (?x)', lower_char))
+ with self.assertWarns(DeprecationWarning):
+ self.assertTrue(re.match(' (?x) (?i) ' + upper_char, lower_char))
+ with self.assertWarns(DeprecationWarning):
+ self.assertTrue(re.match('^(?i)' + upper_char, lower_char))
+ with self.assertWarns(DeprecationWarning):
+ self.assertTrue(re.match('$|(?i)' + upper_char, lower_char))
+ with self.assertWarns(DeprecationWarning):
+ self.assertTrue(re.match('(?:(?i)' + upper_char + ')', lower_char))
+ with self.assertWarns(DeprecationWarning):
+ self.assertTrue(re.fullmatch('(^)?(?(1)(?i)' + upper_char + ')',
+ lower_char))
+ with self.assertWarns(DeprecationWarning):
+ self.assertTrue(re.fullmatch('($)?(?(1)|(?i)' + upper_char + ')',
+ lower_char))
+
+
def test_dollar_matches_twice(self):
"$ matches the end of string, and just before the terminating \n"
pattern = re.compile('$')
diff --git a/Misc/NEWS b/Misc/NEWS
index 64974ef2eb..e7090fc178 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,12 @@ Core and Builtins
Library
-------
+- bpo-30298: Weaken the condition of deprecation warnings for inline modifiers.
+ Now allowed several subsequential inline modifiers at the start of the
+ pattern (e.g. ``'(?i)(?s)...'``). In verbose mode whitespaces and comments
+ now are allowed before and between inline modifiers (e.g.
+ ``'(?x) (?i) (?s)...'``).
+
- bpo-29990: Fix range checking in GB18030 decoder. Original patch by Ma Lin.
- Revert bpo-26293 for zipfile breakage. See also bpo-29094.
--
GitLab
From 81ed53784608d44a8d196ad52288b55c7bf665db Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Wed, 10 May 2017 08:47:22 +0200
Subject: [PATCH 0195/1433] bpo-30320: test_eintr now uses pthread_sigmask()
(#1523) (#1524)
Rewrite sigwaitinfo() and sigtimedwait() unit tests for EINTR using
pthread_sigmask() to fix a race condition between the child and the
parent process.
Remove the pipe which was used as a weak workaround against the race
condition.
sigtimedwait() is now tested with a child process sending a signal
instead of testing the timeout feature which is more unstable
(especially regarding to clock resolution depending on the platform).
(cherry picked from commit 211a392cc15f9a7b1b8ce65d8f6c9f8237d1b77f)
---
Lib/test/eintrdata/eintr_tester.py | 56 ++++++++++++++----------------
1 file changed, 26 insertions(+), 30 deletions(-)
diff --git a/Lib/test/eintrdata/eintr_tester.py b/Lib/test/eintrdata/eintr_tester.py
index c619b3d6c3..1dbe88efe7 100644
--- a/Lib/test/eintrdata/eintr_tester.py
+++ b/Lib/test/eintrdata/eintr_tester.py
@@ -371,59 +371,55 @@ class TimeEINTRTest(EINTRBaseTest):
@unittest.skipUnless(hasattr(signal, "setitimer"), "requires setitimer()")
+# bpo-30320: Need pthread_sigmask() to block the signal, otherwise the test
+# is vulnerable to a race condition between the child and the parent processes.
+@unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
+ 'need signal.pthread_sigmask()')
class SignalEINTRTest(EINTRBaseTest):
""" EINTR tests for the signal module. """
- @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
- 'need signal.sigtimedwait()')
- def test_sigtimedwait(self):
- t0 = time.monotonic()
- signal.sigtimedwait([signal.SIGUSR1], self.sleep_time)
- dt = time.monotonic() - t0
- self.assertGreaterEqual(dt, self.sleep_time)
-
- @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
- 'need signal.sigwaitinfo()')
- def test_sigwaitinfo(self):
- # Issue #25277, #25868: give a few milliseconds to the parent process
- # between os.write() and signal.sigwaitinfo() to works around a race
- # condition
- self.sleep_time = 0.100
-
+ def check_sigwait(self, wait_func):
signum = signal.SIGUSR1
pid = os.getpid()
old_handler = signal.signal(signum, lambda *args: None)
self.addCleanup(signal.signal, signum, old_handler)
- rpipe, wpipe = os.pipe()
-
code = '\n'.join((
'import os, time',
'pid = %s' % os.getpid(),
'signum = %s' % int(signum),
'sleep_time = %r' % self.sleep_time,
- 'rpipe = %r' % rpipe,
- 'os.read(rpipe, 1)',
- 'os.close(rpipe)',
'time.sleep(sleep_time)',
'os.kill(pid, signum)',
))
+ old_mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signum])
+ self.addCleanup(signal.pthread_sigmask, signal.SIG_UNBLOCK, [signum])
+
t0 = time.monotonic()
- proc = self.subprocess(code, pass_fds=(rpipe,))
- os.close(rpipe)
+ proc = self.subprocess(code)
with kill_on_error(proc):
- # sync child-parent
- os.write(wpipe, b'x')
- os.close(wpipe)
+ wait_func(signum)
+ dt = time.monotonic() - t0
+
+ self.assertEqual(proc.wait(), 0)
- # parent
+ @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
+ 'need signal.sigwaitinfo()')
+ def test_sigwaitinfo(self):
+ def wait_func(signum):
signal.sigwaitinfo([signum])
- dt = time.monotonic() - t0
- self.assertEqual(proc.wait(), 0)
- self.assertGreaterEqual(dt, self.sleep_time)
+ self.check_sigwait(wait_func)
+
+ @unittest.skipUnless(hasattr(signal, 'sigtimedwait'),
+ 'need signal.sigwaitinfo()')
+ def test_sigtimedwait(self):
+ def wait_func(signum):
+ signal.sigtimedwait([signum], 120.0)
+
+ self.check_sigwait(wait_func)
@unittest.skipUnless(hasattr(signal, "setitimer"), "requires setitimer()")
--
GitLab
From 98b49a00d413972965044fd355be3b8482caa07c Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Wed, 10 May 2017 19:00:15 +0800
Subject: [PATCH 0196/1433] bpo-30281: Fix the default value for stop in
PySlice_Unpack() (#1480) (#1529)
---
Objects/sliceobject.c | 8 +++++---
Python/ceval.c | 2 +-
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c
index 6a690213d1..4e4b32d324 100644
--- a/Objects/sliceobject.c
+++ b/Objects/sliceobject.c
@@ -197,6 +197,8 @@ PySlice_Unpack(PyObject *_r,
PySliceObject *r = (PySliceObject*)_r;
/* this is harder to get right than you might think */
+ Py_BUILD_ASSERT(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX);
+
if (r->step == Py_None) {
*step = 1;
}
@@ -217,14 +219,14 @@ PySlice_Unpack(PyObject *_r,
}
if (r->start == Py_None) {
- *start = *step < 0 ? PY_SSIZE_T_MAX-1 : 0;;
+ *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
}
else {
if (!_PyEval_SliceIndex(r->start, start)) return -1;
}
if (r->stop == Py_None) {
- *stop = *step < 0 ? -PY_SSIZE_T_MAX : PY_SSIZE_T_MAX;
+ *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
}
else {
if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
@@ -258,7 +260,7 @@ PySlice_AdjustIndices(Py_ssize_t length,
*stop = (step < 0) ? -1 : 0;
}
}
- else if (*stop >= length) {
+ else if (*stop >= length) {
*stop = (step < 0) ? length - 1 : length;
}
diff --git a/Python/ceval.c b/Python/ceval.c
index bce86ab12c..5dc0444a1a 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -5071,7 +5071,7 @@ do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
/* Extract a slice index from a PyLong or an object with the
nb_index slot defined, and store in *pi.
Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
- and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
+ and silently boost values less than PY_SSIZE_T_MIN to PY_SSIZE_T_MIN.
Return 0 on error, 1 on success.
*/
int
--
GitLab
From a4465a5bd08f232cf097893006118c82975c3402 Mon Sep 17 00:00:00 2001
From: stratakis
Date: Thu, 11 May 2017 13:13:18 +0200
Subject: [PATCH 0197/1433] [3.6] bpo-28787: Fix out of tree --with-dtrace
builds (GH-135) (#1543)
* bpo-28787: Fix out of tree --with-dtrace builds
* Unsilence directory creation
* Add Misc/NEWS and Misc/ACKS entries.
(cherry picked from commit f6eae5bf1c5d7b83e5d5bdbecfff928e478c1cfd)
---
Makefile.pre.in | 1 +
Misc/ACKS | 1 +
Misc/NEWS | 3 +++
3 files changed, 5 insertions(+)
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 076fb44631..82e830727e 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -875,6 +875,7 @@ Python/frozen.o: $(srcdir)/Python/importlib.h $(srcdir)/Python/importlib_externa
# follow our naming conventions. dtrace(1) uses the output filename to generate
# an include guard, so we can't use a pipeline to transform its output.
Include/pydtrace_probes.h: $(srcdir)/Include/pydtrace.d
+ $(MKDIR_P) Include
$(DTRACE) $(DFLAGS) -o $@ -h -s $<
: sed in-place edit with POSIX-only tools
sed 's/PYTHON_/PyDTrace_/' $@ > $@.tmp
diff --git a/Misc/ACKS b/Misc/ACKS
index b38a1fe05f..486b6e3285 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1476,6 +1476,7 @@ Daniel Stokes
Michael Stone
Serhiy Storchaka
Ken Stox
+Charalampos Stratakis
Dan Stromberg
Donald Stufft
Daniel Stutzbach
diff --git a/Misc/NEWS b/Misc/NEWS
index e7090fc178..58b8d262ec 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -130,6 +130,9 @@ Library
Build
-----
+- bpo-28787: Fix out-of-tree builds of Python when configured with
+ ``--with--dtrace``.
+
- bpo-29243: Prevent unnecessary rebuilding of Python during ``make test``,
``make install`` and some other make targets when configured with
``--enable-optimizations``.
--
GitLab
From 3dc7c52a9f4fb83be3e26e31e2c7cd9dc1cb41a2 Mon Sep 17 00:00:00 2001
From: INADA Naoki
Date: Thu, 11 May 2017 21:56:42 +0900
Subject: [PATCH 0198/1433] bpo-30048: asyncio: fix Task.cancel() was ignored.
(GH-1546)
when there are no more `await` or `yield (from)` before return in coroutine,
cancel was ignored.
example:
async def coro():
asyncio.Task.current_task().cancel()
return 42
...
res = await coro() # should raise CancelledError
(cherry picked from commit 991adca012f5e106c2d4040ce619c696ba6f9c46)
---
Lib/asyncio/tasks.py | 7 ++++++-
Lib/test/test_asyncio/test_tasks.py | 18 ++++++++++++++++++
Misc/NEWS | 3 +++
Modules/_asynciomodule.c | 12 ++++++++++++
4 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index f91e70aecb..d7867d128a 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -180,7 +180,12 @@ class Task(futures.Future):
else:
result = coro.throw(exc)
except StopIteration as exc:
- self.set_result(exc.value)
+ if self._must_cancel:
+ # Task is cancelled right before coro stops.
+ self._must_cancel = False
+ self.set_exception(futures.CancelledError())
+ else:
+ self.set_result(exc.value)
except futures.CancelledError:
super().cancel() # I.e., Future.cancel(self).
except Exception as exc:
diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py
index 4f05319457..5462c80ad3 100644
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -588,6 +588,24 @@ class BaseTaskTests:
self.assertFalse(t._must_cancel) # White-box test.
self.assertFalse(t.cancel())
+ def test_cancel_at_end(self):
+ """coroutine end right after task is cancelled"""
+ loop = asyncio.new_event_loop()
+ self.set_event_loop(loop)
+
+ @asyncio.coroutine
+ def task():
+ t.cancel()
+ self.assertTrue(t._must_cancel) # White-box test.
+ return 12
+
+ t = self.new_task(loop, task())
+ self.assertRaises(
+ asyncio.CancelledError, loop.run_until_complete, t)
+ self.assertTrue(t.done())
+ self.assertFalse(t._must_cancel) # White-box test.
+ self.assertFalse(t.cancel())
+
def test_stop_while_run_in_complete(self):
def gen():
diff --git a/Misc/NEWS b/Misc/NEWS
index 58b8d262ec..b6b405446f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,9 @@ Core and Builtins
Library
-------
+- bpo-30048: Fixed ``Task.cancel()`` can be ignored when the task is
+ running coroutine and the coroutine returned without any more ``await``.
+
- bpo-30298: Weaken the condition of deprecation warnings for inline modifiers.
Now allowed several subsequential inline modifiers at the start of the
pattern (e.g. ``'(?i)(?s)...'``). In verbose mode whitespaces and comments
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index a77ff9689e..75327fa301 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -1984,6 +1984,16 @@ task_step_impl(TaskObj *task, PyObject *exc)
if (_PyGen_FetchStopIterationValue(&o) == 0) {
/* The error is StopIteration and that means that
the underlying coroutine has resolved */
+ if (task->task_must_cancel) {
+ // Task is cancelled right before coro stops.
+ Py_DECREF(o);
+ task->task_must_cancel = 0;
+ et = asyncio_CancelledError;
+ Py_INCREF(et);
+ ev = NULL;
+ tb = NULL;
+ goto set_exception;
+ }
PyObject *res = future_set_result((FutureObj*)task, o);
Py_DECREF(o);
if (res == NULL) {
@@ -2001,6 +2011,8 @@ task_step_impl(TaskObj *task, PyObject *exc)
/* Some other exception; pop it and call Task.set_exception() */
PyErr_Fetch(&et, &ev, &tb);
+
+set_exception:
assert(et);
if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
PyErr_NormalizeException(&et, &ev, &tb);
--
GitLab
From d05f7fdf6cf77724bd3064fb5a0846ef5cfe0c88 Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Sat, 13 May 2017 00:21:50 +0200
Subject: [PATCH 0199/1433] [3.6] bpo-30345: Update test_gdb.py and
python-gdb.py from master (#1549)
* python-gdb.py supports method-wrapper
bpo-29367: python-gdb.py now supports also method-wrapper (wrapperobject)
objects.
(cherry picked from commit 611083331d534481ca7956a376e38fb0e9ef3854)
* Update and enhance python-gdb.py
bpo-29259: Detect PyCFunction is the current frame, not only in the
older frame.
---
Lib/test/test_gdb.py | 22 +++++++++++++--
Misc/NEWS | 6 ++++
Tools/gdb/libpython.py | 64 ++++++++++++++++++++++++++++++++++--------
3 files changed, 78 insertions(+), 14 deletions(-)
diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py
index 60f1d92846..b7554d698c 100644
--- a/Lib/test/test_gdb.py
+++ b/Lib/test/test_gdb.py
@@ -3,13 +3,14 @@
# The code for testing gdb was adapted from similar work in Unladen Swallow's
# Lib/test/test_jit_gdb.py
+import locale
import os
import re
import subprocess
import sys
import sysconfig
+import textwrap
import unittest
-import locale
# Is this Python configured to support threads?
try:
@@ -845,7 +846,24 @@ id(42)
breakpoint='time_gmtime',
cmds_after_breakpoint=['py-bt-full'],
)
- self.assertIn('#0 '
+
+ def safe_tp_name(self):
+ try:
+ return self.field('self')['ob_type']['tp_name'].string()
+ except (NullPyObjectPtr, RuntimeError):
+ return ''
+
+ def safe_self_addresss(self):
+ try:
+ address = long(self.field('self'))
+ return '%#x' % address
+ except (NullPyObjectPtr, RuntimeError):
+ return ''
+
+ def proxyval(self, visited):
+ name = self.safe_name()
+ tp_name = self.safe_tp_name()
+ self_address = self.safe_self_addresss()
+ return (""
+ % (name, tp_name, self_address))
+
+ def write_repr(self, out, visited):
+ proxy = self.proxyval(visited)
+ out.write(proxy)
def int_from_int(gdbval):
@@ -1364,11 +1398,13 @@ class PyObjectPtrPrinter:
def pretty_printer_lookup(gdbval):
type = gdbval.type.unqualified()
- if type.code == gdb.TYPE_CODE_PTR:
- type = type.target().unqualified()
- t = str(type)
- if t in ("PyObject", "PyFrameObject", "PyUnicodeObject"):
- return PyObjectPtrPrinter(gdbval)
+ if type.code != gdb.TYPE_CODE_PTR:
+ return None
+
+ type = type.target().unqualified()
+ t = str(type)
+ if t in ("PyObject", "PyFrameObject", "PyUnicodeObject", "wrapperobject"):
+ return PyObjectPtrPrinter(gdbval)
"""
During development, I've been manually invoking the code in this way:
@@ -1497,11 +1533,8 @@ class Frame(object):
return 'Garbage-collecting'
# Detect invocations of PyCFunction instances:
- older = self.older()
- if not older:
- return False
-
- caller = older._gdbframe.name()
+ frame = self._gdbframe
+ caller = frame.name()
if not caller:
return False
@@ -1513,18 +1546,25 @@ class Frame(object):
# "self" is the (PyObject*) of the 'self'
try:
# Use the prettyprinter for the func:
- func = older._gdbframe.read_var('func')
+ func = frame.read_var('func')
return str(func)
except RuntimeError:
return 'PyCFunction invocation (unable to read "func")'
elif caller == '_PyCFunction_FastCallDict':
try:
- func = older._gdbframe.read_var('func_obj')
+ func = frame.read_var('func_obj')
return str(func)
except RuntimeError:
return 'PyCFunction invocation (unable to read "func_obj")'
+ if caller == 'wrapper_call':
+ try:
+ func = frame.read_var('wp')
+ return str(func)
+ except RuntimeError:
+ return ''
+
# This frame isn't worth reporting:
return False
--
GitLab
From 3a66ab8695e9ba969ff6bdd8c91f88138c8b5187 Mon Sep 17 00:00:00 2001
From: Mariatta
Date: Sat, 13 May 2017 09:42:39 -0700
Subject: [PATCH 0200/1433] [3.6] bpo-30178: Indent methods and attributes of
MimeType class (GH-1306) (#1570)
(cherry picked from commit c71168090df435c1eb8c03005b11df764cd7ebd6)
---
Doc/library/mimetypes.rst | 86 +++++++++++++++++++--------------------
1 file changed, 43 insertions(+), 43 deletions(-)
diff --git a/Doc/library/mimetypes.rst b/Doc/library/mimetypes.rst
index 464248c3ea..67b7a71785 100644
--- a/Doc/library/mimetypes.rst
+++ b/Doc/library/mimetypes.rst
@@ -186,78 +186,78 @@ than one MIME-type database; it provides an interface similar to the one of the
loaded "on top" of the default database.
-.. attribute:: MimeTypes.suffix_map
+ .. attribute:: MimeTypes.suffix_map
- Dictionary mapping suffixes to suffixes. This is used to allow recognition of
- encoded files for which the encoding and the type are indicated by the same
- extension. For example, the :file:`.tgz` extension is mapped to :file:`.tar.gz`
- to allow the encoding and type to be recognized separately. This is initially a
- copy of the global :data:`suffix_map` defined in the module.
+ Dictionary mapping suffixes to suffixes. This is used to allow recognition of
+ encoded files for which the encoding and the type are indicated by the same
+ extension. For example, the :file:`.tgz` extension is mapped to :file:`.tar.gz`
+ to allow the encoding and type to be recognized separately. This is initially a
+ copy of the global :data:`suffix_map` defined in the module.
-.. attribute:: MimeTypes.encodings_map
+ .. attribute:: MimeTypes.encodings_map
- Dictionary mapping filename extensions to encoding types. This is initially a
- copy of the global :data:`encodings_map` defined in the module.
+ Dictionary mapping filename extensions to encoding types. This is initially a
+ copy of the global :data:`encodings_map` defined in the module.
-.. attribute:: MimeTypes.types_map
+ .. attribute:: MimeTypes.types_map
- Tuple containing two dictionaries, mapping filename extensions to MIME types:
- the first dictionary is for the non-standards types and the second one is for
- the standard types. They are initialized by :data:`common_types` and
- :data:`types_map`.
+ Tuple containing two dictionaries, mapping filename extensions to MIME types:
+ the first dictionary is for the non-standards types and the second one is for
+ the standard types. They are initialized by :data:`common_types` and
+ :data:`types_map`.
-.. attribute:: MimeTypes.types_map_inv
+ .. attribute:: MimeTypes.types_map_inv
- Tuple containing two dictionaries, mapping MIME types to a list of filename
- extensions: the first dictionary is for the non-standards types and the
- second one is for the standard types. They are initialized by
- :data:`common_types` and :data:`types_map`.
+ Tuple containing two dictionaries, mapping MIME types to a list of filename
+ extensions: the first dictionary is for the non-standards types and the
+ second one is for the standard types. They are initialized by
+ :data:`common_types` and :data:`types_map`.
-.. method:: MimeTypes.guess_extension(type, strict=True)
+ .. method:: MimeTypes.guess_extension(type, strict=True)
- Similar to the :func:`guess_extension` function, using the tables stored as part
- of the object.
+ Similar to the :func:`guess_extension` function, using the tables stored as part
+ of the object.
-.. method:: MimeTypes.guess_type(url, strict=True)
+ .. method:: MimeTypes.guess_type(url, strict=True)
- Similar to the :func:`guess_type` function, using the tables stored as part of
- the object.
+ Similar to the :func:`guess_type` function, using the tables stored as part of
+ the object.
-.. method:: MimeTypes.guess_all_extensions(type, strict=True)
+ .. method:: MimeTypes.guess_all_extensions(type, strict=True)
- Similar to the :func:`guess_all_extensions` function, using the tables stored
- as part of the object.
+ Similar to the :func:`guess_all_extensions` function, using the tables stored
+ as part of the object.
-.. method:: MimeTypes.read(filename, strict=True)
+ .. method:: MimeTypes.read(filename, strict=True)
- Load MIME information from a file named *filename*. This uses :meth:`readfp` to
- parse the file.
+ Load MIME information from a file named *filename*. This uses :meth:`readfp` to
+ parse the file.
- If *strict* is ``True``, information will be added to list of standard types,
- else to the list of non-standard types.
+ If *strict* is ``True``, information will be added to list of standard types,
+ else to the list of non-standard types.
-.. method:: MimeTypes.readfp(fp, strict=True)
+ .. method:: MimeTypes.readfp(fp, strict=True)
- Load MIME type information from an open file *fp*. The file must have the format of
- the standard :file:`mime.types` files.
+ Load MIME type information from an open file *fp*. The file must have the format of
+ the standard :file:`mime.types` files.
- If *strict* is ``True``, information will be added to the list of standard
- types, else to the list of non-standard types.
+ If *strict* is ``True``, information will be added to the list of standard
+ types, else to the list of non-standard types.
-.. method:: MimeTypes.read_windows_registry(strict=True)
+ .. method:: MimeTypes.read_windows_registry(strict=True)
- Load MIME type information from the Windows registry. Availability: Windows.
+ Load MIME type information from the Windows registry. Availability: Windows.
- If *strict* is ``True``, information will be added to the list of standard
- types, else to the list of non-standard types.
+ If *strict* is ``True``, information will be added to the list of standard
+ types, else to the list of non-standard types.
- .. versionadded:: 3.2
+ .. versionadded:: 3.2
--
GitLab
From 178756c15da0652b30b55b41f0bb939b61c66513 Mon Sep 17 00:00:00 2001
From: Brett Cannon
Date: Sat, 13 May 2017 13:51:24 -0700
Subject: [PATCH 0201/1433] [3.6] Move Codecov's configuration file under
.github (GH-1494) (GH-1574)
(cherry picked from commit cbddf58c797f850a5b06f317a4bb7ab69c6e9715)
---
.codecov.yml => .github/codecov.yml | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename .codecov.yml => .github/codecov.yml (100%)
diff --git a/.codecov.yml b/.github/codecov.yml
similarity index 100%
rename from .codecov.yml
rename to .github/codecov.yml
--
GitLab
From 61b6e5cf929a80bb44500fb1a212facf66d7f45c Mon Sep 17 00:00:00 2001
From: Berker Peksag
Date: Sun, 14 May 2017 18:30:48 +0300
Subject: [PATCH 0202/1433] bpo-30358: Document sort argument of
profile.runctx() (GH-1566)
(cherry picked from commit 99776296230ddd8429ebad2d07854b8c27ea10ab)
---
Doc/library/profile.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst
index b4b1479e2c..5796e3acb6 100644
--- a/Doc/library/profile.rst
+++ b/Doc/library/profile.rst
@@ -215,11 +215,11 @@ functions:
and gathers profiling statistics from the execution. If no file name is
present, then this function automatically creates a :class:`~pstats.Stats`
- instance and prints a simple profiling report. If the sort value is specified
+ instance and prints a simple profiling report. If the sort value is specified,
it is passed to this :class:`~pstats.Stats` instance to control how the
results are sorted.
-.. function:: runctx(command, globals, locals, filename=None)
+.. function:: runctx(command, globals, locals, filename=None, sort=-1)
This function is similar to :func:`run`, with added arguments to supply the
globals and locals dictionaries for the *command* string. This routine
--
GitLab
From 0ce1f7e02d4102e8a459d1855d689c8e4613a327 Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Mon, 15 May 2017 13:17:01 +0800
Subject: [PATCH 0203/1433] bpo-30110: fix resource leak in
test_asyncio.test_events (#1413) (#1584)
---
Lib/test/test_asyncio/test_events.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
index 802763bd11..492a84a231 100644
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -2194,8 +2194,10 @@ else:
def test_get_event_loop_new_process(self):
async def main():
pool = concurrent.futures.ProcessPoolExecutor()
- return await self.loop.run_in_executor(
+ result = await self.loop.run_in_executor(
pool, _test_get_event_loop_new_process__sub_proc)
+ pool.shutdown()
+ return result
self.unpatch_get_running_loop()
--
GitLab
From aad1caf55f7fadb00ee097a1465bece4e128d8ef Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Mon, 15 May 2017 13:17:28 +0800
Subject: [PATCH 0204/1433] bpo-30242: resolve some undefined behaviours in
struct (#1418) (#1586)
---
Modules/_struct.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 796d1682f0..2635af9db6 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -539,7 +539,7 @@ np_ubyte(char *p, PyObject *v, const formatdef *f)
"ubyte format requires 0 <= number <= 255");
return -1;
}
- *p = (char)x;
+ *(unsigned char *)p = (unsigned char)x;
return 0;
}
@@ -868,6 +868,7 @@ bp_int(char *p, PyObject *v, const formatdef *f)
{
long x;
Py_ssize_t i;
+ unsigned char *q = (unsigned char *)p;
if (get_long(v, &x) < 0)
return -1;
i = f->size;
@@ -880,7 +881,7 @@ bp_int(char *p, PyObject *v, const formatdef *f)
#endif
}
do {
- p[--i] = (char)x;
+ q[--i] = (unsigned char)(x & 0xffL);
x >>= 8;
} while (i > 0);
return 0;
@@ -891,6 +892,7 @@ bp_uint(char *p, PyObject *v, const formatdef *f)
{
unsigned long x;
Py_ssize_t i;
+ unsigned char *q = (unsigned char *)p;
if (get_ulong(v, &x) < 0)
return -1;
i = f->size;
@@ -901,7 +903,7 @@ bp_uint(char *p, PyObject *v, const formatdef *f)
RANGE_ERROR(x, f, 1, maxint - 1);
}
do {
- p[--i] = (char)x;
+ q[--i] = (unsigned char)(x & 0xffUL);
x >>= 8;
} while (i > 0);
return 0;
@@ -1087,6 +1089,7 @@ lp_int(char *p, PyObject *v, const formatdef *f)
{
long x;
Py_ssize_t i;
+ unsigned char *q = (unsigned char *)p;
if (get_long(v, &x) < 0)
return -1;
i = f->size;
@@ -1099,7 +1102,7 @@ lp_int(char *p, PyObject *v, const formatdef *f)
#endif
}
do {
- *p++ = (char)x;
+ *q++ = (unsigned char)(x & 0xffL);
x >>= 8;
} while (--i > 0);
return 0;
@@ -1110,6 +1113,7 @@ lp_uint(char *p, PyObject *v, const formatdef *f)
{
unsigned long x;
Py_ssize_t i;
+ unsigned char *q = (unsigned char *)p;
if (get_ulong(v, &x) < 0)
return -1;
i = f->size;
@@ -1120,7 +1124,7 @@ lp_uint(char *p, PyObject *v, const formatdef *f)
RANGE_ERROR(x, f, 1, maxint - 1);
}
do {
- *p++ = (char)x;
+ *q++ = (unsigned char)(x & 0xffUL);
x >>= 8;
} while (--i > 0);
return 0;
--
GitLab
From 75b8a54bcad70806d9dcbbe20786f4d9092ab39c Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Mon, 15 May 2017 22:41:07 -0700
Subject: [PATCH 0205/1433] bpo-29651 - Cover edge case of square brackets in
urllib docs (#1128) (#1596)
(cherry picked from commit f6e863d868a621594df2a8abe072b5d4766e7137)
---
Doc/library/urllib.parse.rst | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst
index 676321b46a..1cc69e62e6 100644
--- a/Doc/library/urllib.parse.rst
+++ b/Doc/library/urllib.parse.rst
@@ -118,6 +118,9 @@ or on combining URL components into a URL string.
an invalid port is specified in the URL. See section
:ref:`urlparse-result-object` for more information on the result object.
+ Unmatched square brackets in the :attr:`netloc` attribute will raise a
+ :exc:`ValueError`.
+
.. versionchanged:: 3.2
Added IPv6 URL parsing capabilities.
@@ -236,6 +239,9 @@ or on combining URL components into a URL string.
an invalid port is specified in the URL. See section
:ref:`urlparse-result-object` for more information on the result object.
+ Unmatched square brackets in the :attr:`netloc` attribute will raise a
+ :exc:`ValueError`.
+
.. versionchanged:: 3.6
Out-of-range port numbers now raise :exc:`ValueError`, instead of
returning :const:`None`.
--
GitLab
From 73fb45df0487144765808c5d25914c67232d83fe Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Tue, 16 May 2017 18:16:15 +0300
Subject: [PATCH 0206/1433] [3.6] bpo-30375: Correct the stacklevel of regex
compiling warnings. (GH-1595) (#1604)
Warnings emitted when compile a regular expression now always point
to the line in the user code. Previously they could point into inners
of the re module if emitted from inside of groups or conditionals..
(cherry picked from commit c7ac7280c321b3c1679fe5f657a6be0f86adf173)
---
Lib/sre_parse.py | 25 +++++++++++++------------
Lib/test/test_re.py | 17 ++++++++++++++---
Misc/NEWS | 4 ++++
3 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py
index e1c749634b..608f9a2664 100644
--- a/Lib/sre_parse.py
+++ b/Lib/sre_parse.py
@@ -404,7 +404,7 @@ def _escape(source, escape, state):
pass
raise source.error("bad escape %s" % escape, len(escape))
-def _parse_sub(source, state, verbose, nested=True):
+def _parse_sub(source, state, verbose, nested):
# parse an alternation: a|b|c
items = []
@@ -412,7 +412,8 @@ def _parse_sub(source, state, verbose, nested=True):
sourcematch = source.match
start = source.tell()
while True:
- itemsappend(_parse(source, state, verbose, not nested and not items))
+ itemsappend(_parse(source, state, verbose, nested + 1,
+ not nested and not items))
if not sourcematch("|"):
break
@@ -454,10 +455,10 @@ def _parse_sub(source, state, verbose, nested=True):
subpattern.append((BRANCH, (None, items)))
return subpattern
-def _parse_sub_cond(source, state, condgroup, verbose):
- item_yes = _parse(source, state, verbose)
+def _parse_sub_cond(source, state, condgroup, verbose, nested):
+ item_yes = _parse(source, state, verbose, nested + 1)
if source.match("|"):
- item_no = _parse(source, state, verbose)
+ item_no = _parse(source, state, verbose, nested + 1)
if source.next == "|":
raise source.error("conditional backref with more than two branches")
else:
@@ -466,7 +467,7 @@ def _parse_sub_cond(source, state, condgroup, verbose):
subpattern.append((GROUPREF_EXISTS, (condgroup, item_yes, item_no)))
return subpattern
-def _parse(source, state, verbose, first=False):
+def _parse(source, state, verbose, nested, first=False):
# parse a simple pattern
subpattern = SubPattern(state)
@@ -692,7 +693,7 @@ def _parse(source, state, verbose, first=False):
lookbehindgroups = state.lookbehindgroups
if lookbehindgroups is None:
state.lookbehindgroups = state.groups
- p = _parse_sub(source, state, verbose)
+ p = _parse_sub(source, state, verbose, nested + 1)
if dir < 0:
if lookbehindgroups is None:
state.lookbehindgroups = None
@@ -739,7 +740,7 @@ def _parse(source, state, verbose, first=False):
source.string[:20], # truncate long regexes
' (truncated)' if len(source.string) > 20 else '',
),
- DeprecationWarning, stacklevel=7
+ DeprecationWarning, stacklevel=nested + 6
)
if (state.flags & SRE_FLAG_VERBOSE) and not verbose:
raise Verbose
@@ -757,11 +758,11 @@ def _parse(source, state, verbose, first=False):
except error as err:
raise source.error(err.msg, len(name) + 1) from None
if condgroup:
- p = _parse_sub_cond(source, state, condgroup, verbose)
+ p = _parse_sub_cond(source, state, condgroup, verbose, nested + 1)
else:
sub_verbose = ((verbose or (add_flags & SRE_FLAG_VERBOSE)) and
not (del_flags & SRE_FLAG_VERBOSE))
- p = _parse_sub(source, state, sub_verbose)
+ p = _parse_sub(source, state, sub_verbose, nested + 1)
if not source.match(")"):
raise source.error("missing ), unterminated subpattern",
source.tell() - start)
@@ -851,7 +852,7 @@ def parse(str, flags=0, pattern=None):
pattern.str = str
try:
- p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, False)
+ p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, 0)
except Verbose:
# the VERBOSE flag was switched on inside the pattern. to be
# on the safe side, we'll parse the whole thing again...
@@ -859,7 +860,7 @@ def parse(str, flags=0, pattern=None):
pattern.flags = flags | SRE_FLAG_VERBOSE
pattern.str = str
source.seek(0)
- p = _parse_sub(source, pattern, True, False)
+ p = _parse_sub(source, pattern, True, 0)
p.pattern.flags = fix_flags(str, p.pattern.flags)
diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py
index c52417ba00..e88d0b3dcf 100644
--- a/Lib/test/test_re.py
+++ b/Lib/test/test_re.py
@@ -1348,6 +1348,7 @@ class ReTests(unittest.TestCase):
str(warns.warnings[0].message),
'Flags not at the start of the expression %s' % p
)
+ self.assertEqual(warns.warnings[0].filename, __file__)
p = upper_char + '(?i)%s' % ('.?' * 100)
with self.assertWarns(DeprecationWarning) as warns:
@@ -1356,6 +1357,7 @@ class ReTests(unittest.TestCase):
str(warns.warnings[0].message),
'Flags not at the start of the expression %s (truncated)' % p[:20]
)
+ self.assertEqual(warns.warnings[0].filename, __file__)
with self.assertWarns(DeprecationWarning):
self.assertTrue(re.match('(?s).(?i)' + upper_char, '\n' + lower_char))
@@ -1367,14 +1369,23 @@ class ReTests(unittest.TestCase):
self.assertTrue(re.match('^(?i)' + upper_char, lower_char))
with self.assertWarns(DeprecationWarning):
self.assertTrue(re.match('$|(?i)' + upper_char, lower_char))
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarns(DeprecationWarning) as warns:
self.assertTrue(re.match('(?:(?i)' + upper_char + ')', lower_char))
- with self.assertWarns(DeprecationWarning):
+ self.assertRegex(str(warns.warnings[0].message),
+ 'Flags not at the start')
+ self.assertEqual(warns.warnings[0].filename, __file__)
+ with self.assertWarns(DeprecationWarning) as warns:
self.assertTrue(re.fullmatch('(^)?(?(1)(?i)' + upper_char + ')',
lower_char))
- with self.assertWarns(DeprecationWarning):
+ self.assertRegex(str(warns.warnings[0].message),
+ 'Flags not at the start')
+ self.assertEqual(warns.warnings[0].filename, __file__)
+ with self.assertWarns(DeprecationWarning) as warns:
self.assertTrue(re.fullmatch('($)?(?(1)|(?i)' + upper_char + ')',
lower_char))
+ self.assertRegex(str(warns.warnings[0].message),
+ 'Flags not at the start')
+ self.assertEqual(warns.warnings[0].filename, __file__)
def test_dollar_matches_twice(self):
diff --git a/Misc/NEWS b/Misc/NEWS
index bfb14c1365..567f40976e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,10 @@ Core and Builtins
Library
-------
+- bpo-30375: Warnings emitted when compile a regular expression now always
+ point to the line in the user code. Previously they could point into inners
+ of the re module if emitted from inside of groups or conditionals.
+
- bpo-30048: Fixed ``Task.cancel()`` can be ignored when the task is
running coroutine and the coroutine returned without any more ``await``.
--
GitLab
From 8fc1ff51adb52c80f6bf78393413c72543bae3e1 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka
Date: Wed, 17 May 2017 00:09:23 +0300
Subject: [PATCH 0207/1433] [3.6] bpo-30380: Fix Sphinx 1.6.1 warnings.
(GH-1613) (#1614)
* Use explicit numbering for footnotes referred by explicit number.
* Restore missed footnote reference in stdtypes.rst.
* Fix literal strings formatting in howto/urllib2.rst.
* Update susp-ignored.csv for zipapp.rst.
* Fix suspicious mark up in Misc/NEWS..
(cherry picked from commit d97b7dc94b19063f0589d401bdc4aaadc7030762)
---
Doc/howto/urllib2.rst | 10 +++++-----
Doc/library/pyexpat.rst | 2 +-
Doc/library/stdtypes.rst | 2 +-
Doc/library/xml.dom.minidom.rst | 2 +-
Doc/library/xml.etree.elementtree.rst | 2 +-
Doc/tools/susp-ignored.csv | 7 +++----
Misc/NEWS | 2 +-
7 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst
index 18b5c6556b..8d383e03ee 100644
--- a/Doc/howto/urllib2.rst
+++ b/Doc/howto/urllib2.rst
@@ -34,8 +34,8 @@ handling common situations - like basic authentication, cookies, proxies and so
on. These are provided by objects called handlers and openers.
urllib.request supports fetching URLs for many "URL schemes" (identified by the string
-before the ":" in URL - for example "ftp" is the URL scheme of
-"ftp://python.org/") using their associated network protocols (e.g. FTP, HTTP).
+before the ``":"`` in URL - for example ``"ftp"`` is the URL scheme of
+``"ftp://python.org/"``) using their associated network protocols (e.g. FTP, HTTP).
This tutorial focuses on the most common case, HTTP.
For straightforward situations *urlopen* is very easy to use. But as soon as you
@@ -511,10 +511,10 @@ than the URL you pass to .add_password() will also match. ::
``top_level_url`` is in fact *either* a full URL (including the 'http:' scheme
component and the hostname and optionally the port number)
-e.g. "http://example.com/" *or* an "authority" (i.e. the hostname,
-optionally including the port number) e.g. "example.com" or "example.com:8080"
+e.g. ``"http://example.com/"`` *or* an "authority" (i.e. the hostname,
+optionally including the port number) e.g. ``"example.com"`` or ``"example.com:8080"``
(the latter example includes a port number). The authority, if present, must
-NOT contain the "userinfo" component - for example "joe:password@example.com" is
+NOT contain the "userinfo" component - for example ``"joe:password@example.com"`` is
not correct.
diff --git a/Doc/library/pyexpat.rst b/Doc/library/pyexpat.rst
index 075a8b5139..e43b9aecd8 100644
--- a/Doc/library/pyexpat.rst
+++ b/Doc/library/pyexpat.rst
@@ -869,7 +869,7 @@ The ``errors`` module has the following attributes:
.. rubric:: Footnotes
-.. [#] The encoding string included in XML output should conform to the
+.. [1] The encoding string included in XML output should conform to the
appropriate standards. For example, "UTF-8" is valid, but "UTF8" is
not. See https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl
and https://www.iana.org/assignments/character-sets/character-sets.xhtml.
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index 6729a20a9c..af0a7b7fe9 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -829,7 +829,7 @@ restrictions imposed by *s*.
The ``in`` and ``not in`` operations have the same priorities as the
comparison operations. The ``+`` (concatenation) and ``*`` (repetition)
-operations have the same priority as the corresponding numeric operations.
+operations have the same priority as the corresponding numeric operations. [3]_
.. index::
triple: operations on; sequence; types
diff --git a/Doc/library/xml.dom.minidom.rst b/Doc/library/xml.dom.minidom.rst
index 2e9e814693..40470e8736 100644
--- a/Doc/library/xml.dom.minidom.rst
+++ b/Doc/library/xml.dom.minidom.rst
@@ -248,7 +248,7 @@ utility to most DOM users.
.. rubric:: Footnotes
-.. [#] The encoding name included in the XML output should conform to
+.. [1] The encoding name included in the XML output should conform to
the appropriate standards. For example, "UTF-8" is valid, but
"UTF8" is not valid in an XML document's declaration, even though
Python accepts it as an encoding name.
diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst
index b54eace411..7d814ad406 100644
--- a/Doc/library/xml.etree.elementtree.rst
+++ b/Doc/library/xml.etree.elementtree.rst
@@ -1192,7 +1192,7 @@ Exceptions
.. rubric:: Footnotes
-.. [#] The encoding string included in XML output should conform to the
+.. [1] The encoding string included in XML output should conform to the
appropriate standards. For example, "UTF-8" is valid, but "UTF8" is
not. See https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl
and https://www.iana.org/assignments/character-sets/character-sets.xhtml.
diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv
index 57b0cf12f5..2dc5404590 100644
--- a/Doc/tools/susp-ignored.csv
+++ b/Doc/tools/susp-ignored.csv
@@ -106,7 +106,7 @@ howto/pyporting,,::,Programming Language :: Python :: 2
howto/pyporting,,::,Programming Language :: Python :: 3
howto/regex,,::,
howto/regex,,:foo,(?:foo)
-howto/urllib2,,:password,"for example ""joe:password@example.com"""
+howto/urllib2,,:password,"""joe:password@example.com"""
library/audioop,,:ipos,"# factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],"
library/bisect,32,:hi,all(val >= x for val in a[i:hi])
library/bisect,42,:hi,all(val > x for val in a[i:hi])
@@ -316,8 +316,8 @@ library/xml.etree.elementtree,,:actor,"for actor in root.findall('real_person:ac
library/xml.etree.elementtree,,:name,"name = actor.find('real_person:name', ns)"
library/xml.etree.elementtree,,:character,"for char in actor.findall('role:character', ns):"
library/zipapp,,:main,"$ python -m zipapp myapp -m ""myapp:main"""
-library/zipapp,,:fn,"argument should have the form ""pkg.mod:fn"", where ""pkg.mod"" is a"
-library/zipapp,,:callable,"""pkg.module:callable"" and the archive will be run by importing"
+library/zipapp,,:fn,"pkg.mod:fn"
+library/zipapp,,:callable,"pkg.module:callable"
library/stdtypes,,::,>>> m[::2].tolist()
library/sys,,`,# ``wrapper`` creates a ``wrap(coro)`` coroutine:
whatsnew/3.5,,:root,'WARNING:root:warning\n'
@@ -326,4 +326,3 @@ whatsnew/3.5,,::,>>> addr6 = ipaddress.IPv6Address('::1')
whatsnew/3.5,,:root,ERROR:root:exception
whatsnew/3.5,,:exception,ERROR:root:exception
whatsnew/changelog,,:version,import sys; I = version[:version.index(' ')]
-whatsnew/changelog,,`,"for readability (was ""`"")."
diff --git a/Misc/NEWS b/Misc/NEWS
index 567f40976e..ca38fe0e5c 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -783,7 +783,7 @@ Library
non-None value is passed to it.send(val).
- Issue #27025: Generated names for Tkinter widgets now start by the "!" prefix
- for readability (was "`").
+ for readability.
- Issue #25464: Fixed HList.header_exists() in tkinter.tix module by addin
a workaround to Tix library bug.
--
GitLab
From 5e2016dce92d66e6e1fb25e6ce39031d8c7d5412 Mon Sep 17 00:00:00 2001
From: Brett Cannon
Date: Tue, 16 May 2017 14:28:21 -0700
Subject: [PATCH 0208/1433] bpo-30380: Pin the version of Sphinx used to build
the docs (GH-1612) (GH-1617)
---
.travis.yml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 5fee6cd767..fe90bad626 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -37,9 +37,11 @@ matrix:
- TESTING=docs
before_script:
- cd Doc
- - make venv
+ # Sphinx is pinned so that new versions that introduce new warnings won't suddenly cause build failures.
+ # (Updating the version is fine as long as no warnings are raised by doing so.)
+ - python -m pip install sphinx~=1.6.1
script:
- - make check suspicious html PYTHON="./venv/bin/python" SPHINXBUILD="./venv/bin/python -m sphinx" SPHINXOPTS="-q -W"
+ - make check suspicious html SPHINXOPTS="-q -W"
- os: linux
language: c
compiler: gcc
--
GitLab
From 0d267041c40a3ab655676b885c0ba35ed9685848 Mon Sep 17 00:00:00 2001
From: Berker Peksag
Date: Wed, 17 May 2017 00:31:39 +0300
Subject: [PATCH 0209/1433] bpo-29898: Fix incorrect env variable name
(GH-1576)
It should read PYTHONLEGACYWINDOWSSTDIO as stated
in section "Add legacy mode" in PEP 528.
(cherry picked from commit 87fa8a780e9045a26c735f085c07bba4b2d0be60)
---
Doc/using/cmdline.rst | 4 ++--
Doc/whatsnew/3.6.rst | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst
index 08dc311d83..40a06b9adc 100644
--- a/Doc/using/cmdline.rst
+++ b/Doc/using/cmdline.rst
@@ -571,7 +571,7 @@ conflict.
.. versionchanged:: 3.6
On Windows, the encoding specified by this variable is ignored for interactive
- console buffers unless :envvar:`PYTHONLEGACYWINDOWSIOENCODING` is also specified.
+ console buffers unless :envvar:`PYTHONLEGACYWINDOWSSTDIO` is also specified.
Files and pipes redirected through the standard streams are not affected.
.. envvar:: PYTHONNOUSERSITE
@@ -700,7 +700,7 @@ conflict.
.. versionadded:: 3.6
See :pep:`529` for more details.
-.. envvar:: PYTHONLEGACYWINDOWSIOENCODING
+.. envvar:: PYTHONLEGACYWINDOWSSTDIO
If set to a non-empty string, does not use the new console reader and
writer. This means that Unicode characters will be encoded according to
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
index a696af4a99..a701cafa61 100644
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -534,7 +534,7 @@ provide correctly read str objects to Python code. ``sys.stdin``,
This change only applies when using an interactive console, and not when
redirecting files or pipes. To revert to the previous behaviour for interactive
-console use, set :envvar:`PYTHONLEGACYWINDOWSIOENCODING`.
+console use, set :envvar:`PYTHONLEGACYWINDOWSSTDIO`.
.. seealso::
--
GitLab
From aaa053652556aa4e59cb68f3983a09ced1d1fe2a Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Tue, 16 May 2017 15:29:41 -0700
Subject: [PATCH 0210/1433] bpo-30329: Catch Windows error 10022 on shutdown()
(#1538) (#1620)
Catch the Windows socket WSAEINVAL error (code 10022) in imaplib and
poplib on shutdown(SHUT_RDWR): An invalid operation was attempted
This error occurs sometimes on SSL connections.
(cherry picked from commit 83a2c2879839da2e10037f5e4af1bd1dafbf1a52)
---
Lib/imaplib.py | 9 ++++++---
Lib/poplib.py | 9 ++++++---
Misc/NEWS | 4 ++++
3 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/Lib/imaplib.py b/Lib/imaplib.py
index 2fa90120e7..1c0b03bff8 100644
--- a/Lib/imaplib.py
+++ b/Lib/imaplib.py
@@ -318,9 +318,12 @@ class IMAP4:
self.file.close()
try:
self.sock.shutdown(socket.SHUT_RDWR)
- except OSError as e:
- # The server might already have closed the connection
- if e.errno != errno.ENOTCONN:
+ except OSError as exc:
+ # The server might already have closed the connection.
+ # On Windows, this may result in WSAEINVAL (error 10022):
+ # An invalid operation was attempted.
+ if (exc.errno != errno.ENOTCONN
+ and getattr(exc, 'winerror', 0) != 10022):
raise
finally:
self.sock.close()
diff --git a/Lib/poplib.py b/Lib/poplib.py
index cae6950eb6..6bcfa5cfeb 100644
--- a/Lib/poplib.py
+++ b/Lib/poplib.py
@@ -288,9 +288,12 @@ class POP3:
if sock is not None:
try:
sock.shutdown(socket.SHUT_RDWR)
- except OSError as e:
- # The server might already have closed the connection
- if e.errno != errno.ENOTCONN:
+ except OSError as exc:
+ # The server might already have closed the connection.
+ # On Windows, this may result in WSAEINVAL (error 10022):
+ # An invalid operation was attempted.
+ if (exc.errno != errno.ENOTCONN
+ and getattr(exc, 'winerror', 0) != 10022):
raise
finally:
sock.close()
diff --git a/Misc/NEWS b/Misc/NEWS
index ca38fe0e5c..6a50c6265c 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,10 @@ Core and Builtins
Library
-------
+- bpo-30329: imaplib and poplib now catch the Windows socket WSAEINVAL error
+ (code 10022) on shutdown(SHUT_RDWR): An invalid operation was attempted.
+ This error occurs sometimes on SSL connections.
+
- bpo-30375: Warnings emitted when compile a regular expression now always
point to the line in the user code. Previously they could point into inners
of the re module if emitted from inside of groups or conditionals.
--
GitLab
From 6b5b85aecf4db796a05582202a6c875b36eae516 Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Tue, 16 May 2017 17:06:14 -0700
Subject: [PATCH 0211/1433] bpo-30357: test_thread now uses threading_cleanup()
(#1592) (#1622)
test_thread: setUp() now uses support.threading_setup() and
support.threading_cleanup() to wait until threads complete to avoid
random side effects on following tests.
Co-Authored-By: Grzegorz Grzywacz
(cherry picked from commit 79ef7f8e88a4972c4aecf95cfc5cd934f1861e08)
---
Lib/test/test_thread.py | 4 ++++
Misc/ACKS | 1 +
Misc/NEWS | 5 +++++
3 files changed, 10 insertions(+)
diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py
index ef3059b686..3909b75ccd 100644
--- a/Lib/test/test_thread.py
+++ b/Lib/test/test_thread.py
@@ -20,6 +20,7 @@ def verbose_print(arg):
with _print_mutex:
print(arg)
+
class BasicThreadTest(unittest.TestCase):
def setUp(self):
@@ -31,6 +32,9 @@ class BasicThreadTest(unittest.TestCase):
self.running = 0
self.next_ident = 0
+ key = support.threading_setup()
+ self.addCleanup(support.threading_cleanup, *key)
+
class ThreadRunningTests(BasicThreadTest):
diff --git a/Misc/ACKS b/Misc/ACKS
index 486b6e3285..ccc9d2af31 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -551,6 +551,7 @@ Eric Groo
Daniel Andrade Groppe
Dag Gruneau
Filip Gruszczyński
+Grzegorz Grzywacz
Thomas Guettler
Yuyang Guo
Anuj Gupta
diff --git a/Misc/NEWS b/Misc/NEWS
index 6a50c6265c..0459e84900 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -168,6 +168,11 @@ Tools/Demos
Tests
-----
+* bpo-30357: test_thread: setUp() now uses support.threading_setup() and
+ support.threading_cleanup() to wait until threads complete to avoid
+ random side effects on following tests. Initial patch written by Grzegorz
+ Grzywacz.
+
- bpo-30197: Enhanced functions swap_attr() and swap_item() in the
test.support module. They now work when delete replaced attribute or item
inside the with statement. The old value of the attribute or item (or None
--
GitLab
From 460945f22acd288e660b432b288d9d81655572bf Mon Sep 17 00:00:00 2001
From: Victor Stinner
Date: Tue, 16 May 2017 17:58:02 -0700
Subject: [PATCH 0212/1433] bpo-30273: update distutils.sysconfig for venv's
created from Python (#1515) (#1625)
compiled out-of-tree (builddir != srcdir). (see also bpo-15366)
(cherry picked from commit dbdea629e2e0e4bd8845aa55041e0a0ca4172cf3)
---
Lib/distutils/sysconfig.py | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
index 90004acea8..2bcd1dd288 100644
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -93,14 +93,11 @@ def get_python_inc(plat_specific=0, prefix=None):
# the build directory may not be the source directory, we
# must use "srcdir" from the makefile to find the "Include"
# directory.
- base = _sys_home or project_base
if plat_specific:
- return base
- if _sys_home:
- incdir = os.path.join(_sys_home, 'Include')
+ return _sys_home or project_base
else:
incdir = os.path.join(get_config_var('srcdir'), 'Include')
- return os.path.normpath(incdir)
+ return os.path.normpath(incdir)
python_dir = 'python' + get_python_version() + build_flags
return os.path.join(prefix, "include", python_dir)
elif os.name == "nt":
--
GitLab
From b769c91c2db304db44cd514344369cde1f8d9dc5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20Miedzi=C5=84ski?=
Date: Wed, 17 May 2017 08:17:55 +0200
Subject: [PATCH 0213/1433] Fix ModuleNotFoundError typo in import reference
(#1610)
(cherry picked from commit c138d84b8d27d338872587aae69a73d8f9d16641)
---
Doc/reference/import.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst
index 4dbd9d88c3..9475b8d55c 100644
--- a/Doc/reference/import.rst
+++ b/Doc/reference/import.rst
@@ -890,7 +890,7 @@ import statements within that module.
To selectively prevent import of some modules from a hook early on the
meta path (rather than disabling the standard import system entirely),
-it is sufficient to raise :exc:`ModuleNoFoundError` directly from
+it is sufficient to raise :exc:`ModuleNotFoundError` directly from
:meth:`~importlib.abc.MetaPathFinder.find_spec` instead of returning
``None``. The latter indicates that the meta path search should continue,
while raising an exception terminates it immediately.
--
GitLab
From 43d4c0329e2348540a3a16ac61b3032f04eefd34 Mon Sep 17 00:00:00 2001
From: Xiang Zhang
Date: Wed, 17 May 2017 22:03:35 +0800
Subject: [PATCH 0214/1433] bpo-30301: Fix AttributeError when using
SimpleQueue.empty() (#1601) (#1628)
Under *spawn* and *forkserver* start methods, SimpleQueue.empty() could
raise AttributeError due to not setting _poll in __setstate__.
---
Lib/multiprocessing/queues.py | 1 +
Lib/test/_test_multiprocessing.py | 36 +++++++++++++++++++++++++++++++
Misc/NEWS | 3 +++
3 files changed, 40 insertions(+)
diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py
index dda03ddf54..a4f4ef8b7b 100644
--- a/Lib/multiprocessing/queues.py
+++ b/Lib/multiprocessing/queues.py
@@ -337,6 +337,7 @@ class SimpleQueue(object):
def __setstate__(self, state):
(self._reader, self._writer, self._rlock, self._wlock) = state
+ self._poll = self._reader.poll
def get(self):
with self._rlock:
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index 57ada12746..3eb83c59ab 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -3958,6 +3958,42 @@ class TestSemaphoreTracker(unittest.TestCase):
self.assertRegex(err, expected)
self.assertRegex(err, r'semaphore_tracker: %r: \[Errno' % name1)
+class TestSimpleQueue(unittest.TestCase):
+
+ @classmethod
+ def _test_empty(cls, queue, child_can_start, parent_can_continue):
+ child_can_start.wait()
+ # issue 30301, could fail under spawn and forkserver
+ try:
+ queue.put(queue.empty())
+ queue.put(queue.empty())
+ finally:
+ parent_can_continue.set()
+
+ def test_empty(self):
+ queue = multiprocessing.SimpleQueue()
+ child_can_start = multiprocessing.Event()
+ parent_can_continue = multiprocessing.Event()
+
+ proc = multiprocessing.Process(
+ target=self._test_empty,
+ args=(queue, child_can_start, parent_can_continue)
+ )
+ proc.daemon = True
+ proc.start()
+
+ self.assertTrue(queue.empty())
+
+ child_can_start.set()
+ parent_can_continue.wait()
+
+ self.assertFalse(queue.empty())
+ self.assertEqual(queue.get(), True)
+ self.assertEqual(queue.get(), False)
+ self.assertTrue(queue.empty())
+
+ proc.join()
+
#
# Mixins
#
diff --git a/Misc/NEWS b/Misc/NEWS
index 0459e84900..6336e67ee4 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,9 @@ Core and Builtins
Library
-------
+- bpo-30301: Fix AttributeError when using SimpleQueue.empty() under
+ *spawn* and *forkserver* start methods.
+
- bpo-30329: imaplib and poplib now catch the Windows socket WSAEINVAL error
(code 10022) on shutdown(SHUT_RDWR): An invalid operation was attempted.
This error occurs sometimes on SSL connections.
--
GitLab
From 0d1727835f44492c7357b013d94539e3891adf77 Mon Sep 17 00:00:00 2001
From: Senthil Kumaran
Date: Wed, 17 May 2017 10:51:01 -0700
Subject: [PATCH 0215/1433] Remove unused variable in test_urllibnet. (#1598)
(#1600)
(cherry picked from commit 1bd7d299bd2a91f8267f97a413568ab8fe7fdfbb)
---
Lib/test/test_urllibnet.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py
index 865a7f4f5f..4103b6c075 100644
--- a/Lib/test/test_urllibnet.py
+++ b/Lib/test/test_urllibnet.py
@@ -11,6 +11,7 @@ import time
support.requires('network')
+
class URLTimeoutTest(unittest.TestCase):
# XXX this test doesn't seem to test anything useful.
@@ -25,7 +26,7 @@ class URLTimeoutTest(unittest.TestCase):
def testURLread(self):
with support.transient_internet("www.example.com"):
f = urllib.request.urlopen("http://www.example.com/")
- x = f.read()
+ f.read()
class urlopenNetworkTests(unittest.TestCase):
@@ -188,6 +189,7 @@ class urlretrieveNetworkTests(unittest.TestCase):
def test_reporthook(self):
records = []
+
def recording_reporthook(blocks, block_size, total_size):
records.append((blocks, block_size, total_size))
--
GitLab
From 69f3a5ac28041fac86897e0c90d98ad9fd6fa3f7 Mon Sep 17 00:00:00 2001
From: Victor Stinner