From fbdfdcb1f79cd20e786f7db3d71d0177e70cba59 Mon Sep 17 00:00:00 2001 From: Michael Felt Date: Mon, 15 Apr 2019 13:36:05 +0000 Subject: [PATCH 001/212] example of what it could become --- Lib/test/support/__init__.py | 3 +++ Lib/test/test_c_locale_coercion.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 5bd15a2feae9d7..e20567ffca6be4 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -101,6 +101,8 @@ # network "HOST", "IPV6_ENABLED", "find_unused_port", "bind_port", "open_urlresource", "bind_unix_socket", + # platform + "is_aix", # processes 'temp_umask', "reap_children", # logging @@ -815,6 +817,7 @@ def dec(*args, **kwargs): requires_lzma = unittest.skipUnless(lzma, 'requires lzma') is_jython = sys.platform.startswith('java') +is_aix = platform.system() == 'AIX' is_android = hasattr(sys, 'getandroidapilevel') diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index 35272b5c15aca7..0685ed85d2431b 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -10,6 +10,7 @@ from collections import namedtuple from test import support +is_aix = support.is_aix from test.support.script_helper import ( run_python_until_end, interpreter_requires_environment, @@ -40,7 +41,7 @@ # TODO: Once https://bugs.python.org/issue30672 is addressed, we'll be # able to check this case unconditionally EXPECTED_C_LOCALE_EQUIVALENTS.append("POSIX") -elif sys.platform.startswith("aix"): +elif is_aix: # AIX uses iso8859-1 in the C locale, other *nix platforms use ASCII EXPECTED_C_LOCALE_STREAM_ENCODING = "iso8859-1" EXPECTED_C_LOCALE_FS_ENCODING = "iso8859-1" From 112e53e8021037bca6dfa2415534b0855efa1c15 Mon Sep 17 00:00:00 2001 From: Michael Felt Date: Mon, 15 Apr 2019 15:13:50 +0000 Subject: [PATCH 002/212] Add constants in Lib/test/support to signify platform during testing --- Lib/test/support/__init__.py | 12 ++++++++++-- Lib/test/test_c_locale_coercion.py | 4 ++-- Lib/test/test_faulthandler.py | 5 ++--- Lib/test/test_fileio.py | 8 ++++---- Lib/test/test_locale.py | 8 +++----- Lib/test/test_shutil.py | 5 ++--- Lib/test/test_strftime.py | 5 +++-- Lib/test/test_strptime.py | 4 ++-- Lib/test/test_utf8_mode.py | 4 ++-- Lib/test/test_wait4.py | 4 ++-- .../Tests/2019-04-15-14-48-48.bpo-36624.yjmwEK.rst | 4 ++++ 11 files changed, 36 insertions(+), 27 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-04-15-14-48-48.bpo-36624.yjmwEK.rst diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index e20567ffca6be4..891bb878bcfc1a 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -97,12 +97,13 @@ "ignore_warnings", # sys "is_jython", "is_android", "check_impl_detail", "unix_shell", + "ANDROID", "JYTHON", "setswitchinterval", # network "HOST", "IPV6_ENABLED", "find_unused_port", "bind_port", "open_urlresource", "bind_unix_socket", # platform - "is_aix", + "AIX", "LINUX", "MACOS", "MS_WINDOWS", # processes 'temp_umask', "reap_children", # logging @@ -816,8 +817,15 @@ def dec(*args, **kwargs): requires_lzma = unittest.skipUnless(lzma, 'requires lzma') +ANDROID = hasattr(sys, 'getandroidapilevel') +JYTHON = sys.platform.startswith('java') + +AIX = platform.system() == 'AIX' +LINUX = platform.system() == 'Linux' +MACOS = platform.system() == 'Darwin' +MS_WINDOWS = platform.system() == 'Windows' + is_jython = sys.platform.startswith('java') -is_aix = platform.system() == 'AIX' is_android = hasattr(sys, 'getandroidapilevel') diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index 0685ed85d2431b..b1a1e0c8f2eb28 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -10,7 +10,7 @@ from collections import namedtuple from test import support -is_aix = support.is_aix +AIX = support.AIX from test.support.script_helper import ( run_python_until_end, interpreter_requires_environment, @@ -41,7 +41,7 @@ # TODO: Once https://bugs.python.org/issue30672 is addressed, we'll be # able to check this case unconditionally EXPECTED_C_LOCALE_EQUIVALENTS.append("POSIX") -elif is_aix: +elif AIX: # AIX uses iso8859-1 in the C locale, other *nix platforms use ASCII EXPECTED_C_LOCALE_STREAM_ENCODING = "iso8859-1" EXPECTED_C_LOCALE_FS_ENCODING = "iso8859-1" diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index f0be91844ffa7c..7171fc3ec4033a 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -7,7 +7,7 @@ import sys import sysconfig from test import support -from test.support import script_helper, is_android +from test.support import script_helper, is_android, AIX import tempfile import threading import unittest @@ -130,8 +130,7 @@ def check_windows_exception(self, code, line_number, name_regex, **kw): fatal_error = 'Windows fatal exception: %s' % name_regex self.check_error(code, line_number, fatal_error, **kw) - @unittest.skipIf(sys.platform.startswith('aix'), - "the first page of memory is a mapped read-only on AIX") + @unittest.skipIf(AIX, "the first page of memory is a mapped read-only on AIX") def test_read_null(self): if not MS_WINDOWS: self.check_fatal_error(""" diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index 57a02656206ff4..6870762f72bed7 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -10,7 +10,7 @@ from functools import wraps from test.support import (TESTFN, TESTFN_UNICODE, check_warnings, run_unittest, - make_bad_fd, cpython_only, swap_attr) + make_bad_fd, cpython_only, swap_attr, AIX) from collections import UserList import _io # C implementation of io @@ -382,9 +382,9 @@ def testAbles(self): else: self.assertEqual(f.readable(), False) self.assertEqual(f.writable(), True) - if sys.platform != "darwin" and \ - 'bsd' not in sys.platform and \ - not sys.platform.startswith(('sunos', 'aix')): + if sys.platform != "darwin" and not AIX \ + and 'bsd' not in sys.platform \ + and not sys.platform.startswith('sunos'): # Somehow /dev/tty appears seekable on some BSDs self.assertEqual(f.seekable(), False) self.assertEqual(f.isatty(), True) diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index e2c2178ae6cc30..4f902ff58a9074 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -1,4 +1,4 @@ -from test.support import verbose, is_android, check_warnings +from test.support import verbose, is_android, check_warnings, AIX import unittest import locale import sys @@ -370,13 +370,11 @@ def setUp(self): raise unittest.SkipTest('wcscoll/wcsxfrm have known bugs') BaseLocalizedTest.setUp(self) - @unittest.skipIf(sys.platform.startswith('aix'), - 'bpo-29972: broken test on AIX') + @unittest.skipIf(AIX, 'bpo-29972: broken test on AIX') def test_strcoll_with_diacritic(self): self.assertLess(locale.strcoll('à', 'b'), 0) - @unittest.skipIf(sys.platform.startswith('aix'), - 'bpo-29972: broken test on AIX') + @unittest.skipIf(AIX, 'bpo-29972: broken test on AIX') def test_strxfrm_with_diacritic(self): self.assertLess(locale.strxfrm('à'), locale.strxfrm('b')) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 678a190bcf5ee0..a34dc71648b4f5 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -30,11 +30,10 @@ posix = None from test import support -from test.support import TESTFN, FakePath +from test.support import TESTFN, FakePath, AIX, MACOS TESTFN2 = TESTFN + "2" -MACOS = sys.platform.startswith("darwin") -AIX = sys.platform[:3] == 'aix' + try: import grp import pwd diff --git a/Lib/test/test_strftime.py b/Lib/test/test_strftime.py index ec305e54ff24f0..ad348f2d6bc786 100644 --- a/Lib/test/test_strftime.py +++ b/Lib/test/test_strftime.py @@ -6,6 +6,7 @@ import sys import re from test import support +from test.support import AIX import time import unittest @@ -187,8 +188,8 @@ class Y1900Tests(unittest.TestCase): def test_y_before_1900(self): # Issue #13674, #19634 t = (1899, 1, 1, 0, 0, 0, 0, 0, 0) - if (sys.platform == "win32" - or sys.platform.startswith(("aix", "sunos", "solaris"))): + if (sys.platform == "win32" or AIX + or sys.platform.startswith(("sunos", "solaris"))): with self.assertRaises(ValueError): time.strftime("%y", t) else: diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 623da401eee4ff..6285744aeb1ac2 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -7,6 +7,7 @@ import os import sys from test import support +from test.support import AIX from datetime import date as datetime_date import _strptime @@ -531,8 +532,7 @@ def test_day_of_week_calculation(self): _ymd_excluded = () _formats_excluded = () - @unittest.skipIf(sys.platform.startswith('aix'), - 'bpo-29972: broken test on AIX') + @unittest.skipIf(AIX, 'bpo-29972: broken test on AIX') def test_week_of_year_and_day_of_week_calculation(self): # Should be able to infer date if given year, week of year (%U or %W) # and day of the week diff --git a/Lib/test/test_utf8_mode.py b/Lib/test/test_utf8_mode.py index 2429b00459be51..f3f788ee86f478 100644 --- a/Lib/test/test_utf8_mode.py +++ b/Lib/test/test_utf8_mode.py @@ -7,10 +7,10 @@ import textwrap import unittest from test import support +from test.support import AIX, MS_WINDOWS from test.support.script_helper import assert_python_ok, assert_python_failure -MS_WINDOWS = (sys.platform == 'win32') POSIX_LOCALES = ('C', 'POSIX') VXWORKS = (sys.platform == "vxworks") @@ -227,7 +227,7 @@ def check(utf8_opt, expected, **kw): if sys.platform == 'darwin' or support.is_android or VXWORKS: c_arg = arg_utf8 - elif sys.platform.startswith("aix"): + elif AIX: c_arg = arg.decode('iso-8859-1') else: c_arg = arg_ascii diff --git a/Lib/test/test_wait4.py b/Lib/test/test_wait4.py index 3e6a79df463cb4..15582f28d1f022 100644 --- a/Lib/test/test_wait4.py +++ b/Lib/test/test_wait4.py @@ -6,7 +6,7 @@ import sys import unittest from test.fork_wait import ForkWait -from test.support import reap_children, get_attribute +from test.support import reap_children, get_attribute, AIX # If either of these do not exist, skip this test. get_attribute(os, 'fork') @@ -16,7 +16,7 @@ class Wait4Test(ForkWait): def wait_impl(self, cpid): option = os.WNOHANG - if sys.platform.startswith('aix'): + if AIX: # Issue #11185: wait4 is broken on AIX and will always return 0 # with WNOHANG. option = 0 diff --git a/Misc/NEWS.d/next/Tests/2019-04-15-14-48-48.bpo-36624.yjmwEK.rst b/Misc/NEWS.d/next/Tests/2019-04-15-14-48-48.bpo-36624.yjmwEK.rst new file mode 100644 index 00000000000000..fb9014fb9f4e56 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-04-15-14-48-48.bpo-36624.yjmwEK.rst @@ -0,0 +1,4 @@ +Add constants in Lib/test/support to support platform determination. +From platform.system() determine AIX, LINUX, MACOS, WINDOWS. +From sys determine ANDROID (was is_android) and JYTHON (was is_jython). +Patch by M. Felt. From aba7d662abbb847f9f45c6db58242a9b4bf65bff Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 15 Apr 2019 17:29:31 +0200 Subject: [PATCH 003/212] bpo-35134: Add cpython/pymem.h to build system (GH-12842) --- Makefile.pre.in | 1 + PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 +++ 3 files changed, 5 insertions(+) diff --git a/Makefile.pre.in b/Makefile.pre.in index 05c195767a8ba0..cd7098cac72b1d 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1056,6 +1056,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/cpython/objimpl.h \ $(srcdir)/Include/cpython/pyerrors.h \ $(srcdir)/Include/cpython/pylifecycle.h \ + $(srcdir)/Include/cpython/pymem.h \ $(srcdir)/Include/cpython/pystate.h \ $(srcdir)/Include/cpython/tupleobject.h \ $(srcdir)/Include/cpython/unicodeobject.h \ diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index a980799461a306..a135e9326c781e 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -117,6 +117,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index f92433e3e0c97e..9134646567954e 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -102,6 +102,9 @@ Include + + Include + Include From 0810fa79885276114d1a94e2ce61da367ebb1ffc Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 15 Apr 2019 17:54:09 +0200 Subject: [PATCH 004/212] bpo-36389: Cleanup gc.set_threshold() (GH-12844) Don't assign generations[2].threshold to generations[2].threshold: useless operation. --- Modules/gcmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index fad1356d6b443d..a75d5fed95f11e 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1374,7 +1374,7 @@ gc_set_thresh(PyObject *self, PyObject *args) &_PyRuntime.gc.generations[1].threshold, &_PyRuntime.gc.generations[2].threshold)) return NULL; - for (i = 2; i < NUM_GENERATIONS; i++) { + for (i = 3; i < NUM_GENERATIONS; i++) { /* generations higher than 2 get the same threshold */ _PyRuntime.gc.generations[i].threshold = _PyRuntime.gc.generations[2].threshold; } @@ -1524,7 +1524,7 @@ gc_get_objects_impl(PyObject *module, Py_ssize_t generation) } /* If generation is passed, we extract only that generation */ - if (generation != -1) { + if (generation != -1) { if (generation >= NUM_GENERATIONS) { PyErr_Format(PyExc_ValueError, "generation parameter must be less than the number of " From 74125a60b7a477451ff2b8385bfbce3fdaee8dbc Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 15 Apr 2019 18:23:20 +0200 Subject: [PATCH 005/212] bpo-36348: IMAP4.logout() doesn't ignore exc (GH-12411) The imap.IMAP4.logout() method no longer ignores silently arbitrary exceptions. Changes: * The IMAP4.logout() method now expects a "BYE" untagged response, rather than relying on _check_bye() which raises a self.abort() exception. * IMAP4.__exit__() now does nothing if the client already logged out. * Add more debug info if test_logout() tests fail. --- Doc/library/imaplib.rst | 3 +++ Doc/whatsnew/3.8.rst | 3 +++ Lib/imaplib.py | 25 ++++++++++++------- Lib/test/test_imaplib.py | 8 +++--- .../2019-03-18-16-16-55.bpo-36348.E0w_US.rst | 2 ++ 5 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-03-18-16-16-55.bpo-36348.E0w_US.rst diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst index d0709f8b678e43..f027f82ddebe61 100644 --- a/Doc/library/imaplib.rst +++ b/Doc/library/imaplib.rst @@ -327,6 +327,9 @@ An :class:`IMAP4` instance has the following methods: Shutdown connection to server. Returns server ``BYE`` response. + .. versionchanged:: 3.8 + The method no longer ignores silently arbitrary exceptions. + .. method:: IMAP4.lsub(directory='""', pattern='*') diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 39a0da5e61e9ff..f866f9ccb8c16f 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -709,6 +709,9 @@ Changes in Python behavior Changes in the Python API ------------------------- +* The :meth:`imap.IMAP4.logout` method no longer ignores silently arbitrary + exceptions. + * The function :func:`platform.popen` has been removed, it was deprecated since Python 3.3: use :func:`os.popen` instead. diff --git a/Lib/imaplib.py b/Lib/imaplib.py index dd237f7704aca0..341ee25ae96514 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -272,6 +272,9 @@ def __enter__(self): return self def __exit__(self, *args): + if self.state == "LOGOUT": + return + try: self.logout() except OSError: @@ -625,11 +628,8 @@ def logout(self): Returns server 'BYE' response. """ self.state = 'LOGOUT' - try: typ, dat = self._simple_command('LOGOUT') - except: typ, dat = 'NO', ['%s: %s' % sys.exc_info()[:2]] + typ, dat = self._simple_command('LOGOUT') self.shutdown() - if 'BYE' in self.untagged_responses: - return 'BYE', self.untagged_responses['BYE'] return typ, dat @@ -1012,16 +1012,17 @@ def _command(self, name, *args): def _command_complete(self, name, tag): + logout = (name == 'LOGOUT') # BYE is expected after LOGOUT - if name != 'LOGOUT': + if not logout: self._check_bye() try: - typ, data = self._get_tagged_response(tag) + typ, data = self._get_tagged_response(tag, expect_bye=logout) except self.abort as val: raise self.abort('command: %s => %s' % (name, val)) except self.error as val: raise self.error('command: %s => %s' % (name, val)) - if name != 'LOGOUT': + if not logout: self._check_bye() if typ == 'BAD': raise self.error('%s command error: %s %s' % (name, typ, data)) @@ -1117,7 +1118,7 @@ def _get_response(self): return resp - def _get_tagged_response(self, tag): + def _get_tagged_response(self, tag, expect_bye=False): while 1: result = self.tagged_commands[tag] @@ -1125,9 +1126,15 @@ def _get_tagged_response(self, tag): del self.tagged_commands[tag] return result + if expect_bye: + typ = 'BYE' + bye = self.untagged_responses.pop(typ, None) + if bye is not None: + # Server replies to the "LOGOUT" command with "BYE" + return (typ, bye) + # If we've seen a BYE at this point, the socket will be # closed, so report the BYE now. - self._check_bye() # Some have reported "unexpected response" exceptions. diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index aec36af6c525f1..9305e47ee99315 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -470,8 +470,8 @@ def test_logout(self): self.assertEqual(typ, 'OK') self.assertEqual(data[0], b'LOGIN completed') typ, data = client.logout() - self.assertEqual(typ, 'BYE') - self.assertEqual(data[0], b'IMAP4ref1 Server logging out') + self.assertEqual(typ, 'BYE', (typ, data)) + self.assertEqual(data[0], b'IMAP4ref1 Server logging out', (typ, data)) self.assertEqual(client.state, 'LOGOUT') def test_lsub(self): @@ -937,7 +937,7 @@ def test_logout(self): with transient_internet(self.host): rs = self.server.logout() self.server = None - self.assertEqual(rs[0], 'BYE') + self.assertEqual(rs[0], 'BYE', rs) @unittest.skipUnless(ssl, "SSL not available") @@ -995,7 +995,7 @@ def test_logout(self): with transient_internet(self.host): _server = self.imap_class(self.host, self.port) rs = _server.logout() - self.assertEqual(rs[0], 'BYE') + self.assertEqual(rs[0], 'BYE', rs) def test_ssl_context_certfile_exclusive(self): with transient_internet(self.host): diff --git a/Misc/NEWS.d/next/Library/2019-03-18-16-16-55.bpo-36348.E0w_US.rst b/Misc/NEWS.d/next/Library/2019-03-18-16-16-55.bpo-36348.E0w_US.rst new file mode 100644 index 00000000000000..2320b4c05b5367 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-03-18-16-16-55.bpo-36348.E0w_US.rst @@ -0,0 +1,2 @@ +The :meth:`imap.IMAP4.logout` method no longer ignores silently arbitrary +exceptions. From 6fa84bd12c4b83bee6a41b989363230d5c03b96c Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Tue, 16 Apr 2019 08:32:28 +0900 Subject: [PATCH 006/212] bpo-27860: ipaddress: fix Interface missed some attributes (GH-12836) IPv4Interface and IPv6Interface did not has netmask and hostmask attributes when its argument is bytes or int. This commit extracts method for constructors of Network and Interface, and ensure Interface class always provides them. --- Lib/ipaddress.py | 110 ++++++++++++++----------------------- Lib/test/test_ipaddress.py | 17 +++++- 2 files changed, 56 insertions(+), 71 deletions(-) diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 7a3f36f3bc0f48..909a55de4f197d 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -532,6 +532,30 @@ def _prefix_from_ip_string(cls, ip_str): except ValueError: cls._report_invalid_netmask(ip_str) + @classmethod + def _split_addr_prefix(cls, address): + """Helper function to parse address of Network/Interface. + + Arg: + address: Argument of Network/Interface. + + Returns: + (addr, prefix) tuple. + """ + # a packed address or integer + if isinstance(address, (bytes, int)): + return address, cls._max_prefixlen + + if not isinstance(address, tuple): + # Assume input argument to be string or any object representation + # which converts into a formatted IP prefix string. + address = _split_optional_netmask(address) + + # Constructing from a tuple (addr, [mask]) + if len(address) > 1: + return address + return address[0], cls._max_prefixlen + def __reduce__(self): return self.__class__, (str(self),) @@ -1305,32 +1329,16 @@ def is_link_local(self): class IPv4Interface(IPv4Address): def __init__(self, address): - if isinstance(address, (bytes, int)): - IPv4Address.__init__(self, address) - self.network = IPv4Network(self._ip) - self._prefixlen = self._max_prefixlen - return - - if isinstance(address, tuple): - IPv4Address.__init__(self, address[0]) - if len(address) > 1: - self._prefixlen = int(address[1]) - else: - self._prefixlen = self._max_prefixlen - - self.network = IPv4Network(address, strict=False) - self.netmask = self.network.netmask - self.hostmask = self.network.hostmask - return - - addr = _split_optional_netmask(address) - IPv4Address.__init__(self, addr[0]) + addr, mask = self._split_addr_prefix(address) - self.network = IPv4Network(address, strict=False) + IPv4Address.__init__(self, addr) + self.network = IPv4Network((addr, mask), strict=False) + self.netmask = self.network.netmask self._prefixlen = self.network._prefixlen - self.netmask = self.network.netmask - self.hostmask = self.network.hostmask + @functools.cached_property + def hostmask(self): + return self.network.hostmask def __str__(self): return '%s/%d' % (self._string_from_ip_int(self._ip), @@ -1435,20 +1443,7 @@ def __init__(self, address, strict=True): ValueError: If strict is True and a network address is not supplied. """ - # Constructing from a packed address or integer - if isinstance(address, (int, bytes)): - addr = address - mask = self._max_prefixlen - # Constructing from a tuple (addr, [mask]) - elif isinstance(address, tuple): - addr = address[0] - mask = address[1] if len(address) > 1 else self._max_prefixlen - # Assume input argument to be string or any object representation - # which converts into a formatted IP prefix string. - else: - args = _split_optional_netmask(address) - addr = self._ip_int_from_string(args[0]) - mask = args[1] if len(args) == 2 else self._max_prefixlen + addr, mask = self._split_addr_prefix(address) self.network_address = IPv4Address(addr) self.netmask, self._prefixlen = self._make_netmask(mask) @@ -1979,28 +1974,16 @@ def sixtofour(self): class IPv6Interface(IPv6Address): def __init__(self, address): - if isinstance(address, (bytes, int)): - IPv6Address.__init__(self, address) - self.network = IPv6Network(self._ip) - self._prefixlen = self._max_prefixlen - return - if isinstance(address, tuple): - IPv6Address.__init__(self, address[0]) - if len(address) > 1: - self._prefixlen = int(address[1]) - else: - self._prefixlen = self._max_prefixlen - self.network = IPv6Network(address, strict=False) - self.netmask = self.network.netmask - self.hostmask = self.network.hostmask - return + addr, mask = self._split_addr_prefix(address) - addr = _split_optional_netmask(address) - IPv6Address.__init__(self, addr[0]) - self.network = IPv6Network(address, strict=False) + IPv6Address.__init__(self, addr) + self.network = IPv6Network((addr, mask), strict=False) self.netmask = self.network.netmask self._prefixlen = self.network._prefixlen - self.hostmask = self.network.hostmask + + @functools.cached_property + def hostmask(self): + return self.network.hostmask def __str__(self): return '%s/%d' % (self._string_from_ip_int(self._ip), @@ -2110,20 +2093,7 @@ def __init__(self, address, strict=True): ValueError: If strict was True and a network address was not supplied. """ - # Constructing from a packed address or integer - if isinstance(address, (int, bytes)): - addr = address - mask = self._max_prefixlen - # Constructing from a tuple (addr, [mask]) - elif isinstance(address, tuple): - addr = address[0] - mask = address[1] if len(address) > 1 else self._max_prefixlen - # Assume input argument to be string or any object representation - # which converts into a formatted IP prefix string. - else: - args = _split_optional_netmask(address) - addr = self._ip_int_from_string(args[0]) - mask = args[1] if len(args) == 2 else self._max_prefixlen + addr, mask = self._split_addr_prefix(address) self.network_address = IPv6Address(addr) self.netmask, self._prefixlen = self._make_netmask(mask) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 15317c9446306a..20316f15f8cfbd 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -399,7 +399,13 @@ class NetmaskTestMixin_v4(CommonTestMixin_v4): """Input validation on interfaces and networks is very similar""" def test_no_mask(self): - self.assertEqual(str(self.factory('1.2.3.4')), '1.2.3.4/32') + for address in ('1.2.3.4', 0x01020304, b'\x01\x02\x03\x04'): + net = self.factory(address) + self.assertEqual(str(net), '1.2.3.4/32') + self.assertEqual(str(net.netmask), '255.255.255.255') + self.assertEqual(str(net.hostmask), '0.0.0.0') + # IPv4Network has prefixlen, but IPv4Interface doesn't. + # Should we add it to IPv4Interface too? (bpo-36392) def test_split_netmask(self): addr = "1.2.3.4/32/24" @@ -527,6 +533,15 @@ def test_subnet_of_mixed_types(self): class NetmaskTestMixin_v6(CommonTestMixin_v6): """Input validation on interfaces and networks is very similar""" + def test_no_mask(self): + for address in ('::1', 1, b'\x00'*15 + b'\x01'): + net = self.factory(address) + self.assertEqual(str(net), '::1/128') + self.assertEqual(str(net.netmask), 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff') + self.assertEqual(str(net.hostmask), '::') + # IPv6Network has prefixlen, but IPv6Interface doesn't. + # Should we add it to IPv4Interface too? (bpo-36392) + def test_split_netmask(self): addr = "cafe:cafe::/128/190" with self.assertAddressError("Only one '/' permitted in %r" % addr): From 2b7f93b99afbe78e4e567d9252d9470d29f387c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Tue, 16 Apr 2019 14:52:54 +0200 Subject: [PATCH 007/212] bpo-36345: Update wsgiref example (GH-12562) Use literalinclude markup to include Tools/scripts/serve.py code. Tools/scripts/serve.py first argument on the command line is now optional. --- Doc/library/wsgiref.rst | 34 +++---------------- .../2019-03-26-14-58-34.bpo-36345.r2stx3.rst | 3 ++ Tools/scripts/serve.py | 5 +-- 3 files changed, 10 insertions(+), 32 deletions(-) create mode 100644 Misc/NEWS.d/next/Documentation/2019-03-26-14-58-34.bpo-36345.r2stx3.rst diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst index b85ec53c8ae536..ec5136742fa2c4 100644 --- a/Doc/library/wsgiref.rst +++ b/Doc/library/wsgiref.rst @@ -783,33 +783,7 @@ This is a working "Hello World" WSGI application:: httpd.serve_forever() -Example of a small wsgiref-based web server:: - - # Takes a path to serve from and an optional port number (defaults to 8000), - # then tries to serve files. Mime types are guessed from the file names, 404 - # errors are raised if the file is not found. - import sys - import os - import mimetypes - from wsgiref import simple_server, util - - def app(environ, respond): - fn = os.path.join(path, environ['PATH_INFO'][1:]) - if '.' not in fn.split(os.path.sep)[-1]: - fn = os.path.join(fn, 'index.html') - type = mimetypes.guess_type(fn)[0] - - if os.path.exists(fn): - respond('200 OK', [('Content-Type', type)]) - return util.FileWrapper(open(fn, "rb")) - else: - respond('404 Not Found', [('Content-Type', 'text/plain')]) - return [b'not found'] - - path = sys.argv[1] - port = int(sys.argv[2]) if len(sys.argv) > 2 else 8000 - with simple_server.make_server('', port, app) as httpd: - print("Serving {} on port {}, control-C to stop".format(path, port)) - - # Serve until process is killed - httpd.serve_forever() +Example of a WSGI application serving the current directory, accept optional +directory and port number (default: 8000) on the command line: + +.. literalinclude:: ../../Tools/scripts/serve.py diff --git a/Misc/NEWS.d/next/Documentation/2019-03-26-14-58-34.bpo-36345.r2stx3.rst b/Misc/NEWS.d/next/Documentation/2019-03-26-14-58-34.bpo-36345.r2stx3.rst new file mode 100644 index 00000000000000..bbecc947cafa74 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-03-26-14-58-34.bpo-36345.r2stx3.rst @@ -0,0 +1,3 @@ +Avoid the duplication of code from ``Tools/scripts/serve.py`` in using the +:rst:dir:`literalinclude` directive for the basic wsgiref-based web server in the +documentation of :mod:`wsgiref`. Contributed by Stéphane Wirtel. diff --git a/Tools/scripts/serve.py b/Tools/scripts/serve.py index dae21f2260ff13..7ac9c105078329 100755 --- a/Tools/scripts/serve.py +++ b/Tools/scripts/serve.py @@ -25,11 +25,12 @@ def app(environ, respond): return [b'not found'] if __name__ == '__main__': - path = sys.argv[1] + path = sys.argv[1] if len(sys.argv) > 1 else os.getcwd() port = int(sys.argv[2]) if len(sys.argv) > 2 else 8000 httpd = simple_server.make_server('', port, app) print("Serving {} on port {}, control-C to stop".format(path, port)) try: httpd.serve_forever() except KeyboardInterrupt: - print("\b\bShutting down.") + print("Shutting down.") + httpd.server_close() From 2f5b44879f244fbb577bd97df844b7bd4b9a19a5 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Tue, 16 Apr 2019 16:54:56 +0300 Subject: [PATCH 008/212] Add myself to CODEOWNERS for sqlite3 and urllib.robotparser (GH-12856) --- .github/CODEOWNERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 40d2cc127690e5..2ca555b7fa50c4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -43,6 +43,9 @@ Python/bootstrap_hash.c @python/crypto-team **/*imap* @python/email-team **/*poplib* @python/email-team +# SQLite 3 +**/*sqlite* @berkerpeksag + # subprocess **/*subprocess* @gpshead @@ -50,6 +53,9 @@ Python/bootstrap_hash.c @python/crypto-team /PC/ @python/windows-team /PCbuild/ @python/windows-team +# Urllib +**/*robotparser* @berkerpeksag + # Windows installer packages /Tools/msi/ @python/windows-team /Tools/nuget/ @python/windows-team From a4dfc3ba0c264836624793b8d3e5b67bc6e173da Mon Sep 17 00:00:00 2001 From: Michael Felt Date: Tue, 16 Apr 2019 14:36:04 +0000 Subject: [PATCH 009/212] Ready for first CI testing --- Doc/whatsnew/3.8.rst | 10 +++++ Lib/test/_test_multiprocessing.py | 35 +++++++-------- Lib/test/datetimetester.py | 8 ++-- Lib/test/test___all__.py | 3 +- Lib/test/test__osx_support.py | 3 +- Lib/test/test_asynchat.py | 6 +-- Lib/test/test_asyncore.py | 3 +- Lib/test/test_c_locale_coercion.py | 11 ++--- Lib/test/test_cmath.py | 4 +- Lib/test/test_cmd_line.py | 12 +++-- Lib/test/test_cmd_line_script.py | 4 +- Lib/test/test_codecs.py | 6 +-- Lib/test/test_concurrent_futures.py | 5 ++- Lib/test/test_decimal.py | 8 ++-- Lib/test/test_exceptions.py | 7 ++- Lib/test/test_faulthandler.py | 17 +++---- Lib/test/test_fcntl.py | 4 +- Lib/test/test_fileio.py | 9 ++-- Lib/test/test_gdb.py | 4 +- Lib/test/test_genericpath.py | 6 +-- Lib/test/test_glob.py | 6 +-- Lib/test/test_httpservers.py | 9 ++-- Lib/test/test_imp.py | 4 +- Lib/test/test_io.py | 6 +-- Lib/test/test_largefile.py | 4 +- Lib/test/test_locale.py | 8 ++-- Lib/test/test_logging.py | 9 ++-- Lib/test/test_math.py | 4 +- Lib/test/test_mimetypes.py | 3 +- Lib/test/test_mmap.py | 13 +++--- Lib/test/test_multiprocessing_fork.py | 5 ++- Lib/test/test_multiprocessing_forkserver.py | 2 +- Lib/test/test_ntpath.py | 6 +-- Lib/test/test_os.py | 49 ++++++++++----------- Lib/test/test_osx_env.py | 5 +-- Lib/test/test_pathlib.py | 5 +-- Lib/test/test_platform.py | 9 ++-- Lib/test/test_posix.py | 7 +-- Lib/test/test_regrtest.py | 7 +-- Lib/test/test_resource.py | 3 +- Lib/test/test_select.py | 4 +- Lib/test/test_selectors.py | 6 +-- Lib/test/test_shutil.py | 6 +-- Lib/test/test_signal.py | 19 ++++---- Lib/test/test_site.py | 12 ++--- Lib/test/test_smtplib.py | 4 +- Lib/test/test_socket.py | 31 ++++++------- Lib/test/test_ssl.py | 9 ++-- Lib/test/test_stat.py | 4 +- Lib/test/test_strftime.py | 4 +- Lib/test/test_subprocess.py | 34 +++++++------- Lib/test/test_sundry.py | 4 +- Lib/test/test_sys.py | 5 ++- Lib/test/test_sysconfig.py | 17 ++++--- Lib/test/test_tarfile.py | 12 ++--- Lib/test/test_tcl.py | 2 +- Lib/test/test_tempfile.py | 8 ++-- Lib/test/test_threading.py | 4 +- Lib/test/test_threadsignals.py | 9 ++-- Lib/test/test_time.py | 5 ++- Lib/test/test_tix.py | 2 +- Lib/test/test_unicode.py | 13 +++--- Lib/test/test_unicode_file_functions.py | 9 ++-- Lib/test/test_urllib.py | 2 +- Lib/test/test_urllib2.py | 3 +- Lib/test/test_utf8_mode.py | 4 +- Lib/test/test_venv.py | 9 ++-- Lib/test/test_winconsoleio.py | 3 +- Lib/test/test_zipapp.py | 8 ++-- 69 files changed, 293 insertions(+), 288 deletions(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 39a0da5e61e9ff..7f4f8d51b694df 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -374,6 +374,16 @@ in a standardized and extensible format, and offers several other benefits. (Contributed by C.A.M. Gerlach in :issue:`36268`.) +test +---- + +The :mod:`test` module now uses ``CONSTANTS`` for the major platforms +(``AIX``, ``ANDROID``, ``LINUX``, ``JYTHON``, ``MACOS``, ``MS_WINDOWS``) +to standardize the style compared to the current practice of some constants +and different styles of sys.platform and platform.system(). +The constants are defined in `test.support`. +(Contributed by M. Felt in :issue:`36624'.) + tokenize -------- diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 553ab8178316a9..25c2cfce36c633 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -25,6 +25,7 @@ import test.support import test.support.script_helper from test import support +from test.support import LINUX, MACOS, MS_WINDOWS # Skip tests if _multiprocessing wasn't built. @@ -108,8 +109,6 @@ def join_process(process): HAVE_GETVALUE = not getattr(_multiprocessing, 'HAVE_BROKEN_SEM_GETVALUE', False) -WIN32 = (sys.platform == "win32") - from multiprocessing.connection import wait def wait_for_handle(handle, timeout): @@ -508,7 +507,7 @@ def test_many_processes(self): join_process(p) if os.name != 'nt': exitcodes = [-signal.SIGTERM] - if sys.platform == 'darwin': + if MACOS: # bpo-31510: On macOS, killing a freshly started process with # SIGTERM sometimes kills the process with SIGKILL. exitcodes.append(-signal.SIGKILL) @@ -1487,7 +1486,7 @@ def _test_wait_result(cls, c, pid): os.kill(pid, signal.SIGINT) def test_wait_result(self): - if isinstance(self, ProcessesMixin) and sys.platform != 'win32': + if isinstance(self, ProcessesMixin) and not MS_WINDOWS: pid = os.getpid() else: pid = None @@ -3096,8 +3095,7 @@ def test_fd_transfer(self): self.assertEqual(f.read(), b"foo") @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction") - @unittest.skipIf(sys.platform == "win32", - "test semantics don't make sense on Windows") + @unittest.skipIf(MS_WINDOWS, "test semantics don't make sense on Windows") @unittest.skipIf(MAXFD <= 256, "largest assignable fd number is too small") @unittest.skipUnless(hasattr(os, "dup2"), @@ -3133,7 +3131,7 @@ def _send_data_without_fd(self, conn): os.write(conn.fileno(), b"\0") @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction") - @unittest.skipIf(sys.platform == "win32", "doesn't make sense on Windows") + @unittest.skipIf(MS_WINDOWS, "doesn't make sense on Windows") def test_missing_fd_transfer(self): # Check that exception is raised when received data is not # accompanied by a file descriptor in ancillary data. @@ -3747,7 +3745,7 @@ def test_shared_memory_SharedMemoryManager_basics(self): self.assertGreaterEqual(len(doppleganger_shm0.buf), 32) held_name = lom[0].name smm1.shutdown() - if sys.platform != "win32": + if not MS_WINDOWS: # Calls to unlink() have no effect on Windows platform; shared # memory will only be released once final process exits. with self.assertRaises(FileNotFoundError): @@ -3758,7 +3756,7 @@ def test_shared_memory_SharedMemoryManager_basics(self): sl = smm2.ShareableList("howdy") shm = smm2.SharedMemory(size=128) held_name = sl.shm.name - if sys.platform != "win32": + if not MS_WINDOWS: with self.assertRaises(FileNotFoundError): # No longer there to be attached to again. absent_sl = shared_memory.ShareableList(name=held_name) @@ -4011,7 +4009,7 @@ def get_module_names(self): def test_import(self): modules = self.get_module_names() - if sys.platform == 'win32': + if MS_WINDOWS: modules.remove('multiprocessing.popen_fork') modules.remove('multiprocessing.popen_forkserver') modules.remove('multiprocessing.popen_spawn_posix') @@ -4144,7 +4142,7 @@ def record(*args): class TestInvalidHandle(unittest.TestCase): - @unittest.skipIf(WIN32, "skipped on Windows") + @unittest.skipIf(MS_WINDOWS, "skipped on Windows") def test_invalid_handles(self): conn = multiprocessing.connection.Connection(44977608) # check that poll() doesn't crash @@ -4470,12 +4468,12 @@ def test_neg_timeout(self): class TestInvalidFamily(unittest.TestCase): - @unittest.skipIf(WIN32, "skipped on Windows") + @unittest.skipIf(MS_WINDOWS, "skipped on Windows") def test_invalid_family(self): with self.assertRaises(ValueError): multiprocessing.connection.Listener(r'\\.\test') - @unittest.skipUnless(WIN32, "skipped on non-Windows platforms") + @unittest.skipUnless(MS_WINDOWS, "skipped on non-Windows platforms") def test_invalid_family_win32(self): with self.assertRaises(ValueError): multiprocessing.connection.Listener('/var/test.pipe') @@ -4601,7 +4599,7 @@ def test_lock(self): class TestCloseFds(unittest.TestCase): def get_high_socket_fd(self): - if WIN32: + if MS_WINDOWS: # The child process will not have any socket handles, so # calling socket.fromfd() should produce WSAENOTSOCK even # if there is a handle of the same number. @@ -4619,7 +4617,7 @@ def get_high_socket_fd(self): return fd def close(self, fd): - if WIN32: + if MS_WINDOWS: socket.socket(socket.AF_INET, socket.SOCK_STREAM, fileno=fd).close() else: os.close(fd) @@ -4782,7 +4780,7 @@ def test_set_get(self): def test_get_all(self): methods = multiprocessing.get_all_start_methods() - if sys.platform == 'win32': + if MS_WINDOWS: self.assertEqual(methods, ['spawn']) else: self.assertTrue(methods == ['fork', 'spawn'] or @@ -4801,8 +4799,7 @@ def test_preload_resources(self): self.fail("failed spawning forkserver or grandchild") -@unittest.skipIf(sys.platform == "win32", - "test semantics don't make sense on Windows") +@unittest.skipIf(MS_WINDOWS, "test semantics don't make sense on Windows") class TestSemaphoreTracker(unittest.TestCase): def test_semaphore_tracker(self): @@ -5392,7 +5389,7 @@ def setUpModule(): raise unittest.SkipTest(start_method + ' start method not supported') - if sys.platform.startswith("linux"): + if LINUX: try: lock = multiprocessing.RLock() except OSError: diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 715f0ea6b40d23..d01017bd78f9a7 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -2,7 +2,7 @@ See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases """ -from test.support import is_resource_enabled +from test.support import is_resource_enabled, MS_WINDOWS import itertools import bisect @@ -2377,13 +2377,13 @@ def test_insane_utcfromtimestamp(self): self.assertRaises(OverflowError, self.theclass.utcfromtimestamp, insane) - @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps") + @unittest.skipIf(MS_WINDOWS, "Windows doesn't accept negative timestamps") def test_negative_float_fromtimestamp(self): # The result is tz-dependent; at least test that this doesn't # fail (like it did before bug 1646728 was fixed). self.theclass.fromtimestamp(-1.05) - @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps") + @unittest.skipIf(MS_WINDOWS, "Windows doesn't accept negative timestamps") def test_negative_float_utcfromtimestamp(self): d = self.theclass.utcfromtimestamp(-1.05) self.assertEqual(d, self.theclass(1969, 12, 31, 23, 59, 58, 950000)) @@ -5624,7 +5624,7 @@ class ZoneInfoTest(unittest.TestCase): zonename = 'America/New_York' def setUp(self): - if sys.platform == "win32": + if MS_WINDOWS: self.skipTest("Skipping zoneinfo tests on Windows") try: self.tz = ZoneInfo.fromname(self.zonename) diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py index f6e82eb64ab025..c9f29e18605195 100644 --- a/Lib/test/test___all__.py +++ b/Lib/test/test___all__.py @@ -1,5 +1,6 @@ import unittest from test import support +from test.support import JYTHON import os import sys @@ -67,7 +68,7 @@ def test_all(self): '__future__', ]) - if not sys.platform.startswith('java'): + if not JYTHON: # In case _socket fails to build, make this test fail more gracefully # than an AttributeError somewhere deep in CGIHTTPServer. import _socket diff --git a/Lib/test/test__osx_support.py b/Lib/test/test__osx_support.py index 388a2b1a84b17c..4b5897232c2627 100644 --- a/Lib/test/test__osx_support.py +++ b/Lib/test/test__osx_support.py @@ -9,10 +9,11 @@ import unittest import test.support +from test.support import MACOS import _osx_support -@unittest.skipUnless(sys.platform.startswith("darwin"), "requires OS X") +@unittest.skipUnless(MACOS, "requires OS X") class Test_OSXSupport(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_asynchat.py b/Lib/test/test_asynchat.py index 1d147c741961e3..5b3cd0b32f90a9 100644 --- a/Lib/test/test_asynchat.py +++ b/Lib/test/test_asynchat.py @@ -1,6 +1,7 @@ # test asynchat from test import support +from test.support import HOST, MACOS import asynchat import asyncore @@ -13,7 +14,6 @@ import unittest import unittest.mock -HOST = support.HOST SERVER_QUIT = b'QUIT\n' TIMEOUT = 3.0 @@ -77,9 +77,9 @@ def __init__(self, terminator, server_port): def handle_connect(self): pass - if sys.platform == 'darwin': + if MACOS: # select.poll returns a select.POLLHUP at the end of the tests - # on darwin, so just ignore it + # on macOS, so just ignore it def handle_expt(self): pass diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py index 3fcedb58ec18a6..9516621390eab5 100644 --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -10,6 +10,7 @@ import threading from test import support +from test.support import MACOS from io import BytesIO if support.PGO: @@ -658,7 +659,7 @@ def test_handle_expt(self): if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX: self.skipTest("Not applicable to AF_UNIX sockets.") - if sys.platform == "darwin" and self.use_poll: + if MACOS and self.use_poll: self.skipTest("poll may fail on macOS; see issue #28087") class TestClient(BaseClient): diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index b1a1e0c8f2eb28..73610fd9fba4f0 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -10,7 +10,8 @@ from collections import namedtuple from test import support -AIX = support.AIX +from test.support import AIX, ANDROID, LINUX, MACOS + from test.support.script_helper import ( run_python_until_end, interpreter_requires_environment, @@ -30,8 +31,8 @@ TARGET_LOCALES = ["C.UTF-8", "C.utf8", "UTF-8"] # Apply some platform dependent overrides -if sys.platform.startswith("linux"): - if support.is_android: +if LINUX: + if ANDROID: # Android defaults to using UTF-8 for all system interfaces EXPECTED_C_LOCALE_STREAM_ENCODING = "utf-8" EXPECTED_C_LOCALE_FS_ENCODING = "utf-8" @@ -45,7 +46,7 @@ # AIX uses iso8859-1 in the C locale, other *nix platforms use ASCII EXPECTED_C_LOCALE_STREAM_ENCODING = "iso8859-1" EXPECTED_C_LOCALE_FS_ENCODING = "iso8859-1" -elif sys.platform == "darwin": +elif MACOS: # FS encoding is UTF-8 on macOS EXPECTED_C_LOCALE_FS_ENCODING = "utf-8" elif sys.platform == "cygwin": @@ -79,7 +80,7 @@ # `locale.nl_langinfo(locale.CODESET)` works, as if it fails, the interpreter # will skip locale coercion for that particular target locale _check_nl_langinfo_CODESET = bool( - sys.platform not in ("darwin", "linux") and + not (MACOS or LINUX) and hasattr(locale, "nl_langinfo") and hasattr(locale, "CODESET") ) diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py index 43a074b4b66353..81a1991e0c1b93 100644 --- a/Lib/test/test_cmath.py +++ b/Lib/test/test_cmath.py @@ -1,4 +1,4 @@ -from test.support import requires_IEEE_754, cpython_only +from test.support import requires_IEEE_754, cpython_only, MACOS from test.test_math import parse_testfile, test_file import test.test_math as test_math import unittest @@ -339,7 +339,7 @@ def test_specific_values(self): SKIP_ON_TIGER = {'tan0064'} osx_version = None - if sys.platform == 'darwin': + if MACOS: version_txt = platform.mac_ver()[0] try: osx_version = tuple(map(int, version_txt.split('.'))) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 21511b896cad17..e82593760efa06 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -9,6 +9,7 @@ import tempfile import unittest from test import support +from test.support import MS_WINDOWS, MACOS, ANDROID from test.support.script_helper import ( spawn_python, kill_python, assert_python_ok, assert_python_failure, interpreter_requires_environment @@ -152,8 +153,7 @@ def test_non_ascii(self): # command line, but how subprocess does decode bytes to unicode. Python # doesn't decode the command line because Windows provides directly the # arguments as unicode (using wmain() instead of main()). - @unittest.skipIf(sys.platform == 'win32', - 'Windows has a native unicode API') + @unittest.skipIf(MS_WINDOWS, 'Windows has a native unicode API') def test_undecodable_code(self): undecodable = b"\xff" env = os.environ.copy() @@ -187,8 +187,7 @@ def test_undecodable_code(self): if not stdout.startswith(pattern): raise AssertionError("%a doesn't start with %a" % (stdout, pattern)) - @unittest.skipUnless((sys.platform == 'darwin' or - support.is_android), 'test specific to Mac OS X and Android') + @unittest.skipUnless((MACOS or ANDROID), 'test specific to Mac OS X and Android') def test_osx_android_utf8(self): def check_output(text): decoded = text.decode('utf-8', 'surrogateescape') @@ -331,7 +330,7 @@ def test_output_newline(self): print(4, file=sys.stderr)""" rc, out, err = assert_python_ok('-c', code) - if sys.platform == 'win32': + if MS_WINDOWS: self.assertEqual(b'1\r\n2\r\n', out) self.assertEqual(b'3\r\n4', err) else: @@ -727,8 +726,7 @@ def test_pythondevmode_env(self): self.assertEqual(proc.stdout.rstrip(), 'True') self.assertEqual(proc.returncode, 0, proc) - @unittest.skipUnless(sys.platform == 'win32', - 'bpo-32457 only applies on Windows') + @unittest.skipUnless(MS_WINDOWS, 'bpo-32457 only applies on Windows') def test_argv0_normalization(self): args = sys.executable, '-c', 'print(0)' prefix, exe = os.path.split(sys.executable) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index d138ca027c6848..7d9d2e64f11cbe 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -14,6 +14,7 @@ import textwrap from test import support +from test.support import MACOS, MS_WINDOWS from test.support.script_helper import ( make_pkg, make_script, make_zip_pkg, make_zip_script, assert_python_ok, assert_python_failure, spawn_python, kill_python) @@ -532,8 +533,7 @@ def test_non_ascii(self): # Mac OS X denies the creation of a file with an invalid UTF-8 name. # Windows allows creating a name with an arbitrary bytes name, but # Python cannot a undecodable bytes argument to a subprocess. - if (support.TESTFN_UNDECODABLE - and sys.platform not in ('win32', 'darwin')): + if (support.TESTFN_UNDECODABLE and not (MACOS or MS_WINDOWS)): name = os.fsdecode(support.TESTFN_UNDECODABLE) elif support.TESTFN_NONASCII: name = support.TESTFN_NONASCII diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 05843c54bd5f9a..c1c15e71a9ef18 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -855,8 +855,7 @@ def test_surrogatepass_handler(self): b"abc\xed\xa0z".decode(self.encoding, "surrogatepass") -@unittest.skipUnless(sys.platform == 'win32', - 'cp65001 is a Windows-only codec') +@unittest.skipUnless(support.MS_WINDOWS, 'cp65001 is a Windows-only codec') class CP65001Test(ReadTest, unittest.TestCase): encoding = "cp65001" @@ -2936,8 +2935,7 @@ def decode_to_bytes(*args, **kwds): -@unittest.skipUnless(sys.platform == 'win32', - 'code pages are specific to Windows') +@unittest.skipUnless(support.MS_WINDOWS, 'code pages are specific to Windows') class CodePageTest(unittest.TestCase): # CP_UTF8 is already tested by CP65001Test CP_UTF8 = 65001 diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index 903afbd2a4f68a..4fc9e32e56e55a 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -5,6 +5,7 @@ # Skip tests if sem_open implementation is broken. test.support.import_module('multiprocessing.synchronize') +from test.support import MS_WINDOWS from test.support.script_helper import assert_python_ok import contextlib @@ -156,7 +157,7 @@ class ProcessPoolForkMixin(ExecutorMixin): ctx = "fork" def get_context(self): - if sys.platform == "win32": + if MS_WINDOWS: self.skipTest("require unix system") return super().get_context() @@ -171,7 +172,7 @@ class ProcessPoolForkserverMixin(ExecutorMixin): ctx = "forkserver" def get_context(self): - if sys.platform == "win32": + if MS_WINDOWS: self.skipTest("require unix system") return super().get_context() diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 1f37b5372a3e7e..56fd5418e7c626 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -35,7 +35,7 @@ from test.support import (run_unittest, run_doctest, is_resource_enabled, requires_IEEE_754, requires_docstrings) from test.support import (import_fresh_module, TestFailed, - run_with_locale, cpython_only) + run_with_locale, cpython_only, MS_WINDOWS) import random import inspect import threading @@ -4862,7 +4862,7 @@ def test_c_context_errors(self): for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'): self.assertRaises(OverflowError, setattr, c, attr, int_max+1) self.assertRaises(OverflowError, setattr, c, attr, -int_max-2) - if sys.platform != 'win32': + if not MS_WINDOWS: self.assertRaises(ValueError, setattr, c, attr, int_max) self.assertRaises(ValueError, setattr, c, attr, -int_max-1) @@ -4937,7 +4937,7 @@ def test_c_context_errors_extra(self): # OverflowError, general ValueError self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1) self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2) - if sys.platform != 'win32': + if not MS_WINDOWS: self.assertRaises(ValueError, setattr, c, '_allcr', int_max) self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1) @@ -4945,7 +4945,7 @@ def test_c_context_errors_extra(self): for attr in ('_flags', '_traps'): self.assertRaises(OverflowError, setattr, c, attr, int_max+1) self.assertRaises(OverflowError, setattr, c, attr, -int_max-2) - if sys.platform != 'win32': + if not MS_WINDOWS: self.assertRaises(TypeError, setattr, c, attr, int_max) self.assertRaises(TypeError, setattr, c, attr, -int_max-1) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 6ef529e2b015be..749654068f2c21 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -11,7 +11,7 @@ from test.support import (TESTFN, captured_stderr, check_impl_detail, check_warnings, cpython_only, gc_collect, run_unittest, no_tracing, unlink, import_module, script_helper, - SuppressCrashReport) + SuppressCrashReport, JYTHON, MS_WINDOWS) class NaiveException(Exception): def __init__(self, x): self.x = x @@ -270,7 +270,7 @@ def test_capi3(): self.assertRaises(SystemError, _testcapi.raise_exception, InvalidException, 1) - if not sys.platform.startswith('java'): + if not JYTHON: test_capi1() test_capi2() test_capi3() @@ -314,8 +314,7 @@ def test_WindowsError(self): self.assertEqual(w.filename, None) self.assertEqual(w.filename2, None) - @unittest.skipUnless(sys.platform == 'win32', - 'test specific to Windows') + @unittest.skipUnless(MS_WINDOWS, 'test specific to Windows') def test_windows_message(self): """Should fill in unknown error code in Windows error message""" ctypes = import_module('ctypes') diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 7171fc3ec4033a..2e1d8513ca5639 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -7,7 +7,7 @@ import sys import sysconfig from test import support -from test.support import script_helper, is_android, AIX +from test.support import script_helper, is_android, AIX, MS_WINDOWS import tempfile import threading import unittest @@ -19,7 +19,6 @@ _testcapi = None TIMEOUT = 0.5 -MS_WINDOWS = (os.name == 'nt') _cflags = sysconfig.get_config_var('CFLAGS') or '' _config_args = sysconfig.get_config_var('CONFIG_ARGS') or '' UB_SANITIZER = ( @@ -181,7 +180,7 @@ def test_sigabrt(self): 3, 'Aborted') - @unittest.skipIf(sys.platform == 'win32', + @unittest.skipIf(MS_WINDOWS, "SIGFPE cannot be caught on Windows") def test_sigfpe(self): self.check_fatal_error(""" @@ -276,8 +275,7 @@ def test_enable_file(self): 'Segmentation fault', filename=filename) - @unittest.skipIf(sys.platform == "win32", - "subprocess doesn't support pass_fds on Windows") + @unittest.skipIf(MS_WINDOWS, "subprocess doesn't support pass_fds on Windows") @unittest.skipIf(UB_SANITIZER or MEMORY_SANITIZER, "sanitizer builds change crashing process output.") @skip_segfault_on_android @@ -433,8 +431,7 @@ def test_dump_traceback_file(self): with temporary_filename() as filename: self.check_dump_traceback(filename=filename) - @unittest.skipIf(sys.platform == "win32", - "subprocess doesn't support pass_fds on Windows") + @unittest.skipIf(MS_WINDOWS, "subprocess doesn't support pass_fds on Windows") def test_dump_traceback_fd(self): with tempfile.TemporaryFile('wb+') as fp: self.check_dump_traceback(fd=fp.fileno()) @@ -606,8 +603,7 @@ def test_dump_traceback_later_file(self): with temporary_filename() as filename: self.check_dump_traceback_later(filename=filename) - @unittest.skipIf(sys.platform == "win32", - "subprocess doesn't support pass_fds on Windows") + @unittest.skipIf(MS_WINDOWS, "subprocess doesn't support pass_fds on Windows") def test_dump_traceback_later_fd(self): with tempfile.TemporaryFile('wb+') as fp: self.check_dump_traceback_later(fd=fp.fileno()) @@ -708,8 +704,7 @@ def test_register_file(self): with temporary_filename() as filename: self.check_register(filename=filename) - @unittest.skipIf(sys.platform == "win32", - "subprocess doesn't support pass_fds on Windows") + @unittest.skipIf(MS_WINDOWS, "subprocess doesn't support pass_fds on Windows") def test_register_fd(self): with tempfile.TemporaryFile('wb+') as fp: self.check_register(fd=fp.fileno()) diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index 5d4abe388f7828..61148326e6e43d 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -6,7 +6,7 @@ import sys import unittest from test.support import (verbose, TESTFN, unlink, run_unittest, import_module, - cpython_only) + cpython_only, MACOS) # Skip test if no fcntl module. fcntl = import_module('fcntl') @@ -23,7 +23,7 @@ def get_lockdata(): start_len = "qq" if (sys.platform.startswith(('netbsd', 'freebsd', 'openbsd')) - or sys.platform == 'darwin'): + or MACOS): if struct.calcsize('l') == 8: off_t = 'l' pid_t = 'i' diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index 6870762f72bed7..bf85fb5845fb4b 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -10,7 +10,8 @@ from functools import wraps from test.support import (TESTFN, TESTFN_UNICODE, check_warnings, run_unittest, - make_bad_fd, cpython_only, swap_attr, AIX) + make_bad_fd, cpython_only, swap_attr, + AIX, MACOS, MS_WINDOWS) from collections import UserList import _io # C implementation of io @@ -371,7 +372,7 @@ def testAbles(self): self.assertEqual(f.isatty(), False) f.close() - if sys.platform != "win32": + if not MS_WINDOWS: try: f = self.FileIO("/dev/tty", "a") except OSError: @@ -382,7 +383,7 @@ def testAbles(self): else: self.assertEqual(f.readable(), False) self.assertEqual(f.writable(), True) - if sys.platform != "darwin" and not AIX \ + if not (AIX or MACOS) \ and 'bsd' not in sys.platform \ and not sys.platform.startswith('sunos'): # Somehow /dev/tty appears seekable on some BSDs @@ -464,7 +465,7 @@ def testConstructorHandlesNULChars(self): def testInvalidFd(self): self.assertRaises(ValueError, self.FileIO, -10) self.assertRaises(OSError, self.FileIO, make_bad_fd()) - if sys.platform == 'win32': + if MS_WINDOWS: import msvcrt self.assertRaises(OSError, msvcrt.get_osfhandle, make_bad_fd()) diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py index 4d1ce4ed96c06d..da0d6f2708042f 100644 --- a/Lib/test/test_gdb.py +++ b/Lib/test/test_gdb.py @@ -13,7 +13,7 @@ import unittest from test import support -from test.support import run_unittest, findfile, python_is_optimized +from test.support import run_unittest, findfile, python_is_optimized, MACOS def get_gdb_version(): try: @@ -48,7 +48,7 @@ def get_gdb_version(): if not sysconfig.is_python_build(): raise unittest.SkipTest("test_gdb only works on source builds at the moment.") -if 'Clang' in platform.python_compiler() and sys.platform == 'darwin': +if 'Clang' in platform.python_compiler() and MACOS: raise unittest.SkipTest("test_gdb doesn't work correctly when python is" " built with LLVM clang") diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py index 9d5ac44b6d06a7..ce44454318e55a 100644 --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -9,7 +9,7 @@ import warnings from test import support from test.support.script_helper import assert_python_ok -from test.support import FakePath +from test.support import FakePath, MACOS, MS_WINDOWS def create_file(filename, data=b'foo'): @@ -436,7 +436,7 @@ def test_abspath(self): self.assertIn(b"foo", self.pathmodule.abspath(b"foo")) # avoid UnicodeDecodeError on Windows - undecodable_path = b'' if sys.platform == 'win32' else b'f\xf2\xf2' + undecodable_path = b'' if MS_WINDOWS else b'f\xf2\xf2' # Abspath returns bytes when the arg is bytes with warnings.catch_warnings(): @@ -479,7 +479,7 @@ def test_nonascii_abspath(self): # UTF-8 name. Windows allows creating a directory with an # arbitrary bytes name, but fails to enter this directory # (when the bytes name is used). - and sys.platform not in ('win32', 'darwin')): + and not (MACOS or MS_WINDOWS)): name = support.TESTFN_UNDECODABLE elif support.TESTFN_NONASCII: name = support.TESTFN_NONASCII diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py index 767bd3764b8925..43dc720a1cd4dd 100644 --- a/Lib/test/test_glob.py +++ b/Lib/test/test_glob.py @@ -4,7 +4,7 @@ import sys import unittest -from test.support import (TESTFN, skip_unless_symlink, +from test.support import (TESTFN, skip_unless_symlink, MS_WINDOWS, can_symlink, create_empty_file, change_cwd) @@ -161,7 +161,7 @@ def test_glob_broken_symlinks(self): eq(self.glob('sym1'), [self.norm('sym1')]) eq(self.glob('sym2'), [self.norm('sym2')]) - @unittest.skipUnless(sys.platform == "win32", "Win32 specific test") + @unittest.skipUnless(MS_WINDOWS, "Win32 specific test") def test_glob_magic_in_drive(self): eq = self.assertSequencesEqual_noorder eq(glob.glob('*:'), []) @@ -186,7 +186,7 @@ def test_escape(self): check('[[_/*?*/_]]', '[[][[]_/[*][?][*]/_]]') check('/[[_/*?*/_]]/', '/[[][[]_/[*][?][*]/_]]/') - @unittest.skipUnless(sys.platform == "win32", "Win32 specific test") + @unittest.skipUnless(MS_WINDOWS, "Win32 specific test") def test_escape_windows(self): check = self.check_escape check('?:?', '?:[?]') diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 8357ee9145d7e5..abda3ad44cb93a 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -29,6 +29,7 @@ import unittest from test import support +from test.support import MACOS, MS_WINDOWS class NoLogRequestHandler: @@ -385,10 +386,8 @@ def close_conn(): reader.close() return body - @unittest.skipIf(sys.platform == 'darwin', - 'undecodable name cannot always be decoded on macOS') - @unittest.skipIf(sys.platform == 'win32', - 'undecodable name cannot be decoded on win32') + @unittest.skipIf(MACOS, 'undecodable name cannot always be decoded on macOS') + @unittest.skipIf(MS_WINDOWS, 'undecodable name cannot be decoded on win32') @unittest.skipUnless(support.TESTFN_UNDECODABLE, 'need support.TESTFN_UNDECODABLE') def test_undecodable_filename(self): @@ -397,7 +396,7 @@ def test_undecodable_filename(self): with open(os.path.join(self.tempdir, filename), 'wb') as f: f.write(support.TESTFN_UNDECODABLE) response = self.request(self.base_url + '/') - if sys.platform == 'darwin': + if MACOS: # On Mac OS the HFS+ filesystem replaces bytes that aren't valid # UTF-8 into a percent-encoded value. for name in os.listdir(self.tempdir): diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py index fe394dc50c56b1..2cbfabd8c2c3bc 100644 --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -5,7 +5,7 @@ import py_compile import sys from test import support -from test.support import script_helper +from test.support import script_helper, MACOS import unittest import warnings with warnings.catch_warnings(): @@ -136,7 +136,7 @@ def test_issue5604(self): 'cp1258' : b'\xc0', } - if sys.platform == 'darwin': + if MACOS: self.assertEqual(fs_encoding, 'utf-8') # Mac OS X uses the Normal Form D decomposition # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 5406a2891bb251..dbdcaf165f8ae5 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -38,7 +38,7 @@ from itertools import cycle, count from test import support from test.support.script_helper import assert_python_ok, run_python_until_end -from test.support import FakePath +from test.support import FakePath, MACOS, MS_WINDOWS import codecs import io # C implementation of io @@ -500,7 +500,7 @@ class UnseekableWriter(self.MockUnseekableIO): else: self.assertRaises(OSError, obj.write, data) - if sys.platform.startswith("win") and test in ( + if MS_WINDOWS and test in ( pipe_reader, pipe_writer): # Pipes seem to appear as seekable on Windows continue @@ -596,7 +596,7 @@ def test_large_file_ops(self): # On Windows and Mac OSX this test consumes large resources; It takes # a long time to build the >2 GiB file and takes >2 GiB of disk space # therefore the resource must be enabled to run this test. - if sys.platform[:3] == 'win' or sys.platform == 'darwin': + if MACOS or MS_WINDOWS: support.requires( 'largefile', 'test requires %s bytes and a long time to run' % self.LARGE) diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py index 8870c721ab0efb..f278dc16cb2e22 100644 --- a/Lib/test/test_largefile.py +++ b/Lib/test/test_largefile.py @@ -5,7 +5,7 @@ import stat import sys import unittest -from test.support import TESTFN, requires, unlink, bigmemtest +from test.support import TESTFN, requires, unlink, bigmemtest, MACOS, MS_WINDOWS import io # C implementation of io import _pyio as pyio # Python implementation of io @@ -154,7 +154,7 @@ def setUpModule(): # takes a long time to build the >2 GiB file and takes >2 GiB of disk # space therefore the resource must be enabled to run this test. # If not, nothing after this line stanza will be executed. - if sys.platform[:3] == 'win' or sys.platform == 'darwin': + if MS_WINDOWS or MACOS: requires('largefile', 'test requires %s bytes and a long time to run' % str(size)) else: diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index 4f902ff58a9074..27ae945d02ae89 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -1,4 +1,4 @@ -from test.support import verbose, is_android, check_warnings, AIX +from test.support import verbose, check_warnings, ANDROID, AIX, MACOS, MS_WINDOWS import unittest import locale import sys @@ -12,7 +12,7 @@ class BaseLocalizedTest(unittest.TestCase): @classmethod def setUpClass(cls): - if sys.platform == 'darwin': + if MACOS: import os tlocs = ("en_US.UTF-8", "en_US.ISO8859-1", "en_US") if int(os.uname().release.split('.')[0]) < 10: @@ -20,7 +20,7 @@ def setUpClass(cls): # haven't had time yet to verify if tests work on OSX 10.5 # (10.4 is known to be bad) raise unittest.SkipTest("Locale support on MacOSX is minimal") - elif sys.platform.startswith("win"): + elif MS_WINDOWS: tlocs = ("En", "English") else: tlocs = ("en_US.UTF-8", "en_US.ISO8859-1", @@ -365,7 +365,7 @@ def setUp(self): enc = codecs.lookup(locale.getpreferredencoding(False) or 'ascii').name if enc not in ('utf-8', 'iso8859-1', 'cp1252'): raise unittest.SkipTest('encoding not suitable') - if enc != 'iso8859-1' and (sys.platform == 'darwin' or is_android or + if enc != 'iso8859-1' and (MACOS or ANDROID or sys.platform.startswith('freebsd')): raise unittest.SkipTest('wcscoll/wcsxfrm have known bugs') BaseLocalizedTest.setUp(self) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 1805249e48bcc0..a4053fc9142170 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -42,6 +42,7 @@ import sys import tempfile from test.support.script_helper import assert_python_ok, assert_python_failure +from test.support import LINUX, MACOS, MS_WINDOWS from test import support import textwrap import threading @@ -549,7 +550,7 @@ def test_name(self): def test_builtin_handlers(self): # We can't actually *use* too many handlers in the tests, # but we can try instantiating them with various options - if sys.platform in ('linux', 'darwin'): + if LINUX or MACOS: for existing in (True, False): fd, fn = tempfile.mkstemp() os.close(fd) @@ -574,7 +575,7 @@ def test_builtin_handlers(self): h.close() if existing: os.unlink(fn) - if sys.platform == 'darwin': + if MACOS: sockname = '/var/run/syslog' else: sockname = '/dev/log' @@ -615,7 +616,7 @@ def test_path_objects(self): (logging.handlers.RotatingFileHandler, (pfn, 'a')), (logging.handlers.TimedRotatingFileHandler, (pfn, 'h')), ) - if sys.platform in ('linux', 'darwin'): + if LINUX or MACOS: cases += ((logging.handlers.WatchedFileHandler, (pfn, 'w')),) for cls, args in cases: h = cls(*args) @@ -623,7 +624,7 @@ def test_path_objects(self): h.close() os.unlink(fn) - @unittest.skipIf(os.name == 'nt', 'WatchedFileHandler not appropriate for Windows.') + @unittest.skipIf(MS_WINDOWS, 'WatchedFileHandler not appropriate for Windows.') def test_race(self): # Issue #14632 refers. def remove_loop(fname, tries): diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index cb05dee0e0fd3c..a764d2c42c6271 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1,7 +1,7 @@ # Python test set -- math module # XXXX Should not do tests around zero only -from test.support import run_unittest, verbose, requires_IEEE_754 +from test.support import run_unittest, verbose, requires_IEEE_754, MACOS from test import support import unittest import itertools @@ -1478,7 +1478,7 @@ def test_testfile(self): SKIP_ON_TIGER = {'tan0064'} osx_version = None - if sys.platform == 'darwin': + if MACOS: version_txt = platform.mac_ver()[0] try: osx_version = tuple(map(int, version_txt.split('.'))) diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py index 554d3d5cead5db..c88c4b176798c5 100644 --- a/Lib/test/test_mimetypes.py +++ b/Lib/test/test_mimetypes.py @@ -6,6 +6,7 @@ import unittest from test import support +from test.support import MS_WINDOWS # Tell it we don't know about external files: mimetypes.knownfiles = [] @@ -102,7 +103,7 @@ def test_keywords_args_api(self): type='image/jpg', strict=False), '.jpg') -@unittest.skipUnless(sys.platform.startswith("win"), "Windows only") +@unittest.skipUnless(MS_WINDOWS, "Windows only") class Win32MimeTypesTestCase(unittest.TestCase): def setUp(self): # ensure all entries actually come from the Windows registry diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index dd857a0632aeef..7ecb63c8a496b6 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -1,5 +1,6 @@ from test.support import (TESTFN, import_module, unlink, - requires, _2G, _4G, gc_collect, cpython_only) + requires, _2G, _4G, gc_collect, cpython_only, + LINUX, MACOS, MS_WINDOWS) import unittest import os import re @@ -184,14 +185,14 @@ def test_access_parameter(self): # CAUTION: This also changes the size of the file on disk, and # later tests assume that the length hasn't changed. We need to # repair that. - if sys.platform.startswith('win'): + if MS_WINDOWS: self.fail("Opening mmap with size+1 should work on Windows.") else: # we expect a ValueError on Unix, but not on Windows - if not sys.platform.startswith('win'): + if not MS_WINDOWS: self.fail("Opening mmap with size+1 should raise ValueError.") m.close() - if sys.platform.startswith('win'): + if MS_WINDOWS: # Repair damage from the resizing test. with open(TESTFN, 'r+b') as f: f.truncate(mapsize) @@ -734,7 +735,7 @@ def test_flush_return_value(self): mm.write(b'python') result = mm.flush() self.assertIsNone(result) - if sys.platform.startswith('linux'): + if LINUX: # 'offset' must be a multiple of mmap.PAGESIZE on Linux. # See bpo-34754 for details. self.assertRaises(OSError, mm.flush, 1, len(b'python')) @@ -749,7 +750,7 @@ def tearDown(self): unlink(TESTFN) def _make_test_file(self, num_zeroes, tail): - if sys.platform[:3] == 'win' or sys.platform == 'darwin': + if MACOS or MS_WINDOWS: requires('largefile', 'test requires %s bytes and a long time to run' % str(0x180000000)) f = open(TESTFN, 'w+b') diff --git a/Lib/test/test_multiprocessing_fork.py b/Lib/test/test_multiprocessing_fork.py index 5000edb7c5c299..378fd471817950 100644 --- a/Lib/test/test_multiprocessing_fork.py +++ b/Lib/test/test_multiprocessing_fork.py @@ -3,14 +3,15 @@ import sys from test import support +from test.support import MACOS, MS_WINDOWS if support.PGO: raise unittest.SkipTest("test is not helpful for PGO") -if sys.platform == "win32": +if MS_WINDOWS: raise unittest.SkipTest("fork is not available on Windows") -if sys.platform == 'darwin': +if MACOS: raise unittest.SkipTest("test may crash on macOS (bpo-33725)") test._test_multiprocessing.install_tests_in_module_dict(globals(), 'fork') diff --git a/Lib/test/test_multiprocessing_forkserver.py b/Lib/test/test_multiprocessing_forkserver.py index 6ad5faf9e8a329..884f434b56df1f 100644 --- a/Lib/test/test_multiprocessing_forkserver.py +++ b/Lib/test/test_multiprocessing_forkserver.py @@ -7,7 +7,7 @@ if support.PGO: raise unittest.SkipTest("test is not helpful for PGO") -if sys.platform == "win32": +if support.MS_WINDOWS: raise unittest.SkipTest("forkserver is not available on Windows") test._test_multiprocessing.install_tests_in_module_dict(globals(), 'forkserver') diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index fc2398c2d518ba..6f233047abad6d 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -3,7 +3,7 @@ import sys import unittest import warnings -from test.support import TestFailed, FakePath +from test.support import TestFailed, FakePath, MS_WINDOWS from test import support, test_genericpath from tempfile import TemporaryFile @@ -388,7 +388,7 @@ def test_sameopenfile(self): # Make sure different files are really different self.assertFalse(ntpath.sameopenfile(tf1.fileno(), tf2.fileno())) # Make sure invalid values don't cause issues on win32 - if sys.platform == "win32": + if MS_WINDOWS: with self.assertRaises(OSError): # Invalid file descriptors shouldn't display assert # dialogs (#4804) @@ -412,7 +412,7 @@ def test_ismount(self): with support.temp_dir() as d: self.assertFalse(ntpath.ismount(d)) - if sys.platform == "win32": + if MS_WINDOWS: # # Make sure the current folder isn't the root folder # (or any other volume root). The drive-relative diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 4c620ccae9c84c..dfd8d819d42653 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -28,6 +28,7 @@ import uuid import warnings from test import support +from test.support import LINUX, MS_WINDOWS try: import resource @@ -180,8 +181,7 @@ def write_windows_console(self, *args): shell=True) self.assertEqual(retcode, 0) - @unittest.skipUnless(sys.platform == 'win32', - 'test specific to the Windows console') + @unittest.skipUnless(MS_WINDOWS, 'test specific to the Windows console') def test_write_windows_console(self): # Issue #11395: the Windows console returns an error (12: not enough # space error) on writing into stdout if stdout mode is binary and the @@ -380,7 +380,7 @@ def test_statvfs_result_pickle(self): unpickled = pickle.loads(p) self.assertEqual(result, unpickled) - @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") + @unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") def test_1686475(self): # Verify that an open file can be stat'ed try: @@ -390,7 +390,7 @@ def test_1686475(self): except OSError as e: self.fail("Could not stat pagefile.sys") - @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") + @unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") def test_15261(self): # Verify that stat'ing a closed fd does not cause crash @@ -409,8 +409,7 @@ def check_file_attributes(self, result): self.assertTrue(isinstance(result.st_file_attributes, int)) self.assertTrue(0 <= result.st_file_attributes <= 0xFFFFFFFF) - @unittest.skipUnless(sys.platform == "win32", - "st_file_attributes is Win32 specific") + @unittest.skipUnless(MS_WINDOWS, "st_file_attributes is Win32 specific") def test_file_attributes(self): # test file st_file_attributes (FILE_ATTRIBUTE_DIRECTORY not set) result = os.stat(self.fname) @@ -430,7 +429,7 @@ def test_file_attributes(self): result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY, stat.FILE_ATTRIBUTE_DIRECTORY) - @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") + @unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") def test_access_denied(self): # Default to FindFirstFile WIN32_FIND_DATA when access is # denied. See issue 28075. @@ -607,7 +606,7 @@ def set_time(filename): self._test_utime_current(set_time) def get_file_system(self, path): - if sys.platform == 'win32': + if MS_WINDOWS: root = os.path.splitdrive(os.path.abspath(path))[0] + '\\' import ctypes kernel32 = ctypes.windll.kernel32 @@ -808,7 +807,7 @@ def test_environb(self): # On OS X < 10.6, unsetenv() doesn't return a value (bpo-13415). @support.requires_mac_ver(10, 6) def test_unset_error(self): - if sys.platform == "win32": + if MS_WINDOWS: # an environment variable is limited to 32,767 characters key = 'x' * 50000 self.assertRaises(ValueError, os.environ.__delitem__, key) @@ -1610,7 +1609,7 @@ def test_execve_invalid_env(self): with self.assertRaises(ValueError): os.execve(args[0], args, newenv) - @unittest.skipUnless(sys.platform == "win32", "Win32-specific test") + @unittest.skipUnless(MS_WINDOWS, "Win32-specific test") def test_execve_with_empty_path(self): # bpo-32890: Check GetLastError() misuse try: @@ -1621,7 +1620,7 @@ def test_execve_with_empty_path(self): self.fail('No OSError raised') -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") class Win32ErrorTests(unittest.TestCase): def setUp(self): try: @@ -1794,7 +1793,7 @@ def test_unicode_name(self): self.file2 = self.file1 + "2" self._test_link(self.file1, self.file2) -@unittest.skipIf(sys.platform == "win32", "Posix specific tests") +@unittest.skipIf(MS_WINDOWS, "Posix specific tests") class PosixUidGidTests(unittest.TestCase): # uid_t and gid_t are 32-bit unsigned integers on Linux UID_OVERFLOW = (1 << 32) @@ -1862,7 +1861,7 @@ def test_setregid_neg1(self): sys.executable, '-c', 'import os,sys;os.setregid(-1,-1);sys.exit(0)']) -@unittest.skipIf(sys.platform == "win32", "Posix specific tests") +@unittest.skipIf(MS_WINDOWS, "Posix specific tests") class Pep383Tests(unittest.TestCase): def setUp(self): if support.TESTFN_UNENCODABLE: @@ -1934,7 +1933,7 @@ def test_stat(self): for fn in self.unicodefn: os.stat(os.path.join(self.dir, fn)) -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") class Win32KillTests(unittest.TestCase): def _kill(self, sig): # Start sys.executable as a subprocess and communicate from the @@ -2050,7 +2049,7 @@ def test_CTRL_BREAK_EVENT(self): self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT") -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") class Win32ListdirTests(unittest.TestCase): """Test listdir on Windows.""" @@ -2145,7 +2144,7 @@ def test_bytes(self): self.assertIsInstance(path, bytes) -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") @support.skip_unless_symlink class Win32SymlinkTests(unittest.TestCase): filelink = 'filelinktest' @@ -2305,7 +2304,7 @@ def test_buffer_overflow(self): except OSError: pass -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") class Win32JunctionTests(unittest.TestCase): junction = 'junctiontest' junction_target = os.path.dirname(os.path.abspath(__file__)) @@ -2335,7 +2334,7 @@ def test_unlink_removes_junction(self): os.unlink(self.junction) self.assertFalse(os.path.exists(self.junction)) -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") class Win32NtTests(unittest.TestCase): def setUp(self): from test import support @@ -2446,7 +2445,7 @@ def test_bad_fd(self): # Return None when an fd doesn't actually exist. self.assertIsNone(os.device_encoding(123456)) - @unittest.skipUnless(os.isatty(0) and (sys.platform.startswith('win') or + @unittest.skipUnless(os.isatty(0) and (MS_WINDOWS or (hasattr(locale, 'nl_langinfo') and hasattr(locale, 'CODESET'))), 'test requires a tty and either Windows or nl_langinfo(CODESET)') def test_device_encoding(self): @@ -2777,7 +2776,7 @@ def handle_error(self): class TestSendfile(unittest.TestCase): DATA = b"12345abcde" * 16 * 1024 # 160 KiB - SUPPORT_HEADERS_TRAILERS = not sys.platform.startswith("linux") and \ + SUPPORT_HEADERS_TRAILERS = not LINUX and \ not sys.platform.startswith("solaris") and \ not sys.platform.startswith("sunos") requires_headers_trailers = unittest.skipUnless(SUPPORT_HEADERS_TRAILERS, @@ -3091,7 +3090,7 @@ def test_does_not_crash(self): try: size = os.get_terminal_size() except OSError as e: - if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY): + if MS_WINDOWS or e.errno in (errno.EINVAL, errno.ENOTTY): # Under win32 a generic OSError can be thrown if the # handle cannot be retrieved self.skipTest("failed to query terminal size") @@ -3117,7 +3116,7 @@ def test_stty_match(self): try: actual = os.get_terminal_size(sys.__stdin__.fileno()) except OSError as e: - if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY): + if MS_WINDOWS or e.errno in (errno.EINVAL, errno.ENOTTY): # Under win32 a generic OSError can be thrown if the # handle cannot be retrieved self.skipTest("failed to query terminal size") @@ -3158,7 +3157,7 @@ def test_oserror_filename(self): (self.filenames, os.stat,), (self.filenames, os.unlink,), ] - if sys.platform == "win32": + if MS_WINDOWS: funcs.extend(( (self.bytes_filenames, os.rename, b"dst"), (self.bytes_filenames, os.replace, b"dst"), @@ -3185,7 +3184,7 @@ def test_oserror_filename(self): if hasattr(os, "chroot"): funcs.append((self.filenames, os.chroot,)) if hasattr(os, "link"): - if sys.platform == "win32": + if MS_WINDOWS: funcs.append((self.bytes_filenames, os.link, b"dst")) funcs.append((self.unicode_filenames, os.link, "dst")) else: @@ -3200,7 +3199,7 @@ def test_oserror_filename(self): if hasattr(os, "lchmod"): funcs.append((self.filenames, os.lchmod, 0o777)) if hasattr(os, "readlink"): - if sys.platform == "win32": + if MS_WINDOWS: funcs.append((self.unicode_filenames, os.readlink,)) else: funcs.append((self.filenames, os.readlink,)) diff --git a/Lib/test/test_osx_env.py b/Lib/test/test_osx_env.py index 8a3bc5a46e547b..a4918bb0f6798b 100644 --- a/Lib/test/test_osx_env.py +++ b/Lib/test/test_osx_env.py @@ -2,14 +2,13 @@ Test suite for OS X interpreter environment variables. """ -from test.support import EnvironmentVarGuard +from test.support import EnvironmentVarGuard, MACOS import subprocess import sys import sysconfig import unittest -@unittest.skipUnless(sys.platform == 'darwin' and - sysconfig.get_config_var('WITH_NEXT_FRAMEWORK'), +@unittest.skipUnless(MACOS and sysconfig.get_config_var('WITH_NEXT_FRAMEWORK'), 'unnecessary on this platform') class OSXEnvironmentVariableTestCase(unittest.TestCase): def _check_sys(self, ev, cond, sv, val = sys.executable + 'dummy'): diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index f8325eb93275a6..9aa372140d3c64 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -12,7 +12,7 @@ from unittest import mock from test import support -from test.support import TESTFN, FakePath +from test.support import TESTFN, FakePath, MACOS try: import grp, pwd @@ -2207,8 +2207,7 @@ def test_expanduser(self): self.assertEqual(p6.expanduser(), p6) self.assertRaises(RuntimeError, p7.expanduser) - @unittest.skipIf(sys.platform != "darwin", - "Bad file descriptor in /dev/fd affects only macOS") + @unittest.skipIf(MACOS, "Bad file descriptor in /dev/fd affects only macOS") def test_handling_bad_descriptor(self): try: file_descriptors = list(pathlib.Path('/dev/fd').rglob("*"))[3:] diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 9cf17726d92e0d..2839340bbf3879 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -8,6 +8,7 @@ from unittest import mock from test import support +from test.support import JYTHON, MACOS, MS_WINDOWS class PlatformTest(unittest.TestCase): def clear_caches(self): @@ -23,7 +24,7 @@ def test_architecture_via_symlink(self): # issue3762 # On Windows, the EXE needs to know where pythonXY.dll and *.pyd is at # so we add the directory to the path, PYTHONHOME and PYTHONPATH. env = None - if sys.platform == "win32": + if MS_WINDOWS: env = {k.upper(): os.environ[k] for k in os.environ} env["PATH"] = "{};{}".format( os.path.dirname(sys.executable), env.get("PATH", "")) @@ -189,7 +190,7 @@ def test_uname(self): self.assertEqual(res[4], res.machine) self.assertEqual(res[5], res.processor) - @unittest.skipUnless(sys.platform.startswith('win'), "windows only test") + @unittest.skipUnless(MS_WINDOWS, "windows only test") def test_uname_win32_ARCHITEW6432(self): # Issue 7860: make sure we get architecture from the correct variable # on 64 bit Windows: if PROCESSOR_ARCHITEW6432 exists we should be @@ -212,7 +213,7 @@ def test_uname_win32_ARCHITEW6432(self): def test_java_ver(self): res = platform.java_ver() - if sys.platform == 'java': + if JYTHON: self.assertTrue(all(res)) def test_win32_ver(self): @@ -251,7 +252,7 @@ def test_mac_ver(self): self.assertEqual(res[2], 'PowerPC') - @unittest.skipUnless(sys.platform == 'darwin', "OSX only test") + @unittest.skipUnless(MACOS, "OSX only test") def test_mac_ver_with_fork(self): # Issue7895: platform.mac_ver() crashes when using fork without exec # diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 843402930ffc0f..8a103b95fb812d 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1,6 +1,7 @@ "Test posix functions" from test import support +from test.support import MACOS from test.support.script_helper import assert_python_ok # Skip these tests if there is no posix module. @@ -1041,7 +1042,7 @@ def test_getgroups(self): raise unittest.SkipTest("need working 'id -G'") # Issues 16698: OS X ABIs prior to 10.6 have limits on getgroups() - if sys.platform == 'darwin': + if MACOS: import sysconfig dt = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') or '10.0' if tuple(int(n) for n in dt.split('.')[0:2]) < (10, 6): @@ -1285,7 +1286,7 @@ def test_sched_priority(self): self.assertIsInstance(hi, int) self.assertGreaterEqual(hi, lo) # OSX evidently just returns 15 without checking the argument. - if sys.platform != "darwin": + if not MACOS: self.assertRaises(OSError, posix.sched_get_priority_min, -23) self.assertRaises(OSError, posix.sched_get_priority_max, -23) @@ -1464,7 +1465,7 @@ def setUp(self): raise unittest.SkipTest("not enough privileges") if not hasattr(posix, 'getgroups'): raise unittest.SkipTest("need posix.getgroups") - if sys.platform == 'darwin': + if MACOS: raise unittest.SkipTest("getgroups(2) is broken on OSX") self.saved_groups = posix.getgroups() diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 61937767ec126d..3ee8f2e8efdbe8 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -19,6 +19,7 @@ from test import libregrtest from test import support from test.libregrtest import utils +from test.support import MS_WINDOWS Py_DEBUG = hasattr(sys, 'getobjects') @@ -550,7 +551,7 @@ def setUp(self): '--testdir=%s' % self.tmptestdir] if hasattr(faulthandler, 'dump_traceback_later'): self.regrtest_args.extend(('--timeout', '3600', '-j4')) - if sys.platform == 'win32': + if MS_WINDOWS: self.regrtest_args.append('-n') def check_output(self, output): @@ -613,7 +614,7 @@ def run_batch(self, *args): @unittest.skipUnless(sysconfig.is_python_build(), 'test.bat script is not installed') - @unittest.skipUnless(sys.platform == 'win32', 'Windows only') + @unittest.skipUnless(MS_WINDOWS, 'Windows only') def test_tools_buildbot_test(self): # Tools\buildbot\test.bat script = os.path.join(ROOT_DIR, 'Tools', 'buildbot', 'test.bat') @@ -624,7 +625,7 @@ def test_tools_buildbot_test(self): test_args.append('+d') # Release build, use python.exe self.run_batch(script, *test_args, *self.tests) - @unittest.skipUnless(sys.platform == 'win32', 'Windows only') + @unittest.skipUnless(MS_WINDOWS, 'Windows only') def test_pcbuild_rt(self): # PCbuild\rt.bat script = os.path.join(ROOT_DIR, r'PCbuild\rt.bat') diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index 62c7963fe6999f..6ecfacde27a607 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -2,6 +2,7 @@ import sys import unittest from test import support +from test.support import LINUX import time resource = support.import_module('resource') @@ -131,7 +132,7 @@ def test_pagesize(self): self.assertIsInstance(pagesize, int) self.assertGreaterEqual(pagesize, 0) - @unittest.skipUnless(sys.platform == 'linux', 'test requires Linux') + @unittest.skipUnless(LINUX, 'test requires Linux') def test_linux_constants(self): for attr in ['MSGQUEUE', 'NICE', 'RTPRIO', 'RTTIME', 'SIGPENDING']: with contextlib.suppress(AttributeError): diff --git a/Lib/test/test_select.py b/Lib/test/test_select.py index 458998a62fdf5e..8250c21ae1468d 100644 --- a/Lib/test/test_select.py +++ b/Lib/test/test_select.py @@ -4,9 +4,9 @@ import sys import unittest from test import support +from test.support import MS_WINDOWS -@unittest.skipIf((sys.platform[:3]=='win'), - "can't easily test on this system") +@unittest.skipIf(MS_WINDOWS, "can't easily test on this system") class SelectTestCase(unittest.TestCase): class Nope: diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py index 31611224dc71e1..b43504135f2b25 100644 --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -6,6 +6,7 @@ import socket import sys from test import support +from test.support import MACOS, MS_WINDOWS from time import sleep import unittest import unittest.mock @@ -348,8 +349,7 @@ def test_selector(self): self.assertEqual(bufs, [MSG] * NUM_SOCKETS) - @unittest.skipIf(sys.platform == 'win32', - 'select.select() cannot be used with empty fd sets') + @unittest.skipIf(MS_WINDOWS, 'select.select() cannot be used with empty fd sets') def test_empty_select(self): # Issue #23009: Make sure EpollSelector.select() works when no FD is # registered. @@ -484,7 +484,7 @@ def test_above_fd_setsize(self): try: fds = s.select() except OSError as e: - if e.errno == errno.EINVAL and sys.platform == 'darwin': + if e.errno == errno.EINVAL and MACOS: # unexplainable errors on macOS don't need to fail the test self.skipTest("Invalid argument error calling poll()") raise diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index a34dc71648b4f5..6d843e527fb690 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -30,7 +30,7 @@ posix = None from test import support -from test.support import TESTFN, FakePath, AIX, MACOS +from test.support import TESTFN, FakePath, AIX, MACOS, MS_WINDOWS TESTFN2 = TESTFN + "2" @@ -1576,7 +1576,7 @@ def test_cwd(self): base_dir = os.path.dirname(self.dir) with support.change_cwd(path=self.dir): rv = shutil.which(self.file, path=base_dir) - if sys.platform == "win32": + if MS_WINDOWS: # Windows: current directory implicitly on PATH self.assertEqual(rv, os.path.join(self.curdir, self.file)) else: @@ -1604,7 +1604,7 @@ def test_nonexistent_file(self): rv = shutil.which("foo.exe", path=self.dir) self.assertIsNone(rv) - @unittest.skipUnless(sys.platform == "win32", + @unittest.skipUnless(MS_WINDOWS, "pathext check is Windows-only") def test_pathext_checking(self): # Ask for the file without the ".exe" extension, then ensure that diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 063b35ca230f59..8e49e14c4d3dbf 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -10,6 +10,7 @@ import time import unittest from test import support +from test.support import MS_WINDOWS from test.support.script_helper import assert_python_ok, spawn_python try: import _testcapi @@ -33,7 +34,7 @@ def test_enums(self): self.assertEqual(sys.platform, "win32") -@unittest.skipIf(sys.platform == "win32", "Not valid on Windows") +@unittest.skipIf(MS_WINDOWS, "Not valid on Windows") class PosixTests(unittest.TestCase): def trivial_signal_handler(self, *args): pass @@ -95,7 +96,7 @@ def test_keyboard_interrupt_exit_code(self): # to confirm that our process died via a SIGINT proved too complex. -@unittest.skipUnless(sys.platform == "win32", "Windows specific") +@unittest.skipUnless(MS_WINDOWS, "Windows specific") class WindowsSignalTests(unittest.TestCase): def test_valid_signals(self): @@ -201,7 +202,7 @@ def test_set_wakeup_fd_socket_result(self): # On Windows, files are always blocking and Windows does not provide a # function to test if a socket is in non-blocking mode. - @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX") + @unittest.skipIf(MS_WINDOWS, "tests specific to POSIX") def test_set_wakeup_fd_blocking(self): rfd, wfd = os.pipe() self.addCleanup(os.close, rfd) @@ -220,7 +221,7 @@ def test_set_wakeup_fd_blocking(self): signal.set_wakeup_fd(-1) -@unittest.skipIf(sys.platform == "win32", "Not valid on Windows") +@unittest.skipIf(MS_WINDOWS, "Not valid on Windows") class WakeupSignalTests(unittest.TestCase): @unittest.skipIf(_testcapi is None, 'need _testcapi') def check_wakeup(self, test_body, *signals, ordered=True): @@ -498,7 +499,7 @@ def test_warn_on_full_buffer(self): import sys import time import _testcapi - from test.support import captured_stderr + from test.support import captured_stderr, MS_WINDOWS signum = signal.SIGINT @@ -512,7 +513,7 @@ def handler(signum, frame): read, write = socket.socketpair() # Fill the socketpair buffer - if sys.platform == 'win32': + if MS_WINDOWS: # bpo-34130: On Windows, sometimes non-blocking send fails to fill # the full socketpair buffer, so use a timeout of 50 ms instead. write.settimeout(0.050) @@ -594,7 +595,7 @@ def handler(signum, frame): assert_python_ok('-c', code) -@unittest.skipIf(sys.platform == "win32", "Not valid on Windows") +@unittest.skipIf(MS_WINDOWS, "Not valid on Windows") class SiginterruptTest(unittest.TestCase): def readpipe_interrupted(self, interrupt): @@ -679,7 +680,7 @@ def test_siginterrupt_off(self): self.assertFalse(interrupted) -@unittest.skipIf(sys.platform == "win32", "Not valid on Windows") +@unittest.skipIf(MS_WINDOWS, "Not valid on Windows") class ItimerTest(unittest.TestCase): def setUp(self): self.hndl_called = False @@ -1250,7 +1251,7 @@ def test_sigint(self): with self.assertRaises(KeyboardInterrupt): signal.raise_signal(signal.SIGINT) - @unittest.skipIf(sys.platform != "win32", "Windows specific test") + @unittest.skipUnless(MS_WINDOWS, "Windows specific test") def test_invalid_argument(self): try: SIGHUP = 1 # not supported on win32 diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 8643da0540f37b..1e062316c98294 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -8,7 +8,7 @@ import test.support from test import support from test.support import (captured_stderr, TESTFN, EnvironmentVarGuard, - change_cwd) + change_cwd, MACOS, MS_WINDOWS) import builtins import os import sys @@ -186,7 +186,7 @@ def test__getuserbase(self): self.assertEqual(site._getuserbase(), sysconfig._getuserbase()) def test_get_path(self): - if sys.platform == 'darwin' and sys._framework: + if MACOS and sys._framework: scheme = 'osx_framework_user' else: scheme = os.name + '_user' @@ -470,7 +470,7 @@ def test_setting_help(self): self.assertTrue(hasattr(builtins, "help")) def test_aliasing_mbcs(self): - if sys.platform == "win32": + if MS_WINDOWS: import locale if locale.getdefaultlocale()[1].startswith('cp'): for value in encodings.aliases.aliases.values(): @@ -527,11 +527,11 @@ def test_startup_imports(self): # http://bugs.python.org/issue19205 re_mods = {'re', '_sre', 'sre_compile', 'sre_constants', 'sre_parse'} # _osx_support uses the re module in many placs - if sys.platform != 'darwin': + if not MACOS: self.assertFalse(modules.intersection(re_mods), stderr) # http://bugs.python.org/issue9548 self.assertNotIn('locale', modules, stderr) - if sys.platform != 'darwin': + if not MACOS: # http://bugs.python.org/issue19209 self.assertNotIn('copyreg', modules, stderr) # http://bugs.python.org/issue19218> @@ -559,7 +559,7 @@ def test_startup_interactivehook_isolated_explicit(self): self.assertTrue(r, "'__interactivehook__' not added by enablerlcompleter()") -@unittest.skipUnless(sys.platform == 'win32', "only supported on Windows") +@unittest.skipUnless(MS_WINDOWS, "only supported on Windows") class _pthFileTests(unittest.TestCase): def _create_underpth_exe(self, lines): diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index fdcf6f21925645..5fe3bc967f2908 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -19,12 +19,12 @@ import unittest from test import support, mock_socket -from test.support import HOST, HOSTv4, HOSTv6 +from test.support import HOST, HOSTv4, HOSTv6, MACOS from test.support import threading_setup, threading_cleanup, join_thread from unittest.mock import Mock -if sys.platform == 'darwin': +if MACOS: # select.poll returns a select.POLLHUP at the end of the tests # on darwin, so just ignore it def handle_expt(self): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index b0bdb11d9028d7..2f3b061ef96ce4 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1,5 +1,6 @@ import unittest from test import support +from test.support import AIX, LINUX, MACOS, MS_WINDOWS import errno import io @@ -40,7 +41,6 @@ MAIN_TIMEOUT = 60.0 VSOCKPORT = 1234 -AIX = platform.system() == "AIX" try: import _socket @@ -1048,7 +1048,7 @@ def testGetServBy(self): # I've ordered this by protocols that have both a tcp and udp # protocol, at least for modern Linuxes. if (sys.platform.startswith(('freebsd', 'netbsd', 'gnukfreebsd')) - or sys.platform in ('linux', 'darwin')): + or LINUX or MACOS): # avoid the 'echo' service on this platform, as there is an # assumption breaking non-standard port/protocol entry services = ('daytime', 'qotd', 'domain') @@ -1162,7 +1162,7 @@ def testIPv6toString(self): except ImportError: self.skipTest('could not import needed symbols from socket') - if sys.platform == "win32": + if MS_WINDOWS: try: inet_pton(AF_INET6, '::') except OSError as e: @@ -1252,7 +1252,7 @@ def testStringToIPv6(self): except ImportError: self.skipTest('could not import needed symbols from socket') - if sys.platform == "win32": + if MS_WINDOWS: try: inet_ntop(AF_INET6, b'\x00' * 16) except OSError as e: @@ -1655,9 +1655,7 @@ def test_getaddrinfo_ipv6_scopeid_symbolic(self): self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, ifindex)) @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') - @unittest.skipUnless( - sys.platform == 'win32', - 'Numeric scope id does not work or undocumented') + @unittest.skipUnless(MS_WINDOWS, 'Numeric scope id does not work or undocumented') def test_getaddrinfo_ipv6_scopeid_numeric(self): # Also works on Linux and Mac OS X, but is not documented (?) # Windows, Linux and Max OS X allow nonexistent interface numbers here. @@ -1684,8 +1682,7 @@ def test_getnameinfo_ipv6_scopeid_symbolic(self): self.assertEqual(nameinfo, ('ff02::1de:c0:face:8d%' + test_interface, '1234')) @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') - @unittest.skipUnless( sys.platform == 'win32', - 'Numeric scope id does not work or undocumented') + @unittest.skipUnless(MS_WINDOWS, 'Numeric scope id does not work or undocumented') def test_getnameinfo_ipv6_scopeid_numeric(self): # Also works on Linux (undocumented), but does not work on Mac OS X # Windows and Linux allow nonexistent interface numbers here. @@ -2737,7 +2734,7 @@ def _testSendmsgTimeout(self): # Linux supports MSG_DONTWAIT when sending, but in general, it # only works when receiving. Could add other platforms if they # support it too. - @skipWithClientIf(sys.platform not in {"linux"}, + @skipWithClientIf(not LINUX, "MSG_DONTWAIT not known to work on this platform when " "sending") def testSendmsgDontWait(self): @@ -3254,7 +3251,7 @@ def testFDPassCMSG_LEN(self): def _testFDPassCMSG_LEN(self): self.createAndSendFDs(1) - @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(MACOS, "skipping, see issue #12958") @unittest.skipIf(AIX, "skipping, see issue #22397") @requireAttrs(socket, "CMSG_SPACE") def testFDPassSeparate(self): @@ -3265,7 +3262,7 @@ def testFDPassSeparate(self): maxcmsgs=2) @testFDPassSeparate.client_skip - @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(MACOS, "skipping, see issue #12958") @unittest.skipIf(AIX, "skipping, see issue #22397") def _testFDPassSeparate(self): fd0, fd1 = self.newFDs(2) @@ -3278,7 +3275,7 @@ def _testFDPassSeparate(self): array.array("i", [fd1]))]), len(MSG)) - @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(MACOS, "skipping, see issue #12958") @unittest.skipIf(AIX, "skipping, see issue #22397") @requireAttrs(socket, "CMSG_SPACE") def testFDPassSeparateMinSpace(self): @@ -3292,7 +3289,7 @@ def testFDPassSeparateMinSpace(self): maxcmsgs=2, ignoreflags=socket.MSG_CTRUNC) @testFDPassSeparateMinSpace.client_skip - @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(MACOS, "skipping, see issue #12958") @unittest.skipIf(AIX, "skipping, see issue #22397") def _testFDPassSeparateMinSpace(self): fd0, fd1 = self.newFDs(2) @@ -3316,7 +3313,7 @@ def sendAncillaryIfPossible(self, msg, ancdata): nbytes = self.sendmsgToServer([msg]) self.assertEqual(nbytes, len(msg)) - @unittest.skipIf(sys.platform == "darwin", "see issue #24725") + @unittest.skipIf(MACOS, "see issue #24725") def testFDPassEmpty(self): # Try to pass an empty FD array. Can receive either no array # or an empty array. @@ -5023,7 +5020,7 @@ def test_setblocking_invalidfd(self): sock.setblocking(False) -@unittest.skipUnless(sys.platform == 'linux', 'Linux specific test') +@unittest.skipUnless(LINUX, 'Linux specific test') class TestLinuxAbstractNamespace(unittest.TestCase): UNIX_PATH_MAX = 108 @@ -6046,7 +6043,7 @@ def test_length_restriction(self): sock.bind(("type", "n" * 64)) -@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") +@unittest.skipUnless(MS_WINDOWS, "requires Windows") class TestMSWindowsTCPFlags(unittest.TestCase): knownTCPFlags = { # available since long time ago diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 4444e945952fc3..f279be917661fc 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -3,6 +3,7 @@ import sys import unittest from test import support +from test.support import MS_WINDOWS import socket import select import time @@ -805,7 +806,7 @@ def test_get_default_verify_paths(self): self.assertEqual(paths.cafile, CERTFILE) self.assertEqual(paths.capath, CAPATH) - @unittest.skipUnless(sys.platform == "win32", "Windows specific") + @unittest.skipUnless(MS_WINDOWS, "Windows specific") def test_enum_certificates(self): self.assertTrue(ssl.enum_certificates("CA")) self.assertTrue(ssl.enum_certificates("ROOT")) @@ -830,7 +831,7 @@ def test_enum_certificates(self): serverAuth = "1.3.6.1.5.5.7.3.1" self.assertIn(serverAuth, trust_oids) - @unittest.skipUnless(sys.platform == "win32", "Windows specific") + @unittest.skipUnless(MS_WINDOWS, "Windows specific") def test_enum_crls(self): self.assertTrue(ssl.enum_crls("CA")) self.assertRaises(TypeError, ssl.enum_crls) @@ -1476,7 +1477,7 @@ def test_load_default_certs(self): self.assertRaises(TypeError, ctx.load_default_certs, None) self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH') - @unittest.skipIf(sys.platform == "win32", "not-Windows specific") + @unittest.skipIf(MS_WINDOWS, "not-Windows specific") @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars") def test_load_default_certs_env(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) @@ -1486,7 +1487,7 @@ def test_load_default_certs_env(self): ctx.load_default_certs() self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0}) - @unittest.skipUnless(sys.platform == "win32", "Windows specific") + @unittest.skipUnless(MS_WINDOWS, "Windows specific") @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs") def test_load_default_certs_env_windows(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py index 38ff2bcf8a6b64..7c39202b62af14 100644 --- a/Lib/test/test_stat.py +++ b/Lib/test/test_stat.py @@ -2,7 +2,7 @@ import os import socket import sys -from test.support import TESTFN, import_fresh_module +from test.support import TESTFN, import_fresh_module, MS_WINDOWS c_stat = import_fresh_module('stat', fresh=['_stat']) py_stat = import_fresh_module('stat', blocked=['_stat']) @@ -218,7 +218,7 @@ def test_module_attributes(self): self.assertTrue(callable(func)) self.assertEqual(func(0), 0) - @unittest.skipUnless(sys.platform == "win32", + @unittest.skipUnless(MS_WINDOWS, "FILE_ATTRIBUTE_* constants are Win32 specific") def test_file_attribute_constants(self): for key, value in sorted(self.file_attributes.items()): diff --git a/Lib/test/test_strftime.py b/Lib/test/test_strftime.py index ad348f2d6bc786..f06e72addece7b 100644 --- a/Lib/test/test_strftime.py +++ b/Lib/test/test_strftime.py @@ -6,7 +6,7 @@ import sys import re from test import support -from test.support import AIX +from test.support import AIX, MS_WINDOWS import time import unittest @@ -188,7 +188,7 @@ class Y1900Tests(unittest.TestCase): def test_y_before_1900(self): # Issue #13674, #19634 t = (1899, 1, 1, 0, 0, 0, 0, 0, 0) - if (sys.platform == "win32" or AIX + if (MS_WINDOWS or AIX or sys.platform.startswith(("sunos", "solaris"))): with self.assertRaises(ValueError): time.strftime("%y", t) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index b0b6b06e92759e..fc2d76ecd044b1 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -18,7 +18,7 @@ import threading import gc import textwrap -from test.support import FakePath +from test.support import FakePath, MACOS, MS_WINDOWS try: import ctypes @@ -35,13 +35,11 @@ if support.PGO: raise unittest.SkipTest("test is not helpful for PGO") -mswindows = (sys.platform == "win32") - # # Depends on the following external programs: Python # -if mswindows: +if MS_WINDOWS: SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), ' 'os.O_BINARY);') else: @@ -314,7 +312,7 @@ def test_executable_takes_precedence(self): self._assert_python, pre_args, executable=NONEXISTING_CMD[0]) - @unittest.skipIf(mswindows, "executable argument replaces shell") + @unittest.skipIf(MS_WINDOWS, "executable argument replaces shell") def test_executable_replaces_shell(self): # Check that the executable argument replaces the default shell # when shell=True. @@ -363,7 +361,7 @@ def test_cwd_with_pathlike(self): temp_dir = self._normalize_cwd(temp_dir) self._assert_cwd(temp_dir, sys.executable, cwd=FakePath(temp_dir)) - @unittest.skipIf(mswindows, "pending resolution of issue #15533") + @unittest.skipIf(MS_WINDOWS, "pending resolution of issue #15533") def test_cwd_with_relative_arg(self): # Check that Popen looks for args[0] relative to cwd if args[0] # is relative. @@ -379,7 +377,7 @@ def test_cwd_with_relative_arg(self): python_dir = self._normalize_cwd(python_dir) self._assert_cwd(python_dir, rel_python, cwd=python_dir) - @unittest.skipIf(mswindows, "pending resolution of issue #15533") + @unittest.skipIf(MS_WINDOWS, "pending resolution of issue #15533") def test_cwd_with_relative_executable(self): # Check that Popen looks for executable relative to cwd if executable # is relative (and that executable takes precedence over args[0]). @@ -632,8 +630,7 @@ def test_env(self): # Windows requires at least the SYSTEMROOT environment variable to start # Python - @unittest.skipIf(sys.platform == 'win32', - 'cannot test an empty env on Windows') + @unittest.skipIf(MS_WINDOWS, 'cannot test an empty env on Windows') @unittest.skipIf(sysconfig.get_config_var('Py_ENABLE_SHARED') == 1, 'The Python shared library cannot be loaded ' 'with an empty environment.') @@ -1008,7 +1005,7 @@ def test_communicate_errors(self): def test_no_leaking(self): # Make sure we leak no resources - if not mswindows: + if not MS_WINDOWS: max_handles = 1026 # too much for most UNIX systems else: max_handles = 2050 # too much for (at least some) Windows setups @@ -1245,7 +1242,7 @@ def kill_proc_timer_thread(): t = threading.Timer(0.2, kill_proc_timer_thread) t.start() - if mswindows: + if MS_WINDOWS: expected_errorcode = 1 else: # Should be -9 because of the proc.kill() from the thread. @@ -1366,13 +1363,13 @@ def test_failed_child_execute_fd_leak(self): fds_after_exception = os.listdir(fd_directory) self.assertEqual(fds_before_popen, fds_after_exception) - @unittest.skipIf(mswindows, "behavior currently not supported on Windows") + @unittest.skipIf(MS_WINDOWS, "behavior currently not supported on Windows") def test_file_not_found_includes_filename(self): with self.assertRaises(FileNotFoundError) as c: subprocess.call(['/opt/nonexistent_binary', 'with', 'some', 'args']) self.assertEqual(c.exception.filename, '/opt/nonexistent_binary') - @unittest.skipIf(mswindows, "behavior currently not supported on Windows") + @unittest.skipIf(MS_WINDOWS, "behavior currently not supported on Windows") def test_file_not_found_with_bad_cwd(self): with self.assertRaises(FileNotFoundError) as c: subprocess.Popen(['exit', '0'], cwd='/some/nonexistent/directory') @@ -1506,7 +1503,7 @@ def test_stderr_with_capture_output_arg(self): self.assertIn('capture_output', c.exception.args[0]) -@unittest.skipIf(mswindows, "POSIX specific tests") +@unittest.skipIf(MS_WINDOWS, "POSIX specific tests") class POSIXProcessTestCase(BaseTestCase): def setUp(self): @@ -1793,8 +1790,7 @@ def raise_runtime_error(): if not enabled: gc.disable() - @unittest.skipIf( - sys.platform == 'darwin', 'setrlimit() seems to fail on OS X') + @unittest.skipIf(MACOS, 'setrlimit() seems to fail on OS X') def test_preexec_fork_failure(self): # The internal code did not preserve the previous exception when # re-enabling garbage collection @@ -2815,7 +2811,7 @@ def test_stopped(self): self.assertEqual(returncode, -3) -@unittest.skipUnless(mswindows, "Windows specific tests") +@unittest.skipUnless(MS_WINDOWS, "Windows specific tests") class Win32ProcessTestCase(BaseTestCase): def test_startupinfo(self): @@ -3147,7 +3143,7 @@ def test_getoutput(self): dir = tempfile.mkdtemp() name = os.path.join(dir, "foo") status, output = subprocess.getstatusoutput( - ("type " if mswindows else "cat ") + name) + ("type " if MS_WINDOWS else "cat ") + name) self.assertNotEqual(status, 0) finally: if dir is not None: @@ -3181,7 +3177,7 @@ def tearDown(self): ProcessTestCase.tearDown(self) -@unittest.skipUnless(mswindows, "Windows-specific tests") +@unittest.skipUnless(MS_WINDOWS, "Windows-specific tests") class CommandsWithSpaces (BaseTestCase): def setUp(self): diff --git a/Lib/test/test_sundry.py b/Lib/test/test_sundry.py index 6e36a6123daa0e..d4a08f45ddf627 100644 --- a/Lib/test/test_sundry.py +++ b/Lib/test/test_sundry.py @@ -1,7 +1,7 @@ """Do a minimal test of all the modules that aren't otherwise tested.""" import importlib -import sys from test import support +from test.support import MS_WINDOWS import unittest class TestUntestedModules(unittest.TestCase): @@ -25,7 +25,7 @@ def test_untested_modules_can_be_imported(self): import distutils.unixccompiler import distutils.command.bdist_dumb - if sys.platform.startswith('win'): + if MS_WINDOWS: import distutils.command.bdist_msi import distutils.command.bdist import distutils.command.bdist_rpm diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index d1c7daad7bba48..d00f9b822a2a90 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1,4 +1,5 @@ import unittest, test.support +from test.support import MACOS, MS_WINDOWS from test.support.script_helper import assert_python_ok, assert_python_failure import sys, io, os import struct @@ -486,7 +487,7 @@ def test_attributes(self): self.assertTrue(vi > (1,0,0)) self.assertIsInstance(sys.float_repr_style, str) self.assertIn(sys.float_repr_style, ('short', 'legacy')) - if not sys.platform.startswith('win'): + if not MS_WINDOWS: self.assertIsInstance(sys.abiflags, str) def test_thread_info(self): @@ -647,7 +648,7 @@ def check_fsencoding(self, fs_encoding, expected=None): def test_getfilesystemencoding(self): fs_encoding = sys.getfilesystemencoding() - if sys.platform == 'darwin': + if MACOS: expected = 'utf-8' else: expected = None diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 1b1929885edd6b..1eca2f459f7127 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -6,7 +6,8 @@ from copy import copy from test.support import (import_module, TESTFN, unlink, check_warnings, - captured_stdout, skip_unless_symlink, change_cwd) + captured_stdout, skip_unless_symlink, change_cwd, + LINUX, MACOS, MS_WINDOWS) import sysconfig from sysconfig import (get_paths, get_platform, get_config_vars, @@ -236,7 +237,7 @@ def test_symlink(self): # On Windows, the EXE needs to know where pythonXY.dll is at so we have # to add the directory to the path. env = None - if sys.platform == "win32": + if MS_WINDOWS: env = {k.upper(): os.environ[k] for k in os.environ} env["PATH"] = "{};{}".format( os.path.dirname(sys.executable), env.get("PATH", "")) @@ -294,14 +295,14 @@ def test_main(self): _main() self.assertTrue(len(output.getvalue().split('\n')) > 0) - @unittest.skipIf(sys.platform == "win32", "Does not apply to Windows") + @unittest.skipIf(MS_WINDOWS, "Does not apply to Windows") def test_ldshared_value(self): ldflags = sysconfig.get_config_var('LDFLAGS') ldshared = sysconfig.get_config_var('LDSHARED') self.assertIn(ldflags, ldshared) - @unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX") + @unittest.skipUnless(MACOS, "test only relevant on MacOSX") def test_platform_in_subprocess(self): my_platform = sysconfig.get_platform() @@ -391,8 +392,7 @@ def test_SO_in_vars(self): self.assertIsNotNone(vars['SO']) self.assertEqual(vars['SO'], vars['EXT_SUFFIX']) - @unittest.skipUnless(sys.platform == 'linux' and - hasattr(sys.implementation, '_multiarch'), + @unittest.skipUnless(LINUX and hasattr(sys.implementation, '_multiarch'), 'multiarch-specific test') def test_triplet_in_ext_suffix(self): ctypes = import_module('ctypes') @@ -409,15 +409,14 @@ def test_triplet_in_ext_suffix(self): else: # 8 byte pointer size self.assertTrue(suffix.endswith('x86_64-linux-gnu.so'), suffix) - @unittest.skipUnless(sys.platform == 'darwin', 'OS X-specific test') + @unittest.skipUnless(MACOS, 'OS X-specific test') def test_osx_ext_suffix(self): suffix = sysconfig.get_config_var('EXT_SUFFIX') self.assertTrue(suffix.endswith('-darwin.so'), suffix) class MakefileTests(unittest.TestCase): - @unittest.skipIf(sys.platform.startswith('win'), - 'Test is not Windows compatible') + @unittest.skipIf(MS_WINDOWS, 'Test is not Windows compatible') def test_get_makefile_filename(self): makefile = sysconfig.get_makefile_filename() self.assertTrue(os.path.isfile(makefile), makefile) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 7e32cbccd6c56d..b2130c982970db 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -11,7 +11,7 @@ import tarfile from test import support -from test.support import script_helper +from test.support import script_helper, LINUX, MS_WINDOWS # Check for our compression modules. try: @@ -562,7 +562,7 @@ def test_extractall(self): tar.extractall(DIR, directories) for tarinfo in directories: path = os.path.join(DIR, tarinfo.name) - if sys.platform != "win32": + if not MS_WINDOWS: # Win32 has no support for fine grained permissions. self.assertEqual(tarinfo.mode & 0o777, os.stat(path).st_mode & 0o777) @@ -591,7 +591,7 @@ def test_extract_directory(self): tar.extract(tarinfo, path=DIR) extracted = os.path.join(DIR, dirtype) self.assertEqual(os.path.getmtime(extracted), tarinfo.mtime) - if sys.platform != "win32": + if not MS_WINDOWS: self.assertEqual(os.stat(extracted).st_mode & 0o777, 0o755) finally: support.rmtree(DIR) @@ -974,7 +974,7 @@ def _fs_supports_holes(): # # The function returns False if page size is larger than 4 KiB. # For example, ppc64 uses pages of 64 KiB. - if sys.platform.startswith("linux"): + if LINUX: # Linux evidentially has 512 byte st_blocks units. name = os.path.join(TEMPDIR, "sparse-test") with open(name, "wb") as fobj: @@ -1334,7 +1334,7 @@ def test_pathnames(self): self._test_pathname("foo" + os.sep + os.sep, "foo", dir=True) def test_abs_pathnames(self): - if sys.platform == "win32": + if MS_WINDOWS: self._test_pathname("C:\\foo", "foo") else: self._test_pathname("/foo", "foo") @@ -1404,7 +1404,7 @@ def test_stream_padding(self): self.assertEqual(data.count(b"\0"), tarfile.RECORDSIZE, "incorrect zero padding") - @unittest.skipUnless(sys.platform != "win32" and hasattr(os, "umask"), + @unittest.skipUnless(not MS_WINDOWS and hasattr(os, "umask"), "Missing umask implementation") def test_file_mode(self): # Test for issue #8464: Create files with correct diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py index 80f1668bcecab8..c12f694ba7b501 100644 --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -226,7 +226,7 @@ def testPackageRequireException(self): tcl = self.interp self.assertRaises(TclError,tcl.eval,'package require DNE') - @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows') + @unittest.skipUnless(support.MS_WINDOWS, 'Requires Windows') def testLoadWithUNC(self): # Build a UNC path from the regular path. # Something like diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 489141d6ad726a..9e1b86d259a08e 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -14,7 +14,7 @@ import unittest from test import support -from test.support import script_helper +from test.support import script_helper, MS_WINDOWS has_textmode = (tempfile._text_openflags != tempfile._bin_openflags) @@ -434,7 +434,7 @@ def test_file_mode(self): file = self.do_create() mode = stat.S_IMODE(os.stat(file.name).st_mode) expected = 0o600 - if sys.platform == 'win32': + if MS_WINDOWS: # There's no distinction among 'user', 'group' and 'world'; # replicate the 'user' bits. user = expected >> 6 @@ -468,7 +468,7 @@ def test_noinherit(self): # On Windows a spawn* /path/ with embedded spaces shouldn't be quoted, # but an arg with embedded spaces should be decorated with double # quotes on each end - if sys.platform == 'win32': + if MS_WINDOWS: decorated = '"%s"' % sys.executable tester = '"%s"' % tester else: @@ -739,7 +739,7 @@ def test_mode(self): mode = stat.S_IMODE(os.stat(dir).st_mode) mode &= 0o777 # Mask off sticky bits inherited from /tmp expected = 0o700 - if sys.platform == 'win32': + if MS_WINDOWS: # There's no distinction among 'user', 'group' and 'world'; # replicate the 'user' bits. user = expected >> 6 diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 2ddc77b266b542..ac67f824a77ad0 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -3,7 +3,7 @@ """ import test.support -from test.support import (verbose, import_module, cpython_only, +from test.support import (verbose, import_module, cpython_only, MACOS, requires_type_collecting) from test.support.script_helper import assert_python_ok, assert_python_failure @@ -970,7 +970,7 @@ def test_releasing_unacquired_lock(self): lock = threading.Lock() self.assertRaises(RuntimeError, lock.release) - @unittest.skipUnless(sys.platform == 'darwin' and test.support.python_is_optimized(), + @unittest.skipUnless(MACOS and test.support.python_is_optimized(), 'test macosx problem') def test_recursion_limit(self): # Issue 9670 diff --git a/Lib/test/test_threadsignals.py b/Lib/test/test_threadsignals.py index eeacd3698cb138..a1fd870eaf3106 100644 --- a/Lib/test/test_threadsignals.py +++ b/Lib/test/test_threadsignals.py @@ -5,10 +5,11 @@ import os import sys from test import support +from test.support import LINUX, MS_WINDOWS import _thread as thread import time -if (sys.platform[:3] == 'win'): +if MS_WINDOWS: raise unittest.SkipTest("Can't test signal on %s" % sys.platform) process_pid = os.getpid() @@ -78,8 +79,7 @@ def alarm_interrupt(self, sig, frame): @unittest.skipIf(USING_PTHREAD_COND, 'POSIX condition variables cannot be interrupted') - @unittest.skipIf(sys.platform.startswith('linux') and - not sys.thread_info.version, + @unittest.skipIf(LINUX and not sys.thread_info.version, 'Issue 34004: musl does not allow interruption of locks ' 'by signals.') # Issue #20564: sem_timedwait() cannot be interrupted on OpenBSD @@ -109,8 +109,7 @@ def test_lock_acquire_interruption(self): @unittest.skipIf(USING_PTHREAD_COND, 'POSIX condition variables cannot be interrupted') - @unittest.skipIf(sys.platform.startswith('linux') and - not sys.thread_info.version, + @unittest.skipIf(LINUX and not sys.thread_info.version, 'Issue 34004: musl does not allow interruption of locks ' 'by signals.') # Issue #20564: sem_timedwait() cannot be interrupted on OpenBSD diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 136ad29e20adf0..1262b62e1953eb 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -1,4 +1,5 @@ from test import support +from test.support import LINUX, MS_WINDOWS import decimal import enum import locale @@ -494,7 +495,7 @@ def test_process_time(self): def test_thread_time(self): if not hasattr(time, 'thread_time'): - if sys.platform.startswith(('linux', 'win')): + if LINUX or MS_WINDOWS: self.fail("time.thread_time() should be available on %r" % (sys.platform,)) else: @@ -941,7 +942,7 @@ def timeval_converter(ns): us = us_converter(ns) return divmod(us, SEC_TO_US) - if sys.platform == 'win32': + if MS_WINDOWS: from _testcapi import LONG_MIN, LONG_MAX # On Windows, timeval.tv_sec type is a C long diff --git a/Lib/test/test_tix.py b/Lib/test/test_tix.py index e6ea3d07444ce7..983a9ec62567db 100644 --- a/Lib/test/test_tix.py +++ b/Lib/test/test_tix.py @@ -17,7 +17,7 @@ def setUp(self): try: self.root = tix.Tk() except TclError: - if sys.platform.startswith('win'): + if support.MS_WINDOWS: self.fail('Tix should always be available on Windows') self.skipTest('Tix not available') else: diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index 36b72e40c7e419..ab95a6412d7f2b 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -14,6 +14,7 @@ import unittest import warnings from test import support, string_tests +from test.support import JYTHON # Error handling (bad decoder return) def search_function(encoding): @@ -81,7 +82,7 @@ def test_literals(self): self.assertNotEqual(r"\u0020", " ") def test_ascii(self): - if not sys.platform.startswith('java'): + if not support.JYTHON: # Test basic sanity of repr() self.assertEqual(ascii('abc'), "'abc'") self.assertEqual(ascii('ab\\c'), "'ab\\\\c'") @@ -123,7 +124,7 @@ def __repr__(self): self.assertRaises(TypeError, ascii, WrongRepr()) def test_repr(self): - if not sys.platform.startswith('java'): + if not support.JYTHON: # Test basic sanity of repr() self.assertEqual(repr('abc'), "'abc'") self.assertEqual(repr('ab\\c'), "'ab\\\\c'") @@ -584,7 +585,7 @@ def test_islower(self): def test_isupper(self): super().test_isupper() - if not sys.platform.startswith('java'): + if not support.JYTHON: self.checkequalnofix(False, '\u1FFc', 'isupper') self.assertTrue('\u2167'.isupper()) self.assertFalse('\u2177'.isupper()) @@ -1344,7 +1345,7 @@ def test_formatting(self): self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", -1, -2, 3.5), 'abc, abc, -1, -2.000000, 3.50') self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", -1, -2, 3.57), 'abc, abc, -1, -2.000000, 3.57') self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", -1, -2, 1003.57), 'abc, abc, -1, -2.000000, 1003.57') - if not sys.platform.startswith('java'): + if not support.JYTHON: self.assertEqual("%r, %r" % (b"abc", "abc"), "b'abc', 'abc'") self.assertEqual("%r" % ("\u1234",), "'\u1234'") self.assertEqual("%a" % ("\u1234",), "'\\u1234'") @@ -1537,7 +1538,7 @@ def __str__(self): # unicode(obj, encoding, error) tests (this maps to # PyUnicode_FromEncodedObject() at C level) - if not sys.platform.startswith('java'): + if not support.JYTHON: self.assertRaises( TypeError, str, @@ -1551,7 +1552,7 @@ def __str__(self): 'strings are decoded to unicode' ) - if not sys.platform.startswith('java'): + if not support.JYTHON: self.assertEqual( str( memoryview(b'character buffers are decoded to unicode'), diff --git a/Lib/test/test_unicode_file_functions.py b/Lib/test/test_unicode_file_functions.py index 1cd0d621cd4b3a..d61090293a18af 100644 --- a/Lib/test/test_unicode_file_functions.py +++ b/Lib/test/test_unicode_file_functions.py @@ -6,6 +6,7 @@ import warnings from unicodedata import normalize from test import support +from test.support import MACOS, MS_WINDOWS filenames = [ '1_abc', @@ -27,7 +28,7 @@ # these normal forms. For example, HFS Plus uses a variant of Normal Form D # in which U+2000 through U+2FFF, U+F900 through U+FAFF, and U+2F800 through # U+2FAFF are not decomposed." -if sys.platform != 'darwin': +if not MACOS: filenames.extend([ # Specific code points: NFC(fn), NFD(fn), NFKC(fn) and NFKD(fn) all different '11_\u0385\u03d3\u03d4', @@ -103,7 +104,7 @@ def test_failures(self): self._apply_failure(os.remove, name) self._apply_failure(os.listdir, name) - if sys.platform == 'win32': + if MS_WINDOWS: # Windows is lunatic. Issue #13366. _listdir_failure = NotADirectoryError, FileNotFoundError else: @@ -121,7 +122,7 @@ def test_open(self): # NFD (a variant of Unicode NFD form). Normalize the filename to NFC, NFKC, # NFKD in Python is useless, because darwin will normalize it later and so # open(), os.stat(), etc. don't raise any exception. - @unittest.skipIf(sys.platform == 'darwin', 'irrelevant test on Mac OS X') + @unittest.skipIf(MACOS, 'irrelevant test on Mac OS X') def test_normalize(self): files = set(self.files) others = set() @@ -139,7 +140,7 @@ def test_normalize(self): # Skip the test on darwin, because darwin uses a normalization different # than Python NFD normalization: filenames are different even if we use # Python NFD normalization. - @unittest.skipIf(sys.platform == 'darwin', 'irrelevant test on Mac OS X') + @unittest.skipIf(MACOS, 'irrelevant test on Mac OS X') def test_listdir(self): sf0 = set(self.files) with warnings.catch_warnings(): diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index 2ac73b58d83206..a4c2b92fe93ed0 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -1367,7 +1367,7 @@ def test_quoting(self): "url2pathname() failed; %s != %s" % (expect, result)) - @unittest.skipUnless(sys.platform == 'win32', + @unittest.skipUnless(support.MS_WINDOWS, 'test specific to the urllib.url2path function.') def test_ntpath(self): given = ('/C:/', '///C:/', '/C|//') diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py index c6d275e16b097f..2beddfecc3567a 100644 --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -1,6 +1,7 @@ import unittest from test import support from test import test_urllib +from test.support import MACOS import os import io @@ -1421,7 +1422,7 @@ def test_proxy_https_proxy_authorization(self): self.assertEqual(req.host, "proxy.example.com:3128") self.assertEqual(req.get_header("Proxy-authorization"), "FooBar") - @unittest.skipUnless(sys.platform == 'darwin', "only relevant for OSX") + @unittest.skipUnless(MACOS, "only relevant for OSX") def test_osx_proxy_bypass(self): bypass = { 'exclude_simple': False, diff --git a/Lib/test/test_utf8_mode.py b/Lib/test/test_utf8_mode.py index f3f788ee86f478..8421d968851ab1 100644 --- a/Lib/test/test_utf8_mode.py +++ b/Lib/test/test_utf8_mode.py @@ -7,7 +7,7 @@ import textwrap import unittest from test import support -from test.support import AIX, MS_WINDOWS +from test.support import AIX, ANDROID, MACOS, MS_WINDOWS from test.support.script_helper import assert_python_ok, assert_python_failure @@ -225,7 +225,7 @@ def check(utf8_opt, expected, **kw): with self.subTest(LC_ALL=loc): check('utf8', [arg_utf8], LC_ALL=loc) - if sys.platform == 'darwin' or support.is_android or VXWORKS: + if MACOS or ANDROID or VXWORKS: c_arg = arg_utf8 elif AIX: c_arg = arg.decode('iso-8859-1') diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 6822d567e42b58..7d5630848e1989 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -14,7 +14,8 @@ import sys import tempfile from test.support import (captured_stdout, captured_stderr, requires_zlib, - can_symlink, EnvironmentVarGuard, rmtree) + can_symlink, EnvironmentVarGuard, rmtree, + MACOS, MS_WINDOWS) import threading import unittest import venv @@ -94,8 +95,8 @@ def test_defaults(self): self.isdir(*self.lib) # Issue 21197 p = self.get_env_file('lib64') - conditions = ((struct.calcsize('P') == 8) and (os.name == 'posix') and - (sys.platform != 'darwin')) + conditions = ((struct.calcsize('P') == 8) + and (os.name == 'posix') and not MACOS) if conditions: self.assertTrue(os.path.islink(p)) else: @@ -153,7 +154,7 @@ def test_prefixes(self): out, err = check_output(cmd) self.assertEqual(out.strip(), expected.encode()) - if sys.platform == 'win32': + if MS_WINDOWS: ENV_SUBDIRS = ( ('Scripts',), ('Include',), diff --git a/Lib/test/test_winconsoleio.py b/Lib/test/test_winconsoleio.py index a78fa4d7d919ff..894659887304cd 100644 --- a/Lib/test/test_winconsoleio.py +++ b/Lib/test/test_winconsoleio.py @@ -7,8 +7,9 @@ import tempfile import unittest from test import support +from test.support import MS_WINDOWS -if sys.platform != 'win32': +if not MS_WINDOWS: raise unittest.SkipTest("test only relevant on win32") from _testconsole import write_input diff --git a/Lib/test/test_zipapp.py b/Lib/test/test_zipapp.py index 73bddc79c17ab6..8119d29aa18a6a 100644 --- a/Lib/test/test_zipapp.py +++ b/Lib/test/test_zipapp.py @@ -8,7 +8,7 @@ import unittest import zipapp import zipfile -from test.support import requires_zlib +from test.support import requires_zlib, MS_WINDOWS from unittest.mock import patch @@ -299,8 +299,7 @@ def test_content_of_copied_archive(self): self.assertEqual(set(z.namelist()), {'__main__.py'}) # (Unix only) tests that archives with shebang lines are made executable - @unittest.skipIf(sys.platform == 'win32', - 'Windows does not support an executable bit') + @unittest.skipIf(MS_WINDOWS, 'Windows does not support an executable bit') def test_shebang_is_executable(self): # Test that an archive with a shebang line is made executable. source = self.tmpdir / 'source' @@ -310,8 +309,7 @@ def test_shebang_is_executable(self): zipapp.create_archive(str(source), str(target), interpreter='python') self.assertTrue(target.stat().st_mode & stat.S_IEXEC) - @unittest.skipIf(sys.platform == 'win32', - 'Windows does not support an executable bit') + @unittest.skipIf(MS_WINDOWS, 'Windows does not support an executable bit') def test_no_shebang_is_not_executable(self): # Test that an archive with no shebang line is not made executable. source = self.tmpdir / 'source' From de5cfdd8429d7fbb763a8c7ed507a9ad33901c54 Mon Sep 17 00:00:00 2001 From: Michael Felt Date: Tue, 16 Apr 2019 15:32:37 +0000 Subject: [PATCH 010/212] Correct typo in Doc --- Doc/whatsnew/3.8.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 7f4f8d51b694df..466bcc364018be 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -382,7 +382,7 @@ The :mod:`test` module now uses ``CONSTANTS`` for the major platforms to standardize the style compared to the current practice of some constants and different styles of sys.platform and platform.system(). The constants are defined in `test.support`. -(Contributed by M. Felt in :issue:`36624'.) +(Contributed by M. Felt in :issue:`36624`.) tokenize -------- From 31e8d69bfe7cf5d4ffe0967cb225d2a8a229cc97 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Tue, 16 Apr 2019 09:47:11 -0700 Subject: [PATCH 011/212] =?UTF-8?q?bpo-33783:=20Use=20proper=20class=20mar?= =?UTF-8?q?kup=20for=20random.Random=20docs=20(GH=C3=A87817)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matthias Bussonnier --- Doc/library/random.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Doc/library/random.rst b/Doc/library/random.rst index 79a7bddad49792..fcedba4dbc2052 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -310,6 +310,11 @@ be found in any statistics text. Alternative Generator --------------------- +.. class:: Random([seed]) + + Class that implements the default pseudo-random number generator used by the + :mod:`random` module. + .. class:: SystemRandom([seed]) Class that uses the :func:`os.urandom` function for generating random numbers From 926b0cb5f688808dc11448a0bf3e452d1b92c232 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 17 Apr 2019 08:39:46 +0900 Subject: [PATCH 012/212] bpo-36641: Add "const" to PyDoc_VAR macro (GH-12854) It reduces "data" segment in python about 200KB. --- Include/pymacro.h | 2 +- Misc/NEWS.d/next/C API/2019-04-16-21-18-19.bpo-36641.pz-DIR.rst | 2 ++ Modules/_ssl.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2019-04-16-21-18-19.bpo-36641.pz-DIR.rst diff --git a/Include/pymacro.h b/Include/pymacro.h index 3f6ddbe9977ace..546f9c6e702025 100644 --- a/Include/pymacro.h +++ b/Include/pymacro.h @@ -67,7 +67,7 @@ /* Define macros for inline documentation. */ -#define PyDoc_VAR(name) static char name[] +#define PyDoc_VAR(name) static const char name[] #define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str) #ifdef WITH_DOC_STRINGS #define PyDoc_STR(str) str diff --git a/Misc/NEWS.d/next/C API/2019-04-16-21-18-19.bpo-36641.pz-DIR.rst b/Misc/NEWS.d/next/C API/2019-04-16-21-18-19.bpo-36641.pz-DIR.rst new file mode 100644 index 00000000000000..f92af63029be0f --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-04-16-21-18-19.bpo-36641.pz-DIR.rst @@ -0,0 +1,2 @@ +:c:macro:`PyDoc_VAR(name)` and :c:macro:`PyDoc_STRVAR(name,str)` now create +``static const char name[]`` instead of ``static char name[]``. Patch by Inada Naoki. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index f8ae916735f440..e75e3466dd3f2a 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -557,7 +557,7 @@ SSLError_str(PyOSErrorObject *self) static PyType_Slot sslerror_type_slots[] = { {Py_tp_base, NULL}, /* Filled out in module init as it's not a constant */ - {Py_tp_doc, SSLError_doc}, + {Py_tp_doc, (void*)SSLError_doc}, {Py_tp_str, SSLError_str}, {0, 0}, }; From 6fec905de5c139017f36b212e54cac46959808fe Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Wed, 17 Apr 2019 08:40:34 +0900 Subject: [PATCH 013/212] bpo-36642: make unicodedata const (GH-12855) --- Modules/unicodedata.c | 2 +- Modules/unicodedata_db.h | 18 +++++++++--------- Modules/unicodename_db.h | 12 ++++++------ Objects/unicodetype_db.h | 4 ++-- Tools/unicode/makeunicodedata.py | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index 9ceab1b3db4f78..7fdbf332ee7423 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -1029,7 +1029,7 @@ _getucname(PyObject *self, Py_UCS4 code, char* buffer, int buflen, int offset; int i; int word; - unsigned char* w; + const unsigned char* w; if (code >= 0x110000) return 0; diff --git a/Modules/unicodedata_db.h b/Modules/unicodedata_db.h index 11c7dc87244a17..66f81e311e2933 100644 --- a/Modules/unicodedata_db.h +++ b/Modules/unicodedata_db.h @@ -699,7 +699,7 @@ static const char *decomp_prefix[] = { }; /* index tables for the database records */ #define SHIFT 7 -static unsigned short index1[] = { +static const unsigned short index1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, @@ -1322,7 +1322,7 @@ static unsigned short index1[] = { 121, 260, }; -static unsigned short index2[] = { +static const unsigned short index2[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 2, 5, 6, 6, 7, 8, 7, 6, 6, 9, 10, 6, 11, 12, 13, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 6, 15, 16, 15, 6, 6, 17, @@ -3260,7 +3260,7 @@ static unsigned short index2[] = { }; /* decomposition data */ -static unsigned int decomp_data[] = { +static const unsigned int decomp_data[] = { 0, 257, 32, 514, 32, 776, 259, 97, 514, 32, 772, 259, 50, 259, 51, 514, 32, 769, 258, 956, 514, 32, 807, 259, 49, 259, 111, 772, 49, 8260, 52, 772, 49, 8260, 50, 772, 51, 8260, 52, 512, 65, 768, 512, 65, 769, 512, @@ -4328,7 +4328,7 @@ static unsigned int decomp_data[] = { /* index tables for the decomposition data */ #define DECOMP_SHIFT 7 -static unsigned char decomp_index1[] = { +static const unsigned char decomp_index1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 0, 0, 0, 0, 13, 14, 15, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 29, 30, 31, 32, 33, 34, @@ -4695,7 +4695,7 @@ static unsigned char decomp_index1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -static unsigned short decomp_index2[] = { +static const unsigned short decomp_index2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5512,7 +5512,7 @@ static unsigned short decomp_index2[] = { /* NFC pairs */ #define COMP_SHIFT 2 -static unsigned short comp_index[] = { +static const unsigned short comp_index[] = { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 12, 0, 13, 0, 0, @@ -5772,7 +5772,7 @@ static unsigned short comp_index[] = { 656, }; -static unsigned int comp_data[] = { +static const unsigned int comp_data[] = { 0, 0, 0, 0, 0, 0, 0, 8814, 0, 8800, 0, 0, 0, 0, 0, 8815, 0, 0, 192, 193, 194, 195, 256, 258, 550, 196, 7842, 197, 0, 461, 512, 514, 0, 0, 0, 7840, 0, 7680, 0, 0, 260, 0, 0, 0, 0, 0, 7682, 0, 0, 7684, 0, 0, 0, 0, 7686, 0, @@ -5982,7 +5982,7 @@ static const change_record change_records_3_2_0[] = { { 255, 19, 255, 255, 255, -1 }, { 1, 255, 255, 0, 255, 0 }, }; -static unsigned char changes_3_2_0_index[] = { +static const unsigned char changes_3_2_0_index[] = { 0, 1, 2, 2, 3, 4, 5, 6, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 2, 2, 2, 38, 39, 2, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, @@ -6356,7 +6356,7 @@ static unsigned char changes_3_2_0_index[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; -static unsigned char changes_3_2_0_data[] = { +static const unsigned char changes_3_2_0_data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/Modules/unicodename_db.h b/Modules/unicodename_db.h index 8fa87a02cd26a6..372616966aa438 100644 --- a/Modules/unicodename_db.h +++ b/Modules/unicodename_db.h @@ -3,7 +3,7 @@ #define NAME_MAXLEN 256 /* lexicon */ -static unsigned char lexicon[] = { +static const unsigned char lexicon[] = { 76, 69, 84, 84, 69, 210, 83, 73, 71, 206, 87, 73, 84, 200, 83, 77, 65, 76, 204, 83, 89, 76, 76, 65, 66, 76, 197, 67, 65, 80, 73, 84, 65, 204, 72, 73, 69, 82, 79, 71, 76, 89, 80, 200, 76, 65, 84, 73, 206, 65, 82, 65, @@ -6442,7 +6442,7 @@ static unsigned char lexicon[] = { 45, 68, 90, 85, 196, 45, 67, 72, 65, 210, 45, 67, 72, 65, 76, 128, }; -static unsigned int lexicon_offset[] = { +static const unsigned int lexicon_offset[] = { 0, 0, 6, 10, 14, 19, 27, 34, 44, 49, 55, 64, 66, 69, 81, 89, 102, 108, 113, 118, 124, 129, 137, 146, 157, 162, 167, 170, 174, 183, 189, 195, 201, 206, 214, 221, 229, 171, 232, 241, 242, 250, 256, 261, 266, 273, @@ -8012,7 +8012,7 @@ static unsigned int lexicon_offset[] = { /* code->name phrasebook */ #define phrasebook_shift 7 #define phrasebook_short 194 -static unsigned char phrasebook[] = { +static const unsigned char phrasebook[] = { 0, 205, 148, 236, 89, 78, 211, 61, 78, 31, 55, 239, 9, 55, 213, 44, 55, 251, 110, 251, 29, 50, 213, 139, 53, 213, 139, 250, 178, 98, 55, 244, 158, 231, 5, 234, 216, 204, 226, 205, 177, 17, 195, 79, 17, 100, 17, 102, @@ -19073,7 +19073,7 @@ static unsigned char phrasebook[] = { 73, 241, 124, 152, 154, }; -static unsigned short phrasebook_offset1[] = { +static const unsigned short phrasebook_offset1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, @@ -19696,7 +19696,7 @@ static unsigned short phrasebook_offset1[] = { 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, }; -static unsigned int phrasebook_offset2[] = { +static const unsigned int phrasebook_offset2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 6, 9, 11, 14, 17, 19, 21, 24, 27, 29, 31, 33, 35, 39, 41, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 69, 72, @@ -23496,7 +23496,7 @@ static unsigned int phrasebook_offset2[] = { }; /* name->code dictionary */ -static unsigned int code_hash[] = { +static const unsigned int code_hash[] = { 74224, 4851, 0, 0, 0, 0, 7929, 0, 0, 0, 0, 127931, 0, 42833, 983091, 12064, 0, 129548, 194597, 69850, 65842, 0, 0, 0, 78159, 68476, 72392, 1373, 0, 0, 5816, 0, 0, 4231, 0, 0, 4233, 4234, 4232, 68885, 70351, 0, diff --git a/Objects/unicodetype_db.h b/Objects/unicodetype_db.h index e64b5059342a85..957bd4c621269a 100644 --- a/Objects/unicodetype_db.h +++ b/Objects/unicodetype_db.h @@ -1750,7 +1750,7 @@ const Py_UCS4 _PyUnicode_ExtendedCase[] = { /* type indexes */ #define SHIFT 7 -static unsigned short index1[] = { +static const unsigned short index1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, @@ -2359,7 +2359,7 @@ static unsigned short index1[] = { 126, 126, 126, 126, 126, 126, 126, 269, }; -static unsigned short index2[] = { +static const unsigned short index2[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 2, 4, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 6, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 6, 5, 5, 5, 5, 5, 5, 17, 17, 17, 17, diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py index 9327693a1732ee..2550b8f940c2ef 100644 --- a/Tools/unicode/makeunicodedata.py +++ b/Tools/unicode/makeunicodedata.py @@ -1249,7 +1249,7 @@ def dump(self, file, trace=0): size = getsize(self.data) if trace: print(self.name+":", size*len(self.data), "bytes", file=sys.stderr) - file.write("static ") + file.write("static const ") if size == 1: file.write("unsigned char") elif size == 2: From 36c41bc2017921321dbb19557f616a6bb7572c83 Mon Sep 17 00:00:00 2001 From: Lihua Zhao <44661095+LihuaZhao@users.noreply.github.com> Date: Wed, 17 Apr 2019 17:46:50 +0800 Subject: [PATCH 014/212] bpo-31904: Fix test_tabnanny on VxWorks (GH-12646) Fix test_tabnanny on VxWorks: adjust ENOENT error message, use os.strerror(). --- Lib/test/test_tabnanny.py | 6 ++++-- .../next/Tests/2019-04-01-16-06-36.bpo-31904.peaceF.rst | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-04-01-16-06-36.bpo-31904.peaceF.rst diff --git a/Lib/test/test_tabnanny.py b/Lib/test/test_tabnanny.py index 845096e63c269c..81549d14ae2b79 100644 --- a/Lib/test/test_tabnanny.py +++ b/Lib/test/test_tabnanny.py @@ -6,6 +6,8 @@ from unittest import TestCase, mock from unittest import mock import errno +import os +import sys import tabnanny import tokenize import tempfile @@ -233,8 +235,8 @@ def test_when_nannynag_error(self): def test_when_no_file(self): """A python file which does not exist actually in system.""" path = 'no_file.py' - err = f"{path!r}: I/O Error: [Errno {errno.ENOENT}] " \ - f"No such file or directory: {path!r}\n" + err = (f"{path!r}: I/O Error: [Errno {errno.ENOENT}] " + f"{os.strerror(errno.ENOENT)}: {path!r}\n") self.verify_tabnanny_check(path, err=err) def test_errored_directory(self): diff --git a/Misc/NEWS.d/next/Tests/2019-04-01-16-06-36.bpo-31904.peaceF.rst b/Misc/NEWS.d/next/Tests/2019-04-01-16-06-36.bpo-31904.peaceF.rst new file mode 100644 index 00000000000000..6297717e0fc68e --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-04-01-16-06-36.bpo-31904.peaceF.rst @@ -0,0 +1 @@ +Fix test_tabnanny on VxWorks: adjust ENOENT error message. From 71ce03df9c643faa94fbdf73bbb4e99a9a62cbdc Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 17 Apr 2019 13:18:37 +0100 Subject: [PATCH 015/212] Clarify file-closing example in tutorial (GH-11652) --- Doc/tutorial/inputoutput.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst index 79427860f518ff..fc2bd5578c4cf1 100644 --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -322,6 +322,8 @@ equivalent :keyword:`try`\ -\ :keyword:`finally` blocks:: >>> with open('workfile') as f: ... read_data = f.read() + + >>> # We can check that the file has been automatically closed. >>> f.closed True From 228a3c99bdb2d02771bead66a0beabafad3a90d3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 17 Apr 2019 16:26:36 +0200 Subject: [PATCH 016/212] bpo-35755: shutil.which() uses os.confstr("CS_PATH") (GH-12858) shutil.which() and distutils.spawn.find_executable() now use os.confstr("CS_PATH") if available instead of os.defpath, if the PATH environment variable is not set. Don't use os.confstr("CS_PATH") nor os.defpath if the PATH environment variable is set to an empty string to mimick Unix 'which' command behavior. Changes: * find_executable() now starts by checking for the executable in the current working directly case. Add an explicit "if not path: return None". * Add tests for PATH='' (empty string), PATH=':' and for PATHEXT. --- Lib/distutils/spawn.py | 39 +++++++---- Lib/distutils/tests/test_spawn.py | 47 ++++++++++++- Lib/shutil.py | 13 +++- Lib/test/test_shutil.py | 68 +++++++++++++++++++ .../2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst | 6 ++ 5 files changed, 155 insertions(+), 18 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst diff --git a/Lib/distutils/spawn.py b/Lib/distutils/spawn.py index 53876880932795..888327270e2294 100644 --- a/Lib/distutils/spawn.py +++ b/Lib/distutils/spawn.py @@ -172,21 +172,32 @@ def find_executable(executable, path=None): A string listing directories separated by 'os.pathsep'; defaults to os.environ['PATH']. Returns the complete filename or None if not found. """ - if path is None: - path = os.environ.get('PATH', os.defpath) - - paths = path.split(os.pathsep) - base, ext = os.path.splitext(executable) - + _, ext = os.path.splitext(executable) if (sys.platform == 'win32') and (ext != '.exe'): executable = executable + '.exe' - if not os.path.isfile(executable): - for p in paths: - f = os.path.join(p, executable) - if os.path.isfile(f): - # the file exists, we have a shot at spawn working - return f - return None - else: + if os.path.isfile(executable): return executable + + if path is None: + path = os.environ.get('PATH', None) + if path is None: + try: + path = os.confstr("CS_PATH") + except (AttributeError, ValueError): + # os.confstr() or CS_PATH is not available + path = os.defpath + # bpo-35755: Don't use os.defpath if the PATH environment variable is + # set to an empty string to mimick Unix which command behavior + + # PATH='' doesn't match, whereas PATH=':' looks in the current directory + if not path: + return None + + paths = path.split(os.pathsep) + for p in paths: + f = os.path.join(p, executable) + if os.path.isfile(f): + # the file exists, we have a shot at spawn working + return f + return None diff --git a/Lib/distutils/tests/test_spawn.py b/Lib/distutils/tests/test_spawn.py index 0d455385d8ace9..f9ae69ef86b3da 100644 --- a/Lib/distutils/tests/test_spawn.py +++ b/Lib/distutils/tests/test_spawn.py @@ -87,11 +87,52 @@ def test_find_executable(self): rv = find_executable(dont_exist_program , path=tmp_dir) self.assertIsNone(rv) - # test os.defpath: missing PATH environment variable + # PATH='': no match, except in the current directory with test_support.EnvironmentVarGuard() as env: - with mock.patch('distutils.spawn.os.defpath', tmp_dir): - env.pop('PATH') + env['PATH'] = '' + with unittest.mock.patch('distutils.spawn.os.confstr', + return_value=tmp_dir, create=True), \ + unittest.mock.patch('distutils.spawn.os.defpath', + tmp_dir): + rv = find_executable(program) + self.assertIsNone(rv) + + # look in current directory + with test_support.change_cwd(tmp_dir): + rv = find_executable(program) + self.assertEqual(rv, program) + + # PATH=':': explicitly looks in the current directory + with test_support.EnvironmentVarGuard() as env: + env['PATH'] = os.pathsep + with unittest.mock.patch('distutils.spawn.os.confstr', + return_value='', create=True), \ + unittest.mock.patch('distutils.spawn.os.defpath', ''): + rv = find_executable(program) + self.assertIsNone(rv) + + # look in current directory + with test_support.change_cwd(tmp_dir): + rv = find_executable(program) + self.assertEqual(rv, program) + + # missing PATH: test os.confstr("CS_PATH") and os.defpath + with test_support.EnvironmentVarGuard() as env: + env.pop('PATH', None) + + # without confstr + with unittest.mock.patch('distutils.spawn.os.confstr', + side_effect=ValueError, + create=True), \ + unittest.mock.patch('distutils.spawn.os.defpath', + tmp_dir): + rv = find_executable(program) + self.assertEqual(rv, filename) + # with confstr + with unittest.mock.patch('distutils.spawn.os.confstr', + return_value=tmp_dir, create=True), \ + unittest.mock.patch('distutils.spawn.os.defpath', ''): rv = find_executable(program) self.assertEqual(rv, filename) diff --git a/Lib/shutil.py b/Lib/shutil.py index 7dd470dfaba41a..34df9cc4746388 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1309,9 +1309,20 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None): use_bytes = isinstance(cmd, bytes) if path is None: - path = os.environ.get("PATH", os.defpath) + path = os.environ.get("PATH", None) + if path is None: + try: + path = os.confstr("CS_PATH") + except (AttributeError, ValueError): + # os.confstr() or CS_PATH is not available + path = os.defpath + # bpo-35755: Don't use os.defpath if the PATH environment variable is + # set to an empty string to mimick Unix which command behavior + + # PATH='' doesn't match, whereas PATH=':' looks in the current directory if not path: return None + if use_bytes: path = os.fsencode(path) path = path.split(os.fsencode(os.pathsep)) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 678a190bcf5ee0..e709a5661bf3ef 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1619,6 +1619,57 @@ def test_environ_path(self): rv = shutil.which(self.file) self.assertEqual(rv, self.temp_file.name) + def test_environ_path_empty(self): + # PATH='': no match + with support.EnvironmentVarGuard() as env: + env['PATH'] = '' + with unittest.mock.patch('os.confstr', return_value=self.dir, \ + create=True), \ + support.swap_attr(os, 'defpath', self.dir), \ + support.change_cwd(self.dir): + rv = shutil.which(self.file) + self.assertIsNone(rv) + + def test_environ_path_cwd(self): + expected_cwd = os.path.basename(self.temp_file.name) + if sys.platform == "win32": + curdir = os.curdir + if isinstance(expected_cwd, bytes): + curdir = os.fsencode(curdir) + expected_cwd = os.path.join(curdir, expected_cwd) + + # PATH=':': explicitly looks in the current directory + with support.EnvironmentVarGuard() as env: + env['PATH'] = os.pathsep + with unittest.mock.patch('os.confstr', return_value=self.dir, \ + create=True), \ + support.swap_attr(os, 'defpath', self.dir): + rv = shutil.which(self.file) + self.assertIsNone(rv) + + # look in current directory + with support.change_cwd(self.dir): + rv = shutil.which(self.file) + self.assertEqual(rv, expected_cwd) + + def test_environ_path_missing(self): + with support.EnvironmentVarGuard() as env: + env.pop('PATH', None) + + # without confstr + with unittest.mock.patch('os.confstr', side_effect=ValueError, \ + create=True), \ + support.swap_attr(os, 'defpath', self.dir): + rv = shutil.which(self.file) + self.assertEqual(rv, self.temp_file.name) + + # with confstr + with unittest.mock.patch('os.confstr', return_value=self.dir, \ + create=True), \ + support.swap_attr(os, 'defpath', ''): + rv = shutil.which(self.file) + self.assertEqual(rv, self.temp_file.name) + def test_empty_path(self): base_dir = os.path.dirname(self.dir) with support.change_cwd(path=self.dir), \ @@ -1633,6 +1684,23 @@ def test_empty_path_no_PATH(self): rv = shutil.which(self.file) self.assertIsNone(rv) + @unittest.skipUnless(sys.platform == "win32", 'test specific to Windows') + def test_pathext(self): + ext = ".xyz" + temp_filexyz = tempfile.NamedTemporaryFile(dir=self.temp_dir, + prefix="Tmp2", suffix=ext) + os.chmod(temp_filexyz.name, stat.S_IXUSR) + self.addCleanup(temp_filexyz.close) + + # strip path and extension + program = os.path.basename(temp_filexyz.name) + program = os.path.splitext(program)[0] + + with support.EnvironmentVarGuard() as env: + env['PATHEXT'] = ext + rv = shutil.which(program, path=self.temp_dir) + self.assertEqual(rv, temp_filexyz.name) + class TestWhichBytes(TestWhich): def setUp(self): diff --git a/Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst b/Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst new file mode 100644 index 00000000000000..8e92ffdec235a9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst @@ -0,0 +1,6 @@ +:func:`shutil.which` and :func:`distutils.spawn.find_executable` now use +``os.confstr("CS_PATH")`` if available instead of :data:`os.defpath`, if the +``PATH`` environment variable is not set. Moreover, don't use +``os.confstr("CS_PATH")`` nor :data:`os.defpath` if the ``PATH`` environment +variable is set to an empty string to mimick Unix ``which`` command +behavior. From 2c4c02f8a876fcf084575dcaf857a0236c81261a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 17 Apr 2019 17:05:30 +0200 Subject: [PATCH 017/212] bpo-35755: Remove current directory from posixpath.defpath (GH-11586) Document the change in a NEWS entry of the Security category. --- Lib/posixpath.py | 2 +- .../next/Security/2019-01-17-10-03-48.bpo-35755.GmllIs.rst | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Security/2019-01-17-10-03-48.bpo-35755.GmllIs.rst diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 21ce72fd79cdef..ecb4e5a8f7072c 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -18,7 +18,7 @@ extsep = '.' sep = '/' pathsep = ':' -defpath = ':/bin:/usr/bin' +defpath = '/bin:/usr/bin' altsep = None devnull = '/dev/null' diff --git a/Misc/NEWS.d/next/Security/2019-01-17-10-03-48.bpo-35755.GmllIs.rst b/Misc/NEWS.d/next/Security/2019-01-17-10-03-48.bpo-35755.GmllIs.rst new file mode 100644 index 00000000000000..959aafd73449e1 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2019-01-17-10-03-48.bpo-35755.GmllIs.rst @@ -0,0 +1,5 @@ +:func:`shutil.which` now uses ``os.confstr("CS_PATH")`` if available and if the +:envvar:`PATH` environment variable is not set. Remove also the current +directory from :data:`posixpath.defpath`. On Unix, :func:`shutil.which` and the +:mod:`subprocess` module no longer search the executable in the current +directory if the :envvar:`PATH` environment variable is not set. From 2954550818e5c23a082e6279eb326168230ebf04 Mon Sep 17 00:00:00 2001 From: Lihua Zhao <44661095+LihuaZhao@users.noreply.github.com> Date: Wed, 17 Apr 2019 23:33:25 +0800 Subject: [PATCH 018/212] bpo-31904: Port test_cmd_line to VxWorks (#12648) subprocess.Popen doesn't support preexec on VxWorks. --- Lib/test/test_cmd_line.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 21511b896cad17..f7925eb795c71e 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -369,6 +369,8 @@ def test_closed_stdout(self): # Issue #7111: Python should work without standard streams @unittest.skipIf(os.name != 'posix', "test needs POSIX semantics") + @unittest.skipIf(sys.platform == "vxworks", + "test needs preexec support in subprocess.Popen") def _test_no_stdio(self, streams): code = """if 1: import os, sys From 693c104ae74feea11f0b51176dc91ecd153230c0 Mon Sep 17 00:00:00 2001 From: Lihua Zhao <44661095+LihuaZhao@users.noreply.github.com> Date: Wed, 17 Apr 2019 23:41:33 +0800 Subject: [PATCH 019/212] bpo-31904: Port test_resource to VxWorks (GH-12719) Skip tests cases setting RLIMIT_FSIZE and RLIMIT_CPU on VxWorks. --- Doc/library/resource.rst | 2 ++ Lib/test/test_resource.py | 4 ++++ .../next/Tests/2019-04-08-09-24-36.bpo-31904.ab03ea.rst | 1 + 3 files changed, 7 insertions(+) create mode 100644 Misc/NEWS.d/next/Tests/2019-04-08-09-24-36.bpo-31904.ab03ea.rst diff --git a/Doc/library/resource.rst b/Doc/library/resource.rst index 2ed15c13673668..3573da7ea2d716 100644 --- a/Doc/library/resource.rst +++ b/Doc/library/resource.rst @@ -76,6 +76,8 @@ this module for those platforms. ``setrlimit`` may also raise :exc:`error` if the underlying system call fails. + VxWorks only supports setting :data:`RLIMIT_NOFILE`. + .. function:: prlimit(pid, resource[, limits]) Combines :func:`setrlimit` and :func:`getrlimit` in one function and diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index 62c7963fe6999f..e5ece5284cf15b 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -16,6 +16,8 @@ def test_args(self): self.assertRaises(TypeError, resource.setrlimit) self.assertRaises(TypeError, resource.setrlimit, 42, 42, 42) + @unittest.skipIf(sys.platform == "vxworks", + "setting RLIMIT_FSIZE is not supported on VxWorks") def test_fsize_ismax(self): try: (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) @@ -110,6 +112,8 @@ def test_getrusage(self): pass # Issue 6083: Reference counting bug + @unittest.skipIf(sys.platform == "vxworks", + "setting RLIMIT_CPU is not supported on VxWorks") def test_setrusage_refcount(self): try: limits = resource.getrlimit(resource.RLIMIT_CPU) diff --git a/Misc/NEWS.d/next/Tests/2019-04-08-09-24-36.bpo-31904.ab03ea.rst b/Misc/NEWS.d/next/Tests/2019-04-08-09-24-36.bpo-31904.ab03ea.rst new file mode 100644 index 00000000000000..2b361011abaed6 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-04-08-09-24-36.bpo-31904.ab03ea.rst @@ -0,0 +1 @@ +Port test_resource to VxWorks: skip tests cases setting RLIMIT_FSIZE and RLIMIT_CPU. From 197f0447e3bcfa4f529fedab09966d7e3d283979 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 17 Apr 2019 17:44:06 +0200 Subject: [PATCH 020/212] bpo-35755: Don't say "to mimick Unix which command behavior" (GH-12861) --- Lib/distutils/spawn.py | 2 +- Lib/shutil.py | 2 +- .../next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Lib/distutils/spawn.py b/Lib/distutils/spawn.py index 888327270e2294..d3a12c28339782 100644 --- a/Lib/distutils/spawn.py +++ b/Lib/distutils/spawn.py @@ -188,7 +188,7 @@ def find_executable(executable, path=None): # os.confstr() or CS_PATH is not available path = os.defpath # bpo-35755: Don't use os.defpath if the PATH environment variable is - # set to an empty string to mimick Unix which command behavior + # set to an empty string # PATH='' doesn't match, whereas PATH=':' looks in the current directory if not path: diff --git a/Lib/shutil.py b/Lib/shutil.py index 34df9cc4746388..6cfe3738f6eb47 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1317,7 +1317,7 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None): # os.confstr() or CS_PATH is not available path = os.defpath # bpo-35755: Don't use os.defpath if the PATH environment variable is - # set to an empty string to mimick Unix which command behavior + # set to an empty string # PATH='' doesn't match, whereas PATH=':' looks in the current directory if not path: diff --git a/Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst b/Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst index 8e92ffdec235a9..d84f63bf7b838b 100644 --- a/Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst +++ b/Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst @@ -2,5 +2,4 @@ ``os.confstr("CS_PATH")`` if available instead of :data:`os.defpath`, if the ``PATH`` environment variable is not set. Moreover, don't use ``os.confstr("CS_PATH")`` nor :data:`os.defpath` if the ``PATH`` environment -variable is set to an empty string to mimick Unix ``which`` command -behavior. +variable is set to an empty string. From 3092d6b2630e4d2bd200fbc3231c27a7cba4d6b2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 17 Apr 2019 18:09:12 +0200 Subject: [PATCH 021/212] bpo-32849: Fix is_valid_fd() on FreeBSD (GH-12852) Fix Python Initialization code on FreeBSD to detect properly when stdin file descriptor (fd 0) is invalid. On FreeBSD, fstat() must be used to check if stdin (fd 0) is valid. dup(0) doesn't fail if stdin is invalid in some cases. --- .../2019-04-16-11-56-12.bpo-32849.aeSg-D.rst | 2 + Python/pylifecycle.c | 38 +++++++++++-------- 2 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst new file mode 100644 index 00000000000000..6a9a85c4b13472 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst @@ -0,0 +1,2 @@ +Fix Python Initialization code on FreeBSD to detect properly when stdin file +descriptor (fd 0) is invalid. diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index ad1447256cc697..c7920ef6262d3c 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1664,26 +1664,34 @@ 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) +/* dup() is faster than fstat(): fstat() can require input/output operations, + whereas dup() doesn't. There is a low risk of EMFILE/ENFILE at Python + startup. Problem: dup() doesn't check if the file descriptor is valid on + some platforms. + + 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. FreeBSD has similar issue (bpo-32849). + + Only use dup() on platforms where dup() is enough to detect invalid FD in + corner cases: on Linux and Windows (bpo-32849). */ +#if defined(__linux__) || defined(MS_WINDOWS) + if (fd < 0) { return 0; + } + int fd2; + _Py_BEGIN_SUPPRESS_IPH - /* Prefer dup() over fstat(). fstat() can require input/output whereas - dup() doesn't, there is a low risk of EMFILE/ENFILE at Python - startup. */ fd2 = dup(fd); - if (fd2 >= 0) + if (fd2 >= 0) { close(fd2); + } _Py_END_SUPPRESS_IPH - return fd2 >= 0; + + return (fd2 >= 0); +#else + struct stat st; + return (fstat(fd, &st) == 0); #endif } From 5c75f37d473140f0e0b7d9bf3a8c08343447ded1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 17 Apr 2019 23:02:26 +0200 Subject: [PATCH 022/212] bpo-36635: Change pyport.h for Py_BUILD_CORE_MODULE define (GH-12853) Change PyAPI_FUNC(type), PyAPI_DATA(type) and PyMODINIT_FUNC macros of pyport.h when Py_BUILD_CORE_MODULE is defined. The Py_BUILD_CORE_MODULE define must be now be used to build a C extension as a dynamic library accessing Python internals: export the PyInit_xxx() function in DLL exports on Windows. Changes: * Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE now imply Py_BUILD_CORE directy in pyport.h. * ceval.c compilation now fails with an error if Py_BUILD_CORE is not defined, just to ensure that Python is build with the correct defines. * setup.py now compiles _pickle.c with Py_BUILD_CORE_MODULE define. * setup.py compiles _json.c with Py_BUILD_CORE_MODULE define, rather than Py_BUILD_CORE_BUILTIN define * PCbuild/pythoncore.vcxproj: Add Py_BUILD_CORE_BUILTIN define. --- Include/internal/pycore_accu.h | 4 +-- Include/internal/pycore_atomic.h | 4 +-- Include/internal/pycore_ceval.h | 4 +-- Include/internal/pycore_condvar.h | 4 +-- Include/internal/pycore_context.h | 4 +-- Include/internal/pycore_coreconfig.h | 4 +-- Include/internal/pycore_getopt.h | 4 +-- Include/internal/pycore_gil.h | 4 +-- Include/internal/pycore_hamt.h | 4 +-- Include/internal/pycore_object.h | 4 +-- Include/internal/pycore_pathconfig.h | 4 +-- Include/internal/pycore_pyhash.h | 4 +-- Include/internal/pycore_pylifecycle.h | 4 +-- Include/internal/pycore_pymem.h | 4 +-- Include/internal/pycore_pystate.h | 4 +-- Include/internal/pycore_tupleobject.h | 4 +-- Include/internal/pycore_warnings.h | 4 +-- Include/pyport.h | 25 +++++++++++++++++-- .../2019-04-16-13-58-52.bpo-36635.JKlzkf.rst | 5 ++++ Modules/Setup | 14 +++++------ Modules/_json.c | 13 ++++++---- Modules/_pickle.c | 11 +++++--- Modules/_testcapimodule.c | 5 ++++ PCbuild/pythoncore.vcxproj | 2 +- Python/ceval.c | 4 +++ setup.py | 6 ++--- 26 files changed, 97 insertions(+), 56 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2019-04-16-13-58-52.bpo-36635.JKlzkf.rst diff --git a/Include/internal/pycore_accu.h b/Include/internal/pycore_accu.h index 4350db58a26905..d346222e4dd0c9 100644 --- a/Include/internal/pycore_accu.h +++ b/Include/internal/pycore_accu.h @@ -9,8 +9,8 @@ extern "C" { *** Its definition may be changed or removed at any moment. ***/ -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif /* diff --git a/Include/internal/pycore_atomic.h b/Include/internal/pycore_atomic.h index 7aa7eed6f7c20c..b3ec44c1bcfee1 100644 --- a/Include/internal/pycore_atomic.h +++ b/Include/internal/pycore_atomic.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #include "dynamic_annotations.h" diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 2ead96c7abe32a..0bb19f1aa3b642 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #include "pycore_atomic.h" diff --git a/Include/internal/pycore_condvar.h b/Include/internal/pycore_condvar.h index a12b6994ad55cc..8b89d709510a33 100644 --- a/Include/internal/pycore_condvar.h +++ b/Include/internal/pycore_condvar.h @@ -1,8 +1,8 @@ #ifndef Py_INTERNAL_CONDVAR_H #define Py_INTERNAL_CONDVAR_H -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #ifndef _POSIX_THREADS diff --git a/Include/internal/pycore_context.h b/Include/internal/pycore_context.h index 70701cdd11dc61..5e1ba0d0393f4a 100644 --- a/Include/internal/pycore_context.h +++ b/Include/internal/pycore_context.h @@ -1,8 +1,8 @@ #ifndef Py_INTERNAL_CONTEXT_H #define Py_INTERNAL_CONTEXT_H -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #include "pycore_hamt.h" diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index 3a27628aa7408b..33538442043baf 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN defined" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif diff --git a/Include/internal/pycore_getopt.h b/Include/internal/pycore_getopt.h index 0d1897c75a6403..834b8c8a14092f 100644 --- a/Include/internal/pycore_getopt.h +++ b/Include/internal/pycore_getopt.h @@ -1,8 +1,8 @@ #ifndef Py_INTERNAL_PYGETOPT_H #define Py_INTERNAL_PYGETOPT_H -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif extern int _PyOS_opterr; diff --git a/Include/internal/pycore_gil.h b/Include/internal/pycore_gil.h index 014e75fd182f18..7de316397b15e8 100644 --- a/Include/internal/pycore_gil.h +++ b/Include/internal/pycore_gil.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #include "pycore_condvar.h" diff --git a/Include/internal/pycore_hamt.h b/Include/internal/pycore_hamt.h index 8b2ce1fc96c346..e65aef5e21a954 100644 --- a/Include/internal/pycore_hamt.h +++ b/Include/internal/pycore_hamt.h @@ -1,8 +1,8 @@ #ifndef Py_INTERNAL_HAMT_H #define Py_INTERNAL_HAMT_H -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #define _Py_HAMT_MAX_TREE_DEPTH 7 diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index c95595358a9e84..81548f819198e3 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN defined" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #include "pycore_pystate.h" /* _PyRuntime */ diff --git a/Include/internal/pycore_pathconfig.h b/Include/internal/pycore_pathconfig.h index 80d86a0dd1b54c..9eb8e88df76736 100644 --- a/Include/internal/pycore_pathconfig.h +++ b/Include/internal/pycore_pathconfig.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif typedef struct _PyPathConfig { diff --git a/Include/internal/pycore_pyhash.h b/Include/internal/pycore_pyhash.h index babbc95b879e35..a229f8d8b7f0a2 100644 --- a/Include/internal/pycore_pyhash.h +++ b/Include/internal/pycore_pyhash.h @@ -1,8 +1,8 @@ #ifndef Py_INTERNAL_HASH_H #define Py_INTERNAL_HASH_H -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif uint64_t _Py_KeyedHash(uint64_t, const char *, Py_ssize_t); diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index d837ea4fb33a51..bfff24b80a9fe1 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif /* True if the main interpreter thread exited due to an unhandled diff --git a/Include/internal/pycore_pymem.h b/Include/internal/pycore_pymem.h index 8da1bd9e304ac6..20f3b5e40067c6 100644 --- a/Include/internal/pycore_pymem.h +++ b/Include/internal/pycore_pymem.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN defined" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #include "objimpl.h" diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index df3730f8014ae4..e1ce08d335b9cc 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #include "cpython/coreconfig.h" diff --git a/Include/internal/pycore_tupleobject.h b/Include/internal/pycore_tupleobject.h index d0c5b620d3561e..9fcfc5c6ec7196 100644 --- a/Include/internal/pycore_tupleobject.h +++ b/Include/internal/pycore_tupleobject.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #include "tupleobject.h" diff --git a/Include/internal/pycore_warnings.h b/Include/internal/pycore_warnings.h index 91bf90232f5c79..73e5350aff1451 100644 --- a/Include/internal/pycore_warnings.h +++ b/Include/internal/pycore_warnings.h @@ -4,8 +4,8 @@ extern "C" { #endif -#if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) -# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN define" +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" #endif #include "object.h" diff --git a/Include/pyport.h b/Include/pyport.h index 4971a493ccee22..075b36028b8a06 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -5,6 +5,27 @@ #include + +/* Defines to build Python and its standard library: + * + * - Py_BUILD_CORE: Build Python core. Give access to Python internals, but + * should not be used by third-party modules. + * - Py_BUILD_CORE_BUILTIN: Build a Python stdlib module as a built-in module. + * - Py_BUILD_CORE_MODULE: Build a Python stdlib module as a dynamic library. + * + * Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE imply Py_BUILD_CORE. + * + * On Windows, Py_BUILD_CORE_MODULE exports "PyInit_xxx" symbol, whereas + * Py_BUILD_CORE_BUILTIN does not. + */ +#if defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE) +# define Py_BUILD_CORE +#endif +#if defined(Py_BUILD_CORE_MODULE) && !defined(Py_BUILD_CORE) +# define Py_BUILD_CORE +#endif + + /************************************************************************** Symbols and macros to supply platform-independent interfaces to basic C language & library operations whose spellings vary across platforms. @@ -623,7 +644,7 @@ extern char * _getpty(int *, int, mode_t, int); /* only get special linkage if built as shared or platform is Cygwin */ #if defined(Py_ENABLE_SHARED) || defined(__CYGWIN__) # if defined(HAVE_DECLSPEC_DLL) -# if defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_BUILTIN) +# if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) # define PyAPI_FUNC(RTYPE) __declspec(dllexport) RTYPE # define PyAPI_DATA(RTYPE) extern __declspec(dllexport) RTYPE /* module init functions inside the core need no external linkage */ @@ -755,7 +776,7 @@ extern char * _getpty(int *, int, mode_t, int); #define PY_LITTLE_ENDIAN 1 #endif -#if defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_BUILTIN) +#ifdef Py_BUILD_CORE /* * Macros to protect CRT calls against instant termination when passed an * invalid parameter (issue23524). diff --git a/Misc/NEWS.d/next/Build/2019-04-16-13-58-52.bpo-36635.JKlzkf.rst b/Misc/NEWS.d/next/Build/2019-04-16-13-58-52.bpo-36635.JKlzkf.rst new file mode 100644 index 00000000000000..6d346d22b80762 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2019-04-16-13-58-52.bpo-36635.JKlzkf.rst @@ -0,0 +1,5 @@ +Change ``PyAPI_FUNC(type)``, ``PyAPI_DATA(type)`` and ``PyMODINIT_FUNC`` +macros of ``pyport.h`` when ``Py_BUILD_CORE_MODULE`` is defined. The +``Py_BUILD_CORE_MODULE`` define must be now be used to build a C extension +as a dynamic library accessing Python internals: export the PyInit_xxx() +function in DLL exports on Windows. diff --git a/Modules/Setup b/Modules/Setup index 11ddd0c7b2029b..03aa0f16be14db 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -101,29 +101,29 @@ PYTHONPATH=$(COREPYTHONPATH) # This only contains the minimal set of modules required to run the # setup.py script in the root of the Python source tree. -posix -DPy_BUILD_CORE -I$(srcdir)/Include/internal posixmodule.c # posix (UNIX) system calls +posix -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal posixmodule.c # posix (UNIX) system calls errno errnomodule.c # posix (UNIX) errno values pwd pwdmodule.c # this is needed to find out the user's home dir # if $HOME is not set _sre _sre.c # Fredrik Lundh's new regular expressions _codecs _codecsmodule.c # access to the builtin codecs and codec registry _weakref _weakref.c # weak references -_functools -DPy_BUILD_CORE -I$(srcdir)/Include/internal _functoolsmodule.c # Tools for working with functions and callable objects +_functools -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal _functoolsmodule.c # Tools for working with functions and callable objects _operator _operator.c # operator.add() and similar goodies _collections _collectionsmodule.c # Container types _abc _abc.c # Abstract base classes itertools itertoolsmodule.c # Functions creating iterators for efficient looping atexit atexitmodule.c # Register functions to be run at interpreter-shutdown -_signal -DPy_BUILD_CORE -I$(srcdir)/Include/internal signalmodule.c +_signal -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal signalmodule.c _stat _stat.c # stat.h interface -time -DPy_BUILD_CORE -I$(srcdir)/Include/internal timemodule.c # -lm # time operations and variables -_thread -DPy_BUILD_CORE -I$(srcdir)/Include/internal _threadmodule.c # low-level threading interface +time -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal timemodule.c # -lm # time operations and variables +_thread -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal _threadmodule.c # low-level threading interface # access to ISO C locale support -_locale -DPy_BUILD_CORE _localemodule.c # -lintl +_locale -DPy_BUILD_CORE_BUILTIN _localemodule.c # -lintl # Standard I/O baseline -_io -DPy_BUILD_CORE -I$(srcdir)/Include/internal -I$(srcdir)/Modules/_io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c +_io -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal -I$(srcdir)/Modules/_io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c # faulthandler module faulthandler faulthandler.c diff --git a/Modules/_json.c b/Modules/_json.c index 94a7c0d2bf09e4..2d7c1bf1e1c77d 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1,8 +1,11 @@ - -/* Core extension modules are built-in on some platforms (e.g. Windows). */ -#ifdef Py_BUILD_CORE -#define Py_BUILD_CORE_BUILTIN -#undef Py_BUILD_CORE +/* JSON accelerator C extensor: _json module. + * + * It is built as a built-in module (Py_BUILD_CORE_BUILTIN define) on Windows + * and as an extension module (Py_BUILD_CORE_MODULE define) on other + * platforms. */ + +#if !defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE_MODULE) +# error "Py_BUILD_CORE_BUILTIN or Py_BUILD_CORE_MODULE must be defined" #endif #include "Python.h" diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 2b97294e1e86f8..f956a382ac5310 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1,8 +1,11 @@ +/* pickle accelerator C extensor: _pickle module. + * + * It is built as a built-in module (Py_BUILD_CORE_BUILTIN define) on Windows + * and as an extension module (Py_BUILD_CORE_MODULE define) on other + * platforms. */ -/* Core extension modules are built-in on some platforms (e.g. Windows). */ -#ifdef Py_BUILD_CORE -#define Py_BUILD_CORE_BUILTIN -#undef Py_BUILD_CORE +#if !defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE_MODULE) +# error "Py_BUILD_CORE_BUILTIN or Py_BUILD_CORE_MODULE must be defined" #endif #include "Python.h" diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 1180b4b176e9c1..ae960deba78c97 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5,6 +5,11 @@ * standard Python regression test, via Lib/test/test_capi.py. */ +/* The Visual Studio projects builds _testcapi with Py_BUILD_CORE_MODULE + define, but we only want to test the public C API, not the internal + C API. */ +#undef Py_BUILD_CORE_MODULE + #define PY_SSIZE_T_CLEAN #include "Python.h" diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index a135e9326c781e..5c5a720ba0c818 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -86,7 +86,7 @@ /Zm200 %(AdditionalOptions) $(PySourcePath)Python;%(AdditionalIncludeDirectories) $(zlibDir);%(AdditionalIncludeDirectories) - _USRDLL;Py_BUILD_CORE;Py_ENABLE_SHARED;MS_DLL_ID="$(SysWinVer)";%(PreprocessorDefinitions) + _USRDLL;Py_BUILD_CORE;Py_BUILD_CORE_BUILTIN;Py_ENABLE_SHARED;MS_DLL_ID="$(SysWinVer)";%(PreprocessorDefinitions) _Py_HAVE_ZLIB;%(PreprocessorDefinitions) diff --git a/Python/ceval.c b/Python/ceval.c index 28e923219d389c..342dc10af6a629 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -30,6 +30,10 @@ #define CHECKEXC 1 /* Double-check exception checking */ #endif +#if !defined(Py_BUILD_CORE) +# error "ceval.c must be build with Py_BUILD_CORE define for best performance" +#endif + /* Private API for the LOAD_METHOD opcode. */ extern int _PyObject_GetMethod(PyObject *, PyObject *, PyObject **); diff --git a/setup.py b/setup.py index 9c83914fd907ba..c470719a6a804f 100644 --- a/setup.py +++ b/setup.py @@ -725,13 +725,13 @@ def detect_simple_extensions(self): # heapq self.add(Extension("_heapq", ["_heapqmodule.c"])) # C-optimized pickle replacement - self.add(Extension("_pickle", ["_pickle.c"])) + self.add(Extension("_pickle", ["_pickle.c"], + extra_compile_args=['-D Py_BUILD_CORE_MODULE'])) # atexit self.add(Extension("atexit", ["atexitmodule.c"])) # _json speedups self.add(Extension("_json", ["_json.c"], - # pycore_accu.h requires Py_BUILD_CORE_BUILTIN - extra_compile_args=['-DPy_BUILD_CORE_BUILTIN'])) + extra_compile_args=['-D Py_BUILD_CORE_MODULE'])) # profiler (_lsprof is for cProfile.py) self.add(Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c'])) From 4c3efd9cd07194b5db2a60ae5951134cda8b69db Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 17 Apr 2019 14:31:32 -0700 Subject: [PATCH 023/212] bpo-36649: Remove trailing spaces for registry keys when installed via the Store (GH-12865) --- .../2019-04-17-11-39-24.bpo-36649.arbzIo.rst | 1 + PC/layout/support/appxmanifest.py | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2019-04-17-11-39-24.bpo-36649.arbzIo.rst diff --git a/Misc/NEWS.d/next/Windows/2019-04-17-11-39-24.bpo-36649.arbzIo.rst b/Misc/NEWS.d/next/Windows/2019-04-17-11-39-24.bpo-36649.arbzIo.rst new file mode 100644 index 00000000000000..8b44feb9f4c03c --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-04-17-11-39-24.bpo-36649.arbzIo.rst @@ -0,0 +1 @@ +Remove trailing spaces for registry keys when installed via the Store. diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index c5dda70c7ef85c..49a35fa1f0468e 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -159,21 +159,20 @@ def public(f): "SysVersion": VER_DOT, "Version": "{}.{}.{}".format(VER_MAJOR, VER_MINOR, VER_MICRO), "InstallPath": { - # I have no idea why the trailing spaces are needed, but they seem to be needed. - "": "[{AppVPackageRoot}][ ]", - "ExecutablePath": "[{AppVPackageRoot}]python.exe[ ]", - "WindowedExecutablePath": "[{AppVPackageRoot}]pythonw.exe[ ]", + "": "[{AppVPackageRoot}]", + "ExecutablePath": "[{AppVPackageRoot}]\\python.exe", + "WindowedExecutablePath": "[{AppVPackageRoot}]\\pythonw.exe", }, "Help": { "Main Python Documentation": { "_condition": lambda ns: ns.include_chm, - "": "[{{AppVPackageRoot}}]Doc\\{}[ ]".format( + "": "[{{AppVPackageRoot}}]\\Doc\\{}".format( PYTHON_CHM_NAME ), }, "Local Python Documentation": { "_condition": lambda ns: ns.include_html_doc, - "": "[{AppVPackageRoot}]Doc\\html\\index.html[ ]", + "": "[{AppVPackageRoot}]\\Doc\\html\\index.html", }, "Online Python Documentation": { "": "https://docs.python.org/{}".format(VER_DOT) @@ -181,7 +180,7 @@ def public(f): }, "Idle": { "_condition": lambda ns: ns.include_idle, - "": "[{AppVPackageRoot}]Lib\\idlelib\\idle.pyw[ ]", + "": "[{AppVPackageRoot}]\\Lib\\idlelib\\idle.pyw", }, } } From a6de52c74d831e45ee0ff105196da8a58b9e43cd Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 17 Apr 2019 22:43:30 +0000 Subject: [PATCH 024/212] bpo-32913: Added re.Match.groupdict example to regex HOWTO (GH-5821) --- Doc/howto/regex.rst | 7 +++++++ .../Documentation/2018-02-22-15-48-16.bpo-32913.f3utho.rst | 1 + 2 files changed, 8 insertions(+) create mode 100644 Misc/NEWS.d/next/Documentation/2018-02-22-15-48-16.bpo-32913.f3utho.rst diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index d385d991344b28..d574c3736b1cb7 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -942,6 +942,13 @@ given numbers, so you can retrieve information about a group in two ways:: >>> m.group(1) 'Lots' +Additionally, you can retrieve named groups as a dictionary with +:meth:`~re.Match.groupdict`:: + + >>> m = re.match(r'(?P\w+) (?P\w+)', 'Jane Doe') + >>> m.groupdict() + {'first': 'Jane', 'last': 'Doe'} + Named groups are handy because they let you use easily-remembered names, instead of having to remember numbers. Here's an example RE from the :mod:`imaplib` module:: diff --git a/Misc/NEWS.d/next/Documentation/2018-02-22-15-48-16.bpo-32913.f3utho.rst b/Misc/NEWS.d/next/Documentation/2018-02-22-15-48-16.bpo-32913.f3utho.rst new file mode 100644 index 00000000000000..caa9590abbaf3e --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-22-15-48-16.bpo-32913.f3utho.rst @@ -0,0 +1 @@ +Added re.Match.groupdict example to regex HOWTO. From 9941f963fe085261aec25545fa9f0cc35f750120 Mon Sep 17 00:00:00 2001 From: cocoatomo Date: Thu, 18 Apr 2019 09:54:51 +0900 Subject: [PATCH 025/212] Fix wrong indentation of a paragraph in documentation (GH-12868) This paragraph doesn't seem to be a part of code, but merged into previous code block. --- Doc/library/typing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index ed5f547e3ce371..c2523ed5296003 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -966,8 +966,8 @@ The module defines the following classes, functions and decorators: def fetch_response() -> Response: ... - Note that returning instances of private classes is not recommended. - It is usually preferable to make such classes public. + Note that returning instances of private classes is not recommended. + It is usually preferable to make such classes public. .. data:: Any From 264a0b40b030fc0ff919b8294df91bdaac853bfb Mon Sep 17 00:00:00 2001 From: Paul Monson Date: Wed, 17 Apr 2019 18:06:06 -0700 Subject: [PATCH 026/212] bpo-36638: Fix WindowsLoadTracker exception on some Windows versions (GH-12849) --- Lib/test/libregrtest/main.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 18ef6d0609cd63..d20e1746781f0a 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -626,8 +626,13 @@ def getloadavg_1m(): elif sys.platform == 'win32' and (self.ns.worker_args is None): from test.libregrtest.win_utils import WindowsLoadTracker - load_tracker = WindowsLoadTracker() - self.getloadavg = load_tracker.getloadavg + try: + load_tracker = WindowsLoadTracker() + self.getloadavg = load_tracker.getloadavg + except FileNotFoundError as error: + # Windows IoT Core and Windows Nano Server do not provide + # typeperf.exe for x64, x86 or ARM + print('Failed to create WindowsLoadTracker: {}'.format(error)) self.run_tests() self.display_result() From 11efd79076559cc6e4034bb36db73e5e4293f02d Mon Sep 17 00:00:00 2001 From: Paul Monson Date: Wed, 17 Apr 2019 18:09:16 -0700 Subject: [PATCH 027/212] bpo-36071 Add support for Windows ARM32 in ctypes/libffi (GH-12059) --- Include/pyport.h | 2 +- Include/pythonrun.h | 2 +- Modules/_ctypes/callbacks.c | 2 +- Modules/_ctypes/callproc.c | 11 ++++++++--- Modules/_ctypes/malloc_closure.c | 5 +++++ PCbuild/pcbuild.sln | 2 ++ PCbuild/prepare_libffi.bat | 15 +++++++++++++-- 7 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Include/pyport.h b/Include/pyport.h index 075b36028b8a06..acbae5bafeb512 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -427,7 +427,7 @@ extern "C" { #endif /* get and set x87 control word for VisualStudio/x86 */ -#if defined(_MSC_VER) && defined(_M_IX86) /* x87 only supported in x86 */ +#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_M_ARM) /* x87 not supported in 64-bit or ARM */ #define HAVE_PY_SET_53BIT_PRECISION 1 #define _Py_SET_53BIT_PRECISION_HEADER \ unsigned int old_387controlword, new_387controlword, out_387controlword diff --git a/Include/pythonrun.h b/Include/pythonrun.h index 6f0c6fc6554379..e83846add981cd 100644 --- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -165,7 +165,7 @@ PyAPI_DATA(PyThreadState*) _PyOS_ReadlineTState; to an 8k margin. */ #define PYOS_STACK_MARGIN 2048 -#if defined(WIN32) && !defined(MS_WIN64) && defined(_MSC_VER) && _MSC_VER >= 1300 +#if defined(WIN32) && !defined(MS_WIN64) && !defined(_M_ARM) && defined(_MSC_VER) && _MSC_VER >= 1300 /* Enable stack checking under Microsoft C */ #define USE_STACKCHECK #endif diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 2b7cb06ea8a95b..9f793c2771bfb9 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -380,7 +380,7 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable, } cc = FFI_DEFAULT_ABI; -#if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64) +#if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64) && !defined(_M_ARM) if ((flags & FUNCFLAG_CDECL) == 0) cc = FFI_STDCALL; #endif diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 5a943d3c37081e..1ad842eb3d4098 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -737,12 +737,17 @@ of 1, 2, 4, 8, 16, 32, or 64 bits */ int can_return_struct_as_int(size_t s) { - return s == 1 || s == 2 || s == 4; + return s == 1 || s == 2 || s == 4; } int can_return_struct_as_sint64(size_t s) { - return s == 8; +#ifdef _M_ARM + // 8 byte structs cannot be returned in a register on ARM32 + return 0; +#else + return s == 8; +#endif } #endif @@ -807,7 +812,7 @@ static int _call_function_pointer(int flags, } cc = FFI_DEFAULT_ABI; -#if defined(MS_WIN32) && !defined(MS_WIN64) && !defined(_WIN32_WCE) +#if defined(MS_WIN32) && !defined(MS_WIN64) && !defined(_WIN32_WCE) && !defined(_M_ARM) if ((flags & FUNCFLAG_CDECL) == 0) cc = FFI_STDCALL; #endif diff --git a/Modules/_ctypes/malloc_closure.c b/Modules/_ctypes/malloc_closure.c index 8ad76497c7b3f2..f9cdb336958c6f 100644 --- a/Modules/_ctypes/malloc_closure.c +++ b/Modules/_ctypes/malloc_closure.c @@ -106,6 +106,11 @@ void *ffi_closure_alloc(size_t ignored, void** codeloc) return NULL; item = free_list; free_list = item->next; +#ifdef _M_ARM + // set Thumb bit so that blx is called correctly + *codeloc = (ITEM*)((uintptr_t)item | 1); +#else *codeloc = (void *)item; +#endif return (void *)item; } diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln index 1bbfd180df14a0..e9239365b5c1af 100644 --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -238,6 +238,7 @@ Global {0E9791DB-593A-465F-98BC-681011311617}.Release|x64.ActiveCfg = Release|x64 {0E9791DB-593A-465F-98BC-681011311617}.Release|x64.Build.0 = Release|x64 {0E9791DB-593A-465F-98BC-681011311618}.Debug|ARM.ActiveCfg = Debug|ARM + {0E9791DB-593A-465F-98BC-681011311618}.Debug|ARM.Build.0 = Debug|ARM {0E9791DB-593A-465F-98BC-681011311618}.Debug|Win32.ActiveCfg = Debug|Win32 {0E9791DB-593A-465F-98BC-681011311618}.Debug|Win32.Build.0 = Debug|Win32 {0E9791DB-593A-465F-98BC-681011311618}.Debug|x64.ActiveCfg = Debug|x64 @@ -255,6 +256,7 @@ Global {0E9791DB-593A-465F-98BC-681011311618}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 {0E9791DB-593A-465F-98BC-681011311618}.PGUpdate|x64.Build.0 = PGUpdate|x64 {0E9791DB-593A-465F-98BC-681011311618}.Release|ARM.ActiveCfg = Release|ARM + {0E9791DB-593A-465F-98BC-681011311618}.Release|ARM.Build.0 = Release|ARM {0E9791DB-593A-465F-98BC-681011311618}.Release|Win32.ActiveCfg = Release|Win32 {0E9791DB-593A-465F-98BC-681011311618}.Release|Win32.Build.0 = Release|Win32 {0E9791DB-593A-465F-98BC-681011311618}.Release|x64.ActiveCfg = Release|x64 diff --git a/PCbuild/prepare_libffi.bat b/PCbuild/prepare_libffi.bat index 3df85130f48adb..307739d874a213 100644 --- a/PCbuild/prepare_libffi.bat +++ b/PCbuild/prepare_libffi.bat @@ -24,6 +24,7 @@ echo. echo.Available flags: echo. -x64 build for x64 echo. -x86 build for x86 +echo. -arm32 build for arm32 echo. -? this help echo. --install-cygwin install cygwin to c:\cygwin exit /b 127 @@ -32,12 +33,14 @@ exit /b 127 set BUILD_X64= set BUILD_X86= +set BUILD_ARM32= set INSTALL_CYGWIN= :CheckOpts if "%1"=="" goto :CheckOptsDone if /I "%1"=="-x64" (set BUILD_X64=1) & shift & goto :CheckOpts if /I "%1"=="-x86" (set BUILD_X86=1) & shift & goto :CheckOpts +if /I "%1"=="-arm32" (set BUILD_ARM32=1) & shift & goto :CheckOpts if /I "%1"=="-?" goto :Usage if /I "%1"=="--install-cygwin" (set INSTALL_CYGWIN=1) & shift & goto :CheckOpts goto :Usage @@ -47,6 +50,7 @@ goto :Usage if NOT DEFINED BUILD_X64 if NOT DEFINED BUILD_X86 if NOT DEFINED BUILD_ARM32 ( set BUILD_X64=1 set BUILD_X86=1 + set BUILD_ARM32=1 ) if "%INSTALL_CYGWIN%"=="1" call :InstallCygwin @@ -83,8 +87,9 @@ echo. if not exist Makefile.in (%SH% -lc "(cd $LIBFFI_SOURCE; ./autogen.sh;)") -call :BuildOne x86 i686-pc-cygwin i686-pc-cygwin -call :BuildOne x64 x86_64-w64-cygwin x86_64-w64-cygwin +if "%BUILD_X64%"=="1" call :BuildOne x64 x86_64-w64-cygwin x86_64-w64-cygwin +if "%BUILD_X86%"=="1" call :BuildOne x86 i686-pc-cygwin i686-pc-cygwin +if "%BUILD_ARM32%"=="1" call :BuildOne x86_arm i686-pc-cygwin arm-w32-cygwin popd endlocal @@ -118,6 +123,12 @@ if /I "%VCVARS_PLATFORM%" EQU "x86" ( set ASSEMBLER= set SRC_ARCHITECTURE=x86 ) +if /I "%VCVARS_PLATFORM%" EQU "x86_arm" ( + set ARCH=arm32 + set ARTIFACTS=%LIBFFI_SOURCE%\arm-w32-cygwin + set ASSEMBLER=-marm + set SRC_ARCHITECTURE=ARM +) if NOT DEFINED LIBFFI_OUT set LIBFFI_OUT=%~dp0\..\externals\libffi set _LIBFFI_OUT=%LIBFFI_OUT%\%ARCH% From 23bace26ec265557697cf3b578b361c178070cd5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 18 Apr 2019 11:37:26 +0200 Subject: [PATCH 028/212] bpo-36635: Add _testinternalcapi module (GH-12841) Add a new _testinternalcapi module to test the internal C API. Move _Py_GetConfigsAsDict() function to the internal C API: _testembed now uses _testinternalcapi to access the function. --- Include/cpython/coreconfig.h | 5 - Include/internal/pycore_coreconfig.h | 5 + Lib/test/pythoninfo.py | 2 +- .../2019-04-15-16-55-49.bpo-36635.__FTq9.rst | 1 + Modules/Setup | 1 + Modules/_testcapimodule.c | 8 -- Modules/_testinternalcapi.c | 45 +++++++++ PCbuild/_testinternalcapi.vcxproj | 94 +++++++++++++++++++ PCbuild/_testinternalcapi.vcxproj.filters | 13 +++ PCbuild/pcbuild.proj | 4 +- PCbuild/pcbuild.sln | 2 + Programs/_testembed.c | 37 +------- setup.py | 4 + 13 files changed, 172 insertions(+), 49 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-04-15-16-55-49.bpo-36635.__FTq9.rst create mode 100644 Modules/_testinternalcapi.c create mode 100644 PCbuild/_testinternalcapi.vcxproj create mode 100644 PCbuild/_testinternalcapi.vcxproj.filters diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index 7ce1a02e16c635..c1a72989a5e979 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -408,11 +408,6 @@ typedef struct { ._init_main = 1} /* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */ - -/* --- Function used for testing ---------------------------------- */ - -PyAPI_FUNC(PyObject*) _Py_GetConfigsAsDict(void); - #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index 33538442043baf..e88a46314c897d 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -110,6 +110,11 @@ PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config, const _PyArgv *args); PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config); + +/* --- Function used for testing ---------------------------------- */ + +PyAPI_FUNC(PyObject*) _Py_GetConfigsAsDict(void); + #ifdef __cplusplus } #endif diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 79f7e82e000635..19f274a6b6294b 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -598,7 +598,7 @@ def collect_get_config(info_add): # Dump global configuration variables, _PyCoreConfig # and _PyMainInterpreterConfig try: - from _testcapi import get_configs + from _testinternalcapi import get_configs except ImportError: return diff --git a/Misc/NEWS.d/next/Tests/2019-04-15-16-55-49.bpo-36635.__FTq9.rst b/Misc/NEWS.d/next/Tests/2019-04-15-16-55-49.bpo-36635.__FTq9.rst new file mode 100644 index 00000000000000..855d1cb27764ca --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-04-15-16-55-49.bpo-36635.__FTq9.rst @@ -0,0 +1 @@ +Add a new :mod:`_testinternalcapi` module to test the internal C API. diff --git a/Modules/Setup b/Modules/Setup index 03aa0f16be14db..e729ab883f410b 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -173,6 +173,7 @@ _symtable symtablemodule.c #_struct _struct.c # binary structure packing/unpacking #_weakref _weakref.c # basic weak reference support #_testcapi _testcapimodule.c # Python C API test module +#_testinternalcapi _testinternalcapi.c -I$(srcdir)/Include/internal -DPy_BUILD_CORE_MODULE # Python internal C API test module #_random _randommodule.c # Random number generator #_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c # elementtree accelerator #_pickle _pickle.c # pickle accelerator diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index ae960deba78c97..6f4eb53d7e9239 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4736,13 +4736,6 @@ decode_locale_ex(PyObject *self, PyObject *args) } -static PyObject * -get_configs(PyObject *self, PyObject *Py_UNUSED(args)) -{ - return _Py_GetConfigsAsDict(); -} - - #ifdef Py_REF_DEBUG static PyObject * negative_refcount(PyObject *self, PyObject *Py_UNUSED(args)) @@ -4990,7 +4983,6 @@ static PyMethodDef TestMethods[] = { {"bad_get", (PyCFunction)(void(*)(void))bad_get, METH_FASTCALL}, {"EncodeLocaleEx", encode_locale_ex, METH_VARARGS}, {"DecodeLocaleEx", decode_locale_ex, METH_VARARGS}, - {"get_configs", get_configs, METH_NOARGS}, #ifdef Py_REF_DEBUG {"negative_refcount", negative_refcount, METH_NOARGS}, #endif diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c new file mode 100644 index 00000000000000..3a43ec16850fcf --- /dev/null +++ b/Modules/_testinternalcapi.c @@ -0,0 +1,45 @@ +/* + * C Extension module to test Python internal C APIs (Include/internal). + */ + +#if !defined(Py_BUILD_CORE_BUILTIN) && !defined(Py_BUILD_CORE_MODULE) +# error "Py_BUILD_CORE_BUILTIN or Py_BUILD_CORE_MODULE must be defined" +#endif + +#define PY_SSIZE_T_CLEAN + +#include "Python.h" +#include "pycore_coreconfig.h" + + +static PyObject * +get_configs(PyObject *self, PyObject *Py_UNUSED(args)) +{ + return _Py_GetConfigsAsDict(); +} + + +static PyMethodDef TestMethods[] = { + {"get_configs", get_configs, METH_NOARGS}, + {NULL, NULL} /* sentinel */ +}; + + +static struct PyModuleDef _testcapimodule = { + PyModuleDef_HEAD_INIT, + "_testinternalcapi", + NULL, + -1, + TestMethods, + NULL, + NULL, + NULL, + NULL +}; + + +PyMODINIT_FUNC +PyInit__testinternalcapi(void) +{ + return PyModule_Create(&_testcapimodule); +} diff --git a/PCbuild/_testinternalcapi.vcxproj b/PCbuild/_testinternalcapi.vcxproj new file mode 100644 index 00000000000000..116d193a39cf4d --- /dev/null +++ b/PCbuild/_testinternalcapi.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + ARM + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + ARM + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {900342D7-516A-4469-B1AD-59A66E49A25F} + _testinternalcapi + Win32Proj + false + + + + + DynamicLibrary + NotSet + + + + .pyd + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + + + + diff --git a/PCbuild/_testinternalcapi.vcxproj.filters b/PCbuild/_testinternalcapi.vcxproj.filters new file mode 100644 index 00000000000000..4644f230be1ce3 --- /dev/null +++ b/PCbuild/_testinternalcapi.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + {136fc5eb-7fe4-4486-8c6d-b49f37a00199} + + + + + Source Files + + + diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj index 574c4f02913b1e..d16ddef89f62d0 100644 --- a/PCbuild/pcbuild.proj +++ b/PCbuild/pcbuild.proj @@ -62,13 +62,13 @@ - + false - + diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln index e9239365b5c1af..951dc932a8e570 100644 --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -37,6 +37,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ssl", "_ssl.vcxproj", "{C6 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testcapi", "_testcapi.vcxproj", "{6901D91C-6E48-4BB7-9FEC-700C8131DF1D}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testinternalcapi", "_testinternalcapi.vcxproj", "{900342D7-516A-4469-B1AD-59A66E49A25F}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testimportmultiple", "_testimportmultiple.vcxproj", "{36D0C52C-DF4E-45D0-8BC7-E294C3ABC781}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_tkinter", "_tkinter.vcxproj", "{4946ECAC-2E69-4BF8-A90A-F5136F5094DF}" diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 7d71a961602d62..3fc8e6d8c6b220 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -298,42 +298,13 @@ static int test_initialize_pymain(void) } -static int -dump_config_impl(void) -{ - PyObject *config = _Py_GetConfigsAsDict(); - if (config == NULL) { - return -1; - } - - PyObject *res; - PyObject *json = PyImport_ImportModule("json"); - if (json) { - res = PyObject_CallMethod(json, "dumps", "O", config); - Py_DECREF(json); - } - else { - res = NULL; - } - Py_CLEAR(config); - if (res == NULL) { - return -1; - } - - PySys_FormatStdout("%S\n", res); - Py_DECREF(res); - - return 0; -} - - static void dump_config(void) { - if (dump_config_impl() < 0) { - fprintf(stderr, "failed to dump the configuration:\n"); - PyErr_Print(); - } + (void) PyRun_SimpleStringFlags( + "import _testinternalcapi, json; " + "print(json.dumps(_testinternalcapi.get_configs()))", + 0); } diff --git a/setup.py b/setup.py index c470719a6a804f..3d6404f89eef70 100644 --- a/setup.py +++ b/setup.py @@ -814,6 +814,10 @@ def detect_test_extensions(self): self.add(Extension('_testcapi', ['_testcapimodule.c'], depends=['testcapi_long.h'])) + # Python Internal C API test module + self.add(Extension('_testinternalcapi', ['_testinternalcapi.c'], + extra_compile_args=['-D Py_BUILD_CORE_MODULE'])) + # Python PEP-3118 (buffer protocol) test module self.add(Extension('_testbuffer', ['_testbuffer.c'])) From 7e954e7de4f3777b5ce239640bd2b76aced09561 Mon Sep 17 00:00:00 2001 From: Enrico Alarico Carbognani Date: Thu, 18 Apr 2019 14:43:14 +0200 Subject: [PATCH 029/212] bpo-36651: Fixed Asyncio Event Loop documentation inconsistency (GH-12866) # [bpo-36651](https://bugs.python.org/issue36651): Fixed Asyncio Event Loop documentation inconsistency In the documentation for the call_later and the call_at methods there is a note which says that the delay cannot be longer than a day, but both methods have a note saying that this limitation was removed in Python 3.8 Here I fixed this issue by removing the pre-exising note and added a versionchanged. To test my changes I have rebuilt the documentation with ```make html```. I did not have any errors and the effected page displayed correctly on a browser. https://bugs.python.org/issue36651 --- Doc/library/asyncio-eventloop.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 8d157fd5f599ae..bf7c93a86fd041 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -281,9 +281,9 @@ clocks to track time. the event loop's internal monotonic clock. .. note:: - - Timeouts (relative *delay* or absolute *when*) should not - exceed one day. + .. versionchanged:: 3.8 + In Python 3.7 and earlier timeouts (relative *delay* or absolute *when*) + should not exceed one day. This has been fixed in Python 3.8. .. seealso:: From e8113f51a8bdf33188ee30a1c038a298329e7bfa Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Thu, 18 Apr 2019 19:05:03 +0200 Subject: [PATCH 030/212] bpo-30485: Change the prefix for defining the default namespace in ElementPath from None to '' since there is existing code that uses that and it's more convenient to have an all-string-keys dict (e.g. when sorting items etc.). (#12860) --- Doc/library/xml.etree.elementtree.rst | 6 +++--- Lib/test/test_xml_etree.py | 2 +- Lib/xml/etree/ElementPath.py | 8 ++------ .../next/Library/2019-04-13-23-42-33.bpo-30485.JHhjJS.rst | 2 +- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index c83e719e959a29..9e2c295867ca3a 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -764,7 +764,7 @@ Element Objects Finds the first subelement matching *match*. *match* may be a tag name or a :ref:`path `. Returns an element instance or ``None``. *namespaces* is an optional mapping from namespace prefix - to full name. Pass ``None`` as prefix to move all unprefixed tag names + to full name. Pass ``''`` as prefix to move all unprefixed tag names in the expression into the given namespace. @@ -773,7 +773,7 @@ Element Objects Finds all matching subelements, by tag name or :ref:`path `. Returns a list containing all matching elements in document order. *namespaces* is an optional mapping from - namespace prefix to full name. Pass ``None`` as prefix to move all + namespace prefix to full name. Pass ``''`` as prefix to move all unprefixed tag names in the expression into the given namespace. @@ -784,7 +784,7 @@ Element Objects of the first matching element, or *default* if no element was found. Note that if the matching element has no text content an empty string is returned. *namespaces* is an optional mapping from namespace prefix - to full name. Pass ``None`` as prefix to move all unprefixed tag names + to full name. Pass ``''`` as prefix to move all unprefixed tag names in the expression into the given namespace. diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index f5b118b079ee3b..14ce32af802624 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -2463,7 +2463,7 @@ def test_findall_different_nsmaps(self): nsmap = {'xx': 'Y'} self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1) self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2) - nsmap = {'xx': 'X', None: 'Y'} + nsmap = {'xx': 'X', '': 'Y'} self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2) self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1) diff --git a/Lib/xml/etree/ElementPath.py b/Lib/xml/etree/ElementPath.py index 4d231a7df65677..b670d58f3f0121 100644 --- a/Lib/xml/etree/ElementPath.py +++ b/Lib/xml/etree/ElementPath.py @@ -71,7 +71,7 @@ ) def xpath_tokenizer(pattern, namespaces=None): - default_namespace = namespaces.get(None) if namespaces else None + default_namespace = namespaces.get('') if namespaces else None for token in xpath_tokenizer_re.findall(pattern): tag = token[1] if tag and tag[0] != "{": @@ -275,11 +275,7 @@ def iterfind(elem, path, namespaces=None): cache_key = (path,) if namespaces: - if None in namespaces: - cache_key += (namespaces[None],) + tuple(sorted( - item for item in namespaces.items() if item[0] is not None)) - else: - cache_key += tuple(sorted(namespaces.items())) + cache_key += tuple(sorted(namespaces.items())) try: selector = _cache[cache_key] diff --git a/Misc/NEWS.d/next/Library/2019-04-13-23-42-33.bpo-30485.JHhjJS.rst b/Misc/NEWS.d/next/Library/2019-04-13-23-42-33.bpo-30485.JHhjJS.rst index 6c82efd3e00922..900edf8c755355 100644 --- a/Misc/NEWS.d/next/Library/2019-04-13-23-42-33.bpo-30485.JHhjJS.rst +++ b/Misc/NEWS.d/next/Library/2019-04-13-23-42-33.bpo-30485.JHhjJS.rst @@ -1,3 +1,3 @@ Path expressions in xml.etree.ElementTree can now avoid explicit namespace prefixes for tags (or the "{namespace}tag" notation) by passing a default -namespace with a 'None' prefix. +namespace with an empty string prefix. From 9d062d690b768252204992fc6ab7c3873a87442d Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Fri, 19 Apr 2019 16:07:19 +0900 Subject: [PATCH 031/212] ctypes: remove use of legacy unicode API (GH-12340) PyUnicode_AsUnicodeAndSize() -> PyUnicode_AsWideChar() --- Modules/_ctypes/_ctypes.c | 14 +++++++------- Modules/_ctypes/cfield.c | 20 ++++++++++++-------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index ac071bbb708b15..13cf76a16d768a 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1304,8 +1304,6 @@ static int WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) { Py_ssize_t result = 0; - Py_UNICODE *wstr; - Py_ssize_t len; if (value == NULL) { PyErr_SetString(PyExc_TypeError, @@ -1320,12 +1318,14 @@ WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored } else Py_INCREF(value); - wstr = PyUnicode_AsUnicodeAndSize(value, &len); - if (wstr == NULL) + Py_ssize_t len = PyUnicode_AsWideChar(value, NULL, 0); + if (len < 0) { return -1; - if ((size_t)len > self->b_size/sizeof(wchar_t)) { - PyErr_SetString(PyExc_ValueError, - "string too long"); + } + // PyUnicode_AsWideChar() returns number of wchars including trailing null byte, + // when it is called with NULL. + if (((size_t)len-1) > self->b_size/sizeof(wchar_t)) { + PyErr_SetString(PyExc_ValueError, "string too long"); result = -1; goto done; } diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 5f194e21550f7b..157c32fd90967f 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -1229,9 +1229,6 @@ U_get(void *ptr, Py_ssize_t size) static PyObject * U_set(void *ptr, PyObject *value, Py_ssize_t length) { - Py_UNICODE *wstr; - Py_ssize_t size; - /* It's easier to calculate in characters than in bytes */ length /= sizeof(wchar_t); @@ -1242,9 +1239,14 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) return NULL; } - wstr = PyUnicode_AsUnicodeAndSize(value, &size); - if (wstr == NULL) + Py_ssize_t size = PyUnicode_AsWideChar(value, NULL, 0); + if (size < 0) { return NULL; + } + // PyUnicode_AsWideChar() returns number of wchars including trailing null byte, + // when it is called with NULL. + size--; + assert(size >= 0); if (size > length) { PyErr_Format(PyExc_ValueError, "string too long (%zd, maximum length %zd)", @@ -1421,16 +1423,18 @@ BSTR_set(void *ptr, PyObject *value, Py_ssize_t size) /* create a BSTR from value */ if (value) { - wchar_t* wvalue; Py_ssize_t wsize; - wvalue = PyUnicode_AsUnicodeAndSize(value, &wsize); - if (wvalue == NULL) + wchar_t *wvalue = PyUnicode_AsWideCharString(value, &wsize); + if (wvalue == NULL) { return NULL; + } if ((unsigned) wsize != wsize) { PyErr_SetString(PyExc_ValueError, "String too long for BSTR"); + PyMem_Free(wvalue); return NULL; } bstr = SysAllocStringLen(wvalue, (unsigned)wsize); + PyMem_Free(wvalue); } else bstr = NULL; From 14adbd45980f705cb6554ca17b8a66b56e105296 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 20 Apr 2019 07:20:44 -1000 Subject: [PATCH 032/212] bpo-36650: Fix handling of empty keyword args in C version of lru_cache. (GH-12881) --- Lib/test/test_functools.py | 14 ++++++++++++++ .../2019-04-19-15-29-55.bpo-36650._EVdrz.rst | 4 ++++ Modules/_functoolsmodule.c | 7 +++---- 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-19-15-29-55.bpo-36650._EVdrz.rst diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 4b2b9ab61fa756..98908405e1401a 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1271,6 +1271,20 @@ def f(x): self.assertEqual(f(20), '.20.') self.assertEqual(f.cache_info().currsize, 10) + def test_lru_bug_36650(self): + # C version of lru_cache was treating a call with an empty **kwargs + # dictionary as being distinct from a call with no keywords at all. + # This did not result in an incorrect answer, but it did trigger + # an unexpected cache miss. + + @self.module.lru_cache() + def f(x): + pass + + f(0) + f(0, **{}) + self.assertEqual(f.cache_info().hits, 1) + def test_lru_hash_only_once(self): # To protect against weird reentrancy bugs and to improve # efficiency when faced with slow __hash__ methods, the diff --git a/Misc/NEWS.d/next/Library/2019-04-19-15-29-55.bpo-36650._EVdrz.rst b/Misc/NEWS.d/next/Library/2019-04-19-15-29-55.bpo-36650._EVdrz.rst new file mode 100644 index 00000000000000..de10575fc2720e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-19-15-29-55.bpo-36650._EVdrz.rst @@ -0,0 +1,4 @@ +The C version of functools.lru_cache() was treating calls with an empty +``**kwargs`` dictionary as being distinct from calls with no keywords at all. +This did not result in an incorrect answer, but it did trigger an unexpected +cache miss. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 3f1c01651ded1b..dcc9129fc6b183 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -750,8 +750,10 @@ lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) PyObject *key, *keyword, *value; Py_ssize_t key_size, pos, key_pos, kwds_size; + kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0; + /* short path, key will match args anyway, which is a tuple */ - if (!typed && !kwds) { + if (!typed && !kwds_size) { if (PyTuple_GET_SIZE(args) == 1) { key = PyTuple_GET_ITEM(args, 0); if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) { @@ -765,9 +767,6 @@ lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) return args; } - kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0; - assert(kwds_size >= 0); - key_size = PyTuple_GET_SIZE(args); if (kwds_size) key_size += kwds_size * 2 + 1; From 3e986de0d65e78901b55d4e500b1d05c847b6d5e Mon Sep 17 00:00:00 2001 From: Fredrik Averpil Date: Sun, 21 Apr 2019 01:06:38 +0200 Subject: [PATCH 033/212] Fix typo (GH-12878) "sychronization" -> "synchronization" --- Doc/library/asyncio-sync.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst index 18da18873dbfb5..e3f18ccb4341fe 100644 --- a/Doc/library/asyncio-sync.rst +++ b/Doc/library/asyncio-sync.rst @@ -17,7 +17,7 @@ those of the :mod:`threading` module with two important caveats: argument; use the :func:`asyncio.wait_for` function to perform operations with timeouts. -asyncio has the following basic sychronization primitives: +asyncio has the following basic synchronization primitives: * :class:`Lock` * :class:`Event` From 5ebfa840a1c9967da299356733da41b532688988 Mon Sep 17 00:00:00 2001 From: mollison Date: Sun, 21 Apr 2019 18:14:45 -0400 Subject: [PATCH 034/212] bpo-36645: Fix ambiguous formatting in re.sub() documentation (GH-12879) --- Doc/library/re.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 4ac5dee1407110..5ef72b535ce8d4 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -908,6 +908,7 @@ form. Unknown escapes in *repl* consisting of ``'\'`` and an ASCII letter now are errors. + .. versionchanged:: 3.7 Empty matches for the pattern are replaced when adjacent to a previous non-empty match. From 9541bd321a94f13dc41163a5d7a1a847816fac84 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com> Date: Sun, 21 Apr 2019 21:47:06 -0400 Subject: [PATCH 035/212] bpo-24011: Use PyModule_Add{Object,IntMacro} in PyInit__signal() (GH-12765) --- Modules/signalmodule.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 4590017c170a52..8c5a0d044ab613 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1350,17 +1350,15 @@ PyInit__signal(void) d = PyModule_GetDict(m); x = DefaultHandler = PyLong_FromVoidPtr((void *)SIG_DFL); - if (!x || PyDict_SetItemString(d, "SIG_DFL", x) < 0) + if (PyModule_AddObject(m, "SIG_DFL", x)) goto finally; x = IgnoreHandler = PyLong_FromVoidPtr((void *)SIG_IGN); - if (!x || PyDict_SetItemString(d, "SIG_IGN", x) < 0) + if (PyModule_AddObject(m, "SIG_IGN", x)) goto finally; - x = PyLong_FromLong((long)NSIG); - if (!x || PyDict_SetItemString(d, "NSIG", x) < 0) + if (PyModule_AddIntMacro(m, NSIG)) goto finally; - Py_DECREF(x); #ifdef SIG_BLOCK if (PyModule_AddIntMacro(m, SIG_BLOCK)) @@ -1569,8 +1567,8 @@ PyInit__signal(void) #if defined (HAVE_SETITIMER) || defined (HAVE_GETITIMER) ItimerError = PyErr_NewException("signal.ItimerError", PyExc_OSError, NULL); - if (ItimerError != NULL) - PyDict_SetItemString(d, "ItimerError", ItimerError); + if (PyModule_AddObject(m, "ItimerError", ItimerError)) + goto finally; #endif #ifdef CTRL_C_EVENT From 9b21856b0fcda949de239edc7aa6cf3f2f4f77a3 Mon Sep 17 00:00:00 2001 From: Xtreak Date: Mon, 22 Apr 2019 08:00:23 +0530 Subject: [PATCH 036/212] bpo-23078: Add support for {class,static}method to mock.create_autospec() (GH-11613) Co-authored-by: Felipe --- Lib/unittest/mock.py | 4 +- Lib/unittest/test/testmock/testhelpers.py | 40 ++++++++++++++++++- Lib/unittest/test/testmock/testmock.py | 17 ++++++++ Lib/unittest/test/testmock/testpatch.py | 20 ++++++++++ .../2019-01-18-23-10-10.bpo-23078.l4dFoj.rst | 2 + 5 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 0e77f0e48943af..1636073ff00935 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -29,7 +29,7 @@ import pprint import sys import builtins -from types import ModuleType +from types import ModuleType, MethodType from unittest.util import safe_repr from functools import wraps, partial @@ -122,6 +122,8 @@ def _copy_func_details(func, funcopy): def _callable(obj): if isinstance(obj, type): return True + if isinstance(obj, (staticmethod, classmethod, MethodType)): + return _callable(obj.__func__) if getattr(obj, '__call__', None) is not None: return True return False diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py index 9f1bf2676bf5d9..0d03108aca5570 100644 --- a/Lib/unittest/test/testmock/testhelpers.py +++ b/Lib/unittest/test/testmock/testhelpers.py @@ -5,7 +5,7 @@ from unittest.mock import ( call, _Call, create_autospec, MagicMock, - Mock, ANY, _CallList, patch, PropertyMock + Mock, ANY, _CallList, patch, PropertyMock, _callable ) from datetime import datetime @@ -1011,5 +1011,43 @@ def test_propertymock_returnvalue(self): self.assertNotIsInstance(returned, PropertyMock) +class TestCallablePredicate(unittest.TestCase): + + def test_type(self): + for obj in [str, bytes, int, list, tuple, SomeClass]: + self.assertTrue(_callable(obj)) + + def test_call_magic_method(self): + class Callable: + def __call__(self): + pass + instance = Callable() + self.assertTrue(_callable(instance)) + + def test_staticmethod(self): + class WithStaticMethod: + @staticmethod + def staticfunc(): + pass + self.assertTrue(_callable(WithStaticMethod.staticfunc)) + + def test_non_callable_staticmethod(self): + class BadStaticMethod: + not_callable = staticmethod(None) + self.assertFalse(_callable(BadStaticMethod.not_callable)) + + def test_classmethod(self): + class WithClassMethod: + @classmethod + def classfunc(cls): + pass + self.assertTrue(_callable(WithClassMethod.classfunc)) + + def test_non_callable_classmethod(self): + class BadClassMethod: + not_callable = classmethod(None) + self.assertFalse(_callable(BadClassMethod.not_callable)) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index 37f14c37f47d59..bdaebbe66b74db 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1419,6 +1419,23 @@ def test_create_autospec_with_name(self): m = mock.create_autospec(object(), name='sweet_func') self.assertIn('sweet_func', repr(m)) + #Issue23078 + def test_create_autospec_classmethod_and_staticmethod(self): + class TestClass: + @classmethod + def class_method(cls): + pass + + @staticmethod + def static_method(): + pass + for method in ('class_method', 'static_method'): + with self.subTest(method=method): + mock_method = mock.create_autospec(getattr(TestClass, method)) + mock_method() + mock_method.assert_called_once_with() + self.assertRaises(TypeError, mock_method, 'extra_arg') + #Issue21238 def test_mock_unsafe(self): m = Mock() diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index 2c14360b2df530..51c66fec67fc45 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -51,6 +51,14 @@ def g(self): pass foo = 'bar' + @staticmethod + def static_method(): + return 24 + + @classmethod + def class_method(cls): + return 42 + class Bar(object): def a(self): pass @@ -1023,6 +1031,18 @@ def test(mock_function): self.assertEqual(result, 3) + def test_autospec_staticmethod(self): + with patch('%s.Foo.static_method' % __name__, autospec=True) as method: + Foo.static_method() + method.assert_called_once_with() + + + def test_autospec_classmethod(self): + with patch('%s.Foo.class_method' % __name__, autospec=True) as method: + Foo.class_method() + method.assert_called_once_with() + + def test_autospec_with_new(self): patcher = patch('%s.function' % __name__, new=3, autospec=True) self.assertRaises(TypeError, patcher.start) diff --git a/Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst b/Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst new file mode 100644 index 00000000000000..975cc9c0454c70 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst @@ -0,0 +1,2 @@ +Add support for :func:`classmethod` and :func:`staticmethod` to +:func:`unittest.mock.create_autospec`. Initial patch by Felipe Ochoa. From 662ebd2ab2047aeae9689ad254b39915c38069fd Mon Sep 17 00:00:00 2001 From: Wu Wei Date: Mon, 22 Apr 2019 19:08:20 +0800 Subject: [PATCH 037/212] Doc: add the missing ".tp_flags" in type definition (GH-12902) --- Doc/extending/newtypes_tutorial.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/extending/newtypes_tutorial.rst b/Doc/extending/newtypes_tutorial.rst index bb8a40d0fb06f5..b4bf9b9e6f75f8 100644 --- a/Doc/extending/newtypes_tutorial.rst +++ b/Doc/extending/newtypes_tutorial.rst @@ -92,6 +92,7 @@ The second bit is the definition of the type object. :: .tp_doc = "Custom objects", .tp_basicsize = sizeof(CustomObject), .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, .tp_new = PyType_GenericNew, }; From ab86521a9d9999731e39bd9056420bb7774fd144 Mon Sep 17 00:00:00 2001 From: Marcin Niemira Date: Mon, 22 Apr 2019 21:13:51 +1000 Subject: [PATCH 038/212] bpo-36523: Add docstring to io.IOBase.writelines (GH-12683) --- Lib/_pyio.py | 5 +++++ .../2019-04-04-19-11-47.bpo-36523.sG1Tr4.rst | 1 + Modules/_io/clinic/iobase.c.h | 8 ++++++-- Modules/_io/iobase.c | 7 ++++++- 4 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Documentation/2019-04-04-19-11-47.bpo-36523.sG1Tr4.rst diff --git a/Lib/_pyio.py b/Lib/_pyio.py index e868fdc7cbc5c2..af2ce30c278062 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -551,6 +551,11 @@ def readlines(self, hint=None): return lines def writelines(self, lines): + """Write a list of lines to the stream. + + Line separators are not added, so it is usual for each of the lines + provided to have a line separator at the end. + """ self._checkClosed() for line in lines: self.write(line) diff --git a/Misc/NEWS.d/next/Documentation/2019-04-04-19-11-47.bpo-36523.sG1Tr4.rst b/Misc/NEWS.d/next/Documentation/2019-04-04-19-11-47.bpo-36523.sG1Tr4.rst new file mode 100644 index 00000000000000..9355f607d760ad --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-04-04-19-11-47.bpo-36523.sG1Tr4.rst @@ -0,0 +1 @@ +Add docstring for io.IOBase.writelines(). diff --git a/Modules/_io/clinic/iobase.c.h b/Modules/_io/clinic/iobase.c.h index a5c8eea3ec3aed..ddaff7b5d135d8 100644 --- a/Modules/_io/clinic/iobase.c.h +++ b/Modules/_io/clinic/iobase.c.h @@ -242,7 +242,11 @@ _io__IOBase_readlines(PyObject *self, PyObject *const *args, Py_ssize_t nargs) PyDoc_STRVAR(_io__IOBase_writelines__doc__, "writelines($self, lines, /)\n" "--\n" -"\n"); +"\n" +"Write a list of lines to stream.\n" +"\n" +"Line separators are not added, so it is usual for each of the\n" +"lines provided to have a line separator at the end."); #define _IO__IOBASE_WRITELINES_METHODDEF \ {"writelines", (PyCFunction)_io__IOBase_writelines, METH_O, _io__IOBase_writelines__doc__}, @@ -311,4 +315,4 @@ _io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored)) { return _io__RawIOBase_readall_impl(self); } -/*[clinic end generated code: output=60e43a7cbd9f314e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=61b6ea7153ef9940 input=a9049054013a1b77]*/ diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 3a8f16ae0b6589..6a0d9bec5af320 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -751,11 +751,16 @@ _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint) _io._IOBase.writelines lines: object / + +Write a list of lines to stream. + +Line separators are not added, so it is usual for each of the +lines provided to have a line separator at the end. [clinic start generated code]*/ static PyObject * _io__IOBase_writelines(PyObject *self, PyObject *lines) -/*[clinic end generated code: output=976eb0a9b60a6628 input=432e729a8450b3cb]*/ +/*[clinic end generated code: output=976eb0a9b60a6628 input=cac3fc8864183359]*/ { PyObject *iter, *res; From d59b662e490d3fae662c5f81fa5248f0445d2158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E5=AE=B6=E6=9C=AA?= <752736341@qq.com> Date: Mon, 22 Apr 2019 21:28:57 +0800 Subject: [PATCH 039/212] bpo-36690: Fix typo in Tools/demo/rpython.py (GH-12903) --- Tools/demo/rpython.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/demo/rpython.py b/Tools/demo/rpython.py index 8d7e2747636c4f..11f72cb3dd26a6 100755 --- a/Tools/demo/rpython.py +++ b/Tools/demo/rpython.py @@ -19,7 +19,7 @@ def main(): port = PORT i = host.find(':') if i >= 0: - port = int(port[i+1:]) + port = int(host[i+1:]) host = host[:i] command = ' '.join(sys.argv[2:]) with socket(AF_INET, SOCK_STREAM) as s: From 6ef726af3ec106013c7c4261ddb306854f2b1778 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Mon, 22 Apr 2019 18:46:28 +0300 Subject: [PATCH 040/212] bpo-29734: Cleanup test_getfinalpathname_handles test (GH-12908) --- Lib/test/test_os.py | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 4c620ccae9c84c..bbadb81069b9da 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2337,19 +2337,10 @@ def test_unlink_removes_junction(self): @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") class Win32NtTests(unittest.TestCase): - def setUp(self): - from test import support - self.nt = support.import_module('nt') - pass - - def tearDown(self): - pass - def test_getfinalpathname_handles(self): - try: - import ctypes, ctypes.wintypes - except ImportError: - raise unittest.SkipTest('ctypes module is required for this test') + nt = support.import_module('nt') + ctypes = support.import_module('ctypes') + import ctypes.wintypes kernel = ctypes.WinDLL('Kernel32.dll', use_last_error=True) kernel.GetCurrentProcess.restype = ctypes.wintypes.HANDLE @@ -2368,21 +2359,23 @@ def test_getfinalpathname_handles(self): before_count = handle_count.value # The first two test the error path, __file__ tests the success path - filenames = [ r'\\?\C:', - r'\\?\NUL', - r'\\?\CONIN', - __file__ ] + filenames = [ + r'\\?\C:', + r'\\?\NUL', + r'\\?\CONIN', + __file__, + ] - for i in range(10): + for _ in range(10): for name in filenames: try: - tmp = self.nt._getfinalpathname(name) - except: + nt._getfinalpathname(name) + except Exception: # Failure is expected pass try: - tmp = os.stat(name) - except: + os.stat(name) + except Exception: pass ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count)) From 56ed86490cb8221c874d432461d77702437f63e5 Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Mon, 22 Apr 2019 11:01:32 -0600 Subject: [PATCH 041/212] bpo-9194: Fix the bounds checking in winreg.c's fixupMultiSZ() (GH-12687) --- PC/winreg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PC/winreg.c b/PC/winreg.c index ae0c292b7172e9..28b316ae2f4cb9 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -521,7 +521,7 @@ fixupMultiSZ(wchar_t **str, wchar_t *data, int len) Q = data + len; for (P = data, i = 0; P < Q && *P != '\0'; P++, i++) { str[i] = P; - for(; *P != '\0'; P++) + for (; P < Q && *P != '\0'; P++) ; } } From 34366b7f914eedbcc33aebe882098a2199ffaf82 Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Mon, 22 Apr 2019 11:08:05 -0600 Subject: [PATCH 042/212] bpo-36672: Fix a compiler warning in winreg.SetValue() (GH-12882) --- PC/winreg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PC/winreg.c b/PC/winreg.c index 28b316ae2f4cb9..5469fcba044432 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1614,7 +1614,7 @@ winreg_SetValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key, } Py_BEGIN_ALLOW_THREADS - rc = RegSetValueW(key, sub_key, REG_SZ, value, value_length+1); + rc = RegSetValueW(key, sub_key, REG_SZ, value, (DWORD)(value_length + 1)); Py_END_ALLOW_THREADS if (rc != ERROR_SUCCESS) return PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValue"); From 264490797ad936868c54b3d4ceb0343e7ba4be76 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Mon, 22 Apr 2019 11:13:11 -0700 Subject: [PATCH 043/212] bpo-33608: Normalize atomic macros so that they all expect an atomic struct (GH-12877) --- Include/internal/pycore_atomic.h | 60 +++++++++++++++++++------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/Include/internal/pycore_atomic.h b/Include/internal/pycore_atomic.h index b3ec44c1bcfee1..336bc3fec27e5d 100644 --- a/Include/internal/pycore_atomic.h +++ b/Include/internal/pycore_atomic.h @@ -261,13 +261,13 @@ typedef struct _Py_atomic_int { #define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) \ switch (ORDER) { \ case _Py_memory_order_acquire: \ - _InterlockedExchange64_HLEAcquire((__int64 volatile*)ATOMIC_VAL, (__int64)NEW_VAL); \ + _InterlockedExchange64_HLEAcquire((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)(NEW_VAL)); \ break; \ case _Py_memory_order_release: \ - _InterlockedExchange64_HLERelease((__int64 volatile*)ATOMIC_VAL, (__int64)NEW_VAL); \ + _InterlockedExchange64_HLERelease((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)(NEW_VAL)); \ break; \ default: \ - _InterlockedExchange64((__int64 volatile*)ATOMIC_VAL, (__int64)NEW_VAL); \ + _InterlockedExchange64((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)(NEW_VAL)); \ break; \ } #else @@ -277,13 +277,13 @@ typedef struct _Py_atomic_int { #define _Py_atomic_store_32bit(ATOMIC_VAL, NEW_VAL, ORDER) \ switch (ORDER) { \ case _Py_memory_order_acquire: \ - _InterlockedExchange_HLEAcquire((volatile long*)ATOMIC_VAL, (int)NEW_VAL); \ + _InterlockedExchange_HLEAcquire((volatile long*)&((ATOMIC_VAL)->_value), (int)(NEW_VAL)); \ break; \ case _Py_memory_order_release: \ - _InterlockedExchange_HLERelease((volatile long*)ATOMIC_VAL, (int)NEW_VAL); \ + _InterlockedExchange_HLERelease((volatile long*)&((ATOMIC_VAL)->_value), (int)(NEW_VAL)); \ break; \ default: \ - _InterlockedExchange((volatile long*)ATOMIC_VAL, (int)NEW_VAL); \ + _InterlockedExchange((volatile long*)&((ATOMIC_VAL)->_value), (int)(NEW_VAL)); \ break; \ } @@ -292,7 +292,7 @@ typedef struct _Py_atomic_int { gil_created() uses -1 as a sentinel value, if this returns a uintptr_t it will do an unsigned compare and crash */ -inline intptr_t _Py_atomic_load_64bit(volatile uintptr_t* value, int order) { +inline intptr_t _Py_atomic_load_64bit_impl(volatile uintptr_t* value, int order) { __int64 old; switch (order) { case _Py_memory_order_acquire: @@ -323,11 +323,14 @@ inline intptr_t _Py_atomic_load_64bit(volatile uintptr_t* value, int order) { return old; } +#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) \ + _Py_atomic_load_64bit_impl((volatile uintptr_t*)&((ATOMIC_VAL)->_value), (ORDER)) + #else -#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) *(ATOMIC_VAL) +#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) ((ATOMIC_VAL)->_value) #endif -inline int _Py_atomic_load_32bit(volatile int* value, int order) { +inline int _Py_atomic_load_32bit_impl(volatile int* value, int order) { long old; switch (order) { case _Py_memory_order_acquire: @@ -358,16 +361,19 @@ inline int _Py_atomic_load_32bit(volatile int* value, int order) { return old; } +#define _Py_atomic_load_32bit(ATOMIC_VAL, ORDER) \ + _Py_atomic_load_32bit_impl((volatile int*)&((ATOMIC_VAL)->_value), (ORDER)) + #define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ if (sizeof((ATOMIC_VAL)->_value) == 8) { \ - _Py_atomic_store_64bit((volatile long long*)&((ATOMIC_VAL)->_value), NEW_VAL, ORDER) } else { \ - _Py_atomic_store_32bit((volatile long*)&((ATOMIC_VAL)->_value), NEW_VAL, ORDER) } + _Py_atomic_store_64bit((ATOMIC_VAL), NEW_VAL, ORDER) } else { \ + _Py_atomic_store_32bit((ATOMIC_VAL), NEW_VAL, ORDER) } #define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ ( \ sizeof((ATOMIC_VAL)->_value) == 8 ? \ - _Py_atomic_load_64bit((volatile long long*)&((ATOMIC_VAL)->_value), ORDER) : \ - _Py_atomic_load_32bit((volatile long*)&((ATOMIC_VAL)->_value), ORDER) \ + _Py_atomic_load_64bit((ATOMIC_VAL), ORDER) : \ + _Py_atomic_load_32bit((ATOMIC_VAL), ORDER) \ ) #elif defined(_M_ARM) || defined(_M_ARM64) typedef enum _Py_memory_order { @@ -422,7 +428,7 @@ typedef struct _Py_atomic_int { gil_created() uses -1 as a sentinel value, if this returns a uintptr_t it will do an unsigned compare and crash */ -inline intptr_t _Py_atomic_load_64bit(volatile uintptr_t* value, int order) { +inline intptr_t _Py_atomic_load_64bit_impl(volatile uintptr_t* value, int order) { uintptr_t old; switch (order) { case _Py_memory_order_acquire: @@ -453,11 +459,14 @@ inline intptr_t _Py_atomic_load_64bit(volatile uintptr_t* value, int order) { return old; } +#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) \ + _Py_atomic_load_64bit_impl((volatile uintptr_t*)&((ATOMIC_VAL)->_value), (ORDER)) + #else -#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) *(ATOMIC_VAL) +#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) ((ATOMIC_VAL)->_value) #endif -inline int _Py_atomic_load_32bit(volatile int* value, int order) { +inline int _Py_atomic_load_32bit_impl(volatile int* value, int order) { int old; switch (order) { case _Py_memory_order_acquire: @@ -488,16 +497,19 @@ inline int _Py_atomic_load_32bit(volatile int* value, int order) { return old; } +#define _Py_atomic_load_32bit(ATOMIC_VAL, ORDER) \ + _Py_atomic_load_32bit_impl((volatile int*)&((ATOMIC_VAL)->_value), (ORDER)) + #define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ if (sizeof((ATOMIC_VAL)->_value) == 8) { \ - _Py_atomic_store_64bit(&((ATOMIC_VAL)->_value), NEW_VAL, ORDER) } else { \ - _Py_atomic_store_32bit(&((ATOMIC_VAL)->_value), NEW_VAL, ORDER) } + _Py_atomic_store_64bit((ATOMIC_VAL), (NEW_VAL), (ORDER)) } else { \ + _Py_atomic_store_32bit((ATOMIC_VAL), (NEW_VAL), (ORDER)) } #define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ ( \ sizeof((ATOMIC_VAL)->_value) == 8 ? \ - _Py_atomic_load_64bit(&((ATOMIC_VAL)->_value), ORDER) : \ - _Py_atomic_load_32bit(&((ATOMIC_VAL)->_value), ORDER) \ + _Py_atomic_load_64bit((ATOMIC_VAL), (ORDER)) : \ + _Py_atomic_load_32bit((ATOMIC_VAL), (ORDER)) \ ) #endif #else /* !gcc x86 !_msc_ver */ @@ -529,16 +541,16 @@ typedef struct _Py_atomic_int { /* Standardized shortcuts. */ #define _Py_atomic_store(ATOMIC_VAL, NEW_VAL) \ - _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, _Py_memory_order_seq_cst) + _Py_atomic_store_explicit((ATOMIC_VAL), (NEW_VAL), _Py_memory_order_seq_cst) #define _Py_atomic_load(ATOMIC_VAL) \ - _Py_atomic_load_explicit(ATOMIC_VAL, _Py_memory_order_seq_cst) + _Py_atomic_load_explicit((ATOMIC_VAL), _Py_memory_order_seq_cst) /* Python-local extensions */ #define _Py_atomic_store_relaxed(ATOMIC_VAL, NEW_VAL) \ - _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, _Py_memory_order_relaxed) + _Py_atomic_store_explicit((ATOMIC_VAL), (NEW_VAL), _Py_memory_order_relaxed) #define _Py_atomic_load_relaxed(ATOMIC_VAL) \ - _Py_atomic_load_explicit(ATOMIC_VAL, _Py_memory_order_relaxed) + _Py_atomic_load_explicit((ATOMIC_VAL), _Py_memory_order_relaxed) #ifdef __cplusplus } From d307d05350e26a7a5f8f74db9af632a15215b50f Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Mon, 22 Apr 2019 11:40:12 -0700 Subject: [PATCH 044/212] Fixes platform.win32_ver on non-Windows platforms (GH-12912) --- Lib/platform.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Lib/platform.py b/Lib/platform.py index 2ab68aed786138..21defd1095d247 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -339,10 +339,6 @@ def win32_ver(release='', version='', csd='', ptype=''): from sys import getwindowsversion except ImportError: return release, version, csd, ptype - try: - from winreg import OpenKeyEx, QueryValueEx, CloseKey, HKEY_LOCAL_MACHINE - except ImportError: - from _winreg import OpenKeyEx, QueryValueEx, CloseKey, HKEY_LOCAL_MACHINE winver = getwindowsversion() maj, min, build = winver.platform_version or winver[:3] @@ -368,16 +364,20 @@ def win32_ver(release='', version='', csd='', ptype=''): _WIN32_SERVER_RELEASES.get((maj, None)) or release) - key = None try: - key = OpenKeyEx(HKEY_LOCAL_MACHINE, - r'SOFTWARE\Microsoft\Windows NT\CurrentVersion') - ptype = QueryValueEx(key, 'CurrentType')[0] - except: + try: + import winreg + except ImportError: + import _winreg as winreg + except ImportError: pass - finally: - if key: - CloseKey(key) + else: + try: + cvkey = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion' + with winreg.OpenKeyEx(HKEY_LOCAL_MACHINE, cvkey) as key: + ptype = QueryValueEx(key, 'CurrentType')[0] + except: + pass return release, version, csd, ptype From be372d73b4c59026134a7e722ece34367c3bd3b6 Mon Sep 17 00:00:00 2001 From: Windson yang Date: Tue, 23 Apr 2019 02:45:34 +0800 Subject: [PATCH 045/212] bpo-36678: Rename duplicate tests in test_dataclasses (GH-12899) --- Lib/test/test_dataclasses.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 9c83459f09e797..d320a969876e3b 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -697,7 +697,7 @@ class C: y: int self.assertNotEqual(Point(1, 3), C(1, 3)) - def test_not_tuple(self): + def test_not_other_dataclass(self): # Test that some of the problems with namedtuple don't happen # here. @dataclass @@ -1403,7 +1403,7 @@ class GroupDict: self.assertEqual(asdict(gd), {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1}, 'second': {'name': 'Bob', 'id': 2}}}) - def test_helper_asdict_builtin_containers(self): + def test_helper_asdict_builtin_object_containers(self): @dataclass class Child: d: object @@ -1576,7 +1576,7 @@ class GroupDict: self.assertEqual(astuple(gt), (0, (('Alice', 1), ('Bob', 2)))) self.assertEqual(astuple(gd), (0, {'first': ('Alice', 1), 'second': ('Bob', 2)})) - def test_helper_astuple_builtin_containers(self): + def test_helper_astuple_builtin_object_containers(self): @dataclass class Child: d: object @@ -3242,18 +3242,6 @@ class E: "..D(f=TestReplace.test_recursive_repr_indirection_two" "..E(f=...)))") - def test_recursive_repr_two_attrs(self): - @dataclass - class C: - f: "C" - g: "C" - - c = C(None, None) - c.f = c - c.g = c - self.assertEqual(repr(c), "TestReplace.test_recursive_repr_two_attrs" - "..C(f=..., g=...)") - def test_recursive_repr_misc_attrs(self): @dataclass class C: From f51dd4feb0794b7659f281173da9d8a04317d134 Mon Sep 17 00:00:00 2001 From: Windson yang Date: Tue, 23 Apr 2019 02:46:27 +0800 Subject: [PATCH 046/212] bpo-36683: Rename duplicate test_io_encoding to test_pyio_encoding (GH-12896) --- Lib/test/test_utf8_mode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_utf8_mode.py b/Lib/test/test_utf8_mode.py index 2429b00459be51..bdb93457cfc405 100644 --- a/Lib/test/test_utf8_mode.py +++ b/Lib/test/test_utf8_mode.py @@ -195,7 +195,7 @@ def check_io_encoding(self, module): def test_io_encoding(self): self.check_io_encoding('io') - def test_io_encoding(self): + def test_pyio_encoding(self): self.check_io_encoding('_pyio') def test_locale_getpreferredencoding(self): From 007d0b0188a16273a5850d89857ecef97c1f4595 Mon Sep 17 00:00:00 2001 From: Windson yang Date: Tue, 23 Apr 2019 02:48:12 +0800 Subject: [PATCH 047/212] bpo-36682: Rename duplicate tests in test_sys_setprofile (GH-12895) --- Lib/test/test_sys_setprofile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys_setprofile.py b/Lib/test/test_sys_setprofile.py index c2ecf8eeed9f9a..b64bcbc5b6862b 100644 --- a/Lib/test/test_sys_setprofile.py +++ b/Lib/test/test_sys_setprofile.py @@ -351,7 +351,7 @@ def f(p): (1, 'return', f_ident)]) # Test an invalid call (bpo-34125) - def test_unbound_method_no_args(self): + def test_unbound_method_no_keyword_args(self): kwargs = {} def f(p): dict.get(**kwargs) @@ -360,7 +360,7 @@ def f(p): (1, 'return', f_ident)]) # Test an invalid call (bpo-34125) - def test_unbound_method_invalid_args(self): + def test_unbound_method_invalid_keyword_args(self): kwargs = {} def f(p): dict.get(print, 42, **kwargs) From 3d6f61edb8a6161148b3cf3eeb291408cc91154a Mon Sep 17 00:00:00 2001 From: Windson yang Date: Tue, 23 Apr 2019 02:49:11 +0800 Subject: [PATCH 048/212] bpo-36681: Remove duplicate test_regression_29220 function (GH-12894) --- Lib/test/test_logging.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 1805249e48bcc0..82cbedada47247 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -315,12 +315,6 @@ def test_regression_22386(self): self.assertEqual(logging.getLevelName('INFO'), logging.INFO) self.assertEqual(logging.getLevelName(logging.INFO), 'INFO') - def test_regression_29220(self): - """See issue #29220 for more information.""" - logging.addLevelName(logging.INFO, '') - self.addCleanup(logging.addLevelName, logging.INFO, 'INFO') - self.assertEqual(logging.getLevelName(logging.INFO), '') - def test_issue27935(self): fatal = logging.getLevelName('FATAL') self.assertEqual(fatal, logging.FATAL) From c442b1c486db5cb0aa589b43f73385d9cc5706e3 Mon Sep 17 00:00:00 2001 From: Windson yang Date: Tue, 23 Apr 2019 02:50:24 +0800 Subject: [PATCH 049/212] bpo-36680: Rename duplicate test_source_from_cache_path_like_arg function (GH-12893) --- Lib/test/test_importlib/test_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py index d134e3c3b04dfc..8739eea841d051 100644 --- a/Lib/test/test_importlib/test_util.py +++ b/Lib/test/test_importlib/test_util.py @@ -682,7 +682,7 @@ def test_sep_altsep_and_sep_cache_from_source(self): @unittest.skipIf(sys.implementation.cache_tag is None, 'requires sys.implementation.cache_tag not be None') - def test_source_from_cache_path_like_arg(self): + def test_cache_from_source_path_like_arg(self): path = pathlib.PurePath('foo', 'bar', 'baz', 'qux.py') expect = os.path.join('foo', 'bar', 'baz', '__pycache__', 'qux.{}.pyc'.format(self.tag)) From d437012cdd4a38b5b3d05f139d5f0a28196e4769 Mon Sep 17 00:00:00 2001 From: Windson yang Date: Tue, 23 Apr 2019 02:51:06 +0800 Subject: [PATCH 050/212] bpo-36679: Rename duplicate test_class_getitem function (GH-12892) --- Lib/test/test_genericclass.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_genericclass.py b/Lib/test/test_genericclass.py index 37a87bc6815ec2..27420d4f2bad54 100644 --- a/Lib/test/test_genericclass.py +++ b/Lib/test/test_genericclass.py @@ -158,7 +158,7 @@ def __class_getitem__(*args, **kwargs): self.assertEqual(getitem_args[0], (C, (int, str))) self.assertEqual(getitem_args[1], {}) - def test_class_getitem(self): + def test_class_getitem_format(self): class C: def __class_getitem__(cls, item): return f'C[{item.__name__}]' From 9013ccf6d8037f6ae78145a42d194141cb10d332 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Tue, 23 Apr 2019 00:06:35 -0700 Subject: [PATCH 051/212] bpo-36546: Add statistics.quantiles() (#12710) --- Doc/library/statistics.rst | 54 ++++++- Doc/whatsnew/3.8.rst | 4 + Lib/statistics.py | 57 ++++++- Lib/test/test_statistics.py | 142 ++++++++++++++++++ .../2019-04-06-14-23-00.bpo-36546.YXjbyY.rst | 1 + 5 files changed, 251 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-06-14-23-00.bpo-36546.YXjbyY.rst diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 8bb2bdf7b697de..b62bcfdffd0b39 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -48,6 +48,7 @@ or sample. :func:`median_grouped` Median, or 50th percentile, of grouped data. :func:`mode` Single mode (most common value) of discrete or nominal data. :func:`multimode` List of modes (most common values) of discrete or nomimal data. +:func:`quantiles` Divide data into intervals with equal probability. ======================= =============================================================== Measures of spread @@ -499,6 +500,53 @@ However, for reading convenience, most of the examples show sorted sequences. :func:`pvariance` function as the *mu* parameter to get the variance of a sample. +.. function:: quantiles(dist, *, n=4, method='exclusive') + + Divide *dist* into *n* continuous intervals with equal probability. + Returns a list of ``n - 1`` cut points separating the intervals. + + Set *n* to 4 for quartiles (the default). Set *n* to 10 for deciles. Set + *n* to 100 for percentiles which gives the 99 cuts points that separate + *dist* in to 100 equal sized groups. Raises :exc:`StatisticsError` if *n* + is not least 1. + + The *dist* can be any iterable containing sample data or it can be an + instance of a class that defines an :meth:`~inv_cdf` method. + Raises :exc:`StatisticsError` if there are not at least two data points. + + For sample data, the cut points are linearly interpolated from the + two nearest data points. For example, if a cut point falls one-third + of the distance between two sample values, ``100`` and ``112``, the + cut-point will evaluate to ``104``. Other selection methods may be + offered in the future (for example choose ``100`` as the nearest + value or compute ``106`` as the midpoint). This might matter if + there are too few samples for a given number of cut points. + + If *method* is set to *inclusive*, *dist* is treated as population data. + The minimum value is treated as the 0th percentile and the maximum + value is treated as the 100th percentile. If *dist* is an instance of + a class that defines an :meth:`~inv_cdf` method, setting *method* + has no effect. + + .. doctest:: + + # Decile cut points for empirically sampled data + >>> data = [105, 129, 87, 86, 111, 111, 89, 81, 108, 92, 110, + ... 100, 75, 105, 103, 109, 76, 119, 99, 91, 103, 129, + ... 106, 101, 84, 111, 74, 87, 86, 103, 103, 106, 86, + ... 111, 75, 87, 102, 121, 111, 88, 89, 101, 106, 95, + ... 103, 107, 101, 81, 109, 104] + >>> [round(q, 1) for q in quantiles(data, n=10)] + [81.0, 86.2, 89.0, 99.4, 102.5, 103.6, 106.0, 109.8, 111.0] + + >>> # Quartile cut points for the standard normal distibution + >>> Z = NormalDist() + >>> [round(q, 4) for q in quantiles(Z, n=4)] + [-0.6745, 0.0, 0.6745] + + .. versionadded:: 3.8 + + Exceptions ---------- @@ -606,7 +654,7 @@ of applications in statistics. `_ between two normal distributions, giving a measure of agreement. Returns a value between 0.0 and 1.0 giving `the overlapping area for - two probability density functions + the two probability density functions `_. Instances of :class:`NormalDist` support addition, subtraction, @@ -649,8 +697,8 @@ of applications in statistics. For example, given `historical data for SAT exams `_ showing that scores are normally distributed with a mean of 1060 and a standard deviation of 192, -determine the percentage of students with scores between 1100 and 1200, after -rounding to the nearest whole number: +determine the percentage of students with test scores between 1100 and +1200, after rounding to the nearest whole number: .. doctest:: diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index f866f9ccb8c16f..bd7ad3f87cb504 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -337,6 +337,10 @@ Added :func:`statistics.geometric_mean()` Added :func:`statistics.multimode` that returns a list of the most common values. (Contributed by Raymond Hettinger in :issue:`35892`.) +Added :func:`statistics.quantiles` that divides data or a distribution +in to equiprobable intervals (e.g. quartiles, deciles, or percentiles). +(Contributed by Raymond Hettinger in :issue:`36546`.) + Added :class:`statistics.NormalDist`, a tool for creating and manipulating normal distributions of a random variable. (Contributed by Raymond Hettinger in :issue:`36018`.) diff --git a/Lib/statistics.py b/Lib/statistics.py index 262ad976b65cb2..05edfdf98e06a8 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -7,9 +7,9 @@ Calculating averages -------------------- -================== ============================================= +================== ================================================== Function Description -================== ============================================= +================== ================================================== mean Arithmetic mean (average) of data. geometric_mean Geometric mean of data. harmonic_mean Harmonic mean of data. @@ -19,7 +19,8 @@ median_grouped Median, or 50th percentile, of grouped data. mode Mode (most common value) of data. multimode List of modes (most common values of data). -================== ============================================= +quantiles Divide data into intervals with equal probability. +================== ================================================== Calculate the arithmetic mean ("the average") of data: @@ -78,7 +79,7 @@ """ -__all__ = [ 'StatisticsError', 'NormalDist', +__all__ = [ 'StatisticsError', 'NormalDist', 'quantiles', 'pstdev', 'pvariance', 'stdev', 'variance', 'median', 'median_low', 'median_high', 'median_grouped', 'mean', 'mode', 'multimode', 'harmonic_mean', 'fmean', @@ -562,6 +563,54 @@ def multimode(data): maxcount, mode_items = next(groupby(counts, key=itemgetter(1)), (0, [])) return list(map(itemgetter(0), mode_items)) +def quantiles(dist, *, n=4, method='exclusive'): + '''Divide *dist* into *n* continuous intervals with equal probability. + + Returns a list of (n - 1) cut points separating the intervals. + + Set *n* to 4 for quartiles (the default). Set *n* to 10 for deciles. + Set *n* to 100 for percentiles which gives the 99 cuts points that + separate *dist* in to 100 equal sized groups. + + The *dist* can be any iterable containing sample data or it can be + an instance of a class that defines an inv_cdf() method. For sample + data, the cut points are linearly interpolated between data points. + + If *method* is set to *inclusive*, *dist* is treated as population + data. The minimum value is treated as the 0th percentile and the + maximum value is treated as the 100th percentile. + ''' + # Possible future API extensions: + # quantiles(data, already_sorted=True) + # quantiles(data, cut_points=[0.02, 0.25, 0.50, 0.75, 0.98]) + if n < 1: + raise StatisticsError('n must be at least 1') + if hasattr(dist, 'inv_cdf'): + return [dist.inv_cdf(i / n) for i in range(1, n)] + data = sorted(dist) + ld = len(data) + if ld < 2: + raise StatisticsError('must have at least two data points') + if method == 'inclusive': + m = ld - 1 + result = [] + for i in range(1, n): + j = i * m // n + delta = i*m - j*n + interpolated = (data[j] * (n - delta) + data[j+1] * delta) / n + result.append(interpolated) + return result + if method == 'exclusive': + m = ld + 1 + result = [] + for i in range(1, n): + j = i * m // n # rescale i to m/n + j = 1 if j < 1 else ld-1 if j > ld-1 else j # clamp to 1 .. ld-1 + delta = i*m - j*n # exact integer math + interpolated = (data[j-1] * (n - delta) + data[j] * delta) / n + result.append(interpolated) + return result + raise ValueError(f'Unknown method: {method!r}') # === Measures of spread === diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 4d397eb1265d36..c988d7fd8be7b7 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -3,6 +3,7 @@ """ +import bisect import collections import collections.abc import copy @@ -2038,6 +2039,7 @@ def test_compare_to_variance(self): expected = math.sqrt(statistics.variance(data)) self.assertEqual(self.func(data), expected) + class TestGeometricMean(unittest.TestCase): def test_basics(self): @@ -2126,6 +2128,146 @@ def test_special_values(self): with self.assertRaises(ValueError): geometric_mean([Inf, -Inf]) + +class TestQuantiles(unittest.TestCase): + + def test_specific_cases(self): + # Match results computed by hand and cross-checked + # against the PERCENTILE.EXC function in MS Excel. + quantiles = statistics.quantiles + data = [120, 200, 250, 320, 350] + random.shuffle(data) + for n, expected in [ + (1, []), + (2, [250.0]), + (3, [200.0, 320.0]), + (4, [160.0, 250.0, 335.0]), + (5, [136.0, 220.0, 292.0, 344.0]), + (6, [120.0, 200.0, 250.0, 320.0, 350.0]), + (8, [100.0, 160.0, 212.5, 250.0, 302.5, 335.0, 357.5]), + (10, [88.0, 136.0, 184.0, 220.0, 250.0, 292.0, 326.0, 344.0, 362.0]), + (12, [80.0, 120.0, 160.0, 200.0, 225.0, 250.0, 285.0, 320.0, 335.0, + 350.0, 365.0]), + (15, [72.0, 104.0, 136.0, 168.0, 200.0, 220.0, 240.0, 264.0, 292.0, + 320.0, 332.0, 344.0, 356.0, 368.0]), + ]: + self.assertEqual(expected, quantiles(data, n=n)) + self.assertEqual(len(quantiles(data, n=n)), n - 1) + self.assertEqual(list(map(float, expected)), + quantiles(map(Decimal, data), n=n)) + self.assertEqual(list(map(Decimal, expected)), + quantiles(map(Decimal, data), n=n)) + self.assertEqual(list(map(Fraction, expected)), + quantiles(map(Fraction, data), n=n)) + # Invariant under tranlation and scaling + def f(x): + return 3.5 * x - 1234.675 + exp = list(map(f, expected)) + act = quantiles(map(f, data), n=n) + self.assertTrue(all(math.isclose(e, a) for e, a in zip(exp, act))) + # Quartiles of a standard normal distribution + for n, expected in [ + (1, []), + (2, [0.0]), + (3, [-0.4307, 0.4307]), + (4 ,[-0.6745, 0.0, 0.6745]), + ]: + actual = quantiles(statistics.NormalDist(), n=n) + self.assertTrue(all(math.isclose(e, a, abs_tol=0.0001) + for e, a in zip(expected, actual))) + + def test_specific_cases_inclusive(self): + # Match results computed by hand and cross-checked + # against the PERCENTILE.INC function in MS Excel + # and against the quaatile() function in SciPy. + quantiles = statistics.quantiles + data = [100, 200, 400, 800] + random.shuffle(data) + for n, expected in [ + (1, []), + (2, [300.0]), + (3, [200.0, 400.0]), + (4, [175.0, 300.0, 500.0]), + (5, [160.0, 240.0, 360.0, 560.0]), + (6, [150.0, 200.0, 300.0, 400.0, 600.0]), + (8, [137.5, 175, 225.0, 300.0, 375.0, 500.0,650.0]), + (10, [130.0, 160.0, 190.0, 240.0, 300.0, 360.0, 440.0, 560.0, 680.0]), + (12, [125.0, 150.0, 175.0, 200.0, 250.0, 300.0, 350.0, 400.0, + 500.0, 600.0, 700.0]), + (15, [120.0, 140.0, 160.0, 180.0, 200.0, 240.0, 280.0, 320.0, 360.0, + 400.0, 480.0, 560.0, 640.0, 720.0]), + ]: + self.assertEqual(expected, quantiles(data, n=n, method="inclusive")) + self.assertEqual(len(quantiles(data, n=n, method="inclusive")), n - 1) + self.assertEqual(list(map(float, expected)), + quantiles(map(Decimal, data), n=n, method="inclusive")) + self.assertEqual(list(map(Decimal, expected)), + quantiles(map(Decimal, data), n=n, method="inclusive")) + self.assertEqual(list(map(Fraction, expected)), + quantiles(map(Fraction, data), n=n, method="inclusive")) + # Invariant under tranlation and scaling + def f(x): + return 3.5 * x - 1234.675 + exp = list(map(f, expected)) + act = quantiles(map(f, data), n=n, method="inclusive") + self.assertTrue(all(math.isclose(e, a) for e, a in zip(exp, act))) + # Quartiles of a standard normal distribution + for n, expected in [ + (1, []), + (2, [0.0]), + (3, [-0.4307, 0.4307]), + (4 ,[-0.6745, 0.0, 0.6745]), + ]: + actual = quantiles(statistics.NormalDist(), n=n, method="inclusive") + self.assertTrue(all(math.isclose(e, a, abs_tol=0.0001) + for e, a in zip(expected, actual))) + + def test_equal_sized_groups(self): + quantiles = statistics.quantiles + total = 10_000 + data = [random.expovariate(0.2) for i in range(total)] + while len(set(data)) != total: + data.append(random.expovariate(0.2)) + data.sort() + + # Cases where the group size exactly divides the total + for n in (1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000): + group_size = total // n + self.assertEqual( + [bisect.bisect(data, q) for q in quantiles(data, n=n)], + list(range(group_size, total, group_size))) + + # When the group sizes can't be exactly equal, they should + # differ by no more than one + for n in (13, 19, 59, 109, 211, 571, 1019, 1907, 5261, 9769): + group_sizes = {total // n, total // n + 1} + pos = [bisect.bisect(data, q) for q in quantiles(data, n=n)] + sizes = {q - p for p, q in zip(pos, pos[1:])} + self.assertTrue(sizes <= group_sizes) + + def test_error_cases(self): + quantiles = statistics.quantiles + StatisticsError = statistics.StatisticsError + with self.assertRaises(TypeError): + quantiles() # Missing arguments + with self.assertRaises(TypeError): + quantiles([10, 20, 30], 13, n=4) # Too many arguments + with self.assertRaises(TypeError): + quantiles([10, 20, 30], 4) # n is a positional argument + with self.assertRaises(StatisticsError): + quantiles([10, 20, 30], n=0) # n is zero + with self.assertRaises(StatisticsError): + quantiles([10, 20, 30], n=-1) # n is negative + with self.assertRaises(TypeError): + quantiles([10, 20, 30], n=1.5) # n is not an integer + with self.assertRaises(ValueError): + quantiles([10, 20, 30], method='X') # method is unknown + with self.assertRaises(StatisticsError): + quantiles([10], n=4) # not enough data points + with self.assertRaises(TypeError): + quantiles([10, None, 30], n=4) # data is non-numeric + + class TestNormalDist(unittest.TestCase): # General note on precision: The pdf(), cdf(), and overlap() methods diff --git a/Misc/NEWS.d/next/Library/2019-04-06-14-23-00.bpo-36546.YXjbyY.rst b/Misc/NEWS.d/next/Library/2019-04-06-14-23-00.bpo-36546.YXjbyY.rst new file mode 100644 index 00000000000000..c69aadf3b69e8e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-06-14-23-00.bpo-36546.YXjbyY.rst @@ -0,0 +1 @@ +Add statistics.quantiles() From b4c7f39bbf8f16a0da758601b33aec3ba531c8d6 Mon Sep 17 00:00:00 2001 From: Jakub Molinski Date: Tue, 23 Apr 2019 10:30:30 +0200 Subject: [PATCH 052/212] Add module specification: itemgetter -> operator.itemgetter (GH-12823) --- Doc/library/itertools.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 3d4e5836cf205e..b3a0a5f5192da1 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -827,7 +827,7 @@ which incur interpreter overhead. "List unique elements, preserving order. Remember only the element just seen." # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B # unique_justseen('ABBCcAD', str.lower) --> A B C A D - return map(next, map(itemgetter(1), groupby(iterable, key))) + return map(next, map(operator.itemgetter(1), groupby(iterable, key))) def iter_except(func, exception, first=None): """ Call a function repeatedly until an exception is raised. From 39baace622564867f55cea49483dd1443b8655e3 Mon Sep 17 00:00:00 2001 From: jkleint Date: Tue, 23 Apr 2019 01:34:29 -0700 Subject: [PATCH 053/212] Document that TestCase.assertCountEqual() can take iterables (GH-686) --- Lib/unittest/case.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 972a4658b17ba8..8ff2546fc207cc 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -1244,9 +1244,8 @@ def assertDictContainsSubset(self, subset, dictionary, msg=None): def assertCountEqual(self, first, second, msg=None): - """An unordered sequence comparison asserting that the same elements, - regardless of order. If the same element occurs more than once, - it verifies that the elements occur the same number of times. + """Asserts that two iterables have the same elements, the same number of + times, without regard to order. self.assertEqual(Counter(list(first)), Counter(list(second))) From 7280048690244e73b13f4f68b96c244bcb5434e8 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Tue, 23 Apr 2019 01:35:16 -0700 Subject: [PATCH 054/212] bpo-35904: Add missing fmean() entry to the summary table (GH-12919) --- Lib/statistics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/statistics.py b/Lib/statistics.py index 05edfdf98e06a8..4a0978cbcd9c89 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -11,6 +11,7 @@ Function Description ================== ================================================== mean Arithmetic mean (average) of data. +fmean Fast, floating point arithmetic mean. geometric_mean Geometric mean of data. harmonic_mean Harmonic mean of data. median Median (middle value) of data. From fb8c7d53326d137785ca311bfc48c8284da46770 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Tue, 23 Apr 2019 01:46:18 -0700 Subject: [PATCH 055/212] bpo-36018: Make "seed" into a keyword only argument (GH-12921) --- Doc/library/statistics.rst | 2 +- Lib/statistics.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index b62bcfdffd0b39..fb7df4e7188a07 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -607,7 +607,7 @@ of applications in statistics. :exc:`StatisticsError` because it takes at least one point to estimate a central value and at least two points to estimate dispersion. - .. method:: NormalDist.samples(n, seed=None) + .. method:: NormalDist.samples(n, *, seed=None) Generates *n* random samples for a given mean and standard deviation. Returns a :class:`list` of :class:`float` values. diff --git a/Lib/statistics.py b/Lib/statistics.py index 4a0978cbcd9c89..19db8e82801013 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -797,7 +797,7 @@ def from_samples(cls, data): xbar = fmean(data) return cls(xbar, stdev(data, xbar)) - def samples(self, n, seed=None): + def samples(self, n, *, seed=None): 'Generate *n* samples for a given mean and standard deviation.' gauss = random.gauss if seed is None else random.Random(seed).gauss mu, sigma = self.mu, self.sigma From 84b4784f12d4b8aab2b4cc5a4f5b64f45ec3e5d4 Mon Sep 17 00:00:00 2001 From: tyomitch Date: Tue, 23 Apr 2019 12:29:57 +0300 Subject: [PATCH 056/212] use `const` in graminit.c (GH-12713) --- Include/grammar.h | 10 +- Parser/pgen/grammar.py | 6 +- Python/graminit.c | 820 ++++++++++++++++++++--------------------- 3 files changed, 418 insertions(+), 418 deletions(-) diff --git a/Include/grammar.h b/Include/grammar.h index 7a6182bb76d57c..faccae4657ee9c 100644 --- a/Include/grammar.h +++ b/Include/grammar.h @@ -13,7 +13,7 @@ extern "C" { typedef struct { int lb_type; - char *lb_str; + const char *lb_str; } label; #define EMPTY 0 /* Label number 0 is by definition the empty label */ @@ -22,7 +22,7 @@ typedef struct { typedef struct { int ll_nlabels; - label *ll_label; + const label *ll_label; } labellist; /* An arc from one state to another */ @@ -36,7 +36,7 @@ typedef struct { typedef struct { int s_narcs; - arc *s_arc; /* Array of arcs */ + const arc *s_arc; /* Array of arcs */ /* Optional accelerators */ int s_lower; /* Lowest label index */ @@ -59,8 +59,8 @@ typedef struct { typedef struct { int g_ndfas; - dfa *g_dfa; /* Array of DFAs */ - labellist g_ll; + const dfa *g_dfa; /* Array of DFAs */ + const labellist g_ll; int g_start; /* Start symbol of the grammar */ int g_accel; /* Set if accelerators present */ } grammar; diff --git a/Parser/pgen/grammar.py b/Parser/pgen/grammar.py index 1ab9434fa887a6..5cd652426b4755 100644 --- a/Parser/pgen/grammar.py +++ b/Parser/pgen/grammar.py @@ -76,7 +76,7 @@ def produce_graminit_c(self, writer): def print_labels(self, writer): writer( - "static label labels[{n_labels}] = {{\n".format(n_labels=len(self.labels)) + "static const label labels[{n_labels}] = {{\n".format(n_labels=len(self.labels)) ) for label, name in self.labels: label_name = '"{}"'.format(name) if name is not None else 0 @@ -89,7 +89,7 @@ def print_labels(self, writer): def print_dfas(self, writer): self.print_states(writer) - writer("static dfa dfas[{}] = {{\n".format(len(self.dfas))) + writer("static const dfa dfas[{}] = {{\n".format(len(self.dfas))) for dfaindex, dfa_elem in enumerate(self.dfas.items()): symbol, (dfa, first_sets) = dfa_elem writer( @@ -131,7 +131,7 @@ def print_arcs(self, write, dfaindex, states): for stateindex, state in enumerate(states): narcs = len(state) write( - "static arc arcs_{dfa_index}_{state_index}[{n_arcs}] = {{\n".format( + "static const arc arcs_{dfa_index}_{state_index}[{n_arcs}] = {{\n".format( dfa_index=dfaindex, state_index=stateindex, n_arcs=narcs ) ) diff --git a/Python/graminit.c b/Python/graminit.c index cd90032417004c..96e32aa8fd338e 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -2,15 +2,15 @@ #include "grammar.h" grammar _PyParser_Grammar; -static arc arcs_0_0[3] = { +static const arc arcs_0_0[3] = { {2, 1}, {3, 2}, {4, 1}, }; -static arc arcs_0_1[1] = { +static const arc arcs_0_1[1] = { {0, 1}, }; -static arc arcs_0_2[1] = { +static const arc arcs_0_2[1] = { {2, 1}, }; static state states_0[3] = { @@ -18,26 +18,26 @@ static state states_0[3] = { {1, arcs_0_1}, {1, arcs_0_2}, }; -static arc arcs_1_0[3] = { +static const arc arcs_1_0[3] = { {44, 1}, {2, 0}, {45, 0}, }; -static arc arcs_1_1[1] = { +static const arc arcs_1_1[1] = { {0, 1}, }; static state states_1[2] = { {3, arcs_1_0}, {1, arcs_1_1}, }; -static arc arcs_2_0[1] = { +static const arc arcs_2_0[1] = { {47, 1}, }; -static arc arcs_2_1[2] = { +static const arc arcs_2_1[2] = { {44, 2}, {2, 1}, }; -static arc arcs_2_2[1] = { +static const arc arcs_2_2[1] = { {0, 2}, }; static state states_2[3] = { @@ -45,27 +45,27 @@ static state states_2[3] = { {2, arcs_2_1}, {1, arcs_2_2}, }; -static arc arcs_3_0[1] = { +static const arc arcs_3_0[1] = { {10, 1}, }; -static arc arcs_3_1[1] = { +static const arc arcs_3_1[1] = { {49, 2}, }; -static arc arcs_3_2[2] = { +static const arc arcs_3_2[2] = { {5, 3}, {2, 4}, }; -static arc arcs_3_3[2] = { +static const arc arcs_3_3[2] = { {50, 5}, {51, 6}, }; -static arc arcs_3_4[1] = { +static const arc arcs_3_4[1] = { {0, 4}, }; -static arc arcs_3_5[1] = { +static const arc arcs_3_5[1] = { {2, 4}, }; -static arc arcs_3_6[1] = { +static const arc arcs_3_6[1] = { {50, 5}, }; static state states_3[7] = { @@ -77,10 +77,10 @@ static state states_3[7] = { {1, arcs_3_5}, {1, arcs_3_6}, }; -static arc arcs_4_0[1] = { +static const arc arcs_4_0[1] = { {48, 1}, }; -static arc arcs_4_1[2] = { +static const arc arcs_4_1[2] = { {48, 1}, {0, 1}, }; @@ -88,15 +88,15 @@ static state states_4[2] = { {1, arcs_4_0}, {2, arcs_4_1}, }; -static arc arcs_5_0[1] = { +static const arc arcs_5_0[1] = { {52, 1}, }; -static arc arcs_5_1[3] = { +static const arc arcs_5_1[3] = { {54, 2}, {55, 2}, {56, 2}, }; -static arc arcs_5_2[1] = { +static const arc arcs_5_2[1] = { {0, 2}, }; static state states_5[3] = { @@ -104,13 +104,13 @@ static state states_5[3] = { {3, arcs_5_1}, {1, arcs_5_2}, }; -static arc arcs_6_0[1] = { +static const arc arcs_6_0[1] = { {38, 1}, }; -static arc arcs_6_1[1] = { +static const arc arcs_6_1[1] = { {56, 2}, }; -static arc arcs_6_2[1] = { +static const arc arcs_6_2[1] = { {0, 2}, }; static state states_6[3] = { @@ -118,33 +118,33 @@ static state states_6[3] = { {1, arcs_6_1}, {1, arcs_6_2}, }; -static arc arcs_7_0[1] = { +static const arc arcs_7_0[1] = { {19, 1}, }; -static arc arcs_7_1[1] = { +static const arc arcs_7_1[1] = { {40, 2}, }; -static arc arcs_7_2[1] = { +static const arc arcs_7_2[1] = { {57, 3}, }; -static arc arcs_7_3[2] = { +static const arc arcs_7_3[2] = { {58, 4}, {59, 5}, }; -static arc arcs_7_4[1] = { +static const arc arcs_7_4[1] = { {60, 6}, }; -static arc arcs_7_5[2] = { +static const arc arcs_7_5[2] = { {61, 7}, {62, 8}, }; -static arc arcs_7_6[1] = { +static const arc arcs_7_6[1] = { {59, 5}, }; -static arc arcs_7_7[1] = { +static const arc arcs_7_7[1] = { {62, 8}, }; -static arc arcs_7_8[1] = { +static const arc arcs_7_8[1] = { {0, 8}, }; static state states_7[9] = { @@ -158,17 +158,17 @@ static state states_7[9] = { {1, arcs_7_7}, {1, arcs_7_8}, }; -static arc arcs_8_0[1] = { +static const arc arcs_8_0[1] = { {5, 1}, }; -static arc arcs_8_1[2] = { +static const arc arcs_8_1[2] = { {50, 2}, {63, 3}, }; -static arc arcs_8_2[1] = { +static const arc arcs_8_2[1] = { {0, 2}, }; -static arc arcs_8_3[1] = { +static const arc arcs_8_3[1] = { {50, 2}, }; static state states_8[4] = { @@ -177,113 +177,113 @@ static state states_8[4] = { {1, arcs_8_2}, {1, arcs_8_3}, }; -static arc arcs_9_0[3] = { +static const arc arcs_9_0[3] = { {6, 1}, {64, 2}, {65, 3}, }; -static arc arcs_9_1[4] = { +static const arc arcs_9_1[4] = { {66, 4}, {61, 5}, {65, 6}, {0, 1}, }; -static arc arcs_9_2[1] = { +static const arc arcs_9_2[1] = { {65, 7}, }; -static arc arcs_9_3[4] = { +static const arc arcs_9_3[4] = { {66, 8}, {67, 9}, {61, 5}, {0, 3}, }; -static arc arcs_9_4[4] = { +static const arc arcs_9_4[4] = { {64, 2}, {61, 10}, {65, 11}, {0, 4}, }; -static arc arcs_9_5[1] = { +static const arc arcs_9_5[1] = { {0, 5}, }; -static arc arcs_9_6[3] = { +static const arc arcs_9_6[3] = { {66, 4}, {61, 5}, {0, 6}, }; -static arc arcs_9_7[3] = { +static const arc arcs_9_7[3] = { {66, 12}, {61, 5}, {0, 7}, }; -static arc arcs_9_8[5] = { +static const arc arcs_9_8[5] = { {6, 13}, {64, 2}, {61, 14}, {65, 3}, {0, 8}, }; -static arc arcs_9_9[1] = { +static const arc arcs_9_9[1] = { {60, 15}, }; -static arc arcs_9_10[3] = { +static const arc arcs_9_10[3] = { {64, 2}, {65, 11}, {0, 10}, }; -static arc arcs_9_11[4] = { +static const arc arcs_9_11[4] = { {66, 4}, {67, 16}, {61, 5}, {0, 11}, }; -static arc arcs_9_12[2] = { +static const arc arcs_9_12[2] = { {61, 5}, {0, 12}, }; -static arc arcs_9_13[4] = { +static const arc arcs_9_13[4] = { {66, 17}, {61, 5}, {65, 18}, {0, 13}, }; -static arc arcs_9_14[4] = { +static const arc arcs_9_14[4] = { {6, 13}, {64, 2}, {65, 3}, {0, 14}, }; -static arc arcs_9_15[3] = { +static const arc arcs_9_15[3] = { {66, 8}, {61, 5}, {0, 15}, }; -static arc arcs_9_16[1] = { +static const arc arcs_9_16[1] = { {60, 6}, }; -static arc arcs_9_17[4] = { +static const arc arcs_9_17[4] = { {64, 2}, {61, 19}, {65, 20}, {0, 17}, }; -static arc arcs_9_18[3] = { +static const arc arcs_9_18[3] = { {66, 17}, {61, 5}, {0, 18}, }; -static arc arcs_9_19[3] = { +static const arc arcs_9_19[3] = { {64, 2}, {65, 20}, {0, 19}, }; -static arc arcs_9_20[4] = { +static const arc arcs_9_20[4] = { {66, 17}, {67, 21}, {61, 5}, {0, 20}, }; -static arc arcs_9_21[1] = { +static const arc arcs_9_21[1] = { {60, 18}, }; static state states_9[22] = { @@ -310,17 +310,17 @@ static state states_9[22] = { {4, arcs_9_20}, {1, arcs_9_21}, }; -static arc arcs_10_0[1] = { +static const arc arcs_10_0[1] = { {40, 1}, }; -static arc arcs_10_1[2] = { +static const arc arcs_10_1[2] = { {59, 2}, {0, 1}, }; -static arc arcs_10_2[1] = { +static const arc arcs_10_2[1] = { {60, 3}, }; -static arc arcs_10_3[1] = { +static const arc arcs_10_3[1] = { {0, 3}, }; static state states_10[4] = { @@ -329,81 +329,81 @@ static state states_10[4] = { {1, arcs_10_2}, {1, arcs_10_3}, }; -static arc arcs_11_0[3] = { +static const arc arcs_11_0[3] = { {6, 1}, {64, 2}, {69, 3}, }; -static arc arcs_11_1[3] = { +static const arc arcs_11_1[3] = { {66, 4}, {69, 5}, {0, 1}, }; -static arc arcs_11_2[1] = { +static const arc arcs_11_2[1] = { {69, 6}, }; -static arc arcs_11_3[3] = { +static const arc arcs_11_3[3] = { {66, 7}, {67, 8}, {0, 3}, }; -static arc arcs_11_4[3] = { +static const arc arcs_11_4[3] = { {64, 2}, {69, 9}, {0, 4}, }; -static arc arcs_11_5[2] = { +static const arc arcs_11_5[2] = { {66, 4}, {0, 5}, }; -static arc arcs_11_6[2] = { +static const arc arcs_11_6[2] = { {66, 10}, {0, 6}, }; -static arc arcs_11_7[4] = { +static const arc arcs_11_7[4] = { {6, 11}, {64, 2}, {69, 3}, {0, 7}, }; -static arc arcs_11_8[1] = { +static const arc arcs_11_8[1] = { {60, 12}, }; -static arc arcs_11_9[3] = { +static const arc arcs_11_9[3] = { {66, 4}, {67, 13}, {0, 9}, }; -static arc arcs_11_10[1] = { +static const arc arcs_11_10[1] = { {0, 10}, }; -static arc arcs_11_11[3] = { +static const arc arcs_11_11[3] = { {66, 14}, {69, 15}, {0, 11}, }; -static arc arcs_11_12[2] = { +static const arc arcs_11_12[2] = { {66, 7}, {0, 12}, }; -static arc arcs_11_13[1] = { +static const arc arcs_11_13[1] = { {60, 5}, }; -static arc arcs_11_14[3] = { +static const arc arcs_11_14[3] = { {64, 2}, {69, 16}, {0, 14}, }; -static arc arcs_11_15[2] = { +static const arc arcs_11_15[2] = { {66, 14}, {0, 15}, }; -static arc arcs_11_16[3] = { +static const arc arcs_11_16[3] = { {66, 14}, {67, 17}, {0, 16}, }; -static arc arcs_11_17[1] = { +static const arc arcs_11_17[1] = { {60, 15}, }; static state states_11[18] = { @@ -426,39 +426,39 @@ static state states_11[18] = { {3, arcs_11_16}, {1, arcs_11_17}, }; -static arc arcs_12_0[1] = { +static const arc arcs_12_0[1] = { {40, 1}, }; -static arc arcs_12_1[1] = { +static const arc arcs_12_1[1] = { {0, 1}, }; static state states_12[2] = { {1, arcs_12_0}, {1, arcs_12_1}, }; -static arc arcs_13_0[2] = { +static const arc arcs_13_0[2] = { {3, 1}, {4, 1}, }; -static arc arcs_13_1[1] = { +static const arc arcs_13_1[1] = { {0, 1}, }; static state states_13[2] = { {2, arcs_13_0}, {1, arcs_13_1}, }; -static arc arcs_14_0[1] = { +static const arc arcs_14_0[1] = { {70, 1}, }; -static arc arcs_14_1[2] = { +static const arc arcs_14_1[2] = { {71, 2}, {2, 3}, }; -static arc arcs_14_2[2] = { +static const arc arcs_14_2[2] = { {2, 3}, {70, 1}, }; -static arc arcs_14_3[1] = { +static const arc arcs_14_3[1] = { {0, 3}, }; static state states_14[4] = { @@ -467,7 +467,7 @@ static state states_14[4] = { {2, arcs_14_2}, {1, arcs_14_3}, }; -static arc arcs_15_0[8] = { +static const arc arcs_15_0[8] = { {72, 1}, {73, 1}, {74, 1}, @@ -477,34 +477,34 @@ static arc arcs_15_0[8] = { {78, 1}, {79, 1}, }; -static arc arcs_15_1[1] = { +static const arc arcs_15_1[1] = { {0, 1}, }; static state states_15[2] = { {8, arcs_15_0}, {1, arcs_15_1}, }; -static arc arcs_16_0[1] = { +static const arc arcs_16_0[1] = { {80, 1}, }; -static arc arcs_16_1[4] = { +static const arc arcs_16_1[4] = { {67, 2}, {81, 3}, {82, 4}, {0, 1}, }; -static arc arcs_16_2[2] = { +static const arc arcs_16_2[2] = { {80, 5}, {83, 5}, }; -static arc arcs_16_3[1] = { +static const arc arcs_16_3[1] = { {0, 3}, }; -static arc arcs_16_4[2] = { +static const arc arcs_16_4[2] = { {47, 3}, {83, 3}, }; -static arc arcs_16_5[3] = { +static const arc arcs_16_5[3] = { {67, 2}, {61, 3}, {0, 5}, @@ -517,21 +517,21 @@ static state states_16[6] = { {2, arcs_16_4}, {3, arcs_16_5}, }; -static arc arcs_17_0[1] = { +static const arc arcs_17_0[1] = { {59, 1}, }; -static arc arcs_17_1[1] = { +static const arc arcs_17_1[1] = { {60, 2}, }; -static arc arcs_17_2[2] = { +static const arc arcs_17_2[2] = { {67, 3}, {0, 2}, }; -static arc arcs_17_3[2] = { +static const arc arcs_17_3[2] = { {47, 4}, {83, 4}, }; -static arc arcs_17_4[1] = { +static const arc arcs_17_4[1] = { {0, 4}, }; static state states_17[5] = { @@ -541,15 +541,15 @@ static state states_17[5] = { {2, arcs_17_3}, {1, arcs_17_4}, }; -static arc arcs_18_0[2] = { +static const arc arcs_18_0[2] = { {84, 1}, {60, 1}, }; -static arc arcs_18_1[2] = { +static const arc arcs_18_1[2] = { {66, 2}, {0, 1}, }; -static arc arcs_18_2[3] = { +static const arc arcs_18_2[3] = { {84, 1}, {60, 1}, {0, 2}, @@ -559,7 +559,7 @@ static state states_18[3] = { {2, arcs_18_1}, {3, arcs_18_2}, }; -static arc arcs_19_0[13] = { +static const arc arcs_19_0[13] = { {85, 1}, {86, 1}, {87, 1}, @@ -574,20 +574,20 @@ static arc arcs_19_0[13] = { {96, 1}, {97, 1}, }; -static arc arcs_19_1[1] = { +static const arc arcs_19_1[1] = { {0, 1}, }; static state states_19[2] = { {13, arcs_19_0}, {1, arcs_19_1}, }; -static arc arcs_20_0[1] = { +static const arc arcs_20_0[1] = { {20, 1}, }; -static arc arcs_20_1[1] = { +static const arc arcs_20_1[1] = { {98, 2}, }; -static arc arcs_20_2[1] = { +static const arc arcs_20_2[1] = { {0, 2}, }; static state states_20[3] = { @@ -595,58 +595,58 @@ static state states_20[3] = { {1, arcs_20_1}, {1, arcs_20_2}, }; -static arc arcs_21_0[1] = { +static const arc arcs_21_0[1] = { {29, 1}, }; -static arc arcs_21_1[1] = { +static const arc arcs_21_1[1] = { {0, 1}, }; static state states_21[2] = { {1, arcs_21_0}, {1, arcs_21_1}, }; -static arc arcs_22_0[5] = { +static const arc arcs_22_0[5] = { {99, 1}, {100, 1}, {101, 1}, {102, 1}, {103, 1}, }; -static arc arcs_22_1[1] = { +static const arc arcs_22_1[1] = { {0, 1}, }; static state states_22[2] = { {5, arcs_22_0}, {1, arcs_22_1}, }; -static arc arcs_23_0[1] = { +static const arc arcs_23_0[1] = { {16, 1}, }; -static arc arcs_23_1[1] = { +static const arc arcs_23_1[1] = { {0, 1}, }; static state states_23[2] = { {1, arcs_23_0}, {1, arcs_23_1}, }; -static arc arcs_24_0[1] = { +static const arc arcs_24_0[1] = { {18, 1}, }; -static arc arcs_24_1[1] = { +static const arc arcs_24_1[1] = { {0, 1}, }; static state states_24[2] = { {1, arcs_24_0}, {1, arcs_24_1}, }; -static arc arcs_25_0[1] = { +static const arc arcs_25_0[1] = { {31, 1}, }; -static arc arcs_25_1[2] = { +static const arc arcs_25_1[2] = { {80, 2}, {0, 1}, }; -static arc arcs_25_2[1] = { +static const arc arcs_25_2[1] = { {0, 2}, }; static state states_25[3] = { @@ -654,31 +654,31 @@ static state states_25[3] = { {2, arcs_25_1}, {1, arcs_25_2}, }; -static arc arcs_26_0[1] = { +static const arc arcs_26_0[1] = { {83, 1}, }; -static arc arcs_26_1[1] = { +static const arc arcs_26_1[1] = { {0, 1}, }; static state states_26[2] = { {1, arcs_26_0}, {1, arcs_26_1}, }; -static arc arcs_27_0[1] = { +static const arc arcs_27_0[1] = { {30, 1}, }; -static arc arcs_27_1[2] = { +static const arc arcs_27_1[2] = { {60, 2}, {0, 1}, }; -static arc arcs_27_2[2] = { +static const arc arcs_27_2[2] = { {22, 3}, {0, 2}, }; -static arc arcs_27_3[1] = { +static const arc arcs_27_3[1] = { {60, 4}, }; -static arc arcs_27_4[1] = { +static const arc arcs_27_4[1] = { {0, 4}, }; static state states_27[5] = { @@ -688,24 +688,24 @@ static state states_27[5] = { {1, arcs_27_3}, {1, arcs_27_4}, }; -static arc arcs_28_0[2] = { +static const arc arcs_28_0[2] = { {104, 1}, {105, 1}, }; -static arc arcs_28_1[1] = { +static const arc arcs_28_1[1] = { {0, 1}, }; static state states_28[2] = { {2, arcs_28_0}, {1, arcs_28_1}, }; -static arc arcs_29_0[1] = { +static const arc arcs_29_0[1] = { {25, 1}, }; -static arc arcs_29_1[1] = { +static const arc arcs_29_1[1] = { {106, 2}, }; -static arc arcs_29_2[1] = { +static const arc arcs_29_2[1] = { {0, 2}, }; static state states_29[3] = { @@ -713,35 +713,35 @@ static state states_29[3] = { {1, arcs_29_1}, {1, arcs_29_2}, }; -static arc arcs_30_0[1] = { +static const arc arcs_30_0[1] = { {22, 1}, }; -static arc arcs_30_1[3] = { +static const arc arcs_30_1[3] = { {107, 2}, {9, 2}, {49, 3}, }; -static arc arcs_30_2[4] = { +static const arc arcs_30_2[4] = { {107, 2}, {9, 2}, {25, 4}, {49, 3}, }; -static arc arcs_30_3[1] = { +static const arc arcs_30_3[1] = { {25, 4}, }; -static arc arcs_30_4[3] = { +static const arc arcs_30_4[3] = { {5, 5}, {6, 6}, {108, 6}, }; -static arc arcs_30_5[1] = { +static const arc arcs_30_5[1] = { {108, 7}, }; -static arc arcs_30_6[1] = { +static const arc arcs_30_6[1] = { {0, 6}, }; -static arc arcs_30_7[1] = { +static const arc arcs_30_7[1] = { {50, 6}, }; static state states_30[8] = { @@ -754,17 +754,17 @@ static state states_30[8] = { {1, arcs_30_6}, {1, arcs_30_7}, }; -static arc arcs_31_0[1] = { +static const arc arcs_31_0[1] = { {40, 1}, }; -static arc arcs_31_1[2] = { +static const arc arcs_31_1[2] = { {110, 2}, {0, 1}, }; -static arc arcs_31_2[1] = { +static const arc arcs_31_2[1] = { {40, 3}, }; -static arc arcs_31_3[1] = { +static const arc arcs_31_3[1] = { {0, 3}, }; static state states_31[4] = { @@ -773,17 +773,17 @@ static state states_31[4] = { {1, arcs_31_2}, {1, arcs_31_3}, }; -static arc arcs_32_0[1] = { +static const arc arcs_32_0[1] = { {49, 1}, }; -static arc arcs_32_1[2] = { +static const arc arcs_32_1[2] = { {110, 2}, {0, 1}, }; -static arc arcs_32_2[1] = { +static const arc arcs_32_2[1] = { {40, 3}, }; -static arc arcs_32_3[1] = { +static const arc arcs_32_3[1] = { {0, 3}, }; static state states_32[4] = { @@ -792,14 +792,14 @@ static state states_32[4] = { {1, arcs_32_2}, {1, arcs_32_3}, }; -static arc arcs_33_0[1] = { +static const arc arcs_33_0[1] = { {109, 1}, }; -static arc arcs_33_1[2] = { +static const arc arcs_33_1[2] = { {66, 2}, {0, 1}, }; -static arc arcs_33_2[2] = { +static const arc arcs_33_2[2] = { {109, 1}, {0, 2}, }; @@ -808,10 +808,10 @@ static state states_33[3] = { {2, arcs_33_1}, {2, arcs_33_2}, }; -static arc arcs_34_0[1] = { +static const arc arcs_34_0[1] = { {111, 1}, }; -static arc arcs_34_1[2] = { +static const arc arcs_34_1[2] = { {66, 0}, {0, 1}, }; @@ -819,10 +819,10 @@ static state states_34[2] = { {1, arcs_34_0}, {2, arcs_34_1}, }; -static arc arcs_35_0[1] = { +static const arc arcs_35_0[1] = { {40, 1}, }; -static arc arcs_35_1[2] = { +static const arc arcs_35_1[2] = { {107, 0}, {0, 1}, }; @@ -830,13 +830,13 @@ static state states_35[2] = { {1, arcs_35_0}, {2, arcs_35_1}, }; -static arc arcs_36_0[1] = { +static const arc arcs_36_0[1] = { {23, 1}, }; -static arc arcs_36_1[1] = { +static const arc arcs_36_1[1] = { {40, 2}, }; -static arc arcs_36_2[2] = { +static const arc arcs_36_2[2] = { {66, 1}, {0, 2}, }; @@ -845,13 +845,13 @@ static state states_36[3] = { {1, arcs_36_1}, {2, arcs_36_2}, }; -static arc arcs_37_0[1] = { +static const arc arcs_37_0[1] = { {27, 1}, }; -static arc arcs_37_1[1] = { +static const arc arcs_37_1[1] = { {40, 2}, }; -static arc arcs_37_2[2] = { +static const arc arcs_37_2[2] = { {66, 1}, {0, 2}, }; @@ -860,20 +860,20 @@ static state states_37[3] = { {1, arcs_37_1}, {2, arcs_37_2}, }; -static arc arcs_38_0[1] = { +static const arc arcs_38_0[1] = { {15, 1}, }; -static arc arcs_38_1[1] = { +static const arc arcs_38_1[1] = { {60, 2}, }; -static arc arcs_38_2[2] = { +static const arc arcs_38_2[2] = { {66, 3}, {0, 2}, }; -static arc arcs_38_3[1] = { +static const arc arcs_38_3[1] = { {60, 4}, }; -static arc arcs_38_4[1] = { +static const arc arcs_38_4[1] = { {0, 4}, }; static state states_38[5] = { @@ -883,7 +883,7 @@ static state states_38[5] = { {1, arcs_38_3}, {1, arcs_38_4}, }; -static arc arcs_39_0[9] = { +static const arc arcs_39_0[9] = { {112, 1}, {55, 1}, {53, 1}, @@ -894,22 +894,22 @@ static arc arcs_39_0[9] = { {116, 1}, {117, 1}, }; -static arc arcs_39_1[1] = { +static const arc arcs_39_1[1] = { {0, 1}, }; static state states_39[2] = { {9, arcs_39_0}, {1, arcs_39_1}, }; -static arc arcs_40_0[1] = { +static const arc arcs_40_0[1] = { {38, 1}, }; -static arc arcs_40_1[3] = { +static const arc arcs_40_1[3] = { {113, 2}, {56, 2}, {117, 2}, }; -static arc arcs_40_2[1] = { +static const arc arcs_40_2[1] = { {0, 2}, }; static state states_40[3] = { @@ -917,30 +917,30 @@ static state states_40[3] = { {3, arcs_40_1}, {1, arcs_40_2}, }; -static arc arcs_41_0[1] = { +static const arc arcs_41_0[1] = { {24, 1}, }; -static arc arcs_41_1[1] = { +static const arc arcs_41_1[1] = { {118, 2}, }; -static arc arcs_41_2[1] = { +static const arc arcs_41_2[1] = { {59, 3}, }; -static arc arcs_41_3[1] = { +static const arc arcs_41_3[1] = { {119, 4}, }; -static arc arcs_41_4[3] = { +static const arc arcs_41_4[3] = { {120, 1}, {121, 5}, {0, 4}, }; -static arc arcs_41_5[1] = { +static const arc arcs_41_5[1] = { {59, 6}, }; -static arc arcs_41_6[1] = { +static const arc arcs_41_6[1] = { {119, 7}, }; -static arc arcs_41_7[1] = { +static const arc arcs_41_7[1] = { {0, 7}, }; static state states_41[8] = { @@ -953,29 +953,29 @@ static state states_41[8] = { {1, arcs_41_6}, {1, arcs_41_7}, }; -static arc arcs_42_0[1] = { +static const arc arcs_42_0[1] = { {33, 1}, }; -static arc arcs_42_1[1] = { +static const arc arcs_42_1[1] = { {118, 2}, }; -static arc arcs_42_2[1] = { +static const arc arcs_42_2[1] = { {59, 3}, }; -static arc arcs_42_3[1] = { +static const arc arcs_42_3[1] = { {119, 4}, }; -static arc arcs_42_4[2] = { +static const arc arcs_42_4[2] = { {121, 5}, {0, 4}, }; -static arc arcs_42_5[1] = { +static const arc arcs_42_5[1] = { {59, 6}, }; -static arc arcs_42_6[1] = { +static const arc arcs_42_6[1] = { {119, 7}, }; -static arc arcs_42_7[1] = { +static const arc arcs_42_7[1] = { {0, 7}, }; static state states_42[8] = { @@ -988,39 +988,39 @@ static state states_42[8] = { {1, arcs_42_6}, {1, arcs_42_7}, }; -static arc arcs_43_0[1] = { +static const arc arcs_43_0[1] = { {21, 1}, }; -static arc arcs_43_1[1] = { +static const arc arcs_43_1[1] = { {98, 2}, }; -static arc arcs_43_2[1] = { +static const arc arcs_43_2[1] = { {122, 3}, }; -static arc arcs_43_3[1] = { +static const arc arcs_43_3[1] = { {47, 4}, }; -static arc arcs_43_4[1] = { +static const arc arcs_43_4[1] = { {59, 5}, }; -static arc arcs_43_5[2] = { +static const arc arcs_43_5[2] = { {61, 6}, {119, 7}, }; -static arc arcs_43_6[1] = { +static const arc arcs_43_6[1] = { {119, 7}, }; -static arc arcs_43_7[2] = { +static const arc arcs_43_7[2] = { {121, 8}, {0, 7}, }; -static arc arcs_43_8[1] = { +static const arc arcs_43_8[1] = { {59, 9}, }; -static arc arcs_43_9[1] = { +static const arc arcs_43_9[1] = { {119, 10}, }; -static arc arcs_43_10[1] = { +static const arc arcs_43_10[1] = { {0, 10}, }; static state states_43[11] = { @@ -1036,47 +1036,47 @@ static state states_43[11] = { {1, arcs_43_9}, {1, arcs_43_10}, }; -static arc arcs_44_0[1] = { +static const arc arcs_44_0[1] = { {32, 1}, }; -static arc arcs_44_1[1] = { +static const arc arcs_44_1[1] = { {59, 2}, }; -static arc arcs_44_2[1] = { +static const arc arcs_44_2[1] = { {119, 3}, }; -static arc arcs_44_3[2] = { +static const arc arcs_44_3[2] = { {123, 4}, {124, 5}, }; -static arc arcs_44_4[1] = { +static const arc arcs_44_4[1] = { {59, 6}, }; -static arc arcs_44_5[1] = { +static const arc arcs_44_5[1] = { {59, 7}, }; -static arc arcs_44_6[1] = { +static const arc arcs_44_6[1] = { {119, 8}, }; -static arc arcs_44_7[1] = { +static const arc arcs_44_7[1] = { {119, 9}, }; -static arc arcs_44_8[1] = { +static const arc arcs_44_8[1] = { {0, 8}, }; -static arc arcs_44_9[4] = { +static const arc arcs_44_9[4] = { {121, 10}, {123, 4}, {124, 5}, {0, 9}, }; -static arc arcs_44_10[1] = { +static const arc arcs_44_10[1] = { {59, 11}, }; -static arc arcs_44_11[1] = { +static const arc arcs_44_11[1] = { {119, 12}, }; -static arc arcs_44_12[2] = { +static const arc arcs_44_12[2] = { {123, 4}, {0, 12}, }; @@ -1095,24 +1095,24 @@ static state states_44[13] = { {1, arcs_44_11}, {2, arcs_44_12}, }; -static arc arcs_45_0[1] = { +static const arc arcs_45_0[1] = { {34, 1}, }; -static arc arcs_45_1[1] = { +static const arc arcs_45_1[1] = { {125, 2}, }; -static arc arcs_45_2[2] = { +static const arc arcs_45_2[2] = { {66, 1}, {59, 3}, }; -static arc arcs_45_3[2] = { +static const arc arcs_45_3[2] = { {61, 4}, {119, 5}, }; -static arc arcs_45_4[1] = { +static const arc arcs_45_4[1] = { {119, 5}, }; -static arc arcs_45_5[1] = { +static const arc arcs_45_5[1] = { {0, 5}, }; static state states_45[6] = { @@ -1123,17 +1123,17 @@ static state states_45[6] = { {1, arcs_45_4}, {1, arcs_45_5}, }; -static arc arcs_46_0[1] = { +static const arc arcs_46_0[1] = { {60, 1}, }; -static arc arcs_46_1[2] = { +static const arc arcs_46_1[2] = { {110, 2}, {0, 1}, }; -static arc arcs_46_2[1] = { +static const arc arcs_46_2[1] = { {126, 3}, }; -static arc arcs_46_3[1] = { +static const arc arcs_46_3[1] = { {0, 3}, }; static state states_46[4] = { @@ -1142,21 +1142,21 @@ static state states_46[4] = { {1, arcs_46_2}, {1, arcs_46_3}, }; -static arc arcs_47_0[1] = { +static const arc arcs_47_0[1] = { {127, 1}, }; -static arc arcs_47_1[2] = { +static const arc arcs_47_1[2] = { {60, 2}, {0, 1}, }; -static arc arcs_47_2[2] = { +static const arc arcs_47_2[2] = { {110, 3}, {0, 2}, }; -static arc arcs_47_3[1] = { +static const arc arcs_47_3[1] = { {40, 4}, }; -static arc arcs_47_4[1] = { +static const arc arcs_47_4[1] = { {0, 4}, }; static state states_47[5] = { @@ -1166,20 +1166,20 @@ static state states_47[5] = { {1, arcs_47_3}, {1, arcs_47_4}, }; -static arc arcs_48_0[2] = { +static const arc arcs_48_0[2] = { {2, 1}, {4, 2}, }; -static arc arcs_48_1[1] = { +static const arc arcs_48_1[1] = { {128, 3}, }; -static arc arcs_48_2[1] = { +static const arc arcs_48_2[1] = { {0, 2}, }; -static arc arcs_48_3[1] = { +static const arc arcs_48_3[1] = { {45, 4}, }; -static arc arcs_48_4[2] = { +static const arc arcs_48_4[2] = { {129, 2}, {45, 4}, }; @@ -1190,17 +1190,17 @@ static state states_48[5] = { {1, arcs_48_3}, {2, arcs_48_4}, }; -static arc arcs_49_0[1] = { +static const arc arcs_49_0[1] = { {60, 1}, }; -static arc arcs_49_1[2] = { +static const arc arcs_49_1[2] = { {130, 2}, {0, 1}, }; -static arc arcs_49_2[1] = { +static const arc arcs_49_2[1] = { {60, 3}, }; -static arc arcs_49_3[1] = { +static const arc arcs_49_3[1] = { {0, 3}, }; static state states_49[4] = { @@ -1209,24 +1209,24 @@ static state states_49[4] = { {1, arcs_49_2}, {1, arcs_49_3}, }; -static arc arcs_50_0[2] = { +static const arc arcs_50_0[2] = { {131, 1}, {132, 2}, }; -static arc arcs_50_1[1] = { +static const arc arcs_50_1[1] = { {0, 1}, }; -static arc arcs_50_2[2] = { +static const arc arcs_50_2[2] = { {24, 3}, {0, 2}, }; -static arc arcs_50_3[1] = { +static const arc arcs_50_3[1] = { {132, 4}, }; -static arc arcs_50_4[1] = { +static const arc arcs_50_4[1] = { {121, 5}, }; -static arc arcs_50_5[1] = { +static const arc arcs_50_5[1] = { {60, 1}, }; static state states_50[6] = { @@ -1237,31 +1237,31 @@ static state states_50[6] = { {1, arcs_50_4}, {1, arcs_50_5}, }; -static arc arcs_51_0[2] = { +static const arc arcs_51_0[2] = { {134, 1}, {132, 1}, }; -static arc arcs_51_1[1] = { +static const arc arcs_51_1[1] = { {0, 1}, }; static state states_51[2] = { {2, arcs_51_0}, {1, arcs_51_1}, }; -static arc arcs_52_0[1] = { +static const arc arcs_52_0[1] = { {26, 1}, }; -static arc arcs_52_1[2] = { +static const arc arcs_52_1[2] = { {59, 2}, {68, 3}, }; -static arc arcs_52_2[1] = { +static const arc arcs_52_2[1] = { {60, 4}, }; -static arc arcs_52_3[1] = { +static const arc arcs_52_3[1] = { {59, 2}, }; -static arc arcs_52_4[1] = { +static const arc arcs_52_4[1] = { {0, 4}, }; static state states_52[5] = { @@ -1271,20 +1271,20 @@ static state states_52[5] = { {1, arcs_52_3}, {1, arcs_52_4}, }; -static arc arcs_53_0[1] = { +static const arc arcs_53_0[1] = { {26, 1}, }; -static arc arcs_53_1[2] = { +static const arc arcs_53_1[2] = { {59, 2}, {68, 3}, }; -static arc arcs_53_2[1] = { +static const arc arcs_53_2[1] = { {133, 4}, }; -static arc arcs_53_3[1] = { +static const arc arcs_53_3[1] = { {59, 2}, }; -static arc arcs_53_4[1] = { +static const arc arcs_53_4[1] = { {0, 4}, }; static state states_53[5] = { @@ -1294,10 +1294,10 @@ static state states_53[5] = { {1, arcs_53_3}, {1, arcs_53_4}, }; -static arc arcs_54_0[1] = { +static const arc arcs_54_0[1] = { {135, 1}, }; -static arc arcs_54_1[2] = { +static const arc arcs_54_1[2] = { {136, 0}, {0, 1}, }; @@ -1305,10 +1305,10 @@ static state states_54[2] = { {1, arcs_54_0}, {2, arcs_54_1}, }; -static arc arcs_55_0[1] = { +static const arc arcs_55_0[1] = { {137, 1}, }; -static arc arcs_55_1[2] = { +static const arc arcs_55_1[2] = { {138, 0}, {0, 1}, }; @@ -1316,14 +1316,14 @@ static state states_55[2] = { {1, arcs_55_0}, {2, arcs_55_1}, }; -static arc arcs_56_0[2] = { +static const arc arcs_56_0[2] = { {28, 1}, {139, 2}, }; -static arc arcs_56_1[1] = { +static const arc arcs_56_1[1] = { {137, 2}, }; -static arc arcs_56_2[1] = { +static const arc arcs_56_2[1] = { {0, 2}, }; static state states_56[3] = { @@ -1331,10 +1331,10 @@ static state states_56[3] = { {1, arcs_56_1}, {1, arcs_56_2}, }; -static arc arcs_57_0[1] = { +static const arc arcs_57_0[1] = { {126, 1}, }; -static arc arcs_57_1[2] = { +static const arc arcs_57_1[2] = { {140, 0}, {0, 1}, }; @@ -1342,7 +1342,7 @@ static state states_57[2] = { {1, arcs_57_0}, {2, arcs_57_1}, }; -static arc arcs_58_0[10] = { +static const arc arcs_58_0[10] = { {141, 1}, {142, 1}, {143, 1}, @@ -1354,14 +1354,14 @@ static arc arcs_58_0[10] = { {147, 2}, {28, 3}, }; -static arc arcs_58_1[1] = { +static const arc arcs_58_1[1] = { {0, 1}, }; -static arc arcs_58_2[2] = { +static const arc arcs_58_2[2] = { {28, 1}, {0, 2}, }; -static arc arcs_58_3[1] = { +static const arc arcs_58_3[1] = { {122, 1}, }; static state states_58[4] = { @@ -1370,13 +1370,13 @@ static state states_58[4] = { {2, arcs_58_2}, {1, arcs_58_3}, }; -static arc arcs_59_0[1] = { +static const arc arcs_59_0[1] = { {6, 1}, }; -static arc arcs_59_1[1] = { +static const arc arcs_59_1[1] = { {126, 2}, }; -static arc arcs_59_2[1] = { +static const arc arcs_59_2[1] = { {0, 2}, }; static state states_59[3] = { @@ -1384,10 +1384,10 @@ static state states_59[3] = { {1, arcs_59_1}, {1, arcs_59_2}, }; -static arc arcs_60_0[1] = { +static const arc arcs_60_0[1] = { {148, 1}, }; -static arc arcs_60_1[2] = { +static const arc arcs_60_1[2] = { {149, 0}, {0, 1}, }; @@ -1395,10 +1395,10 @@ static state states_60[2] = { {1, arcs_60_0}, {2, arcs_60_1}, }; -static arc arcs_61_0[1] = { +static const arc arcs_61_0[1] = { {150, 1}, }; -static arc arcs_61_1[2] = { +static const arc arcs_61_1[2] = { {151, 0}, {0, 1}, }; @@ -1406,10 +1406,10 @@ static state states_61[2] = { {1, arcs_61_0}, {2, arcs_61_1}, }; -static arc arcs_62_0[1] = { +static const arc arcs_62_0[1] = { {152, 1}, }; -static arc arcs_62_1[2] = { +static const arc arcs_62_1[2] = { {153, 0}, {0, 1}, }; @@ -1417,10 +1417,10 @@ static state states_62[2] = { {1, arcs_62_0}, {2, arcs_62_1}, }; -static arc arcs_63_0[1] = { +static const arc arcs_63_0[1] = { {154, 1}, }; -static arc arcs_63_1[3] = { +static const arc arcs_63_1[3] = { {155, 0}, {156, 0}, {0, 1}, @@ -1429,10 +1429,10 @@ static state states_63[2] = { {1, arcs_63_0}, {3, arcs_63_1}, }; -static arc arcs_64_0[1] = { +static const arc arcs_64_0[1] = { {157, 1}, }; -static arc arcs_64_1[3] = { +static const arc arcs_64_1[3] = { {7, 0}, {8, 0}, {0, 1}, @@ -1441,10 +1441,10 @@ static state states_64[2] = { {1, arcs_64_0}, {3, arcs_64_1}, }; -static arc arcs_65_0[1] = { +static const arc arcs_65_0[1] = { {158, 1}, }; -static arc arcs_65_1[6] = { +static const arc arcs_65_1[6] = { {159, 0}, {6, 0}, {160, 0}, @@ -1456,16 +1456,16 @@ static state states_65[2] = { {1, arcs_65_0}, {6, arcs_65_1}, }; -static arc arcs_66_0[4] = { +static const arc arcs_66_0[4] = { {7, 1}, {8, 1}, {37, 1}, {162, 2}, }; -static arc arcs_66_1[1] = { +static const arc arcs_66_1[1] = { {158, 2}, }; -static arc arcs_66_2[1] = { +static const arc arcs_66_2[1] = { {0, 2}, }; static state states_66[3] = { @@ -1473,17 +1473,17 @@ static state states_66[3] = { {1, arcs_66_1}, {1, arcs_66_2}, }; -static arc arcs_67_0[1] = { +static const arc arcs_67_0[1] = { {163, 1}, }; -static arc arcs_67_1[2] = { +static const arc arcs_67_1[2] = { {64, 2}, {0, 1}, }; -static arc arcs_67_2[1] = { +static const arc arcs_67_2[1] = { {158, 3}, }; -static arc arcs_67_3[1] = { +static const arc arcs_67_3[1] = { {0, 3}, }; static state states_67[4] = { @@ -1492,14 +1492,14 @@ static state states_67[4] = { {1, arcs_67_2}, {1, arcs_67_3}, }; -static arc arcs_68_0[2] = { +static const arc arcs_68_0[2] = { {39, 1}, {164, 2}, }; -static arc arcs_68_1[1] = { +static const arc arcs_68_1[1] = { {164, 2}, }; -static arc arcs_68_2[2] = { +static const arc arcs_68_2[2] = { {165, 2}, {0, 2}, }; @@ -1508,7 +1508,7 @@ static state states_68[3] = { {1, arcs_68_1}, {2, arcs_68_2}, }; -static arc arcs_69_0[10] = { +static const arc arcs_69_0[10] = { {5, 1}, {9, 2}, {11, 2}, @@ -1520,33 +1520,33 @@ static arc arcs_69_0[10] = { {41, 2}, {42, 5}, }; -static arc arcs_69_1[3] = { +static const arc arcs_69_1[3] = { {50, 2}, {166, 6}, {83, 6}, }; -static arc arcs_69_2[1] = { +static const arc arcs_69_2[1] = { {0, 2}, }; -static arc arcs_69_3[2] = { +static const arc arcs_69_3[2] = { {167, 2}, {166, 7}, }; -static arc arcs_69_4[2] = { +static const arc arcs_69_4[2] = { {168, 2}, {169, 8}, }; -static arc arcs_69_5[2] = { +static const arc arcs_69_5[2] = { {42, 5}, {0, 5}, }; -static arc arcs_69_6[1] = { +static const arc arcs_69_6[1] = { {50, 2}, }; -static arc arcs_69_7[1] = { +static const arc arcs_69_7[1] = { {167, 2}, }; -static arc arcs_69_8[1] = { +static const arc arcs_69_8[1] = { {168, 2}, }; static state states_69[9] = { @@ -1560,24 +1560,24 @@ static state states_69[9] = { {1, arcs_69_7}, {1, arcs_69_8}, }; -static arc arcs_70_0[2] = { +static const arc arcs_70_0[2] = { {118, 1}, {84, 1}, }; -static arc arcs_70_1[3] = { +static const arc arcs_70_1[3] = { {66, 2}, {170, 3}, {0, 1}, }; -static arc arcs_70_2[3] = { +static const arc arcs_70_2[3] = { {118, 4}, {84, 4}, {0, 2}, }; -static arc arcs_70_3[1] = { +static const arc arcs_70_3[1] = { {0, 3}, }; -static arc arcs_70_4[2] = { +static const arc arcs_70_4[2] = { {66, 2}, {0, 4}, }; @@ -1588,28 +1588,28 @@ static state states_70[5] = { {1, arcs_70_3}, {2, arcs_70_4}, }; -static arc arcs_71_0[3] = { +static const arc arcs_71_0[3] = { {5, 1}, {107, 2}, {14, 3}, }; -static arc arcs_71_1[2] = { +static const arc arcs_71_1[2] = { {50, 4}, {51, 5}, }; -static arc arcs_71_2[1] = { +static const arc arcs_71_2[1] = { {40, 4}, }; -static arc arcs_71_3[1] = { +static const arc arcs_71_3[1] = { {171, 6}, }; -static arc arcs_71_4[1] = { +static const arc arcs_71_4[1] = { {0, 4}, }; -static arc arcs_71_5[1] = { +static const arc arcs_71_5[1] = { {50, 4}, }; -static arc arcs_71_6[1] = { +static const arc arcs_71_6[1] = { {167, 4}, }; static state states_71[7] = { @@ -1621,14 +1621,14 @@ static state states_71[7] = { {1, arcs_71_5}, {1, arcs_71_6}, }; -static arc arcs_72_0[1] = { +static const arc arcs_72_0[1] = { {172, 1}, }; -static arc arcs_72_1[2] = { +static const arc arcs_72_1[2] = { {66, 2}, {0, 1}, }; -static arc arcs_72_2[2] = { +static const arc arcs_72_2[2] = { {172, 1}, {0, 2}, }; @@ -1637,23 +1637,23 @@ static state states_72[3] = { {2, arcs_72_1}, {2, arcs_72_2}, }; -static arc arcs_73_0[2] = { +static const arc arcs_73_0[2] = { {59, 1}, {60, 2}, }; -static arc arcs_73_1[3] = { +static const arc arcs_73_1[3] = { {173, 3}, {60, 4}, {0, 1}, }; -static arc arcs_73_2[2] = { +static const arc arcs_73_2[2] = { {59, 1}, {0, 2}, }; -static arc arcs_73_3[1] = { +static const arc arcs_73_3[1] = { {0, 3}, }; -static arc arcs_73_4[2] = { +static const arc arcs_73_4[2] = { {173, 3}, {0, 4}, }; @@ -1664,14 +1664,14 @@ static state states_73[5] = { {1, arcs_73_3}, {2, arcs_73_4}, }; -static arc arcs_74_0[1] = { +static const arc arcs_74_0[1] = { {59, 1}, }; -static arc arcs_74_1[2] = { +static const arc arcs_74_1[2] = { {60, 2}, {0, 1}, }; -static arc arcs_74_2[1] = { +static const arc arcs_74_2[1] = { {0, 2}, }; static state states_74[3] = { @@ -1679,15 +1679,15 @@ static state states_74[3] = { {2, arcs_74_1}, {1, arcs_74_2}, }; -static arc arcs_75_0[2] = { +static const arc arcs_75_0[2] = { {126, 1}, {84, 1}, }; -static arc arcs_75_1[2] = { +static const arc arcs_75_1[2] = { {66, 2}, {0, 1}, }; -static arc arcs_75_2[3] = { +static const arc arcs_75_2[3] = { {126, 1}, {84, 1}, {0, 2}, @@ -1697,14 +1697,14 @@ static state states_75[3] = { {2, arcs_75_1}, {3, arcs_75_2}, }; -static arc arcs_76_0[1] = { +static const arc arcs_76_0[1] = { {60, 1}, }; -static arc arcs_76_1[2] = { +static const arc arcs_76_1[2] = { {66, 2}, {0, 1}, }; -static arc arcs_76_2[2] = { +static const arc arcs_76_2[2] = { {60, 1}, {0, 2}, }; @@ -1713,61 +1713,61 @@ static state states_76[3] = { {2, arcs_76_1}, {2, arcs_76_2}, }; -static arc arcs_77_0[3] = { +static const arc arcs_77_0[3] = { {64, 1}, {84, 2}, {60, 3}, }; -static arc arcs_77_1[1] = { +static const arc arcs_77_1[1] = { {126, 4}, }; -static arc arcs_77_2[3] = { +static const arc arcs_77_2[3] = { {66, 5}, {170, 6}, {0, 2}, }; -static arc arcs_77_3[4] = { +static const arc arcs_77_3[4] = { {66, 5}, {59, 7}, {170, 6}, {0, 3}, }; -static arc arcs_77_4[3] = { +static const arc arcs_77_4[3] = { {66, 8}, {170, 6}, {0, 4}, }; -static arc arcs_77_5[3] = { +static const arc arcs_77_5[3] = { {84, 9}, {60, 9}, {0, 5}, }; -static arc arcs_77_6[1] = { +static const arc arcs_77_6[1] = { {0, 6}, }; -static arc arcs_77_7[1] = { +static const arc arcs_77_7[1] = { {60, 4}, }; -static arc arcs_77_8[3] = { +static const arc arcs_77_8[3] = { {64, 10}, {60, 11}, {0, 8}, }; -static arc arcs_77_9[2] = { +static const arc arcs_77_9[2] = { {66, 5}, {0, 9}, }; -static arc arcs_77_10[1] = { +static const arc arcs_77_10[1] = { {126, 12}, }; -static arc arcs_77_11[1] = { +static const arc arcs_77_11[1] = { {59, 13}, }; -static arc arcs_77_12[2] = { +static const arc arcs_77_12[2] = { {66, 8}, {0, 12}, }; -static arc arcs_77_13[1] = { +static const arc arcs_77_13[1] = { {60, 12}, }; static state states_77[14] = { @@ -1786,30 +1786,30 @@ static state states_77[14] = { {2, arcs_77_12}, {1, arcs_77_13}, }; -static arc arcs_78_0[1] = { +static const arc arcs_78_0[1] = { {17, 1}, }; -static arc arcs_78_1[1] = { +static const arc arcs_78_1[1] = { {40, 2}, }; -static arc arcs_78_2[2] = { +static const arc arcs_78_2[2] = { {5, 3}, {59, 4}, }; -static arc arcs_78_3[2] = { +static const arc arcs_78_3[2] = { {50, 5}, {51, 6}, }; -static arc arcs_78_4[1] = { +static const arc arcs_78_4[1] = { {119, 7}, }; -static arc arcs_78_5[1] = { +static const arc arcs_78_5[1] = { {59, 4}, }; -static arc arcs_78_6[1] = { +static const arc arcs_78_6[1] = { {50, 5}, }; -static arc arcs_78_7[1] = { +static const arc arcs_78_7[1] = { {0, 7}, }; static state states_78[8] = { @@ -1822,14 +1822,14 @@ static state states_78[8] = { {1, arcs_78_6}, {1, arcs_78_7}, }; -static arc arcs_79_0[1] = { +static const arc arcs_79_0[1] = { {174, 1}, }; -static arc arcs_79_1[2] = { +static const arc arcs_79_1[2] = { {66, 2}, {0, 1}, }; -static arc arcs_79_2[2] = { +static const arc arcs_79_2[2] = { {174, 1}, {0, 2}, }; @@ -1838,21 +1838,21 @@ static state states_79[3] = { {2, arcs_79_1}, {2, arcs_79_2}, }; -static arc arcs_80_0[3] = { +static const arc arcs_80_0[3] = { {6, 1}, {64, 1}, {60, 2}, }; -static arc arcs_80_1[1] = { +static const arc arcs_80_1[1] = { {60, 3}, }; -static arc arcs_80_2[4] = { +static const arc arcs_80_2[4] = { {130, 1}, {67, 1}, {170, 3}, {0, 2}, }; -static arc arcs_80_3[1] = { +static const arc arcs_80_3[1] = { {0, 3}, }; static state states_80[4] = { @@ -1861,34 +1861,34 @@ static state states_80[4] = { {4, arcs_80_2}, {1, arcs_80_3}, }; -static arc arcs_81_0[2] = { +static const arc arcs_81_0[2] = { {170, 1}, {176, 1}, }; -static arc arcs_81_1[1] = { +static const arc arcs_81_1[1] = { {0, 1}, }; static state states_81[2] = { {2, arcs_81_0}, {1, arcs_81_1}, }; -static arc arcs_82_0[1] = { +static const arc arcs_82_0[1] = { {21, 1}, }; -static arc arcs_82_1[1] = { +static const arc arcs_82_1[1] = { {98, 2}, }; -static arc arcs_82_2[1] = { +static const arc arcs_82_2[1] = { {122, 3}, }; -static arc arcs_82_3[1] = { +static const arc arcs_82_3[1] = { {132, 4}, }; -static arc arcs_82_4[2] = { +static const arc arcs_82_4[2] = { {175, 5}, {0, 4}, }; -static arc arcs_82_5[1] = { +static const arc arcs_82_5[1] = { {0, 5}, }; static state states_82[6] = { @@ -1899,14 +1899,14 @@ static state states_82[6] = { {2, arcs_82_4}, {1, arcs_82_5}, }; -static arc arcs_83_0[2] = { +static const arc arcs_83_0[2] = { {38, 1}, {177, 2}, }; -static arc arcs_83_1[1] = { +static const arc arcs_83_1[1] = { {177, 2}, }; -static arc arcs_83_2[1] = { +static const arc arcs_83_2[1] = { {0, 2}, }; static state states_83[3] = { @@ -1914,17 +1914,17 @@ static state states_83[3] = { {1, arcs_83_1}, {1, arcs_83_2}, }; -static arc arcs_84_0[1] = { +static const arc arcs_84_0[1] = { {24, 1}, }; -static arc arcs_84_1[1] = { +static const arc arcs_84_1[1] = { {133, 2}, }; -static arc arcs_84_2[2] = { +static const arc arcs_84_2[2] = { {175, 3}, {0, 2}, }; -static arc arcs_84_3[1] = { +static const arc arcs_84_3[1] = { {0, 3}, }; static state states_84[4] = { @@ -1933,24 +1933,24 @@ static state states_84[4] = { {2, arcs_84_2}, {1, arcs_84_3}, }; -static arc arcs_85_0[1] = { +static const arc arcs_85_0[1] = { {40, 1}, }; -static arc arcs_85_1[1] = { +static const arc arcs_85_1[1] = { {0, 1}, }; static state states_85[2] = { {1, arcs_85_0}, {1, arcs_85_1}, }; -static arc arcs_86_0[1] = { +static const arc arcs_86_0[1] = { {35, 1}, }; -static arc arcs_86_1[2] = { +static const arc arcs_86_1[2] = { {179, 2}, {0, 1}, }; -static arc arcs_86_2[1] = { +static const arc arcs_86_2[1] = { {0, 2}, }; static state states_86[3] = { @@ -1958,14 +1958,14 @@ static state states_86[3] = { {2, arcs_86_1}, {1, arcs_86_2}, }; -static arc arcs_87_0[2] = { +static const arc arcs_87_0[2] = { {22, 1}, {80, 2}, }; -static arc arcs_87_1[1] = { +static const arc arcs_87_1[1] = { {60, 2}, }; -static arc arcs_87_2[1] = { +static const arc arcs_87_2[1] = { {0, 2}, }; static state states_87[3] = { @@ -1973,28 +1973,28 @@ static state states_87[3] = { {1, arcs_87_1}, {1, arcs_87_2}, }; -static arc arcs_88_0[2] = { +static const arc arcs_88_0[2] = { {2, 1}, {4, 2}, }; -static arc arcs_88_1[2] = { +static const arc arcs_88_1[2] = { {128, 3}, {61, 4}, }; -static arc arcs_88_2[1] = { +static const arc arcs_88_2[1] = { {0, 2}, }; -static arc arcs_88_3[1] = { +static const arc arcs_88_3[1] = { {45, 5}, }; -static arc arcs_88_4[1] = { +static const arc arcs_88_4[1] = { {2, 6}, }; -static arc arcs_88_5[2] = { +static const arc arcs_88_5[2] = { {129, 2}, {45, 5}, }; -static arc arcs_88_6[1] = { +static const arc arcs_88_6[1] = { {128, 3}, }; static state states_88[7] = { @@ -2006,14 +2006,14 @@ static state states_88[7] = { {2, arcs_88_5}, {1, arcs_88_6}, }; -static arc arcs_89_0[1] = { +static const arc arcs_89_0[1] = { {181, 1}, }; -static arc arcs_89_1[2] = { +static const arc arcs_89_1[2] = { {44, 2}, {2, 1}, }; -static arc arcs_89_2[1] = { +static const arc arcs_89_2[1] = { {0, 2}, }; static state states_89[3] = { @@ -2021,23 +2021,23 @@ static state states_89[3] = { {2, arcs_89_1}, {1, arcs_89_2}, }; -static arc arcs_90_0[1] = { +static const arc arcs_90_0[1] = { {5, 1}, }; -static arc arcs_90_1[2] = { +static const arc arcs_90_1[2] = { {50, 2}, {182, 3}, }; -static arc arcs_90_2[1] = { +static const arc arcs_90_2[1] = { {58, 4}, }; -static arc arcs_90_3[1] = { +static const arc arcs_90_3[1] = { {50, 2}, }; -static arc arcs_90_4[1] = { +static const arc arcs_90_4[1] = { {60, 5}, }; -static arc arcs_90_5[1] = { +static const arc arcs_90_5[1] = { {0, 5}, }; static state states_90[6] = { @@ -2048,50 +2048,50 @@ static state states_90[6] = { {1, arcs_90_4}, {1, arcs_90_5}, }; -static arc arcs_91_0[3] = { +static const arc arcs_91_0[3] = { {6, 1}, {64, 2}, {60, 3}, }; -static arc arcs_91_1[3] = { +static const arc arcs_91_1[3] = { {66, 4}, {60, 5}, {0, 1}, }; -static arc arcs_91_2[1] = { +static const arc arcs_91_2[1] = { {60, 6}, }; -static arc arcs_91_3[2] = { +static const arc arcs_91_3[2] = { {66, 7}, {0, 3}, }; -static arc arcs_91_4[2] = { +static const arc arcs_91_4[2] = { {64, 2}, {60, 5}, }; -static arc arcs_91_5[2] = { +static const arc arcs_91_5[2] = { {66, 4}, {0, 5}, }; -static arc arcs_91_6[1] = { +static const arc arcs_91_6[1] = { {0, 6}, }; -static arc arcs_91_7[4] = { +static const arc arcs_91_7[4] = { {6, 8}, {64, 2}, {60, 3}, {0, 7}, }; -static arc arcs_91_8[3] = { +static const arc arcs_91_8[3] = { {66, 9}, {60, 10}, {0, 8}, }; -static arc arcs_91_9[2] = { +static const arc arcs_91_9[2] = { {64, 2}, {60, 10}, }; -static arc arcs_91_10[2] = { +static const arc arcs_91_10[2] = { {66, 9}, {0, 10}, }; @@ -2108,7 +2108,7 @@ static state states_91[11] = { {2, arcs_91_9}, {2, arcs_91_10}, }; -static dfa dfas[92] = { +static const dfa dfas[92] = { {256, "single_input", 3, states_0, "\344\377\377\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {257, "file_input", 2, states_1, @@ -2294,7 +2294,7 @@ static dfa dfas[92] = { {347, "typelist", 11, states_91, "\340\173\000\024\260\007\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, }; -static label labels[183] = { +static const label labels[183] = { {0, "EMPTY"}, {256, 0}, {4, 0}, From 574913479f26b5ff48827861bce68281be01d16e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 23 Apr 2019 12:26:33 +0200 Subject: [PATCH 057/212] bpo-36635, bpo-36696: Fix setup.py on AIX (GH-12922) xlc compiler doesn't support "-D define" flag only "-Ddefine". --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 3d6404f89eef70..58c16e8ba49d5c 100644 --- a/setup.py +++ b/setup.py @@ -726,12 +726,12 @@ def detect_simple_extensions(self): self.add(Extension("_heapq", ["_heapqmodule.c"])) # C-optimized pickle replacement self.add(Extension("_pickle", ["_pickle.c"], - extra_compile_args=['-D Py_BUILD_CORE_MODULE'])) + extra_compile_args=['-DPy_BUILD_CORE_MODULE'])) # atexit self.add(Extension("atexit", ["atexitmodule.c"])) # _json speedups self.add(Extension("_json", ["_json.c"], - extra_compile_args=['-D Py_BUILD_CORE_MODULE'])) + extra_compile_args=['-DPy_BUILD_CORE_MODULE'])) # profiler (_lsprof is for cProfile.py) self.add(Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c'])) @@ -816,7 +816,7 @@ def detect_test_extensions(self): # Python Internal C API test module self.add(Extension('_testinternalcapi', ['_testinternalcapi.c'], - extra_compile_args=['-D Py_BUILD_CORE_MODULE'])) + extra_compile_args=['-DPy_BUILD_CORE_MODULE'])) # Python PEP-3118 (buffer protocol) test module self.add(Extension('_testbuffer', ['_testbuffer.c'])) From 09415ff0ebbbe97c8cd08ac1f94673d7a49c8018 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Tue, 23 Apr 2019 20:39:37 +0900 Subject: [PATCH 058/212] fix warnings by adding more const (GH-12924) --- Include/grammar.h | 2 +- Modules/parsermodule.c | 3 +-- Parser/acceler.c | 16 +++++++--------- Parser/grammar1.c | 5 ++--- Parser/parser.c | 13 ++++++------- Parser/parser.h | 2 +- 6 files changed, 18 insertions(+), 23 deletions(-) diff --git a/Include/grammar.h b/Include/grammar.h index faccae4657ee9c..4b66b1e9b97451 100644 --- a/Include/grammar.h +++ b/Include/grammar.h @@ -66,7 +66,7 @@ typedef struct { } grammar; /* FUNCTIONS */ -dfa *PyGrammar_FindDFA(grammar *g, int type); +const dfa *PyGrammar_FindDFA(grammar *g, int type); const char *PyGrammar_LabelRepr(label *lb); void PyGrammar_AddAccelerators(grammar *g); void PyGrammar_RemoveAccelerators(grammar *); diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index a215c7ecacd73b..0f681622f28820 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -644,7 +644,6 @@ validate_node(node *tree) { int type = TYPE(tree); int nch = NCH(tree); - dfa *nt_dfa; state *dfa_state; int pos, arc; @@ -654,7 +653,7 @@ validate_node(node *tree) PyErr_Format(parser_error, "Unrecognized node type %d.", TYPE(tree)); return 0; } - nt_dfa = &_PyParser_Grammar.g_dfa[type]; + const dfa *nt_dfa = &_PyParser_Grammar.g_dfa[type]; REQ(tree, nt_dfa->d_type); /* Run the DFA for this nonterminal. */ diff --git a/Parser/acceler.c b/Parser/acceler.c index 3a230c19bb9f80..e515833e1dda1d 100644 --- a/Parser/acceler.c +++ b/Parser/acceler.c @@ -17,15 +17,14 @@ #include "parser.h" /* Forward references */ -static void fixdfa(grammar *, dfa *); +static void fixdfa(grammar *, const dfa *); static void fixstate(grammar *, state *); void PyGrammar_AddAccelerators(grammar *g) { - dfa *d; int i; - d = g->g_dfa; + const dfa *d = g->g_dfa; for (i = g->g_ndfas; --i >= 0; d++) fixdfa(g, d); g->g_accel = 1; @@ -34,10 +33,9 @@ PyGrammar_AddAccelerators(grammar *g) void PyGrammar_RemoveAccelerators(grammar *g) { - dfa *d; int i; g->g_accel = 0; - d = g->g_dfa; + const dfa *d = g->g_dfa; for (i = g->g_ndfas; --i >= 0; d++) { state *s; int j; @@ -51,7 +49,7 @@ PyGrammar_RemoveAccelerators(grammar *g) } static void -fixdfa(grammar *g, dfa *d) +fixdfa(grammar *g, const dfa *d) { state *s; int j; @@ -63,7 +61,7 @@ fixdfa(grammar *g, dfa *d) static void fixstate(grammar *g, state *s) { - arc *a; + const arc *a; int k; int *accel; int nl = g->g_ll.ll_nlabels; @@ -78,14 +76,14 @@ fixstate(grammar *g, state *s) a = s->s_arc; for (k = s->s_narcs; --k >= 0; a++) { int lbl = a->a_lbl; - label *l = &g->g_ll.ll_label[lbl]; + const label *l = &g->g_ll.ll_label[lbl]; int type = l->lb_type; if (a->a_arrow >= (1 << 7)) { printf("XXX too many states!\n"); continue; } if (ISNONTERMINAL(type)) { - dfa *d1 = PyGrammar_FindDFA(g, type); + const dfa *d1 = PyGrammar_FindDFA(g, type); int ibit; if (type - NT_OFFSET >= (1 << 7)) { printf("XXX too high nonterminal number!\n"); diff --git a/Parser/grammar1.c b/Parser/grammar1.c index fec6d9ec0ee281..e0b8fbb8b82886 100644 --- a/Parser/grammar1.c +++ b/Parser/grammar1.c @@ -7,12 +7,11 @@ /* Return the DFA for the given type */ -dfa * +const dfa * PyGrammar_FindDFA(grammar *g, int type) { - dfa *d; /* Massive speed-up */ - d = &g->g_dfa[type - NT_OFFSET]; + const dfa *d = &g->g_dfa[type - NT_OFFSET]; assert(d->d_type == type); return d; } diff --git a/Parser/parser.c b/Parser/parser.c index c21b6fdf466d99..227b9184f471d2 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -35,7 +35,7 @@ s_reset(stack *s) #define s_empty(s) ((s)->s_top == &(s)->s_base[MAXSTACK]) static int -s_push(stack *s, dfa *d, node *parent) +s_push(stack *s, const dfa *d, node *parent) { stackentry *top; if (s->s_top == s->s_base) { @@ -119,7 +119,7 @@ shift(stack *s, int type, char *str, int newstate, int lineno, int col_offset, } static int -push(stack *s, int type, dfa *d, int newstate, int lineno, int col_offset, +push(stack *s, int type, const dfa *d, int newstate, int lineno, int col_offset, int end_lineno, int end_col_offset) { int err; @@ -144,7 +144,7 @@ classify(parser_state *ps, int type, const char *str) int n = g->g_ll.ll_nlabels; if (type == NAME) { - label *l = g->g_ll.ll_label; + const label *l = g->g_ll.ll_label; int i; for (i = n; i > 0; i--, l++) { if (l->lb_type != NAME || l->lb_str == NULL || @@ -168,7 +168,7 @@ classify(parser_state *ps, int type, const char *str) } { - label *l = g->g_ll.ll_label; + const label *l = g->g_ll.ll_label; int i; for (i = n; i > 0; i--, l++) { if (l->lb_type == type && l->lb_str == NULL) { @@ -246,7 +246,7 @@ PyParser_AddToken(parser_state *ps, int type, char *str, /* Loop until the token is shifted or an error occurred */ for (;;) { /* Fetch the current dfa and state */ - dfa *d = ps->p_stack.s_top->s_dfa; + const dfa *d = ps->p_stack.s_top->s_dfa; state *s = &d->d_state[ps->p_stack.s_top->s_state]; D(printf(" DFA '%s', state %d:", @@ -260,7 +260,6 @@ PyParser_AddToken(parser_state *ps, int type, char *str, /* Push non-terminal */ int nt = (x >> 8) + NT_OFFSET; int arrow = x & ((1<<7)-1); - dfa *d1; if (nt == func_body_suite && !(ps->p_flags & PyCF_TYPE_COMMENTS)) { /* When parsing type comments is not requested, we can provide better errors about bad indentation @@ -268,7 +267,7 @@ PyParser_AddToken(parser_state *ps, int type, char *str, D(printf(" [switch func_body_suite to suite]")); nt = suite; } - d1 = PyGrammar_FindDFA( + const dfa *d1 = PyGrammar_FindDFA( ps->p_grammar, nt); if ((err = push(&ps->p_stack, nt, d1, arrow, lineno, col_offset, diff --git a/Parser/parser.h b/Parser/parser.h index ebb06c2b1976e1..b16075e7f29f29 100644 --- a/Parser/parser.h +++ b/Parser/parser.h @@ -11,7 +11,7 @@ extern "C" { typedef struct { int s_state; /* State in current DFA */ - dfa *s_dfa; /* Current DFA */ + const dfa *s_dfa; /* Current DFA */ struct _node *s_parent; /* Where to add next node */ } stackentry; From 359bd4f61b9e1493081f4f67882554247b53926a Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Tue, 23 Apr 2019 05:56:08 -0600 Subject: [PATCH 059/212] bpo-18372: Add missing PyObject_GC_Track() calls in the pickle module (GH-8505) --- .../Core and Builtins/2018-12-08-03-40-43.bpo-18372.DT1nR0.rst | 2 ++ Modules/_pickle.c | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-12-08-03-40-43.bpo-18372.DT1nR0.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-12-08-03-40-43.bpo-18372.DT1nR0.rst b/Misc/NEWS.d/next/Core and Builtins/2018-12-08-03-40-43.bpo-18372.DT1nR0.rst new file mode 100644 index 00000000000000..d8205b8d32d0e4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-12-08-03-40-43.bpo-18372.DT1nR0.rst @@ -0,0 +1,2 @@ +Add missing :c:func:`PyObject_GC_Track` calls in the :mod:`pickle` module. +Patch by Zackery Spytz. diff --git a/Modules/_pickle.c b/Modules/_pickle.c index f956a382ac5310..391ce5e923c6d3 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1119,6 +1119,8 @@ _Pickler_New(void) Py_DECREF(self); return NULL; } + + PyObject_GC_Track(self); return self; } @@ -1496,6 +1498,7 @@ _Unpickler_New(void) return NULL; } + PyObject_GC_Track(self); return self; } From 29d018aa63b72161cfc67602dc3dbd386272da64 Mon Sep 17 00:00:00 2001 From: Mathieu Dupuy Date: Tue, 23 Apr 2019 15:01:09 +0200 Subject: [PATCH 060/212] replace 'sequencial argument' by 'positional' in doc (GH-12925) --- Doc/library/threading.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index d7dbcb107ddadb..c58a6ad75d08fd 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -250,7 +250,7 @@ since it is impossible to detect the termination of alien threads. You may override this method in a subclass. The standard :meth:`run` method invokes the callable object passed to the object's constructor as - the *target* argument, if any, with sequential and keyword arguments taken + the *target* argument, if any, with positional and keyword arguments taken from the *args* and *kwargs* arguments, respectively. .. method:: join(timeout=None) From d246a6766b9d8cc625112906299c4cb019944300 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 24 Apr 2019 00:15:12 +0200 Subject: [PATCH 061/212] bpo-36454: Fix test_time.test_monotonic() (GH-12929) Change test_time.test_monotonic() to test only the lower bound of elapsed time after a sleep command rather than the upper bound. This prevents unnecessary test failures on slow buildbots. Patch by Victor Stinner. --- Lib/test/test_time.py | 5 +++-- .../next/Tests/2019-04-23-17-48-11.bpo-36454.0q4lQz.rst | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-04-23-17-48-11.bpo-36454.0q4lQz.rst diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 303918960b636b..42799b2a21ca34 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -470,8 +470,9 @@ def test_monotonic(self): t2 = time.monotonic() dt = t2 - t1 self.assertGreater(t2, t1) - # Issue #20101: On some Windows machines, dt may be slightly low - self.assertTrue(0.45 <= dt <= 1.0, dt) + # bpo-20101: tolerate a difference of 50 ms because of bad timer + # resolution on Windows + self.assertTrue(0.450 <= dt) # monotonic() is a monotonic but non adjustable clock info = time.get_clock_info('monotonic') diff --git a/Misc/NEWS.d/next/Tests/2019-04-23-17-48-11.bpo-36454.0q4lQz.rst b/Misc/NEWS.d/next/Tests/2019-04-23-17-48-11.bpo-36454.0q4lQz.rst new file mode 100644 index 00000000000000..151c7ab0404026 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-04-23-17-48-11.bpo-36454.0q4lQz.rst @@ -0,0 +1,3 @@ +Change test_time.test_monotonic() to test only the lower bound of elapsed time +after a sleep command rather than the upper bound. This prevents unnecessary +test failures on slow buildbots. Patch by Victor Stinner. From 4f5a3493b534a95fbb01d593b1ffe320db6b395e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20N=C3=B6the?= Date: Wed, 24 Apr 2019 11:21:02 +0200 Subject: [PATCH 062/212] fix typo in gzip.py (GH-12928) --- Lib/gzip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/gzip.py b/Lib/gzip.py index 948fec293e23d9..7c861874198842 100644 --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -283,7 +283,7 @@ def read(self, size=-1): def read1(self, size=-1): """Implements BufferedIOBase.read1() - Reads up to a buffer's worth of data is size is negative.""" + Reads up to a buffer's worth of data if size is negative.""" self._check_not_closed() if self.mode != READ: import errno From 6c44fde3e03079e0c69f823dafbe04af50b5bd0d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 24 Apr 2019 16:10:09 +0200 Subject: [PATCH 063/212] bpo-36707: Remove the "m" flag (pymalloc) from SOABI (GH-12931) "./configure --with-pymalloc" no longer adds the "m" flag to SOABI (sys.implementation.cache_tag). Enabling or disabling pymalloc has no impact on the ABI. --- .../next/Build/2019-04-24-02-29-15.bpo-36707.8ZNB67.rst | 3 +++ configure | 6 +++--- configure.ac | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2019-04-24-02-29-15.bpo-36707.8ZNB67.rst diff --git a/Misc/NEWS.d/next/Build/2019-04-24-02-29-15.bpo-36707.8ZNB67.rst b/Misc/NEWS.d/next/Build/2019-04-24-02-29-15.bpo-36707.8ZNB67.rst new file mode 100644 index 00000000000000..77bd4d73b2a218 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2019-04-24-02-29-15.bpo-36707.8ZNB67.rst @@ -0,0 +1,3 @@ +``./configure --with-pymalloc`` no longer adds the ``m`` flag to SOABI +(sys.implementation.cache_tag). Enabling or disabling pymalloc has no impact +on the ABI. diff --git a/configure b/configure index 9c7eded8535985..e96c03ad4f5942 100755 --- a/configure +++ b/configure @@ -11238,7 +11238,6 @@ then $as_echo "#define WITH_PYMALLOC 1" >>confdefs.h - ABIFLAGS="${ABIFLAGS}m" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_pymalloc" >&5 $as_echo "$with_pymalloc" >&6; } @@ -15086,12 +15085,13 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h # * The Python implementation (always 'cpython-' for us) # * The major and minor version numbers # * --with-pydebug (adds a 'd') -# * --with-pymalloc (adds a 'm') -# * --with-wide-unicode (adds a 'u') # # Thus for example, Python 3.2 built with wide unicode, pydebug, and pymalloc, # would get a shared library ABI version tag of 'cpython-32dmu' and shared # libraries would be named 'foo.cpython-32dmu.so'. +# +# In Python 3.2 and older, --with-wide-unicode added a 'u' flag. +# In Python 3.7 and older, --with-pymalloc added a 'm' flag. { $as_echo "$as_me:${as_lineno-$LINENO}: checking ABIFLAGS" >&5 $as_echo_n "checking ABIFLAGS... " >&6; } diff --git a/configure.ac b/configure.ac index 6450519444c8d3..3f378c97345e2a 100644 --- a/configure.ac +++ b/configure.ac @@ -3400,7 +3400,6 @@ if test "$with_pymalloc" != "no" then AC_DEFINE(WITH_PYMALLOC, 1, [Define if you want to compile in Python-specific mallocs]) - ABIFLAGS="${ABIFLAGS}m" fi AC_MSG_RESULT($with_pymalloc) @@ -4601,12 +4600,13 @@ AC_C_BIGENDIAN # * The Python implementation (always 'cpython-' for us) # * The major and minor version numbers # * --with-pydebug (adds a 'd') -# * --with-pymalloc (adds a 'm') -# * --with-wide-unicode (adds a 'u') # # Thus for example, Python 3.2 built with wide unicode, pydebug, and pymalloc, # would get a shared library ABI version tag of 'cpython-32dmu' and shared # libraries would be named 'foo.cpython-32dmu.so'. +# +# In Python 3.2 and older, --with-wide-unicode added a 'u' flag. +# In Python 3.7 and older, --with-pymalloc added a 'm' flag. AC_SUBST(SOABI) AC_MSG_CHECKING(ABIFLAGS) AC_MSG_RESULT($ABIFLAGS) From 8bb3230149538c25c1bacced5e64a3c071475f73 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 24 Apr 2019 16:47:40 +0200 Subject: [PATCH 064/212] bpo-36710: Add runtime parameter to _PyThreadState_Init() (GH-12935) * Add 'runtime' parameter to _PyThreadState_Init() * Add 'gilstate' parameter to _PyGILState_NoteThreadState() * Move _PyThreadState_Init() and _PyThreadState_DeleteExcept() to the internal C API. --- Include/cpython/pystate.h | 2 - Include/internal/pycore_pystate.h | 5 ++ Modules/_threadmodule.c | 2 +- Python/pystate.c | 138 ++++++++++++++++-------------- 4 files changed, 80 insertions(+), 67 deletions(-) diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index a0953f03261dc3..2341dda3fabdbf 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -155,8 +155,6 @@ PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void); PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*); PyAPI_FUNC(void) _PyState_ClearModules(void); PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *); -PyAPI_FUNC(void) _PyThreadState_Init(PyThreadState *); -PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate); PyAPI_FUNC(void) _PyGILState_Reinit(void); /* Similar to PyThreadState_Get(), but don't issue a fatal error diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index e1ce08d335b9cc..509ca3634a3a13 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -231,6 +231,11 @@ PyAPI_FUNC(void) _PyRuntime_Finalize(void); /* Other */ +PyAPI_FUNC(void) _PyThreadState_Init( + _PyRuntimeState *runtime, + PyThreadState *tstate); +PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate); + PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *); PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(void); diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 73babaf9ca8f46..3c02d8dd514571 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -994,7 +994,7 @@ t_bootstrap(void *boot_raw) tstate = boot->tstate; tstate->thread_id = PyThread_get_thread_ident(); - _PyThreadState_Init(tstate); + _PyThreadState_Init(&_PyRuntime, tstate); PyEval_AcquireThread(tstate); tstate->interp->num_threads++; res = PyObject_Call(boot->func, boot->args, boot->keyw); diff --git a/Python/pystate.c b/Python/pystate.c index a2464b6cf5518f..ef9d79288736d5 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -133,7 +133,9 @@ _PyRuntimeState_ReInitThreads(void) WAIT_LOCK) #define HEAD_UNLOCK() PyThread_release_lock(_PyRuntime.interpreters.mutex) -static void _PyGILState_NoteThreadState(PyThreadState* tstate); +/* Forward declaration */ +static void _PyGILState_NoteThreadState( + struct _gilstate_runtime_state *gilstate, PyThreadState* tstate); _PyInitError _PyInterpreterState_Enable(_PyRuntimeState *runtime) @@ -487,71 +489,74 @@ static PyThreadState * new_threadstate(PyInterpreterState *interp, int init) { PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState)); + if (tstate == NULL) { + return NULL; + } - if (_PyThreadState_GetFrame == NULL) + if (_PyThreadState_GetFrame == NULL) { _PyThreadState_GetFrame = threadstate_getframe; + } - if (tstate != NULL) { - tstate->interp = interp; - - tstate->frame = NULL; - tstate->recursion_depth = 0; - tstate->overflowed = 0; - tstate->recursion_critical = 0; - tstate->stackcheck_counter = 0; - tstate->tracing = 0; - tstate->use_tracing = 0; - tstate->gilstate_counter = 0; - tstate->async_exc = NULL; - tstate->thread_id = PyThread_get_thread_ident(); + tstate->interp = interp; - tstate->dict = NULL; + tstate->frame = NULL; + tstate->recursion_depth = 0; + tstate->overflowed = 0; + tstate->recursion_critical = 0; + tstate->stackcheck_counter = 0; + tstate->tracing = 0; + tstate->use_tracing = 0; + tstate->gilstate_counter = 0; + tstate->async_exc = NULL; + tstate->thread_id = PyThread_get_thread_ident(); - tstate->curexc_type = NULL; - tstate->curexc_value = NULL; - tstate->curexc_traceback = NULL; + tstate->dict = NULL; - tstate->exc_state.exc_type = NULL; - tstate->exc_state.exc_value = NULL; - tstate->exc_state.exc_traceback = NULL; - tstate->exc_state.previous_item = NULL; - tstate->exc_info = &tstate->exc_state; + tstate->curexc_type = NULL; + tstate->curexc_value = NULL; + tstate->curexc_traceback = NULL; - tstate->c_profilefunc = NULL; - tstate->c_tracefunc = NULL; - tstate->c_profileobj = NULL; - tstate->c_traceobj = NULL; + tstate->exc_state.exc_type = NULL; + tstate->exc_state.exc_value = NULL; + tstate->exc_state.exc_traceback = NULL; + tstate->exc_state.previous_item = NULL; + tstate->exc_info = &tstate->exc_state; - tstate->trash_delete_nesting = 0; - tstate->trash_delete_later = NULL; - tstate->on_delete = NULL; - tstate->on_delete_data = NULL; + tstate->c_profilefunc = NULL; + tstate->c_tracefunc = NULL; + tstate->c_profileobj = NULL; + tstate->c_traceobj = NULL; - tstate->coroutine_origin_tracking_depth = 0; + tstate->trash_delete_nesting = 0; + tstate->trash_delete_later = NULL; + tstate->on_delete = NULL; + tstate->on_delete_data = NULL; - tstate->coroutine_wrapper = NULL; - tstate->in_coroutine_wrapper = 0; + tstate->coroutine_origin_tracking_depth = 0; - tstate->async_gen_firstiter = NULL; - tstate->async_gen_finalizer = NULL; + tstate->coroutine_wrapper = NULL; + tstate->in_coroutine_wrapper = 0; - tstate->context = NULL; - tstate->context_ver = 1; + tstate->async_gen_firstiter = NULL; + tstate->async_gen_finalizer = NULL; - tstate->id = ++interp->tstate_next_unique_id; + tstate->context = NULL; + tstate->context_ver = 1; - if (init) - _PyThreadState_Init(tstate); + tstate->id = ++interp->tstate_next_unique_id; - HEAD_LOCK(); - tstate->prev = NULL; - tstate->next = interp->tstate_head; - if (tstate->next) - tstate->next->prev = tstate; - interp->tstate_head = tstate; - HEAD_UNLOCK(); + if (init) { + _PyThreadState_Init(&_PyRuntime, tstate); } + HEAD_LOCK(); + tstate->prev = NULL; + tstate->next = interp->tstate_head; + if (tstate->next) + tstate->next->prev = tstate; + interp->tstate_head = tstate; + HEAD_UNLOCK(); + return tstate; } @@ -568,9 +573,9 @@ _PyThreadState_Prealloc(PyInterpreterState *interp) } void -_PyThreadState_Init(PyThreadState *tstate) +_PyThreadState_Init(_PyRuntimeState *runtime, PyThreadState *tstate) { - _PyGILState_NoteThreadState(tstate); + _PyGILState_NoteThreadState(&runtime->gilstate, tstate); } PyObject* @@ -1037,17 +1042,23 @@ PyThreadState_IsCurrent(PyThreadState *tstate) Py_Initialize/Py_FinalizeEx */ void -_PyGILState_Init(PyInterpreterState *i, PyThreadState *t) +_PyGILState_Init(PyInterpreterState *interp, PyThreadState *tstate) { - assert(i && t); /* must init with valid states */ - if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) { + /* must init with valid states */ + assert(interp != NULL); + assert(tstate != NULL); + + _PyRuntimeState *runtime = &_PyRuntime; + struct _gilstate_runtime_state *gilstate = &runtime->gilstate; + + if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { Py_FatalError("Could not allocate TSS entry"); } - _PyRuntime.gilstate.autoInterpreterState = i; - assert(PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL); - assert(t->gilstate_counter == 0); + gilstate->autoInterpreterState = interp; + assert(PyThread_tss_get(&gilstate->autoTSSkey) == NULL); + assert(tstate->gilstate_counter == 0); - _PyGILState_NoteThreadState(t); + _PyGILState_NoteThreadState(gilstate, tstate); } PyInterpreterState * @@ -1104,13 +1115,14 @@ _PyGILState_Reinit(void) a better fix for SF bug #1010677 than the first one attempted). */ static void -_PyGILState_NoteThreadState(PyThreadState* tstate) +_PyGILState_NoteThreadState(struct _gilstate_runtime_state *gilstate, PyThreadState* tstate) { /* If autoTSSkey isn't initialized, this must be the very first threadstate created in Py_Initialize(). Don't do anything for now (we'll be back here when _PyGILState_Init is called). */ - if (!_PyRuntime.gilstate.autoInterpreterState) + if (!gilstate->autoInterpreterState) { return; + } /* Stick the thread state for this thread in thread specific storage. @@ -1124,10 +1136,8 @@ _PyGILState_NoteThreadState(PyThreadState* tstate) The first thread state created for that given OS level thread will "win", which seems reasonable behaviour. */ - if (PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL) { - if ((PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate) - ) != 0) - { + if (PyThread_tss_get(&gilstate->autoTSSkey) == NULL) { + if ((PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate)) != 0) { Py_FatalError("Couldn't create autoTSSkey mapping"); } } From 1bfc63875981da8f138ba414f624059176cc7c49 Mon Sep 17 00:00:00 2001 From: Michael Felt Date: Wed, 24 Apr 2019 15:05:14 +0000 Subject: [PATCH 065/212] Replace another 60+ references to sys.platform with constants --- Lib/test/eintrdata/eintr_tester.py | 10 ++-- Lib/test/libregrtest/main.py | 2 +- Lib/test/libregrtest/setup.py | 2 +- Lib/test/support/__init__.py | 54 +++++++++---------- Lib/test/support/script_helper.py | 4 +- Lib/test/test_asyncio/test_events.py | 50 ++++++++--------- Lib/test/test_asyncio/test_proactor_events.py | 3 +- Lib/test/test_asyncio/test_sendfile.py | 7 +-- Lib/test/test_asyncio/test_sock_lowlevel.py | 2 +- Lib/test/test_asyncio/test_streams.py | 4 +- Lib/test/test_asyncio/test_subprocess.py | 15 +++--- Lib/test/test_asyncio/test_unix_events.py | 2 +- Lib/test/test_asyncio/test_windows_events.py | 3 +- Lib/test/test_asyncio/test_windows_utils.py | 4 +- Lib/test/test_c_locale_coercion.py | 2 +- Lib/test/test_codeop.py | 8 +-- Lib/test/test_email/test_utils.py | 4 +- Lib/test/test_faulthandler.py | 4 +- Lib/test/test_import/__init__.py | 12 ++--- Lib/test/test_importlib/source/test_finder.py | 4 +- Lib/test/test_importlib/test_windows.py | 4 +- Lib/test/test_importlib/util.py | 2 +- Lib/test/test_socket.py | 2 +- Lib/test/test_strptime.py | 2 +- Lib/test/test_tools/test_sundry.py | 2 +- 25 files changed, 101 insertions(+), 107 deletions(-) diff --git a/Lib/test/eintrdata/eintr_tester.py b/Lib/test/eintrdata/eintr_tester.py index 404934ce97a2bf..e76d7ffec200ea 100644 --- a/Lib/test/eintrdata/eintr_tester.py +++ b/Lib/test/eintrdata/eintr_tester.py @@ -22,6 +22,7 @@ import unittest from test import support +from test.support import MACOS @contextlib.contextmanager def kill_on_error(proc): @@ -347,8 +348,7 @@ def python_open(self, path): fp = open(path, 'w') fp.close() - @unittest.skipIf(sys.platform == "darwin", - "hangs under macOS; see bpo-25234, bpo-35363") + @unittest.skipIf(MACOS, "hangs under macOS; see bpo-25234, bpo-35363") def test_open(self): self._test_open("fp = open(path, 'r')\nfp.close()", self.python_open) @@ -357,8 +357,7 @@ def os_open(self, path): fd = os.open(path, os.O_WRONLY) os.close(fd) - @unittest.skipIf(sys.platform == "darwin", - "hangs under macOS; see bpo-25234, bpo-35363") + @unittest.skipIf(MACOS, "hangs under macOS; see bpo-25234, bpo-35363") def test_os_open(self): self._test_open("fd = os.open(path, os.O_RDONLY)\nos.close(fd)", self.os_open) @@ -439,8 +438,7 @@ def test_select(self): self.stop_alarm() self.assertGreaterEqual(dt, self.sleep_time) - @unittest.skipIf(sys.platform == "darwin", - "poll may fail on macOS; see issue #28087") + @unittest.skipIf(MACOS, "poll may fail on macOS; see issue #28087") @unittest.skipUnless(hasattr(select, 'poll'), 'need select.poll') def test_poll(self): poller = select.poll() diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 18ef6d0609cd63..a4579b7d5d81c1 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -623,7 +623,7 @@ def _main(self, tests, kwargs): def getloadavg_1m(): return os.getloadavg()[0] self.getloadavg = getloadavg_1m - elif sys.platform == 'win32' and (self.ns.worker_args is None): + elif support.MS_WINDOWS and (self.ns.worker_args is None): from test.libregrtest.win_utils import WindowsLoadTracker load_tracker = WindowsLoadTracker() diff --git a/Lib/test/libregrtest/setup.py b/Lib/test/libregrtest/setup.py index 9a6585af9d0dd6..b8c8a64fe0c281 100644 --- a/Lib/test/libregrtest/setup.py +++ b/Lib/test/libregrtest/setup.py @@ -64,7 +64,7 @@ def setup_tests(ns): # fix is to set the stack limit to 2048. # This approach may also be useful for other Unixy platforms that # suffer from small default stack limits. - if sys.platform == 'darwin': + if support.MACOS: try: import resource except ImportError: diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 891bb878bcfc1a..49bf8b1ccbc989 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -36,6 +36,14 @@ import urllib.error import warnings +ANDROID = hasattr(sys, 'getandroidapilevel') +JYTHON = sys.platform.startswith('java') + +AIX = platform.system() == 'AIX' +LINUX = platform.system() == 'Linux' +MACOS = platform.system() == 'Darwin' +MS_WINDOWS = platform.system() == 'Windows' + from .testresult import get_test_runner try: @@ -96,7 +104,7 @@ "check__all__", "skip_unless_bind_unix_socket", "ignore_warnings", # sys - "is_jython", "is_android", "check_impl_detail", "unix_shell", + "check_impl_detail", "unix_shell", "ANDROID", "JYTHON", "setswitchinterval", # network @@ -337,7 +345,7 @@ def _force_run(path, func, *args): os.chmod(path, stat.S_IRWXU) return func(*args) -if sys.platform.startswith("win"): +if MS_WINDOWS: def _waitfor(func, pathname, waitall=False): # Perform the operation func(pathname) @@ -488,7 +496,7 @@ def _is_gui_available(): if hasattr(_is_gui_available, 'result'): return _is_gui_available.result reason = None - if sys.platform.startswith('win'): + if MS_WINDOWS: # if Python is running as a service (such as the buildbot service), # gui interaction may be disallowed import ctypes @@ -514,7 +522,7 @@ class USEROBJECTFLAGS(ctypes.Structure): raise ctypes.WinError() if not bool(uof.dwFlags & WSF_VISIBLE): reason = "gui not available (WSF_VISIBLE flag not set)" - elif sys.platform == 'darwin': + elif MACOS: # The Aqua Tk implementations on OS X can abort the process if # being called in an environment where a window server connection # cannot be made, for instance when invoked by a buildbot or ssh @@ -630,7 +638,7 @@ def requires_mac_ver(*min_version): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): - if sys.platform == 'darwin': + if MACOS: version_txt = platform.mac_ver()[0] try: version = tuple(map(int, version_txt.split('.'))) @@ -817,20 +825,8 @@ def dec(*args, **kwargs): requires_lzma = unittest.skipUnless(lzma, 'requires lzma') -ANDROID = hasattr(sys, 'getandroidapilevel') -JYTHON = sys.platform.startswith('java') - -AIX = platform.system() == 'AIX' -LINUX = platform.system() == 'Linux' -MACOS = platform.system() == 'Darwin' -MS_WINDOWS = platform.system() == 'Windows' - -is_jython = sys.platform.startswith('java') - -is_android = hasattr(sys, 'getandroidapilevel') - -if sys.platform != 'win32': - unix_shell = '/system/bin/sh' if is_android else '/bin/sh' +if not MS_WINDOWS: + unix_shell = '/system/bin/sh' if ANDROID else '/bin/sh' else: unix_shell = None @@ -899,7 +895,7 @@ def dec(*args, **kwargs): # TESTFN_UNICODE is a non-ascii filename TESTFN_UNICODE = TESTFN + "-\xe0\xf2\u0258\u0141\u011f" -if sys.platform == 'darwin': +if MACOS: # In Mac OS X's VFS API file names are, by definition, canonically # decomposed Unicode, encoded using UTF-8. See QA1173: # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html @@ -927,7 +923,7 @@ def dec(*args, **kwargs): % (TESTFN_UNENCODABLE, TESTFN_ENCODING)) TESTFN_UNENCODABLE = None # Mac OS X denies unencodable filenames (invalid utf-8) -elif sys.platform != 'darwin': +elif not MACOS: try: # ascii and utf-8 cannot encode the byte 0xff b'\xff'.decode(TESTFN_ENCODING) @@ -1620,7 +1616,7 @@ def gc_collect(): objects to disappear. """ gc.collect() - if is_jython: + if JYTHON: time.sleep(0.1) gc.collect() gc.collect() @@ -2084,7 +2080,7 @@ def _check_docstrings(): """Just used to check if docstrings are enabled""" MISSING_C_DOCSTRINGS = (check_impl_detail() and - sys.platform != 'win32' and + not MS_WINDOWS and not sysconfig.get_config_var('WITH_DOC_STRINGS')) HAVE_DOCSTRINGS = (_check_docstrings.__doc__ is not None and @@ -2656,7 +2652,7 @@ def __enter__(self): On UNIX, try to save the previous core file size limit, then set soft limit to 0. """ - if sys.platform.startswith('win'): + if MS_WINDOWS: # see http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621.aspx # GetErrorMode is not available on Windows XP and Windows Server 2003, # but SetErrorMode returns the previous value, so we can use that @@ -2694,7 +2690,7 @@ def __enter__(self): except (ValueError, OSError): pass - if sys.platform == 'darwin': + if MACOS: # Check if the 'Crash Reporter' on OSX was configured # in 'Developer' mode and warn that it will get triggered # when it is. @@ -2719,7 +2715,7 @@ def __exit__(self, *ignore_exc): if self.old_value is None: return - if sys.platform.startswith('win'): + if MS_WINDOWS: self._k32.SetErrorMode(self.old_value) if self.old_modes: @@ -2838,7 +2834,7 @@ def setswitchinterval(interval): # Setting a very low gil interval on the Android emulator causes python # to hang (issue #26939). minimum_interval = 1e-5 - if is_android and interval < minimum_interval: + if ANDROID and interval < minimum_interval: global _is_android_emulator if _is_android_emulator is None: _is_android_emulator = (subprocess.check_output( @@ -2867,7 +2863,7 @@ def disable_faulthandler(): def fd_count(): """Count the number of open file descriptors. """ - if sys.platform.startswith(('linux', 'freebsd')): + if LINUX or sys.platform.startswith('freebsd'): try: names = os.listdir("/proc/self/fd") # Substract one because listdir() opens internally a file @@ -2884,7 +2880,7 @@ def fd_count(): pass old_modes = None - if sys.platform == 'win32': + if MACOS: # bpo-25306, bpo-31009: Call CrtSetReportMode() to not kill the process # on invalid file descriptor if Python is compiled in debug mode try: diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py index 27a47f2c4e668c..02411b97a46e8c 100644 --- a/Lib/test/support/script_helper.py +++ b/Lib/test/support/script_helper.py @@ -11,7 +11,7 @@ import zipfile from importlib.util import source_from_cache -from test.support import make_legacy_pyc, strip_python_stderr +from test.support import make_legacy_pyc, strip_python_stderr, MS_WINDOWS # Cached result of the expensive test performed in the function below. @@ -105,7 +105,7 @@ def run_python_until_end(*args, **env_vars): # caller is responsible to pass the full environment. if env_vars.pop('__cleanenv', None): env = {} - if sys.platform == 'win32': + if MS_WINDOWS: # Windows requires at least the SYSTEMROOT environment variable to # start Python. env['SYSTEMROOT'] = os.environ['SYSTEMROOT'] diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index b46b614e556eae..0148a48a5dfec6 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -22,7 +22,10 @@ from unittest import mock import weakref -if sys.platform != 'win32': +from test import support +from test.support import AIX, MACOS, MS_WINDOWS + +if not MS_WINDOWS: import tty import asyncio @@ -33,7 +36,6 @@ from asyncio import proactor_events from asyncio import selector_events from test.test_asyncio import utils as test_utils -from test import support def tearDownModule(): @@ -42,9 +44,9 @@ def tearDownModule(): def broken_unix_getsockname(): """Return True if the platform is Mac OS 10.4 or older.""" - if sys.platform.startswith("aix"): + if AIX: return True - elif sys.platform != 'darwin': + elif not MACOS: return False version = platform.mac_ver()[0] version = tuple(map(int, version.split('.'))) @@ -710,7 +712,7 @@ def client(): @unittest.skipIf(ssl is None, 'No ssl module') def test_ssl_connect_accepted_socket(self): - if (sys.platform == 'win32' and + if (MS_WINDOWS and sys.version_info < (3, 5) and isinstance(self.loop, proactor_events.BaseProactorEventLoop) ): @@ -1252,7 +1254,7 @@ def datagram_received(self, data, addr): server.transport.close() def test_create_datagram_endpoint_sock(self): - if (sys.platform == 'win32' and + if (MS_WINDOWS and isinstance(self.loop, proactor_events.BaseProactorEventLoop)): raise unittest.SkipTest( 'UDP is not supported with proactor event loops') @@ -1294,7 +1296,7 @@ def test_internal_fds(self): self.assertIsNone(loop._csock) self.assertIsNone(loop._ssock) - @unittest.skipUnless(sys.platform != 'win32', + @unittest.skipUnless(MS_WINDOWS, "Don't support pipes for Windows") def test_read_pipe(self): proto = MyReadPipeProto(loop=self.loop) @@ -1328,8 +1330,7 @@ async def connect(): # extra info is available self.assertIsNotNone(proto.transport.get_extra_info('pipe')) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") def test_unclosed_pipe_transport(self): # This test reproduces the issue #314 on GitHub loop = self.create_event_loop() @@ -1362,8 +1363,7 @@ async def connect(): read_transport._pipe = None write_transport._pipe = None - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") def test_read_pty_output(self): proto = MyReadPipeProto(loop=self.loop) @@ -1397,8 +1397,7 @@ async def connect(): # extra info is available self.assertIsNotNone(proto.transport.get_extra_info('pipe')) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") def test_write_pipe(self): rpipe, wpipe = os.pipe() pipeobj = io.open(wpipe, 'wb', 1024) @@ -1436,8 +1435,7 @@ def reader(data): self.loop.run_until_complete(proto.done) self.assertEqual('CLOSED', proto.state) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") def test_write_pipe_disconnect_on_close(self): rsock, wsock = socket.socketpair() rsock.setblocking(False) @@ -1459,8 +1457,7 @@ def test_write_pipe_disconnect_on_close(self): self.loop.run_until_complete(proto.done) self.assertEqual('CLOSED', proto.state) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") # select, poll and kqueue don't support character devices (PTY) on Mac OS X # older than 10.6 (Snow Leopard) @support.requires_mac_ver(10, 6) @@ -1503,8 +1500,7 @@ def reader(data): self.loop.run_until_complete(proto.done) self.assertEqual('CLOSED', proto.state) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") # select, poll and kqueue don't support character devices (PTY) on Mac OS X # older than 10.6 (Snow Leopard) @support.requires_mac_ver(10, 6) @@ -1711,14 +1707,14 @@ def test(): class SubprocessTestsMixin: def check_terminated(self, returncode): - if sys.platform == 'win32': + if MS_WINDOWS: self.assertIsInstance(returncode, int) # expect 1 but sometimes get 0 else: self.assertEqual(-signal.SIGTERM, returncode) def check_killed(self, returncode): - if sys.platform == 'win32': + if MS_WINDOWS: self.assertIsInstance(returncode, int) # expect 1 but sometimes get 0 else: @@ -1839,7 +1835,7 @@ def test_subprocess_terminate(self): self.check_terminated(proto.returncode) transp.close() - @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") + @unittest.skipIf(MS_WINDOWS, "Don't have SIGHUP") def test_subprocess_send_signal(self): # bpo-31034: Make sure that we get the default signal handler (killing # the process). The parent process may have decided to ignore SIGHUP, @@ -1925,7 +1921,7 @@ def test_subprocess_close_client_stream(self): self.loop.run_until_complete(proto.disconnects[1]) stdin.write(b'xxx') self.loop.run_until_complete(proto.got_data[2].wait()) - if sys.platform != 'win32': + if not MS_WINDOWS: self.assertEqual(b'ERR:BrokenPipeError', proto.data[2]) else: # After closing the read-end of a pipe, writing to the @@ -1982,7 +1978,7 @@ async def connect(cmd=None, **kwds): self.loop.run_until_complete(connect(shell=False)) -if sys.platform == 'win32': +if MS_WINDOWS: class SelectEventLoopTests(EventLoopTestsMixin, test_utils.TestCase): @@ -2601,14 +2597,14 @@ def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) - if sys.platform != 'win32': + if not MS_WINDOWS: watcher = asyncio.SafeChildWatcher() watcher.attach_loop(self.loop) asyncio.set_child_watcher(watcher) def tearDown(self): try: - if sys.platform != 'win32': + if not MS_WINDOWS: asyncio.set_child_watcher(None) super().tearDown() @@ -2626,7 +2622,7 @@ def tearDown(self): asyncio.get_running_loop = self.get_running_loop_saved asyncio.get_event_loop = self.get_event_loop_saved - if sys.platform != 'win32': + if not MS_WINDOWS: def test_get_event_loop_new_process(self): # Issue bpo-32126: The multiprocessing module used by diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 5952ccccce0e5d..fad2bfd6c281c5 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -865,8 +865,7 @@ def test_stop_serving(self): self.assertFalse(future2.cancel.called) -@unittest.skipIf(sys.platform != 'win32', - 'Proactor is supported on Windows only') +@unittest.skipUnless(support.MS_WINDOWS, 'Proactor is supported on Windows only') class ProactorEventLoopUnixSockSendfileTests(test_utils.TestCase): DATA = b"12345abcde" * 16 * 1024 # 160 KiB diff --git a/Lib/test/test_asyncio/test_sendfile.py b/Lib/test/test_asyncio/test_sendfile.py index f148fe27e6ad40..18afe1b6ff8a46 100644 --- a/Lib/test/test_asyncio/test_sendfile.py +++ b/Lib/test/test_asyncio/test_sendfile.py @@ -10,6 +10,7 @@ from asyncio import constants from unittest import mock from test import support +from test.support import MS_WINDOWS from test.test_asyncio import utils as test_utils try: @@ -281,7 +282,7 @@ def cleanup(): self.addCleanup(cleanup) return srv_proto, cli_proto - @unittest.skipIf(sys.platform == 'win32', "UDP sockets are not supported") + @unittest.skipIf(MS_WINDOWS, "UDP sockets are not supported") def test_sendfile_not_supported(self): tr, pr = self.run_loop( self.loop.create_datagram_endpoint( @@ -327,7 +328,7 @@ def sendfile_native(transp, file, offset, count): self.assertEqual(self.file.tell(), len(self.DATA)) def test_sendfile_force_unsupported_native(self): - if sys.platform == 'win32': + if MS_WINDOWS: if isinstance(self.loop, asyncio.ProactorEventLoop): self.skipTest("Fails on proactor event loop") srv_proto, cli_proto = self.prepare_sendfile() @@ -507,7 +508,7 @@ class SendfileTestsBase(SendfileMixin, SockSendfileMixin): pass -if sys.platform == 'win32': +if MS_WINDOWS: class SelectEventLoopTests(SendfileTestsBase, test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py index 7b40a765e4a01f..04f939c9bac203 100644 --- a/Lib/test/test_asyncio/test_sock_lowlevel.py +++ b/Lib/test/test_asyncio/test_sock_lowlevel.py @@ -296,7 +296,7 @@ def test_create_connection_sock(self): tr.close() -if sys.platform == 'win32': +if support.MS_WINDOWS: class SelectEventLoopTests(BaseSockTestsMixin, test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 630f91dbf4780f..6a4942f1350e63 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -10,6 +10,8 @@ import unittest from unittest import mock from test import support +from test.support import MS_WINDOWS + try: import ssl except ImportError: @@ -724,7 +726,7 @@ async def client(path): self.assertEqual(messages, []) - @unittest.skipIf(sys.platform == 'win32', "Don't have pipes") + @unittest.skipIf(MS_WINDOWS, "Don't have pipes") def test_read_all_from_pipe_reader(self): # See asyncio issue 168. This test is derived from the example # subprocess_attach_read_pipe.py, but we configure the diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index a5bdb8eca517d3..cfab282a07d2b6 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -9,8 +9,9 @@ from asyncio import subprocess from test.test_asyncio import utils as test_utils from test import support +from test.support import MS_WINDOWS -if sys.platform != 'win32': +if not MS_WINDOWS: from asyncio import unix_events # Program blocking @@ -171,7 +172,7 @@ def test_kill(self): proc = self.loop.run_until_complete(create) proc.kill() returncode = self.loop.run_until_complete(proc.wait()) - if sys.platform == 'win32': + if MS_WINDOWS: self.assertIsInstance(returncode, int) # expect 1 but sometimes get 0 else: @@ -183,13 +184,13 @@ def test_terminate(self): proc = self.loop.run_until_complete(create) proc.terminate() returncode = self.loop.run_until_complete(proc.wait()) - if sys.platform == 'win32': + if MS_WINDOWS: self.assertIsInstance(returncode, int) # expect 1 but sometimes get 0 else: self.assertEqual(-signal.SIGTERM, returncode) - @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") + @unittest.skipIf(MS_WINDOWS, "Don't have SIGHUP") def test_send_signal(self): # bpo-31034: Make sure that we get the default signal handler (killing # the process). The parent process may have decided to ignore SIGHUP, @@ -464,14 +465,14 @@ async def kill_running(): # Unlike SafeChildWatcher, FastChildWatcher does not pop the # callbacks if waitpid() is called elsewhere. Let's clear them # manually to avoid a warning when the watcher is detached. - if (sys.platform != 'win32' and + if (not MS_WINDOWS and isinstance(self, SubprocessFastWatcherTests)): asyncio.get_child_watcher()._callbacks.clear() def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - if sys.platform == 'win32': + if MS_WINDOWS: target = 'asyncio.windows_utils.Popen' else: target = 'subprocess.Popen' @@ -511,7 +512,7 @@ async def execute(): self.loop.run_until_complete(execute()) -if sys.platform != 'win32': +if not MS_WINDOWS: # Unix class SubprocessWatcherMixin(SubprocessMixin): diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 31e710037f76a3..bd7ba4c83da901 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -16,7 +16,7 @@ from unittest import mock from test import support -if sys.platform == 'win32': +if support.MS_WINDOWS: raise unittest.SkipTest('UNIX only') diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index 05f85159be0cd5..78de46d002c748 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -7,8 +7,9 @@ import threading import unittest from unittest import mock +from test.support import MS_WINDOWS -if sys.platform != 'win32': +if not MS_WINDOWS: raise unittest.SkipTest('Windows only') import _overlapped diff --git a/Lib/test/test_asyncio/test_windows_utils.py b/Lib/test/test_asyncio/test_windows_utils.py index 45c09bb4a2d3a0..5bf399a4298b5c 100644 --- a/Lib/test/test_asyncio/test_windows_utils.py +++ b/Lib/test/test_asyncio/test_windows_utils.py @@ -3,8 +3,9 @@ import sys import unittest import warnings +from test import support -if sys.platform != 'win32': +if not support.MS_WINDOWS: raise unittest.SkipTest('Windows only') import _overlapped @@ -12,7 +13,6 @@ import asyncio from asyncio import windows_utils -from test import support def tearDownModule(): diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index 73610fd9fba4f0..8d3c0edf87a72e 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -349,7 +349,7 @@ def _check_c_locale_coercion(self, # locale environment variables are undefined or empty. When # this code path is run with environ['LC_ALL'] == 'C', then # LEGACY_LOCALE_WARNING is printed. - if (support.is_android and + if (support.ANDROID and _expected_warnings == [CLI_COERCION_WARNING]): _expected_warnings = None self._check_child_encoding_details(base_var_dict, diff --git a/Lib/test/test_codeop.py b/Lib/test/test_codeop.py index 98da26fa5dab13..71d9432ddd1d2b 100644 --- a/Lib/test/test_codeop.py +++ b/Lib/test/test_codeop.py @@ -3,12 +3,12 @@ Nick Mathewson """ import unittest -from test.support import is_jython +from test.support import JYTHON from codeop import compile_command, PyCF_DONT_IMPLY_DEDENT import io -if is_jython: +if JYTHON: import sys def unify_callables(d): @@ -21,7 +21,7 @@ class CodeopTests(unittest.TestCase): def assertValid(self, str, symbol='single'): '''succeed iff str is a valid piece of code''' - if is_jython: + if JYTHON: code = compile_command(str, "", symbol) self.assertTrue(code) if symbol == "single": @@ -60,7 +60,7 @@ def test_valid(self): av = self.assertValid # special case - if not is_jython: + if not JYTHON: self.assertEqual(compile_command(""), compile("pass", "", 'single', PyCF_DONT_IMPLY_DEDENT)) diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py index 4e3c3f3a195fc4..4fbdd47c2fa3cf 100644 --- a/Lib/test/test_email/test_utils.py +++ b/Lib/test/test_email/test_utils.py @@ -1,6 +1,7 @@ import datetime from email import utils import test.support +from test.support import MS_WINDOWS import time import unittest import sys @@ -124,8 +125,7 @@ def test_localtime_epoch_notz_daylight_false(self): self.assertEqual(t1, t2) # XXX: Need a more robust test for Olson's tzdata - @unittest.skipIf(sys.platform.startswith('win'), - "Windows does not use Olson's TZ database") + @unittest.skipIf(MS_WINDOWS, "Windows does not use Olson's TZ database") @unittest.skipUnless(os.path.exists('/usr/share/zoneinfo') or os.path.exists('/usr/lib/zoneinfo'), "Can't find the Olson's TZ database") diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 2e1d8513ca5639..f35fc0ff07a7c9 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -7,7 +7,7 @@ import sys import sysconfig from test import support -from test.support import script_helper, is_android, AIX, MS_WINDOWS +from test.support import script_helper, ANDROID, AIX, MS_WINDOWS import tempfile import threading import unittest @@ -42,7 +42,7 @@ def expected_traceback(lineno1, lineno2, header, min_count=1): def skip_segfault_on_android(test): # Issue #32138: Raising SIGSEGV on Android may not cause a crash. - return unittest.skipIf(is_android, + return unittest.skipIf(ANDROID, 'raising SIGSEGV on Android is unreliable')(test) @contextmanager diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index a0bfe1a6c19b3e..d805ed198f795f 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -23,10 +23,10 @@ import test.support from test.support import ( - EnvironmentVarGuard, TESTFN, check_warnings, forget, is_jython, + EnvironmentVarGuard, TESTFN, check_warnings, forget, JYTHON, make_legacy_pyc, rmtree, run_unittest, swap_attr, swap_item, temp_umask, unlink, unload, create_empty_file, cpython_only, TESTFN_UNENCODABLE, - temp_dir, DirsOnSysPath) + temp_dir, DirsOnSysPath, MS_WINDOWS) from test.support import script_helper from test.test_importlib.util import uncache @@ -151,7 +151,7 @@ def test_import(self): def test_with_extension(ext): # The extension is normally ".py", perhaps ".pyw". source = TESTFN + ext - if is_jython: + if JYTHON: pyc = TESTFN + "$py.class" else: pyc = TESTFN + ".pyc" @@ -185,7 +185,7 @@ def test_with_extension(ext): sys.path.insert(0, os.curdir) try: test_with_extension(".py") - if sys.platform.startswith("win"): + if MS_WINDOWS: for ext in [".PY", ".Py", ".pY", ".pyw", ".PYW", ".pYw"]: test_with_extension(ext) finally: @@ -463,7 +463,7 @@ def run(): finally: del sys.path[0] - @unittest.skipUnless(sys.platform == "win32", "Windows-specific") + @unittest.skipUnless(MS_WINDOWS, "Windows-specific") def test_dll_dependency_import(self): from _winapi import GetModuleFileName dllname = GetModuleFileName(sys.dllhandle) @@ -710,7 +710,7 @@ def test_trailing_slash(self): unload("test_trailing_slash") # Regression test for http://bugs.python.org/issue3677. - @unittest.skipUnless(sys.platform == 'win32', 'Windows-specific') + @unittest.skipUnless(MS_WINDOWS, 'Windows-specific') def test_UNC_path(self): with open(os.path.join(self.path, 'test_unc_path.py'), 'w') as f: f.write("testdata = 'test_unc_path'") diff --git a/Lib/test/test_importlib/source/test_finder.py b/Lib/test/test_importlib/source/test_finder.py index f372b850dc7c15..bdad0c69cfa334 100644 --- a/Lib/test/test_importlib/source/test_finder.py +++ b/Lib/test/test_importlib/source/test_finder.py @@ -9,7 +9,7 @@ import stat import sys import tempfile -from test.support import make_legacy_pyc +from test.support import make_legacy_pyc, MS_WINDOWS import unittest import warnings @@ -153,7 +153,7 @@ def test_dir_removal_handling(self): found = self._find(finder, 'mod', loader_only=True) self.assertIsNone(found) - @unittest.skipUnless(sys.platform != 'win32', + @unittest.skipIf(MS_WINDOWS, 'os.chmod() does not support the needed arguments under Windows') def test_no_read_directory(self): # Issue #16730 diff --git a/Lib/test/test_importlib/test_windows.py b/Lib/test/test_importlib/test_windows.py index 005b685cc03cd9..115b7f842823ec 100644 --- a/Lib/test/test_importlib/test_windows.py +++ b/Lib/test/test_importlib/test_windows.py @@ -54,7 +54,7 @@ def setup_module(machinery, name, path=None): delete_registry_tree(HKEY_CURRENT_USER, key) -@unittest.skipUnless(sys.platform.startswith('win'), 'requires Windows') +@unittest.skipUnless(support.MS_WINDOWS, 'requires Windows') class WindowsRegistryFinderTests: # The module name is process-specific, allowing for # simultaneous runs of the same test on a single machine. @@ -86,7 +86,7 @@ def test_module_not_found(self): Source_WindowsRegistryFinderTests ) = test_util.test_both(WindowsRegistryFinderTests, machinery=machinery) -@unittest.skipUnless(sys.platform.startswith('win'), 'requires Windows') +@unittest.skipUnless(support.MS_WINDOWS, 'requires Windows') class WindowsExtensionSuffixTests: def test_tagged_suffix(self): suffixes = self.machinery.EXTENSION_SUFFIXES diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index 196ea1c9d4dda5..b3f3fd5e85345e 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -92,7 +92,7 @@ def test_both(test_class, base=None, **kwargs): CASE_INSENSITIVE_FS = True # Windows is the only OS that is *always* case-insensitive # (OS X *can* be case-sensitive). -if sys.platform not in ('win32', 'cygwin'): +if not (support.MS_WINDOWS or support.MACOS): changed_name = __file__.upper() if changed_name == __file__: changed_name = __file__.lower() diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 2f3b061ef96ce4..56a40cf0703ece 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1077,7 +1077,7 @@ def testGetServBy(self): eq(udpport, port) # Now make sure the lookup by port returns the same service name # Issue #26936: Android getservbyport() is broken. - if not support.is_android: + if not support.ANDROID: eq(socket.getservbyport(port2), service) eq(socket.getservbyport(port, 'tcp'), service) if udpport is not None: diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 6285744aeb1ac2..64bf539efb3af6 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -522,7 +522,7 @@ def test_day_of_week_calculation(self): "Calculation of day of the week failed; " "%s != %s" % (result.tm_wday, self.time_tuple.tm_wday)) - if support.is_android: + if support.ANDROID: # Issue #26929: strftime() on Android incorrectly formats %V or %G for # the last or the first incomplete week in a year. _ymd_excluded = ((1905, 1, 1), (1906, 12, 31), (2008, 12, 29), diff --git a/Lib/test/test_tools/test_sundry.py b/Lib/test/test_tools/test_sundry.py index f5fed01491e3f6..7bad03256306a1 100644 --- a/Lib/test/test_tools/test_sundry.py +++ b/Lib/test/test_tools/test_sundry.py @@ -45,7 +45,7 @@ def test_sundry(self): # Unload all modules loaded in this test support.modules_cleanup(*old_modules) - @unittest.skipIf(sys.platform != "win32", "Windows-only test") + @unittest.skipUnless(support.MS_WINDOWS, "Windows-only test") def test_sundry_windows(self): for name in self.windows_only: import_tool(name) From b930a2d2b1247bdba560db341ba90a9cbb538eb3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 24 Apr 2019 17:14:33 +0200 Subject: [PATCH 066/212] bpo-36710: PyOS_AfterFork_Child() pass runtime parameter (GH-12936) The PyOS_AfterFork_Child() function now pass a 'runtime' parameter to subfunctions. * Fix _PyRuntimeState_ReInitThreads(): use the correct memory allocator * Add runtime parameter to _PyRuntimeState_ReInitThreads(), _PyGILState_Reinit() and _PyInterpreterState_DeleteExceptMain() * Move _PyGILState_Reinit() to the internal C API. --- Include/cpython/pystate.h | 1 - Include/internal/pycore_pystate.h | 12 +++--- Modules/posixmodule.c | 7 ++-- Python/pystate.c | 65 +++++++++++++++---------------- 4 files changed, 43 insertions(+), 42 deletions(-) diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 2341dda3fabdbf..94331f35e1bd43 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -155,7 +155,6 @@ PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void); PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*); PyAPI_FUNC(void) _PyState_ClearModules(void); PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *); -PyAPI_FUNC(void) _PyGILState_Reinit(void); /* Similar to PyThreadState_Get(), but don't issue a fatal error * if it is NULL. */ diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 509ca3634a3a13..2c24f679dc0203 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -185,9 +185,9 @@ typedef struct pyruntimestate { /* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */ PyAPI_DATA(_PyRuntimeState) _PyRuntime; -PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *); -PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *); -PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(void); +PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *runtime); +PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime); +PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime); /* Initialize _PyRuntimeState. Return NULL on success, or return an error message on failure. */ @@ -236,8 +236,10 @@ PyAPI_FUNC(void) _PyThreadState_Init( PyThreadState *tstate); PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate); -PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *); -PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(void); +PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *runtime); +PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime); + +PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime); #ifdef __cplusplus } diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e8dbdcc94aa701..56ec3ee5a0eed3 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -421,12 +421,13 @@ PyOS_AfterFork_Parent(void) void PyOS_AfterFork_Child(void) { - _PyGILState_Reinit(); - _PyInterpreterState_DeleteExceptMain(); + _PyRuntimeState *runtime = &_PyRuntime; + _PyGILState_Reinit(runtime); + _PyInterpreterState_DeleteExceptMain(runtime); PyEval_ReInitThreads(); _PyImport_ReInitLock(); _PySignal_AfterFork(); - _PyRuntimeState_ReInitThreads(); + _PyRuntimeState_ReInitThreads(runtime); run_at_forkers(_PyInterpreterState_Get()->after_forkers_child, 0); } diff --git a/Python/pystate.c b/Python/pystate.c index ef9d79288736d5..6aaf993cfe2cd2 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -108,23 +108,31 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime) */ void -_PyRuntimeState_ReInitThreads(void) +_PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) { // This was initially set in _PyRuntimeState_Init(). - _PyRuntime.main_thread = PyThread_get_thread_ident(); + runtime->main_thread = PyThread_get_thread_ident(); + + /* Force default allocator, since _PyRuntimeState_Fini() must + use the same allocator than this function. */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + runtime->interpreters.mutex = PyThread_allocate_lock(); + runtime->interpreters.main->id_mutex = PyThread_allocate_lock(); + runtime->xidregistry.mutex = PyThread_allocate_lock(); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - _PyRuntime.interpreters.mutex = PyThread_allocate_lock(); - if (_PyRuntime.interpreters.mutex == NULL) { + if (runtime->interpreters.mutex == NULL) { Py_FatalError("Can't initialize lock for runtime interpreters"); } - _PyRuntime.interpreters.main->id_mutex = PyThread_allocate_lock(); - if (_PyRuntime.interpreters.main->id_mutex == NULL) { + if (runtime->interpreters.main->id_mutex == NULL) { Py_FatalError("Can't initialize ID lock for main interpreter"); } - _PyRuntime.xidregistry.mutex = PyThread_allocate_lock(); - if (_PyRuntime.xidregistry.mutex == NULL) { + if (runtime->xidregistry.mutex == NULL) { Py_FatalError("Can't initialize lock for cross-interpreter data registry"); } } @@ -290,20 +298,22 @@ PyInterpreterState_Delete(PyInterpreterState *interp) * is a current interpreter state, it *must* be the main interpreter. */ void -_PyInterpreterState_DeleteExceptMain() +_PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) { + struct pyinterpreters *interpreters = &runtime->interpreters; + PyThreadState *tstate = PyThreadState_Swap(NULL); - if (tstate != NULL && tstate->interp != _PyRuntime.interpreters.main) { + if (tstate != NULL && tstate->interp != interpreters->main) { Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter"); } HEAD_LOCK(); - PyInterpreterState *interp = _PyRuntime.interpreters.head; - _PyRuntime.interpreters.head = NULL; + PyInterpreterState *interp = interpreters->head; + interpreters->head = NULL; while (interp != NULL) { - if (interp == _PyRuntime.interpreters.main) { - _PyRuntime.interpreters.main->next = NULL; - _PyRuntime.interpreters.head = interp; + if (interp == interpreters->main) { + interpreters->main->next = NULL; + interpreters->head = interp; interp = interp->next; continue; } @@ -319,7 +329,7 @@ _PyInterpreterState_DeleteExceptMain() } HEAD_UNLOCK(); - if (_PyRuntime.interpreters.head == NULL) { + if (interpreters->head == NULL) { Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main"); } PyThreadState_Swap(tstate); @@ -1079,31 +1089,20 @@ _PyGILState_Fini(void) * don't reset TSS upon fork(), see issue #10517. */ void -_PyGILState_Reinit(void) +_PyGILState_Reinit(_PyRuntimeState *runtime) { - /* Force default allocator, since _PyRuntimeState_Fini() must - use the same allocator than this function. */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - _PyRuntime.interpreters.mutex = PyThread_allocate_lock(); - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - if (_PyRuntime.interpreters.mutex == NULL) { - Py_FatalError("Can't initialize threads for interpreter"); - } - + struct _gilstate_runtime_state *gilstate = &runtime->gilstate; PyThreadState *tstate = PyGILState_GetThisThreadState(); - PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey); - if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) { + + PyThread_tss_delete(&gilstate->autoTSSkey); + if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { Py_FatalError("Could not allocate TSS entry"); } /* If the thread had an associated auto thread state, reassociate it with * the new key. */ if (tstate && - PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate) != 0) + PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate) != 0) { Py_FatalError("Couldn't create autoTSSkey mapping"); } From 70bf713617e15fad390ed953e48b3c65d9bc90ec Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com> Date: Wed, 24 Apr 2019 11:14:44 -0400 Subject: [PATCH 067/212] bpo-30840: Document relative imports (#12831) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * document relative imports * 📜🤖 Added by blurb_it. * fix indentation error * remove indentation * Document relative imports * Document relative imports * remove from ...package * Document relative imports * remove trailing space * Document relative imports * Document relative imports --- Doc/reference/import.rst | 40 +++++++++++++++++++ Doc/reference/simple_stmts.rst | 3 +- .../2019-04-14-19-46-21.bpo-30840.R-JFzw.rst | 1 + 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Documentation/2019-04-14-19-46-21.bpo-30840.R-JFzw.rst diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst index 9a0ab39d3b4a3e..88290c88bb35d9 100644 --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -921,6 +921,46 @@ it is sufficient to raise :exc:`ModuleNotFoundError` directly from ``None``. The latter indicates that the meta path search should continue, while raising an exception terminates it immediately. +.. _relativeimports: + +Package Relative Imports +======================== + +Relative imports use leading dots. A single leading dot indicates a relative +import, starting with the current package. Two or more leading dots indicate a +relative import to the parent(s) of the current package, one level per dot +after the first. For example, given the following package layout:: + + package/ + __init__.py + subpackage1/ + __init__.py + moduleX.py + moduleY.py + subpackage2/ + __init__.py + moduleZ.py + moduleA.py + +In either ``subpackage1/moduleX.py`` or ``subpackage1/__init__.py``, +the following are valid relative imports:: + + from .moduleY import spam + from .moduleY import spam as ham + from . import moduleY + from ..subpackage1 import moduleY + from ..subpackage2.moduleZ import eggs + from ..moduleA import foo + +Absolute imports may use either the ``import <>`` or ``from <> import <>`` +syntax, but relative imports may only use the second form; the reason +for this is that:: + + import XXX.YYY.ZZZ + +should expose ``XXX.YYY.ZZZ`` as a usable expression, but .moduleY is +not a valid expression. + Special considerations for __main__ =================================== diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index 00964afc6d3d2f..207057cbc12414 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -828,7 +828,8 @@ exists. Two dots means up one package level. Three dots is up two levels, etc. So if you execute ``from . import mod`` from a module in the ``pkg`` package then you will end up importing ``pkg.mod``. If you execute ``from ..subpkg2 import mod`` from within ``pkg.subpkg1`` you will import ``pkg.subpkg2.mod``. -The specification for relative imports is contained within :pep:`328`. +The specification for relative imports is contained in +the :ref:`relativeimports` section. :func:`importlib.import_module` is provided to support applications that determine dynamically the modules to be loaded. diff --git a/Misc/NEWS.d/next/Documentation/2019-04-14-19-46-21.bpo-30840.R-JFzw.rst b/Misc/NEWS.d/next/Documentation/2019-04-14-19-46-21.bpo-30840.R-JFzw.rst new file mode 100644 index 00000000000000..210f54f2593edb --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-04-14-19-46-21.bpo-30840.R-JFzw.rst @@ -0,0 +1 @@ +Document relative imports \ No newline at end of file From 8e91c246e468515b877690e090c73f496552541d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 24 Apr 2019 17:24:01 +0200 Subject: [PATCH 068/212] bpo-36710: Add runtime variable to Py_FinalizeEx() (GH-12937) * Add a 'runtime' variable to Py_FinalizeEx() rather than working directly on the global variable _PyRuntime * Add a 'runtime' parameter to _PyGC_Fini(), _PyGILState_Fini() and call_ll_exitfuncs() --- Include/internal/pycore_pylifecycle.h | 6 +++-- Modules/gcmodule.c | 5 ++-- Python/pylifecycle.c | 35 ++++++++++++++------------- Python/pystate.c | 7 +++--- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index bfff24b80a9fe1..f07bc427bb88a3 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -8,6 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_pystate.h" /* _PyRuntimeState */ + /* True if the main interpreter thread exited due to an unhandled * KeyboardInterrupt exception, suggesting the user pressed ^C. */ PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt; @@ -63,7 +65,7 @@ extern void PyAsyncGen_Fini(void); extern void _PyExc_Fini(void); extern void _PyImport_Fini(void); extern void _PyImport_Fini2(void); -extern void _PyGC_Fini(void); +extern void _PyGC_Fini(_PyRuntimeState *runtime); extern void _PyType_Fini(void); extern void _Py_HashRandomization_Fini(void); extern void _PyUnicode_Fini(void); @@ -73,7 +75,7 @@ extern void _PyHash_Fini(void); extern int _PyTraceMalloc_Fini(void); extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); -extern void _PyGILState_Fini(void); +extern void _PyGILState_Fini(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index a75d5fed95f11e..f36c7f5d5e409e 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1865,9 +1865,10 @@ _PyGC_DumpShutdownStats(void) } void -_PyGC_Fini(void) +_PyGC_Fini(_PyRuntimeState *runtime) { - Py_CLEAR(_PyRuntime.gc.callbacks); + struct _gc_runtime_state *gc = &runtime->gc; + Py_CLEAR(gc->callbacks); } /* for debugging */ diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index c7920ef6262d3c..fe4cb97a4740f1 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -65,7 +65,7 @@ static _PyInitError init_sys_streams(PyInterpreterState *interp); static _PyInitError initsigs(void); static void call_py_exitfuncs(PyInterpreterState *); static void wait_for_thread_shutdown(void); -static void call_ll_exitfuncs(void); +static void call_ll_exitfuncs(_PyRuntimeState *runtime); int _Py_UnhandledKeyboardInterrupt = 0; _PyRuntimeState _PyRuntime = _PyRuntimeState_INIT; @@ -1131,23 +1131,23 @@ flush_std_files(void) int Py_FinalizeEx(void) { - PyInterpreterState *interp; - PyThreadState *tstate; int status = 0; - if (!_PyRuntime.initialized) + _PyRuntimeState *runtime = &_PyRuntime; + if (!runtime->initialized) { return status; + } // Wrap up existing "threading"-module-created, non-daemon threads. wait_for_thread_shutdown(); - /* Get current thread state and interpreter pointer */ - tstate = _PyThreadState_GET(); - interp = tstate->interp; - // Make any remaining pending calls. _Py_FinishPendingCalls(); + /* Get current thread state and interpreter pointer */ + PyThreadState *tstate = _PyThreadState_GET(); + PyInterpreterState *interp = tstate->interp; + /* The interpreter is still entirely intact at this point, and the * exit funcs may be relying on that. In particular, if some thread * or exit func is still waiting to do an import, the import machinery @@ -1174,9 +1174,9 @@ Py_FinalizeEx(void) /* Remaining threads (e.g. daemon threads) will automatically exit after taking the GIL (in PyEval_RestoreThread()). */ - _PyRuntime.finalizing = tstate; - _PyRuntime.initialized = 0; - _PyRuntime.core_initialized = 0; + runtime->finalizing = tstate; + runtime->initialized = 0; + runtime->core_initialized = 0; /* Flush sys.stdout and sys.stderr */ if (flush_std_files() < 0) { @@ -1294,7 +1294,7 @@ Py_FinalizeEx(void) PyFloat_Fini(); PyDict_Fini(); PySlice_Fini(); - _PyGC_Fini(); + _PyGC_Fini(runtime); _Py_HashRandomization_Fini(); _PyArg_Fini(); PyAsyncGen_Fini(); @@ -1314,7 +1314,7 @@ Py_FinalizeEx(void) PyGrammar_RemoveAccelerators(&_PyParser_Grammar); /* Cleanup auto-thread-state */ - _PyGILState_Fini(); + _PyGILState_Fini(runtime); /* Delete current thread. After this, many C API calls become crashy. */ PyThreadState_Swap(NULL); @@ -1336,7 +1336,7 @@ Py_FinalizeEx(void) } #endif - call_ll_exitfuncs(); + call_ll_exitfuncs(runtime); _PyRuntime_Finalize(); return status; @@ -2223,10 +2223,11 @@ int Py_AtExit(void (*func)(void)) } static void -call_ll_exitfuncs(void) +call_ll_exitfuncs(_PyRuntimeState *runtime) { - while (_PyRuntime.nexitfuncs > 0) - (*_PyRuntime.exitfuncs[--_PyRuntime.nexitfuncs])(); + while (runtime->nexitfuncs > 0) { + (*runtime->exitfuncs[--runtime->nexitfuncs])(); + } fflush(stdout); fflush(stderr); diff --git a/Python/pystate.c b/Python/pystate.c index 6aaf993cfe2cd2..498a9546e1b8cc 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1078,10 +1078,11 @@ _PyGILState_GetInterpreterStateUnsafe(void) } void -_PyGILState_Fini(void) +_PyGILState_Fini(_PyRuntimeState *runtime) { - PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey); - _PyRuntime.gilstate.autoInterpreterState = NULL; + struct _gilstate_runtime_state *gilstate = &runtime->gilstate; + PyThread_tss_delete(&gilstate->autoTSSkey); + gilstate->autoInterpreterState = NULL; } /* Reset the TSS key - called by PyOS_AfterFork_Child(). From e3b6ba165c8ca506e1add552b4fd1a09f45605b4 Mon Sep 17 00:00:00 2001 From: Michael Felt Date: Wed, 24 Apr 2019 15:39:37 +0000 Subject: [PATCH 069/212] Correct boolean logic (typo) from SkipIf to SkipUnless for one subtest --- Lib/test/test_asyncio/test_events.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 0148a48a5dfec6..7859756acfce55 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1296,8 +1296,7 @@ def test_internal_fds(self): self.assertIsNone(loop._csock) self.assertIsNone(loop._ssock) - @unittest.skipUnless(MS_WINDOWS, - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") def test_read_pipe(self): proto = MyReadPipeProto(loop=self.loop) From 43125224d6da5febb34101ebfd36536d791d68cd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 24 Apr 2019 18:23:53 +0200 Subject: [PATCH 070/212] bpo-36710: Add runtime variable to Py_InitializeEx() (GH-12939) Py_InitializeEx() now uses a runtime variable passed to subfunctions, rather than working directly on the global variable _PyRuntime. Add 'runtime' parameter to _PyCoreConfig_Write(), _PySys_Create(), _PySys_InitMain(), _PyGILState_Init(), emit_stderr_warning_for_legacy_locale() and other subfunctions. --- Include/internal/pycore_coreconfig.h | 5 +- Include/internal/pycore_pylifecycle.h | 10 +- Python/coreconfig.c | 4 +- Python/pylifecycle.c | 130 +++++++++++++++----------- Python/pystate.c | 4 +- Python/sysmodule.c | 22 +++-- 6 files changed, 104 insertions(+), 71 deletions(-) diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index e88a46314c897d..ac98e00159ce3b 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -8,6 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_pystate.h" /* _PyRuntimeState */ + /* --- _PyWstrList ------------------------------------------------ */ @@ -108,7 +110,8 @@ PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPathConfig( const _PyCoreConfig *config); PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config, const _PyArgv *args); -PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config); +PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config, + _PyRuntimeState *runtime); /* --- Function used for testing ---------------------------------- */ diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index f07bc427bb88a3..69709b10b8f842 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -34,10 +34,13 @@ extern _PyInitError _PyFaulthandler_Init(int enable); extern int _PyTraceMalloc_Init(int enable); extern PyObject * _PyBuiltin_Init(void); extern _PyInitError _PySys_Create( + _PyRuntimeState *runtime, PyInterpreterState *interp, PyObject **sysmod_p); extern _PyInitError _PySys_SetPreliminaryStderr(PyObject *sysdict); -extern int _PySys_InitMain(PyInterpreterState *interp); +extern int _PySys_InitMain( + _PyRuntimeState *runtime, + PyInterpreterState *interp); extern _PyInitError _PyImport_Init(PyInterpreterState *interp); extern _PyInitError _PyExc_Init(void); extern _PyInitError _PyBuiltins_AddExceptions(PyObject * bltinmod); @@ -74,7 +77,10 @@ extern void _PyFaulthandler_Fini(void); extern void _PyHash_Fini(void); extern int _PyTraceMalloc_Fini(void); -extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); +extern void _PyGILState_Init( + _PyRuntimeState *runtime, + PyInterpreterState *interp, + PyThreadState *tstate); extern void _PyGILState_Fini(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 7b55b06b7a6ef2..d05beef2aa5526 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1605,13 +1605,13 @@ config_init_stdio(const _PyCoreConfig *config) - set Py_xxx global configuration variables - initialize C standard streams (stdin, stdout, stderr) */ void -_PyCoreConfig_Write(const _PyCoreConfig *config) +_PyCoreConfig_Write(const _PyCoreConfig *config, _PyRuntimeState *runtime) { _PyCoreConfig_SetGlobalConfig(config); config_init_stdio(config); /* Write the new pre-configuration into _PyRuntime */ - _PyPreConfig *preconfig = &_PyRuntime.preconfig; + _PyPreConfig *preconfig = &runtime->preconfig; preconfig->isolated = config->isolated; preconfig->use_environment = config->use_environment; preconfig->dev_mode = config->dev_mode; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index fe4cb97a4740f1..03486c3b195a52 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -286,9 +286,9 @@ static const char *_C_LOCALE_WARNING = "locales is recommended.\n"; static void -_emit_stderr_warning_for_legacy_locale(void) +emit_stderr_warning_for_legacy_locale(_PyRuntimeState *runtime) { - const _PyPreConfig *preconfig = &_PyRuntime.preconfig; + const _PyPreConfig *preconfig = &runtime->preconfig; if (preconfig->coerce_c_locale_warn && _Py_LegacyLocaleDetected()) { PySys_FormatStderr("%s", _C_LOCALE_WARNING); } @@ -468,7 +468,8 @@ _Py_SetLocaleFromEnv(int category) */ static _PyInitError -_Py_Initialize_ReconfigureCore(PyInterpreterState **interp_p, +_Py_Initialize_ReconfigureCore(_PyRuntimeState *runtime, + PyInterpreterState **interp_p, const _PyCoreConfig *core_config) { PyThreadState *tstate = _PyThreadState_GET(); @@ -482,7 +483,7 @@ _Py_Initialize_ReconfigureCore(PyInterpreterState **interp_p, } *interp_p = interp; - _PyCoreConfig_Write(core_config); + _PyCoreConfig_Write(core_config, runtime); if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) { return _Py_INIT_NO_MEMORY(); @@ -500,18 +501,14 @@ _Py_Initialize_ReconfigureCore(PyInterpreterState **interp_p, static _PyInitError -pycore_init_runtime(const _PyCoreConfig *core_config) +pycore_init_runtime(_PyRuntimeState *runtime, + const _PyCoreConfig *core_config) { - if (_PyRuntime.initialized) { + if (runtime->initialized) { return _Py_INIT_ERR("main interpreter already initialized"); } - _PyCoreConfig_Write(core_config); - - _PyInitError err = _PyRuntime_Initialize(); - if (_Py_INIT_FAILED(err)) { - return err; - } + _PyCoreConfig_Write(core_config, runtime); /* Py_Finalize leaves _Py_Finalizing set in order to help daemon * threads behave a little more gracefully at interpreter shutdown. @@ -522,14 +519,14 @@ pycore_init_runtime(const _PyCoreConfig *core_config) * threads still hanging around from a previous Py_Initialize/Finalize * pair :( */ - _PyRuntime.finalizing = NULL; + runtime->finalizing = NULL; - err = _Py_HashRandomization_Init(core_config); + _PyInitError err = _Py_HashRandomization_Init(core_config); if (_Py_INIT_FAILED(err)) { return err; } - err = _PyInterpreterState_Enable(&_PyRuntime); + err = _PyInterpreterState_Enable(runtime); if (_Py_INIT_FAILED(err)) { return err; } @@ -538,7 +535,8 @@ pycore_init_runtime(const _PyCoreConfig *core_config) static _PyInitError -pycore_create_interpreter(const _PyCoreConfig *core_config, +pycore_create_interpreter(_PyRuntimeState *runtime, + const _PyCoreConfig *core_config, PyInterpreterState **interp_p) { PyInterpreterState *interp = PyInterpreterState_New(); @@ -565,7 +563,7 @@ pycore_create_interpreter(const _PyCoreConfig *core_config, _PyEval_FiniThreads(); /* Auto-thread-state API */ - _PyGILState_Init(interp, tstate); + _PyGILState_Init(runtime, interp, tstate); /* Create the GIL */ PyEval_InitThreads(); @@ -671,19 +669,20 @@ pycore_init_import_warnings(PyInterpreterState *interp, PyObject *sysmod) static _PyInitError -_Py_InitializeCore_impl(PyInterpreterState **interp_p, +_Py_InitializeCore_impl(_PyRuntimeState *runtime, + PyInterpreterState **interp_p, const _PyCoreConfig *core_config) { PyInterpreterState *interp; - _PyCoreConfig_Write(core_config); + _PyCoreConfig_Write(core_config, runtime); - _PyInitError err = pycore_init_runtime(core_config); + _PyInitError err = pycore_init_runtime(runtime, core_config); if (_Py_INIT_FAILED(err)) { return err; } - err = pycore_create_interpreter(core_config, &interp); + err = pycore_create_interpreter(runtime, core_config, &interp); if (_Py_INIT_FAILED(err)) { return err; } @@ -696,7 +695,7 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p, } PyObject *sysmod; - err = _PySys_Create(interp, &sysmod); + err = _PySys_Create(runtime, interp, &sysmod); if (_Py_INIT_FAILED(err)) { return err; } @@ -712,7 +711,7 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p, } /* Only when we get here is the runtime core fully initialized */ - _PyRuntime.core_initialized = 1; + runtime->core_initialized = 1; return _Py_INIT_OK(); } @@ -726,8 +725,9 @@ preinit(const _PyPreConfig *src_config, const _PyArgv *args) if (_Py_INIT_FAILED(err)) { return err; } + _PyRuntimeState *runtime = &_PyRuntime; - if (_PyRuntime.pre_initialized) { + if (runtime->pre_initialized) { /* If it's already configured: ignored the new configuration */ return _Py_INIT_OK(); } @@ -751,7 +751,7 @@ preinit(const _PyPreConfig *src_config, const _PyArgv *args) goto done; } - _PyRuntime.pre_initialized = 1; + runtime->pre_initialized = 1; err = _Py_INIT_OK(); done: @@ -795,7 +795,8 @@ _Py_PreInitializeFromCoreConfig(const _PyCoreConfig *coreconfig) static _PyInitError -pyinit_coreconfig(_PyCoreConfig *config, +pyinit_coreconfig(_PyRuntimeState *runtime, + _PyCoreConfig *config, const _PyCoreConfig *src_config, const _PyArgv *args, PyInterpreterState **interp_p) @@ -811,11 +812,11 @@ pyinit_coreconfig(_PyCoreConfig *config, return err; } - if (!_PyRuntime.core_initialized) { - return _Py_InitializeCore_impl(interp_p, config); + if (!runtime->core_initialized) { + return _Py_InitializeCore_impl(runtime, interp_p, config); } else { - return _Py_Initialize_ReconfigureCore(interp_p, config); + return _Py_Initialize_ReconfigureCore(runtime, interp_p, config); } } @@ -838,7 +839,8 @@ pyinit_coreconfig(_PyCoreConfig *config, * safe to call without calling Py_Initialize first) */ static _PyInitError -_Py_InitializeCore(const _PyCoreConfig *src_config, +_Py_InitializeCore(_PyRuntimeState *runtime, + const _PyCoreConfig *src_config, const _PyArgv *args, PyInterpreterState **interp_p) { @@ -855,7 +857,7 @@ _Py_InitializeCore(const _PyCoreConfig *src_config, } _PyCoreConfig local_config = _PyCoreConfig_INIT; - err = pyinit_coreconfig(&local_config, src_config, args, interp_p); + err = pyinit_coreconfig(runtime, &local_config, src_config, args, interp_p); _PyCoreConfig_Clear(&local_config); return err; } @@ -894,16 +896,17 @@ _Py_ReconfigureMainInterpreter(PyInterpreterState *interp) * non-zero return code. */ static _PyInitError -_Py_InitializeMainInterpreter(PyInterpreterState *interp) +_Py_InitializeMainInterpreter(_PyRuntimeState *runtime, + PyInterpreterState *interp) { - if (!_PyRuntime.core_initialized) { + if (!runtime->core_initialized) { return _Py_INIT_ERR("runtime core not initialized"); } /* Configure the main interpreter */ _PyCoreConfig *core_config = &interp->core_config; - if (_PyRuntime.initialized) { + if (runtime->initialized) { return _Py_ReconfigureMainInterpreter(interp); } @@ -913,7 +916,7 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) * This means anything which needs support from extension modules * or pure Python code in the standard library won't work. */ - _PyRuntime.initialized = 1; + runtime->initialized = 1; return _Py_INIT_OK(); } @@ -921,7 +924,7 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) return _Py_INIT_ERR("can't initialize time"); } - if (_PySys_InitMain(interp) < 0) { + if (_PySys_InitMain(runtime, interp) < 0) { return _Py_INIT_ERR("can't finish initializing sys"); } @@ -974,7 +977,7 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) Py_XDECREF(warnings_module); } - _PyRuntime.initialized = 1; + runtime->initialized = 1; if (core_config->site_import) { err = initsite(); /* Module site */ @@ -984,7 +987,7 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) } #ifndef MS_WINDOWS - _emit_stderr_warning_for_legacy_locale(); + emit_stderr_warning_for_legacy_locale(runtime); #endif return _Py_INIT_OK(); @@ -995,16 +998,23 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) static _PyInitError init_python(const _PyCoreConfig *config, const _PyArgv *args) { - PyInterpreterState *interp = NULL; _PyInitError err; - err = _Py_InitializeCore(config, args, &interp); + + err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyRuntimeState *runtime = &_PyRuntime; + + PyInterpreterState *interp = NULL; + err = _Py_InitializeCore(runtime, config, args, &interp); if (_Py_INIT_FAILED(err)) { return err; } config = &interp->core_config; if (config->_init_main) { - err = _Py_InitializeMainInterpreter(interp); + err = _Py_InitializeMainInterpreter(runtime, interp); if (_Py_INIT_FAILED(err)) { return err; } @@ -1040,7 +1050,15 @@ _Py_InitializeFromConfig(const _PyCoreConfig *config) void Py_InitializeEx(int install_sigs) { - if (_PyRuntime.initialized) { + _PyInitError err; + + err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + _Py_ExitInitError(err); + } + _PyRuntimeState *runtime = &_PyRuntime; + + if (runtime->initialized) { /* bpo-33932: Calling Py_Initialize() twice does nothing. */ return; } @@ -1048,7 +1066,7 @@ Py_InitializeEx(int install_sigs) _PyCoreConfig config = _PyCoreConfig_INIT; config.install_signal_handlers = install_sigs; - _PyInitError err = _Py_InitializeFromConfig(&config); + err = _Py_InitializeFromConfig(&config); if (_Py_INIT_FAILED(err)) { _Py_ExitInitError(err); } @@ -1364,12 +1382,15 @@ Py_Finalize(void) static _PyInitError new_interpreter(PyThreadState **tstate_p) { - PyInterpreterState *interp; - PyThreadState *tstate, *save_tstate; - PyObject *bimod, *sysmod; _PyInitError err; - if (!_PyRuntime.initialized) { + err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyRuntimeState *runtime = &_PyRuntime; + + if (!runtime->initialized) { return _Py_INIT_ERR("Py_Initialize must be called first"); } @@ -1377,20 +1398,20 @@ new_interpreter(PyThreadState **tstate_p) interpreters: disable PyGILState_Check(). */ _PyGILState_check_enabled = 0; - interp = PyInterpreterState_New(); + PyInterpreterState *interp = PyInterpreterState_New(); if (interp == NULL) { *tstate_p = NULL; return _Py_INIT_OK(); } - tstate = PyThreadState_New(interp); + PyThreadState *tstate = PyThreadState_New(interp); if (tstate == NULL) { PyInterpreterState_Delete(interp); *tstate_p = NULL; return _Py_INIT_OK(); } - save_tstate = PyThreadState_Swap(tstate); + PyThreadState *save_tstate = PyThreadState_Swap(tstate); /* Copy the current interpreter config into the new interpreter */ _PyCoreConfig *core_config; @@ -1419,14 +1440,15 @@ new_interpreter(PyThreadState **tstate_p) } interp->modules = modules; - sysmod = _PyImport_FindBuiltin("sys", modules); + PyObject *sysmod = _PyImport_FindBuiltin("sys", modules); if (sysmod != NULL) { interp->sysdict = PyModule_GetDict(sysmod); - if (interp->sysdict == NULL) + if (interp->sysdict == NULL) { goto handle_error; + } Py_INCREF(interp->sysdict); PyDict_SetItemString(interp->sysdict, "modules", modules); - if (_PySys_InitMain(interp) < 0) { + if (_PySys_InitMain(runtime, interp) < 0) { return _Py_INIT_ERR("can't finish initializing sys"); } } @@ -1434,7 +1456,7 @@ new_interpreter(PyThreadState **tstate_p) goto handle_error; } - bimod = _PyImport_FindBuiltin("builtins", modules); + PyObject *bimod = _PyImport_FindBuiltin("builtins", modules); if (bimod != NULL) { interp->builtins = PyModule_GetDict(bimod); if (interp->builtins == NULL) diff --git a/Python/pystate.c b/Python/pystate.c index 498a9546e1b8cc..a413f9d7ab4c57 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1052,13 +1052,13 @@ PyThreadState_IsCurrent(PyThreadState *tstate) Py_Initialize/Py_FinalizeEx */ void -_PyGILState_Init(PyInterpreterState *interp, PyThreadState *tstate) +_PyGILState_Init(_PyRuntimeState *runtime, + PyInterpreterState *interp, PyThreadState *tstate) { /* must init with valid states */ assert(interp != NULL); assert(tstate != NULL); - _PyRuntimeState *runtime = &_PyRuntime; struct _gilstate_runtime_state *gilstate = &runtime->gilstate; if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 3de94e8468bee1..0f7af2c69da538 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2155,12 +2155,12 @@ static PyStructSequence_Desc flags_desc = { }; static PyObject* -make_flags(void) +make_flags(_PyRuntimeState *runtime, PyInterpreterState *interp) { int pos = 0; PyObject *seq; - const _PyPreConfig *preconfig = &_PyRuntime.preconfig; - const _PyCoreConfig *config = &_PyInterpreterState_GET_UNSAFE()->core_config; + const _PyPreConfig *preconfig = &runtime->preconfig; + const _PyCoreConfig *config = &interp->core_config; seq = PyStructSequence_New(&FlagsType); if (seq == NULL) @@ -2375,7 +2375,8 @@ static struct PyModuleDef sysmodule = { } while (0) static _PyInitError -_PySys_InitCore(PyObject *sysdict) +_PySys_InitCore(_PyRuntimeState *runtime, PyInterpreterState *interp, + PyObject *sysdict) { PyObject *version_info; int res; @@ -2465,8 +2466,8 @@ _PySys_InitCore(PyObject *sysdict) goto type_init_failed; } } - /* Set flags to their default values */ - SET_SYS_FROM_STRING("flags", make_flags()); + /* Set flags to their default values (updated by _PySys_InitMain()) */ + SET_SYS_FROM_STRING("flags", make_flags(runtime, interp)); #if defined(MS_WINDOWS) /* getwindowsversion */ @@ -2587,7 +2588,7 @@ sys_create_xoptions_dict(const _PyCoreConfig *config) int -_PySys_InitMain(PyInterpreterState *interp) +_PySys_InitMain(_PyRuntimeState *runtime, PyInterpreterState *interp) { PyObject *sysdict = interp->sysdict; const _PyCoreConfig *config = &interp->core_config; @@ -2641,7 +2642,7 @@ _PySys_InitMain(PyInterpreterState *interp) #undef SET_SYS_FROM_WSTR /* Set flags to their final values */ - SET_SYS_FROM_STRING_INT_RESULT("flags", make_flags()); + SET_SYS_FROM_STRING_INT_RESULT("flags", make_flags(runtime, interp)); /* prevent user from creating new instances */ FlagsType.tp_init = NULL; FlagsType.tp_new = NULL; @@ -2708,7 +2709,8 @@ _PySys_SetPreliminaryStderr(PyObject *sysdict) /* Create sys module without all attributes: _PySys_InitMain() should be called later to add remaining attributes. */ _PyInitError -_PySys_Create(PyInterpreterState *interp, PyObject **sysmod_p) +_PySys_Create(_PyRuntimeState *runtime, PyInterpreterState *interp, + PyObject **sysmod_p) { PyObject *modules = PyDict_New(); if (modules == NULL) { @@ -2737,7 +2739,7 @@ _PySys_Create(PyInterpreterState *interp, PyObject **sysmod_p) return err; } - err = _PySys_InitCore(sysdict); + err = _PySys_InitCore(runtime, interp, sysdict); if (_Py_INIT_FAILED(err)) { return err; } From 09d434caa2c01477ea2ccc3e9b88e9faa0107c61 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 24 Apr 2019 11:30:17 -0700 Subject: [PATCH 071/212] Issue 35224: Add PEP 572 (assignment expressions) to What's New (#12941) This is meant as a stub, during the PyCon sprints we can iterate. --- Doc/whatsnew/3.8.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index bd7ad3f87cb504..ae8163a1b156fc 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -67,6 +67,22 @@ Summary -- Release highlights New Features ============ +Assignment expressions +---------------------- + +There is new syntax (the "walrus operator", ``:=``) to assign values +to variables as part of an expression. Example:: + + if (n := len(a)) > 10: + print(f"List is too long ({n} elements, expected <= 10)") + +See :pep:`572` for a full description. + +(Contributed by Emily Morehouse in :issue:`35224`.) + +.. TODO: Emily will sprint on docs at PyCon US 2019. + + Parallel filesystem cache for compiled bytecode files ----------------------------------------------------- From 004b93ea8947bcbe85b6fa16fe0999bfa712d5c1 Mon Sep 17 00:00:00 2001 From: Thomas Moreau Date: Wed, 24 Apr 2019 21:45:52 +0200 Subject: [PATCH 072/212] bpo-36668: FIX reuse semaphore tracker for child processes (#5172) Fix the multiprocessing.semaphore_tracker so it is reused by child processes. --- Lib/multiprocessing/semaphore_tracker.py | 36 +++++++++++++------ Lib/test/_test_multiprocessing.py | 28 +++++++++++++++ .../2018-04-06-11-06-23.bpo-31310.eq9ky0.rst | 1 + 3 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-04-06-11-06-23.bpo-31310.eq9ky0.rst diff --git a/Lib/multiprocessing/semaphore_tracker.py b/Lib/multiprocessing/semaphore_tracker.py index 82833bcf861a49..3c2c3ad61aeeec 100644 --- a/Lib/multiprocessing/semaphore_tracker.py +++ b/Lib/multiprocessing/semaphore_tracker.py @@ -44,20 +44,23 @@ def ensure_running(self): This can be run from any process. Usually a child process will use the semaphore created by its parent.''' with self._lock: - if self._pid is not None: + if self._fd is not None: # semaphore tracker was launched before, is it still running? + if self._check_alive(): + # => still alive + return + # => dead, launch it again + os.close(self._fd) + + # Clean-up to avoid dangling processes. try: - pid, _ = os.waitpid(self._pid, os.WNOHANG) + # _pid can be None if this process is a child from another + # python process, which has started the semaphore_tracker. + if self._pid is not None: + os.waitpid(self._pid, 0) except ChildProcessError: - # The process terminated + # The semaphore_tracker has already been terminated. pass - else: - if not pid: - # => still alive - return - - # => dead, launch it again - os.close(self._fd) self._fd = None self._pid = None @@ -99,6 +102,17 @@ def ensure_running(self): finally: os.close(r) + def _check_alive(self): + '''Check that the pipe has not been closed by sending a probe.''' + try: + # We cannot use send here as it calls ensure_running, creating + # a cycle. + os.write(self._fd, b'PROBE:0\n') + except OSError: + return False + else: + return True + def register(self, name): '''Register name of semaphore with semaphore tracker.''' self._send('REGISTER', name) @@ -150,6 +164,8 @@ def main(fd): cache.add(name) elif cmd == b'UNREGISTER': cache.remove(name) + elif cmd == b'PROBE': + pass else: raise RuntimeError('unrecognized command %r' % cmd) except Exception: diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 553ab8178316a9..836fde88cd266d 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4891,6 +4891,34 @@ def test_semaphore_tracker_sigkill(self): # Uncatchable signal. self.check_semaphore_tracker_death(signal.SIGKILL, True) + @staticmethod + def _is_semaphore_tracker_reused(conn, pid): + from multiprocessing.semaphore_tracker import _semaphore_tracker + _semaphore_tracker.ensure_running() + # The pid should be None in the child process, expect for the fork + # context. It should not be a new value. + reused = _semaphore_tracker._pid in (None, pid) + reused &= _semaphore_tracker._check_alive() + conn.send(reused) + + def test_semaphore_tracker_reused(self): + from multiprocessing.semaphore_tracker import _semaphore_tracker + _semaphore_tracker.ensure_running() + pid = _semaphore_tracker._pid + + r, w = multiprocessing.Pipe(duplex=False) + p = multiprocessing.Process(target=self._is_semaphore_tracker_reused, + args=(w, pid)) + p.start() + is_semaphore_tracker_reused = r.recv() + + # Clean up + p.join() + w.close() + r.close() + + self.assertTrue(is_semaphore_tracker_reused) + class TestSimpleQueue(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2018-04-06-11-06-23.bpo-31310.eq9ky0.rst b/Misc/NEWS.d/next/Library/2018-04-06-11-06-23.bpo-31310.eq9ky0.rst new file mode 100644 index 00000000000000..32ebf4efb74bdb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-06-11-06-23.bpo-31310.eq9ky0.rst @@ -0,0 +1 @@ +Fix the multiprocessing.semaphore_tracker so it is reused by child processes From 888f37bc2826d9ab2cbec6f153e7f58a34785c4a Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Wed, 24 Apr 2019 21:25:23 +0100 Subject: [PATCH 073/212] Add @pablogsal to code owners file for Parser/pgen (GH-12944) Add myself to the codeowners file as I would like to be automatically added as a reviewer for PRs that touch that component. --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2ca555b7fa50c4..9b7a4032fb4370 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -43,6 +43,9 @@ Python/bootstrap_hash.c @python/crypto-team **/*imap* @python/email-team **/*poplib* @python/email-team +# Parser/Pgen +/Parser/pgen/ @pablogsal + # SQLite 3 **/*sqlite* @berkerpeksag From f4e4703e746067d6630410408d414b11003334d6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 25 Apr 2019 00:56:28 +0200 Subject: [PATCH 074/212] bpo-36465: Make release and debug ABI compatible (GH-12615) Release build and debug build are now ABI compatible: the Py_DEBUG define no longer implies Py_TRACE_REFS define which introduces the only ABI incompatibility. A new "./configure --with-trace-refs" build option is now required to get Py_TRACE_REFS define which adds sys.getobjects() function and PYTHONDUMPREFS environment variable. Changes: * Add ./configure --with-trace-refs * Py_DEBUG no longer implies Py_TRACE_REFS --- Doc/using/cmdline.rst | 7 +++-- Include/object.h | 9 ++---- Lib/test/support/__init__.py | 2 +- .../2019-04-09-18-19-43.bpo-36465.-w6vx6.rst | 5 ++++ configure | 28 +++++++++++++++++-- configure.ac | 17 +++++++++-- pyconfig.h.in | 3 ++ 7 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 0574336cf35403..fd47ce2ab53849 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -922,15 +922,18 @@ conflict. Debug-mode variables ~~~~~~~~~~~~~~~~~~~~ -Setting these variables only has an effect in a debug build of Python, that is, -if Python was configured with the ``--with-pydebug`` build option. +Setting these variables only has an effect in a debug build of Python. .. envvar:: PYTHONTHREADDEBUG If set, Python will print threading debug info. + Need Python configured with the ``--with-pydebug`` build option. + .. envvar:: PYTHONDUMPREFS If set, Python will dump objects and reference counts still alive after shutting down the interpreter. + + Need Python configured with the ``--with-trace-refs`` build option. diff --git a/Include/object.h b/Include/object.h index 86cbfc581ed181..13e88a6dc6f02a 100644 --- a/Include/object.h +++ b/Include/object.h @@ -54,13 +54,8 @@ A standard interface exists for objects that contain an array of items whose size is determined when the object is allocated. */ -/* Py_DEBUG implies Py_TRACE_REFS. */ -#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS) -#define Py_TRACE_REFS -#endif - -/* Py_TRACE_REFS implies Py_REF_DEBUG. */ -#if defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) +/* Py_DEBUG implies Py_REF_DEBUG. */ +#if defined(Py_DEBUG) && !defined(Py_REF_DEBUG) #define Py_REF_DEBUG #endif diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 2bb561b4cee137..dc96318b38f7b9 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1653,7 +1653,7 @@ def python_is_optimized(): _header = 'nP' _align = '0n' -if hasattr(sys, "gettotalrefcount"): +if hasattr(sys, "getobjects"): _header = '2P' + _header _align = '0P' _vheader = _header + 'n' diff --git a/Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst b/Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst new file mode 100644 index 00000000000000..52de1ef44830be --- /dev/null +++ b/Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst @@ -0,0 +1,5 @@ +Release build and debug build are now ABI compatible: the ``Py_DEBUG`` define +no longer implies ``Py_TRACE_REFS`` define which introduces the only ABI +incompatibility. A new ``./configure --with-trace-refs`` build option is now +required to get ``Py_TRACE_REFS`` define which adds :func:`sys.getobjects` +function and ``PYTHONDUMPREFS`` environment variable. diff --git a/configure b/configure index e96c03ad4f5942..b02d17c053c6b5 100755 --- a/configure +++ b/configure @@ -814,6 +814,7 @@ with_suffix enable_shared enable_profiling with_pydebug +with_trace_refs with_assertions enable_optimizations with_lto @@ -1500,6 +1501,7 @@ Optional Packages: compiler --with-suffix=.exe set executable suffix --with-pydebug build with Py_DEBUG defined + --with-trace-refs enable tracing references for debugging purpose --with-assertions build with C assertions enabled --with-lto Enable Link Time Optimization in any build. Disabled by default. @@ -6333,8 +6335,30 @@ $as_echo "no" >&6; } fi -# Check for --with-assertions. Py_DEBUG implies assertions, but also changes -# the ABI. This allows enabling assertions without changing the ABI. +# Check for --with-trace-refs +# --with-trace-refs +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-trace-refs" >&5 +$as_echo_n "checking for --with-trace-refs... " >&6; } + +# Check whether --with-trace-refs was given. +if test "${with_trace_refs+set}" = set; then : + withval=$with_trace_refs; +else + with_trace_refs=no +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_trace_refs" >&5 +$as_echo "$with_trace_refs" >&6; } + +if test "$with_trace_refs" = "yes" +then + +$as_echo "#define Py_TRACE_REFS 1" >>confdefs.h + +fi + +# Check for --with-assertions. +# This allows enabling assertions without Py_DEBUG. assertions='false' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-assertions" >&5 $as_echo_n "checking for --with-assertions... " >&6; } diff --git a/configure.ac b/configure.ac index 3f378c97345e2a..65d3f8e6912983 100644 --- a/configure.ac +++ b/configure.ac @@ -1228,8 +1228,21 @@ else AC_MSG_RESULT(no); Py_DEBUG='false' fi], [AC_MSG_RESULT(no)]) -# Check for --with-assertions. Py_DEBUG implies assertions, but also changes -# the ABI. This allows enabling assertions without changing the ABI. +# Check for --with-trace-refs +# --with-trace-refs +AC_MSG_CHECKING(for --with-trace-refs) +AC_ARG_WITH(trace-refs, + AS_HELP_STRING([--with-trace-refs],[enable tracing references for debugging purpose]),, + with_trace_refs=no) +AC_MSG_RESULT($with_trace_refs) + +if test "$with_trace_refs" = "yes" +then + AC_DEFINE(Py_TRACE_REFS, 1, [Define if you want to enable tracing references for debugging purpose]) +fi + +# Check for --with-assertions. +# This allows enabling assertions without Py_DEBUG. assertions='false' AC_MSG_CHECKING(for --with-assertions) AC_ARG_WITH(assertions, diff --git a/pyconfig.h.in b/pyconfig.h.in index d41d57932766be..562c0271133bdc 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1374,6 +1374,9 @@ externally defined: 0 */ #undef Py_HASH_ALGORITHM +/* Define if you want to enable tracing references for debugging purpose */ +#undef Py_TRACE_REFS + /* assume C89 semantics that RETSIGTYPE is always void */ #undef RETSIGTYPE From 235e7b2b0d937ba8b4a9172aa72206187e3e1f54 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 25 Apr 2019 01:46:31 +0200 Subject: [PATCH 075/212] bpo-36465: Fix test_regrtest on Windows (GH-12945) Fix Py_DEBUG constant: check for sys.gettotalrefcount attribute rather than sys.getobjects. Update also SpecialBuilds.txt documentation. --- Lib/test/test_regrtest.py | 2 +- Misc/SpecialBuilds.txt | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 61937767ec126d..a9febd00eda096 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -21,7 +21,7 @@ from test.libregrtest import utils -Py_DEBUG = hasattr(sys, 'getobjects') +Py_DEBUG = hasattr(sys, 'gettotalrefcount') ROOT_DIR = os.path.join(os.path.dirname(__file__), '..', '..') ROOT_DIR = os.path.abspath(os.path.normpath(ROOT_DIR)) diff --git a/Misc/SpecialBuilds.txt b/Misc/SpecialBuilds.txt index c188dd70759039..193de57b0850bd 100644 --- a/Misc/SpecialBuilds.txt +++ b/Misc/SpecialBuilds.txt @@ -30,6 +30,8 @@ name "_" holds a reference to the last result displayed! Py_REF_DEBUG also checks after every decref to verify that the refcount hasn't gone negative, and causes an immediate fatal error if it has. +Py_DEBUG implies Py_REF_DEBUG. + Special gimmicks: sys.gettotalrefcount() @@ -39,6 +41,8 @@ sys.gettotalrefcount() Py_TRACE_REFS ------------- +Build option: ``./configure --with-trace-refs``. + Turn on heavy reference debugging. This is major surgery. Every PyObject grows two more pointers, to maintain a doubly-linked list of all live heap-allocated objects. Most built-in type objects are not in this list, as they're statically @@ -49,8 +53,6 @@ has been created. Note that because the fundamental PyObject layout changes, Python modules compiled with Py_TRACE_REFS are incompatible with modules compiled without it. -Py_TRACE_REFS implies Py_REF_DEBUG. - Special gimmicks: sys.getobjects(max[, type]) @@ -138,7 +140,8 @@ look at the object, you're likely to see that it's entirely filled with 0xDB (meaning freed memory is getting used) or 0xCB (meaning uninitialized memory is getting used). -Note that PYMALLOC_DEBUG requires WITH_PYMALLOC. +Note that PYMALLOC_DEBUG requires WITH_PYMALLOC. Py_DEBUG implies +PYMALLOC_DEBUG (if WITH_PYMALLOC is enabled). Special gimmicks: @@ -156,7 +159,7 @@ Py_DEBUG This is what is generally meant by "a debug build" of Python. -Py_DEBUG implies LLTRACE, Py_REF_DEBUG, Py_TRACE_REFS, and PYMALLOC_DEBUG (if +Py_DEBUG implies LLTRACE, Py_REF_DEBUG, and PYMALLOC_DEBUG (if WITH_PYMALLOC is enabled). In addition, C assert()s are enabled (via the C way: by not defining NDEBUG), and some routines do additional sanity checks inside "#ifdef Py_DEBUG" blocks. @@ -223,3 +226,5 @@ the interpreter is doing are sprayed to stdout, such as every opcode and opcode argument and values pushed onto and popped off the value stack. Not useful very often, but very useful when needed. + +Py_DEBUG implies LLTRACE. From 0ef8c157e9195df0115c54ba875a5efb92ac22fb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 25 Apr 2019 11:59:34 +0200 Subject: [PATCH 076/212] bpo-28552: Fix distutils.sysconfig for empty sys.executable (GH-12875) bpo-28552, bpo-7774: Fix distutils.sysconfig if sys.executable is None or an empty string: use os.getcwd() to initialize project_base. Fix also the distutils build command: don't use sys.executable if it's evaluated as false (None or empty string). --- Lib/distutils/command/build.py | 2 +- Lib/distutils/sysconfig.py | 7 ++++++- .../next/Library/2019-04-18-16-10-29.bpo-28552.MW1TLt.rst | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-18-16-10-29.bpo-28552.MW1TLt.rst diff --git a/Lib/distutils/command/build.py b/Lib/distutils/command/build.py index c6f52e61e1bc70..a86df0bc7f9218 100644 --- a/Lib/distutils/command/build.py +++ b/Lib/distutils/command/build.py @@ -116,7 +116,7 @@ def finalize_options(self): self.build_scripts = os.path.join(self.build_base, 'scripts-%d.%d' % sys.version_info[:2]) - if self.executable is None: + if self.executable is None and sys.executable: self.executable = os.path.normpath(sys.executable) if isinstance(self.parallel, str): diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py index a3494670db18c1..570a612d1b1029 100644 --- a/Lib/distutils/sysconfig.py +++ b/Lib/distutils/sysconfig.py @@ -28,7 +28,12 @@ if "_PYTHON_PROJECT_BASE" in os.environ: project_base = os.path.abspath(os.environ["_PYTHON_PROJECT_BASE"]) else: - project_base = os.path.dirname(os.path.abspath(sys.executable)) + if sys.executable: + project_base = os.path.dirname(os.path.abspath(sys.executable)) + else: + # sys.executable can be empty if argv[0] has been changed and Python is + # unable to retrieve the real program name + project_base = os.getcwd() # python_build: (Boolean) if true, we're either building Python or diff --git a/Misc/NEWS.d/next/Library/2019-04-18-16-10-29.bpo-28552.MW1TLt.rst b/Misc/NEWS.d/next/Library/2019-04-18-16-10-29.bpo-28552.MW1TLt.rst new file mode 100644 index 00000000000000..2aa30c98c4524a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-18-16-10-29.bpo-28552.MW1TLt.rst @@ -0,0 +1,4 @@ +Fix :mod:`distutils.sysconfig` if :data:`sys.executable` is ``None`` or an +empty string: use :func:`os.getcwd` to initialize ``project_base``. Fix +also the distutils build command: don't use :data:`sys.executable` if it is +``None`` or an empty string. From d7befad328ad1a6d1f812be2bf154c1cd1e01fbc Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 25 Apr 2019 14:30:16 +0200 Subject: [PATCH 077/212] bpo-35537: Document posix_spawn() change in subprocess (GH-11668) Document that subprocess.Popen no longer raise an exception on error like missing program on very specific platforms when using os.posix_spawn() is used. --- Doc/library/subprocess.rst | 7 +++++++ Doc/whatsnew/3.8.rst | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index ca0813c7830ad0..3280c95cacbbc3 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -567,6 +567,13 @@ functions. Popen destructor now emits a :exc:`ResourceWarning` warning if the child process is still running. + .. versionchanged:: 3.8 + Popen can use :func:`os.posix_spawn` in some cases for better + performance. On Windows Subsystem for Linux and QEMU User Emulation, + Popen constructor using :func:`os.posix_spawn` no longer raise an + exception on errors like missing program, but the child process fails + with a non-zero :attr:`~Popen.returncode`. + Exceptions ^^^^^^^^^^ diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index ae8163a1b156fc..344656b9288f65 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -729,6 +729,12 @@ Changes in Python behavior Changes in the Python API ------------------------- +* :class:`subprocess.Popen` can now use :func:`os.posix_spawn` in some cases + for better performance. On Windows Subsystem for Linux and QEMU User + Emulation, Popen constructor using :func:`os.posix_spawn` no longer raise an + exception on errors like missing program, but the child process fails with a + non-zero :attr:`~Popen.returncode`. + * The :meth:`imap.IMAP4.logout` method no longer ignores silently arbitrary exceptions. From 8c3ecc6bacc8d0cd534f2b5b53ed962dd1368c7b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 25 Apr 2019 20:13:10 +0200 Subject: [PATCH 078/212] bpo-21536: C extensions are no longer linked to libpython (GH-12946) On Unix, C extensions are no longer linked to libpython. It is now possible to load a C extension built using a shared library Python with a statically linked Python. When Python is embedded, libpython must not be loaded with RTLD_LOCAL, but RTLD_GLOBAL instead. Previously, using RTLD_LOCAL, it was already not possible to load C extensions which were not linked to libpython, like C extensions of the standard library built by the "*shared*" section of Modules/Setup. distutils, python-config and python-config.py have been modified. --- Doc/distutils/apiref.rst | 4 ++++ Doc/whatsnew/3.8.rst | 11 +++++++---- Lib/distutils/command/build_ext.py | 19 ++----------------- Makefile.pre.in | 2 +- .../2019-04-25-01-51-52.bpo-21536.ACQkiC.rst | 12 ++++++++++++ Misc/python-config.in | 4 +--- Misc/python-config.sh.in | 2 +- 7 files changed, 28 insertions(+), 26 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index a825efc1a67243..c3cdfc8a0a8ec6 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -277,6 +277,10 @@ the full reference. | | simply skip the extension. | | +------------------------+--------------------------------+---------------------------+ + .. versionchanged:: 3.8 + + On Unix, C extensions are no longer linked to libpython. + .. class:: Distribution diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 344656b9288f65..2270334a281b08 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -851,16 +851,19 @@ Changes in the Python API Changes in the C API -------------------- +* On Unix, C extensions are no longer linked to libpython. When Python is + embedded, ``libpython`` must not be loaded with ``RTLD_LOCAL``, but + ``RTLD_GLOBAL`` instead. Previously, using ``RTLD_LOCAL``, it was already not + possible to load C extensions which were not linked to ``libpython``, like C + extensions of the standard library built by the ``*shared*`` section of + ``Modules/Setup``. + * Use of ``#`` variants of formats in parsing or building value (e.g. :c:func:`PyArg_ParseTuple`, :c:func:`Py_BuildValue`, :c:func:`PyObject_CallFunction`, etc.) without ``PY_SSIZE_T_CLEAN`` defined raises ``DeprecationWarning`` now. It will be removed in 3.10 or 4.0. Read :ref:`arg-parsing` for detail. (Contributed by Inada Naoki in :issue:`36381`.) - -Changes in the C API --------------------------- - * Instances of heap-allocated types (such as those created with :c:func:`PyType_FromSpec`) hold a reference to their type object. Increasing the reference count of these type objects has been moved from diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py index 0428466b00c902..1672d02acf1f7a 100644 --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py @@ -714,20 +714,5 @@ def get_libraries(self, ext): # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] - else: - return ext.libraries - elif sys.platform == 'darwin': - # Don't use the default code below - return ext.libraries - elif sys.platform[:3] == 'aix': - # Don't use the default code below - return ext.libraries - else: - from distutils import sysconfig - if sysconfig.get_config_var('Py_ENABLE_SHARED'): - pythonlib = 'python{}.{}{}'.format( - sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff, - sysconfig.get_config_var('ABIFLAGS')) - return ext.libraries + [pythonlib] - else: - return ext.libraries + + return ext.libraries diff --git a/Makefile.pre.in b/Makefile.pre.in index cd7098cac72b1d..68ac7723556e4e 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1460,7 +1460,7 @@ libinstall: build_all $(srcdir)/Modules/xxmodule.c -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/PatternGrammar.txt -python-config: $(srcdir)/Misc/python-config.in Misc/python-config.sh +python-config: $(srcdir)/Misc/python-config.in $(srcdir)/Misc/python-config.sh @ # Substitution happens here, as the completely-expanded BINDIR @ # is not available in configure sed -e "s,@EXENAME@,$(BINDIR)/python$(LDVERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config.py diff --git a/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst b/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst new file mode 100644 index 00000000000000..5e1e717b1ea885 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst @@ -0,0 +1,12 @@ +On Unix, C extensions are no longer linked to libpython. + +It is now possible to load a C extension built using a shared library Python +with a statically linked Python. + +When Python is embedded, ``libpython`` must not be loaded with ``RTLD_LOCAL``, +but ``RTLD_GLOBAL`` instead. Previously, using ``RTLD_LOCAL``, it was already +not possible to load C extensions which were not linked to ``libpython``, like +C extensions of the standard library built by the ``*shared*`` section of +``Modules/Setup``. + +distutils, python-config and python-config.py have been modified. diff --git a/Misc/python-config.in b/Misc/python-config.in index 714415222798d6..31ad55822e55a2 100644 --- a/Misc/python-config.in +++ b/Misc/python-config.in @@ -47,9 +47,7 @@ for opt in opt_flags: print(' '.join(flags)) elif opt in ('--libs', '--ldflags'): - libs = ['-lpython' + pyver + sys.abiflags] - libs += getvar('LIBS').split() - libs += getvar('SYSLIBS').split() + libs = getvar('LIBS').split() + getvar('SYSLIBS').split() # add the prefix/lib/pythonX.Y/config dir, but only if there is no # shared library in prefix/lib/. if opt == '--ldflags': diff --git a/Misc/python-config.sh.in b/Misc/python-config.sh.in index a3c479ce571f87..ac1a467678e44b 100644 --- a/Misc/python-config.sh.in +++ b/Misc/python-config.sh.in @@ -41,7 +41,7 @@ LIBM="@LIBM@" LIBC="@LIBC@" SYSLIBS="$LIBM $LIBC" ABIFLAGS="@ABIFLAGS@" -LIBS="-lpython${VERSION}${ABIFLAGS} @LIBS@ $SYSLIBS" +LIBS="@LIBS@ $SYSLIBS" BASECFLAGS="@BASECFLAGS@" LDLIBRARY="@LDLIBRARY@" OPT="@OPT@" From 62dfd7d6fe11bfa0cd1d7376382c8e7b1275e38c Mon Sep 17 00:00:00 2001 From: Paul Monson Date: Thu, 25 Apr 2019 11:36:45 -0700 Subject: [PATCH 079/212] bpo-35920: Windows 10 ARM32 platform support (GH-11774) --- Doc/library/platform.rst | 15 +++++++++ Lib/distutils/_msvccompiler.py | 16 ++++++++-- Lib/distutils/spawn.py | 2 +- Lib/distutils/sysconfig.py | 1 + Lib/distutils/util.py | 16 ++++++++-- Lib/platform.py | 21 ++++++++++++ Lib/sysconfig.py | 2 ++ Lib/test/test_codecs.py | 32 ++++++++++++++++++- Lib/test/test_mimetypes.py | 3 ++ Lib/test/test_os.py | 3 +- Lib/test/test_startfile.py | 2 ++ Lib/test/test_sundry.py | 3 +- Lib/test/test_winreg.py | 3 +- .../2019-04-22-16-59-20.bpo-35920.VSfGOI.rst | 3 ++ PC/bdist_wininst/bdist_wininst.vcxproj | 16 ++++++++++ PCbuild/build.bat | 2 +- PCbuild/pcbuild.sln | 9 +++--- 17 files changed, 134 insertions(+), 15 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2019-04-22-16-59-20.bpo-35920.VSfGOI.rst diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst index 60c6089ad3ccb5..e07f9d613a0d21 100644 --- a/Doc/library/platform.rst +++ b/Doc/library/platform.rst @@ -216,6 +216,21 @@ Windows Platform later (support for this was added in Python 2.6). It obviously only runs on Win32 compatible platforms. +.. function:: win32_edition() + + Returns a string representing the current Windows edition. Possible + values include but are not limited to ``'Enterprise'``, ``'IoTUAP'``, + ``'ServerStandard'``, and ``'nanoserver'``. + + .. versionadded:: 3.8 + +.. function:: win32_is_iot() + + Returns True if the windows edition returned by win32_edition is recognized + as an IoT edition. + + .. versionadded:: 3.8 + Mac OS Platform --------------- diff --git a/Lib/distutils/_msvccompiler.py b/Lib/distutils/_msvccompiler.py index 58b20a21024733..c7ac3f049ebf22 100644 --- a/Lib/distutils/_msvccompiler.py +++ b/Lib/distutils/_msvccompiler.py @@ -89,13 +89,24 @@ def _find_vc2017(): return None, None +PLAT_SPEC_TO_RUNTIME = { + 'x86' : 'x86', + 'x86_amd64' : 'x64', + 'x86_arm' : 'arm', +} + def _find_vcvarsall(plat_spec): _, best_dir = _find_vc2017() vcruntime = None - vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86' + + if plat_spec in PLAT_SPEC_TO_RUNTIME: + vcruntime_plat = PLAT_SPEC_TO_RUNTIME[plat_spec] + else: + vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86' + if best_dir: vcredist = os.path.join(best_dir, "..", "..", "redist", "MSVC", "**", - "Microsoft.VC141.CRT", "vcruntime140.dll") + vcruntime_plat, "Microsoft.VC141.CRT", "vcruntime140.dll") try: import glob vcruntime = glob.glob(vcredist, recursive=True)[-1] @@ -178,6 +189,7 @@ def _find_exe(exe, paths=None): PLAT_TO_VCVARS = { 'win32' : 'x86', 'win-amd64' : 'x86_amd64', + 'win-arm32' : 'x86_arm', } # A set containing the DLLs that are guaranteed to be available for diff --git a/Lib/distutils/spawn.py b/Lib/distutils/spawn.py index d3a12c28339782..ceb94945dc8bed 100644 --- a/Lib/distutils/spawn.py +++ b/Lib/distutils/spawn.py @@ -81,7 +81,6 @@ def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0): "command %r failed with exit status %d" % (cmd, rc)) if sys.platform == 'darwin': - from distutils import sysconfig _cfg_target = None _cfg_target_split = None @@ -95,6 +94,7 @@ def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0): if sys.platform == 'darwin': global _cfg_target, _cfg_target_split if _cfg_target is None: + from distutils import sysconfig _cfg_target = sysconfig.get_config_var( 'MACOSX_DEPLOYMENT_TARGET') or '' if _cfg_target: diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py index 570a612d1b1029..b51629eb94f825 100644 --- a/Lib/distutils/sysconfig.py +++ b/Lib/distutils/sysconfig.py @@ -15,6 +15,7 @@ import sys from .errors import DistutilsPlatformError +from .util import get_platform, get_host_platform # These are needed in a couple of spots, so just compute them once. PREFIX = os.path.normpath(sys.prefix) diff --git a/Lib/distutils/util.py b/Lib/distutils/util.py index 15cd2ad9a9afb8..50550e1893418c 100644 --- a/Lib/distutils/util.py +++ b/Lib/distutils/util.py @@ -15,7 +15,7 @@ from distutils import log from distutils.errors import DistutilsByteCompileError -def get_platform (): +def get_host_platform(): """Return a string that identifies the current platform. This is used mainly to distinguish platform-specific build directories and platform-specific built distributions. Typically includes the OS name and version and the @@ -38,6 +38,8 @@ def get_platform (): if os.name == 'nt': if 'amd64' in sys.version.lower(): return 'win-amd64' + if '(arm)' in sys.version.lower(): + return 'win-arm32' return sys.platform # Set for cross builds explicitly @@ -90,8 +92,16 @@ def get_platform (): return "%s-%s-%s" % (osname, release, machine) -# get_platform () - +def get_platform(): + if os.name == 'nt': + TARGET_TO_PLAT = { + 'x86' : 'win32', + 'x64' : 'win-amd64', + 'arm' : 'win-arm32', + } + return TARGET_TO_PLAT.get(os.environ.get('VSCMD_ARG_TGT_ARCH')) or get_host_platform() + else: + return get_host_platform() def convert_path (pathname): """Return 'pathname' as a name that will work on the native filesystem, diff --git a/Lib/platform.py b/Lib/platform.py index 21defd1095d247..9f7bd95980a15c 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -334,6 +334,27 @@ def _syscmd_ver(system='', release='', version='', (6, None): "post2012ServerR2", } +def win32_is_iot(): + return win32_edition() in ('IoTUAP', 'NanoServer', 'WindowsCoreHeadless', 'IoTEdgeOS') + +def win32_edition(): + try: + try: + import winreg + except ImportError: + import _winreg as winreg + except ImportError: + pass + else: + try: + cvkey = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion' + with winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE, cvkey) as key: + return winreg.QueryValueEx(key, 'EditionId')[0] + except OSError: + pass + + return None + def win32_ver(release='', version='', csd='', ptype=''): try: from sys import getwindowsversion diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py index cc8c7962b1bca2..8446c8deb2427e 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -626,6 +626,8 @@ def get_platform(): if os.name == 'nt': if 'amd64' in sys.version.lower(): return 'win-amd64' + if '(arm)' in sys.version.lower(): + return 'win-arm32' return sys.platform if os.name != "posix" or not hasattr(os, 'uname'): diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 05843c54bd5f9a..027a84e275e369 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -27,6 +27,26 @@ def check(input, expect): self.assertEqual(coder(input), (expect, len(input))) return check +# On small versions of Windows like Windows IoT or Windows Nano Server not all codepages are present +def is_code_page_present(cp): + from ctypes import POINTER, WINFUNCTYPE, windll, WinError, Structure, WinDLL + from ctypes.wintypes import BOOL, UINT, BYTE, WCHAR, UINT, DWORD + + MAX_LEADBYTES = 12 # 5 ranges, 2 bytes ea., 0 term. + MAX_DEFAULTCHAR = 2 # single or double byte + MAX_PATH = 260 + class CPINFOEXW(ctypes.Structure): + _fields_ = [("MaxCharSize", UINT), + ("DefaultChar", BYTE*MAX_DEFAULTCHAR), + ("LeadByte", BYTE*MAX_LEADBYTES), + ("UnicodeDefaultChar", WCHAR), + ("CodePage", UINT), + ("CodePageName", WCHAR*MAX_PATH)] + + prototype = WINFUNCTYPE(BOOL, UINT, DWORD, POINTER(CPINFOEXW)) + GetCPInfoEx = prototype(("GetCPInfoExW", WinDLL("kernel32"))) + info = CPINFOEXW() + return GetCPInfoEx(cp, 0, info) class Queue(object): """ @@ -3078,9 +3098,19 @@ def test_multibyte_encoding(self): def test_code_page_decode_flags(self): # Issue #36312: For some code pages (e.g. UTF-7) flags for # MultiByteToWideChar() must be set to 0. + if support.verbose: + sys.stdout.write('\n') for cp in (50220, 50221, 50222, 50225, 50227, 50229, *range(57002, 57011+1), 65000): - self.assertEqual(codecs.code_page_decode(cp, b'abc'), ('abc', 3)) + # On small versions of Windows like Windows IoT + # not all codepages are present. + # A missing codepage causes an OSError exception + # so check for the codepage before decoding + if is_code_page_present(cp): + self.assertEqual(codecs.code_page_decode(cp, b'abc'), ('abc', 3), f'cp{cp}') + else: + if support.verbose: + print(f" skipping cp={cp}") self.assertEqual(codecs.code_page_decode(42, b'abc'), ('\uf061\uf062\uf063', 3)) diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py index 554d3d5cead5db..c4b2fe2047a71d 100644 --- a/Lib/test/test_mimetypes.py +++ b/Lib/test/test_mimetypes.py @@ -6,6 +6,7 @@ import unittest from test import support +from platform import win32_edition # Tell it we don't know about external files: mimetypes.knownfiles = [] @@ -116,6 +117,8 @@ def tearDown(self): mimetypes.types_map.clear() mimetypes.types_map.update(self.original_types_map) + @unittest.skipIf(win32_edition() in ('NanoServer', 'WindowsCoreHeadless', 'IoTEdgeOS'), + "MIME types registry keys unavailable") def test_registry_parsing(self): # the original, minimum contents of the MIME database in the # Windows registry is undocumented AFAIK. diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index bbadb81069b9da..a2021b1eba068f 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -28,6 +28,7 @@ import uuid import warnings from test import support +from platform import win32_is_iot try: import resource @@ -2439,7 +2440,7 @@ def test_bad_fd(self): # Return None when an fd doesn't actually exist. self.assertIsNone(os.device_encoding(123456)) - @unittest.skipUnless(os.isatty(0) and (sys.platform.startswith('win') or + @unittest.skipUnless(os.isatty(0) and not win32_is_iot() and (sys.platform.startswith('win') or (hasattr(locale, 'nl_langinfo') and hasattr(locale, 'CODESET'))), 'test requires a tty and either Windows or nl_langinfo(CODESET)') def test_device_encoding(self): diff --git a/Lib/test/test_startfile.py b/Lib/test/test_startfile.py index f59252e97ad051..1a26a8025e6243 100644 --- a/Lib/test/test_startfile.py +++ b/Lib/test/test_startfile.py @@ -10,6 +10,7 @@ import unittest from test import support import os +import platform import sys from os import path @@ -20,6 +21,7 @@ class TestCase(unittest.TestCase): def test_nonexisting(self): self.assertRaises(OSError, startfile, "nonexisting.vbs") + @unittest.skipIf(platform.win32_is_iot(), "starting files is not supported on Windows IoT Core or nanoserver") def test_empty(self): # We need to make sure the child process starts in a directory # we're not about to delete. If we're running under -j, that diff --git a/Lib/test/test_sundry.py b/Lib/test/test_sundry.py index 6e36a6123daa0e..2accad1aeebd4f 100644 --- a/Lib/test/test_sundry.py +++ b/Lib/test/test_sundry.py @@ -1,5 +1,6 @@ """Do a minimal test of all the modules that aren't otherwise tested.""" import importlib +import platform import sys from test import support import unittest @@ -25,7 +26,7 @@ def test_untested_modules_can_be_imported(self): import distutils.unixccompiler import distutils.command.bdist_dumb - if sys.platform.startswith('win'): + if sys.platform.startswith('win') and not platform.win32_is_iot(): import distutils.command.bdist_msi import distutils.command.bdist import distutils.command.bdist_rpm diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index 11d054e16cdbfa..dc2b46e42521f3 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -5,7 +5,7 @@ import unittest from test import support import threading -from platform import machine +from platform import machine, win32_edition # Do this first so test will be skipped if module doesn't exist support.import_module('winreg', required_on=['win']) @@ -399,6 +399,7 @@ def test_named_arguments(self): DeleteKeyEx(key=HKEY_CURRENT_USER, sub_key=test_key_name, access=KEY_ALL_ACCESS, reserved=0) + @unittest.skipIf(win32_edition() in ('WindowsCoreHeadless', 'IoTEdgeOS'), "APIs not available on WindowsCoreHeadless") def test_reflection_functions(self): # Test that we can call the query, enable, and disable functions # on a key which isn't on the reflection list with no consequences. diff --git a/Misc/NEWS.d/next/Windows/2019-04-22-16-59-20.bpo-35920.VSfGOI.rst b/Misc/NEWS.d/next/Windows/2019-04-22-16-59-20.bpo-35920.VSfGOI.rst new file mode 100644 index 00000000000000..455e82450eb2b5 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-04-22-16-59-20.bpo-35920.VSfGOI.rst @@ -0,0 +1,3 @@ +Added platform.win32_edition() and platform.win32_is_iot(). Added support +for cross-compiling packages for Windows ARM32. Skip tests that are not +expected to work on Windows IoT Core ARM32. diff --git a/PC/bdist_wininst/bdist_wininst.vcxproj b/PC/bdist_wininst/bdist_wininst.vcxproj index 70bfb9c9337943..d2f1bb75e30d87 100644 --- a/PC/bdist_wininst/bdist_wininst.vcxproj +++ b/PC/bdist_wininst/bdist_wininst.vcxproj @@ -1,6 +1,10 @@  + + Debug + ARM + Debug Win32 @@ -9,6 +13,10 @@ Debug x64 + + PGInstrument + ARM + PGInstrument Win32 @@ -17,6 +25,10 @@ PGInstrument x64 + + PGUpdate + ARM + PGUpdate Win32 @@ -25,6 +37,10 @@ PGUpdate x64 + + Release + ARM + Release Win32 diff --git a/PCbuild/build.bat b/PCbuild/build.bat index 759aa5221b4266..cd0c07abbf352b 100644 --- a/PCbuild/build.bat +++ b/PCbuild/build.bat @@ -41,7 +41,7 @@ echo. echo.Available arguments: echo. -c Release ^| Debug ^| PGInstrument ^| PGUpdate echo. Set the configuration (default: Release) -echo. -p x64 ^| Win32 +echo. -p x64 ^| Win32 ^| ARM echo. Set the platform (default: Win32) echo. -t Build ^| Rebuild ^| Clean ^| CleanAll echo. Set the target manually diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln index 951dc932a8e570..66be9ac7a4ad94 100644 --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -597,16 +597,16 @@ Global {D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|Win32.Build.0 = Release|Win32 {D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|x64.ActiveCfg = Release|x64 {D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|x64.Build.0 = Release|x64 - {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|ARM.ActiveCfg = Debug|Win32 + {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|ARM.ActiveCfg = Debug|ARM {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|Win32.ActiveCfg = Debug|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|x64.ActiveCfg = Release|x64 - {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|ARM.ActiveCfg = PGInstrument|Win32 + {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|ARM.ActiveCfg = PGInstrument|ARM {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|Win32.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|x64.ActiveCfg = Release|x64 - {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|ARM.ActiveCfg = PGUpdate|Win32 + {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|ARM.ActiveCfg = PGUpdate|ARM {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|Win32.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|x64.ActiveCfg = Release|x64 - {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|ARM.ActiveCfg = Release|Win32 + {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|ARM.ActiveCfg = Release|ARM {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|Win32.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|x64.ActiveCfg = Release|x64 {447F05A8-F581-4CAC-A466-5AC7936E207E}.Debug|ARM.ActiveCfg = Debug|ARM @@ -896,6 +896,7 @@ Global {0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 {0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGUpdate|x64.Build.0 = PGUpdate|x64 {0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|ARM.ActiveCfg = Release|ARM + {0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|ARM.Build.0 = Release|ARM {0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|Win32.ActiveCfg = Release|Win32 {0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|Win32.Build.0 = Release|Win32 {0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|x64.ActiveCfg = Release|x64 From 5422e3cfb7ffc50b147b4662d6f596cd61533754 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 01:40:00 +0200 Subject: [PATCH 080/212] bpo-36722: Debug build loads libraries built in release mode (GH-12952) In debug build, import now also looks for C extensions compiled in release mode and for C extensions compiled in the stable ABI. --- .../2019-04-25-21-02-40.bpo-36722.8NApVM.rst | 2 ++ Python/dynload_shlib.c | 5 +++-- configure | 12 ++++++++++++ configure.ac | 8 ++++++++ pyconfig.h.in | 4 ++++ 5 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-25-21-02-40.bpo-36722.8NApVM.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-25-21-02-40.bpo-36722.8NApVM.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-25-21-02-40.bpo-36722.8NApVM.rst new file mode 100644 index 00000000000000..210a7e0525920d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-04-25-21-02-40.bpo-36722.8NApVM.rst @@ -0,0 +1,2 @@ +In debug build, import now also looks for C extensions compiled in release +mode and for C extensions compiled in the stable ABI. diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index e5bddaab6caa06..c51f97abd28630 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -38,9 +38,10 @@ const char *_PyImport_DynLoadFiletab[] = { ".dll", #else /* !__CYGWIN__ */ "." SOABI ".so", -#ifndef Py_DEBUG +#ifdef ALT_SOABI + "." ALT_SOABI ".so", +#endif ".abi" PYTHON_ABI_STRING ".so", -#endif /* ! Py_DEBUG */ ".so", #endif /* __CYGWIN__ */ NULL, diff --git a/configure b/configure index b02d17c053c6b5..b2775cf04000fd 100755 --- a/configure +++ b/configure @@ -632,6 +632,7 @@ THREADHEADERS LIBPL PY_ENABLE_SHARED EXT_SUFFIX +ALT_SOABI SOABI LIBC LIBM @@ -15127,6 +15128,17 @@ SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${PLATFORM_TRIPLET:+-$PLATFO { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SOABI" >&5 $as_echo "$SOABI" >&6; } +if test "$Py_DEBUG" = 'true'; then + # Similar to SOABI but remove "d" flag from ABIFLAGS + + ALT_SOABI='cpython-'`echo $VERSION | tr -d .``echo $ABIFLAGS | tr -d d`${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} + +cat >>confdefs.h <<_ACEOF +#define ALT_SOABI "${ALT_SOABI}" +_ACEOF + +fi + case $ac_sys_system in Linux*|GNU*|Darwin|VxWorks) diff --git a/configure.ac b/configure.ac index 65d3f8e6912983..312758788e4d7a 100644 --- a/configure.ac +++ b/configure.ac @@ -4627,6 +4627,14 @@ AC_MSG_CHECKING(SOABI) SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} AC_MSG_RESULT($SOABI) +if test "$Py_DEBUG" = 'true'; then + # Similar to SOABI but remove "d" flag from ABIFLAGS + AC_SUBST(ALT_SOABI) + ALT_SOABI='cpython-'`echo $VERSION | tr -d .``echo $ABIFLAGS | tr -d d`${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} + AC_DEFINE_UNQUOTED(ALT_SOABI, "${ALT_SOABI}", + [Alternative SOABI used in debug build to load C extensions built in release mode]) +fi + AC_SUBST(EXT_SUFFIX) case $ac_sys_system in Linux*|GNU*|Darwin|VxWorks) diff --git a/pyconfig.h.in b/pyconfig.h.in index 562c0271133bdc..4b779614727406 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -12,6 +12,10 @@ support for AIX C++ shared extension modules. */ #undef AIX_GENUINE_CPLUSPLUS +/* Alternative SOABI used in debug build to load C extensions built in release + mode */ +#undef ALT_SOABI + /* The Android API level. */ #undef ANDROID_API_LEVEL From 10c8e6af910e3a26e59f913a3c1e4830ca71b1af Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 01:53:18 +0200 Subject: [PATCH 081/212] bpo-36710: Add runtime variable in pystate.c (GH-12956) Add 'gilstate', 'runtime' or 'xidregistry' parameter to many functions on pystate.c to avoid lying on _PyRuntime global. --- Python/pystate.c | 361 ++++++++++++++++++++++++++++------------------- 1 file changed, 219 insertions(+), 142 deletions(-) diff --git a/Python/pystate.c b/Python/pystate.c index a413f9d7ab4c57..f964f4951b9cfd 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -6,11 +6,6 @@ #include "pycore_pymem.h" #include "pycore_pystate.h" -#define _PyThreadState_SET(value) \ - _Py_atomic_store_relaxed(&_PyRuntime.gilstate.tstate_current, \ - (uintptr_t)(value)) - - /* -------------------------------------------------------------------------- CAUTION @@ -34,6 +29,18 @@ to avoid the expense of doing their own locking). extern "C" { #endif +#define _PyRuntimeGILState_GetThreadState(gilstate) \ + ((PyThreadState*)_Py_atomic_load_relaxed(&(gilstate)->tstate_current)) +#define _PyRuntimeGILState_SetThreadState(gilstate, value) \ + _Py_atomic_store_relaxed(&(gilstate)->tstate_current, \ + (uintptr_t)(value)) + +/* Forward declarations */ +static PyThreadState *_PyGILState_GetThisThreadState(struct _gilstate_runtime_state *gilstate); +static void _PyThreadState_Delete(_PyRuntimeState *runtime, PyThreadState *tstate); +static PyThreadState *_PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *newts); + + static _PyInitError _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) { @@ -137,9 +144,10 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) } } -#define HEAD_LOCK() PyThread_acquire_lock(_PyRuntime.interpreters.mutex, \ - WAIT_LOCK) -#define HEAD_UNLOCK() PyThread_release_lock(_PyRuntime.interpreters.mutex) +#define HEAD_LOCK(runtime) \ + PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK) +#define HEAD_UNLOCK(runtime) \ + PyThread_release_lock((runtime)->interpreters.mutex) /* Forward declaration */ static void _PyGILState_NoteThreadState( @@ -148,21 +156,22 @@ static void _PyGILState_NoteThreadState( _PyInitError _PyInterpreterState_Enable(_PyRuntimeState *runtime) { - runtime->interpreters.next_id = 0; + struct pyinterpreters *interpreters = &runtime->interpreters; + interpreters->next_id = 0; /* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex. Create a new mutex if needed. */ - if (runtime->interpreters.mutex == NULL) { + if (interpreters->mutex == NULL) { /* Force default allocator, since _PyRuntimeState_Fini() must use the same allocator than this function. */ PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - runtime->interpreters.mutex = PyThread_allocate_lock(); + interpreters->mutex = PyThread_allocate_lock(); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - if (runtime->interpreters.mutex == NULL) { + if (interpreters->mutex == NULL) { return _Py_INIT_ERR("Can't initialize threads for interpreter"); } } @@ -173,9 +182,7 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime) PyInterpreterState * PyInterpreterState_New(void) { - PyInterpreterState *interp = (PyInterpreterState *) - PyMem_RawMalloc(sizeof(PyInterpreterState)); - + PyInterpreterState *interp = PyMem_RawMalloc(sizeof(PyInterpreterState)); if (interp == NULL) { return NULL; } @@ -193,23 +200,27 @@ PyInterpreterState_New(void) #endif #endif - HEAD_LOCK(); - if (_PyRuntime.interpreters.next_id < 0) { + _PyRuntimeState *runtime = &_PyRuntime; + struct pyinterpreters *interpreters = &runtime->interpreters; + + HEAD_LOCK(runtime); + if (interpreters->next_id < 0) { /* overflow or Py_Initialize() not called! */ PyErr_SetString(PyExc_RuntimeError, "failed to get an interpreter ID"); PyMem_RawFree(interp); interp = NULL; - } else { - interp->id = _PyRuntime.interpreters.next_id; - _PyRuntime.interpreters.next_id += 1; - interp->next = _PyRuntime.interpreters.head; - if (_PyRuntime.interpreters.main == NULL) { - _PyRuntime.interpreters.main = interp; + } + else { + interp->id = interpreters->next_id; + interpreters->next_id += 1; + interp->next = interpreters->head; + if (interpreters->main == NULL) { + interpreters->main = interp; } - _PyRuntime.interpreters.head = interp; + interpreters->head = interp; } - HEAD_UNLOCK(); + HEAD_UNLOCK(runtime); if (interp == NULL) { return NULL; @@ -221,14 +232,14 @@ PyInterpreterState_New(void) } -void -PyInterpreterState_Clear(PyInterpreterState *interp) +static void +_PyInterpreterState_Clear(_PyRuntimeState *runtime, PyInterpreterState *interp) { - PyThreadState *p; - HEAD_LOCK(); - for (p = interp->tstate_head; p != NULL; p = p->next) + HEAD_LOCK(runtime); + for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) { PyThreadState_Clear(p); - HEAD_UNLOCK(); + } + HEAD_UNLOCK(runtime); _PyCoreConfig_Clear(&interp->core_config); Py_CLEAR(interp->codec_search_path); Py_CLEAR(interp->codec_search_cache); @@ -251,41 +262,52 @@ PyInterpreterState_Clear(PyInterpreterState *interp) // objects have been cleaned up at the point. } +void +PyInterpreterState_Clear(PyInterpreterState *interp) +{ + _PyInterpreterState_Clear(&_PyRuntime, interp); +} + static void -zapthreads(PyInterpreterState *interp) +zapthreads(_PyRuntimeState *runtime, PyInterpreterState *interp) { PyThreadState *p; /* No need to lock the mutex here because this should only happen when the threads are all really dead (XXX famous last words). */ while ((p = interp->tstate_head) != NULL) { - PyThreadState_Delete(p); + _PyThreadState_Delete(runtime, p); } } -void -PyInterpreterState_Delete(PyInterpreterState *interp) +static void +_PyInterpreterState_Delete(_PyRuntimeState *runtime, + PyInterpreterState *interp) { + struct pyinterpreters *interpreters = &runtime->interpreters; + zapthreads(runtime, interp); + HEAD_LOCK(runtime); PyInterpreterState **p; - zapthreads(interp); - HEAD_LOCK(); - for (p = &_PyRuntime.interpreters.head; ; p = &(*p)->next) { - if (*p == NULL) - Py_FatalError( - "PyInterpreterState_Delete: invalid interp"); - if (*p == interp) + for (p = &interpreters->head; ; p = &(*p)->next) { + if (*p == NULL) { + Py_FatalError("PyInterpreterState_Delete: invalid interp"); + } + if (*p == interp) { break; + } } - if (interp->tstate_head != NULL) + if (interp->tstate_head != NULL) { Py_FatalError("PyInterpreterState_Delete: remaining threads"); + } *p = interp->next; - if (_PyRuntime.interpreters.main == interp) { - _PyRuntime.interpreters.main = NULL; - if (_PyRuntime.interpreters.head != NULL) + if (interpreters->main == interp) { + interpreters->main = NULL; + if (interpreters->head != NULL) { Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters"); + } } - HEAD_UNLOCK(); + HEAD_UNLOCK(runtime); if (interp->id_mutex != NULL) { PyThread_free_lock(interp->id_mutex); } @@ -293,6 +315,13 @@ PyInterpreterState_Delete(PyInterpreterState *interp) } +void +PyInterpreterState_Delete(PyInterpreterState *interp) +{ + _PyInterpreterState_Delete(&_PyRuntime, interp); +} + + /* * Delete all interpreter states except the main interpreter. If there * is a current interpreter state, it *must* be the main interpreter. @@ -300,14 +329,15 @@ PyInterpreterState_Delete(PyInterpreterState *interp) void _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) { + struct _gilstate_runtime_state *gilstate = &runtime->gilstate; struct pyinterpreters *interpreters = &runtime->interpreters; - PyThreadState *tstate = PyThreadState_Swap(NULL); + PyThreadState *tstate = _PyThreadState_Swap(gilstate, NULL); if (tstate != NULL && tstate->interp != interpreters->main) { Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter"); } - HEAD_LOCK(); + HEAD_LOCK(runtime); PyInterpreterState *interp = interpreters->head; interpreters->head = NULL; while (interp != NULL) { @@ -318,8 +348,8 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) continue; } - PyInterpreterState_Clear(interp); // XXX must activate? - zapthreads(interp); + _PyInterpreterState_Clear(runtime, interp); // XXX must activate? + zapthreads(runtime, interp); if (interp->id_mutex != NULL) { PyThread_free_lock(interp->id_mutex); } @@ -327,12 +357,12 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) interp = interp->next; PyMem_RawFree(prev_interp); } - HEAD_UNLOCK(); + HEAD_UNLOCK(runtime); if (interpreters->head == NULL) { Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main"); } - PyThreadState_Swap(tstate); + _PyThreadState_Swap(gilstate, tstate); } @@ -363,9 +393,9 @@ PyInterpreterState_GetID(PyInterpreterState *interp) static PyInterpreterState * -interp_look_up_id(PY_INT64_T requested_id) +interp_look_up_id(_PyRuntimeState *runtime, PY_INT64_T requested_id) { - PyInterpreterState *interp = PyInterpreterState_Head(); + PyInterpreterState *interp = runtime->interpreters.head; while (interp != NULL) { PY_INT64_T id = PyInterpreterState_GetID(interp); if (id < 0) { @@ -384,9 +414,10 @@ _PyInterpreterState_LookUpID(PY_INT64_T requested_id) { PyInterpreterState *interp = NULL; if (requested_id >= 0) { - HEAD_LOCK(); - interp = interp_look_up_id(requested_id); - HEAD_UNLOCK(); + _PyRuntimeState *runtime = &_PyRuntime; + HEAD_LOCK(runtime); + interp = interp_look_up_id(runtime, requested_id); + HEAD_UNLOCK(runtime); } if (interp == NULL && !PyErr_Occurred()) { PyErr_Format(PyExc_RuntimeError, @@ -431,6 +462,7 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp) if (interp->id_mutex == NULL) { return; } + struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); assert(interp->id_refcount != 0); interp->id_refcount -= 1; @@ -441,9 +473,9 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp) // XXX Using the "head" thread isn't strictly correct. PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); // XXX Possible GILState issues? - PyThreadState *save_tstate = PyThreadState_Swap(tstate); + PyThreadState *save_tstate = _PyThreadState_Swap(gilstate, tstate); Py_EndInterpreter(tstate); - PyThreadState_Swap(save_tstate); + _PyThreadState_Swap(gilstate, save_tstate); } } @@ -498,6 +530,7 @@ threadstate_getframe(PyThreadState *self) static PyThreadState * new_threadstate(PyInterpreterState *interp, int init) { + _PyRuntimeState *runtime = &_PyRuntime; PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState)); if (tstate == NULL) { return NULL; @@ -556,16 +589,16 @@ new_threadstate(PyInterpreterState *interp, int init) tstate->id = ++interp->tstate_next_unique_id; if (init) { - _PyThreadState_Init(&_PyRuntime, tstate); + _PyThreadState_Init(runtime, tstate); } - HEAD_LOCK(); + HEAD_LOCK(runtime); tstate->prev = NULL; tstate->next = interp->tstate_head; if (tstate->next) tstate->next->prev = tstate; interp->tstate_head = tstate; - HEAD_UNLOCK(); + HEAD_UNLOCK(runtime); return tstate; } @@ -750,22 +783,23 @@ PyThreadState_Clear(PyThreadState *tstate) /* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */ static void -tstate_delete_common(PyThreadState *tstate) +tstate_delete_common(_PyRuntimeState *runtime, PyThreadState *tstate) { - PyInterpreterState *interp; - if (tstate == NULL) + if (tstate == NULL) { Py_FatalError("PyThreadState_Delete: NULL tstate"); - interp = tstate->interp; - if (interp == NULL) + } + PyInterpreterState *interp = tstate->interp; + if (interp == NULL) { Py_FatalError("PyThreadState_Delete: NULL interp"); - HEAD_LOCK(); + } + HEAD_LOCK(runtime); if (tstate->prev) tstate->prev->next = tstate->next; else interp->tstate_head = tstate->next; if (tstate->next) tstate->next->prev = tstate->prev; - HEAD_UNLOCK(); + HEAD_UNLOCK(runtime); if (tstate->on_delete != NULL) { tstate->on_delete(tstate->on_delete_data); } @@ -773,37 +807,53 @@ tstate_delete_common(PyThreadState *tstate) } -void -PyThreadState_Delete(PyThreadState *tstate) +static void +_PyThreadState_Delete(_PyRuntimeState *runtime, PyThreadState *tstate) { - if (tstate == _PyThreadState_GET()) + struct _gilstate_runtime_state *gilstate = &runtime->gilstate; + if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) { Py_FatalError("PyThreadState_Delete: tstate is still current"); - if (_PyRuntime.gilstate.autoInterpreterState && - PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == tstate) + } + if (gilstate->autoInterpreterState && + PyThread_tss_get(&gilstate->autoTSSkey) == tstate) { - PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, NULL); + PyThread_tss_set(&gilstate->autoTSSkey, NULL); } - tstate_delete_common(tstate); + tstate_delete_common(runtime, tstate); } void -PyThreadState_DeleteCurrent() +PyThreadState_Delete(PyThreadState *tstate) { - PyThreadState *tstate = _PyThreadState_GET(); + return _PyThreadState_Delete(&_PyRuntime, tstate); +} + + +static void +_PyThreadState_DeleteCurrent(_PyRuntimeState *runtime) +{ + struct _gilstate_runtime_state *gilstate = &runtime->gilstate; + PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate); if (tstate == NULL) Py_FatalError( "PyThreadState_DeleteCurrent: no current tstate"); - tstate_delete_common(tstate); - if (_PyRuntime.gilstate.autoInterpreterState && - PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == tstate) + tstate_delete_common(runtime, tstate); + if (gilstate->autoInterpreterState && + PyThread_tss_get(&gilstate->autoTSSkey) == tstate) { - PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, NULL); + PyThread_tss_set(&gilstate->autoTSSkey, NULL); } - _PyThreadState_SET(NULL); + _PyRuntimeGILState_SetThreadState(gilstate, NULL); PyEval_ReleaseLock(); } +void +PyThreadState_DeleteCurrent() +{ + _PyThreadState_DeleteCurrent(&_PyRuntime); +} + /* * Delete all thread states except the one passed as argument. @@ -815,9 +865,10 @@ PyThreadState_DeleteCurrent() void _PyThreadState_DeleteExcept(PyThreadState *tstate) { + _PyRuntimeState *runtime = &_PyRuntime; PyInterpreterState *interp = tstate->interp; PyThreadState *p, *next, *garbage; - HEAD_LOCK(); + HEAD_LOCK(runtime); /* Remove all thread states, except tstate, from the linked list of thread states. This will allow calling PyThreadState_Clear() without holding the lock. */ @@ -830,7 +881,7 @@ _PyThreadState_DeleteExcept(PyThreadState *tstate) tstate->next->prev = tstate->prev; tstate->prev = tstate->next = NULL; interp->tstate_head = tstate; - HEAD_UNLOCK(); + HEAD_UNLOCK(runtime); /* Clear and deallocate all stale thread states. Even if this executes Python code, we should be safe since it executes in the current thread, not one of the stale threads. */ @@ -860,12 +911,12 @@ PyThreadState_Get(void) } -PyThreadState * -PyThreadState_Swap(PyThreadState *newts) +static PyThreadState * +_PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *newts) { - PyThreadState *oldts = _PyThreadState_GET(); + PyThreadState *oldts = _PyRuntimeGILState_GetThreadState(gilstate); - _PyThreadState_SET(newts); + _PyRuntimeGILState_SetThreadState(gilstate, newts); /* It should not be possible for more than one thread state to be used for a thread. Check this the best we can in debug builds. @@ -876,7 +927,7 @@ PyThreadState_Swap(PyThreadState *newts) to it, we need to ensure errno doesn't change. */ int err = errno; - PyThreadState *check = PyGILState_GetThisThreadState(); + PyThreadState *check = _PyGILState_GetThisThreadState(gilstate); if (check && check->interp == newts->interp && check != newts) Py_FatalError("Invalid thread state for this thread"); errno = err; @@ -885,6 +936,12 @@ PyThreadState_Swap(PyThreadState *newts) return oldts; } +PyThreadState * +PyThreadState_Swap(PyThreadState *newts) +{ + return _PyThreadState_Swap(&_PyRuntime.gilstate, newts); +} + /* An extension mechanism to store arbitrary additional per-thread state. PyThreadState_GetDict() returns a dictionary that can be used to hold such state; the caller should pick a unique key and store its state there. If @@ -928,7 +985,8 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) * list of thread states we're traversing, so to prevent that we lock * head_mutex for the duration. */ - HEAD_LOCK(); + _PyRuntimeState *runtime = &_PyRuntime; + HEAD_LOCK(runtime); for (p = interp->tstate_head; p != NULL; p = p->next) { if (p->thread_id == id) { /* Tricky: we need to decref the current value @@ -941,13 +999,13 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) PyObject *old_exc = p->async_exc; Py_XINCREF(exc); p->async_exc = exc; - HEAD_UNLOCK(); + HEAD_UNLOCK(runtime); Py_XDECREF(old_exc); _PyEval_SignalAsyncExc(); return 1; } } - HEAD_UNLOCK(); + HEAD_UNLOCK(runtime); return 0; } @@ -1003,8 +1061,9 @@ _PyThread_CurrentFrames(void) * Because these lists can mutate even when the GIL is held, we * need to grab head_mutex for the duration. */ - HEAD_LOCK(); - for (i = _PyRuntime.interpreters.head; i != NULL; i = i->next) { + _PyRuntimeState *runtime = &_PyRuntime; + HEAD_LOCK(runtime); + for (i = runtime->interpreters.head; i != NULL; i = i->next) { PyThreadState *t; for (t = i->tstate_head; t != NULL; t = t->next) { PyObject *id; @@ -1021,11 +1080,11 @@ _PyThread_CurrentFrames(void) goto Fail; } } - HEAD_UNLOCK(); + HEAD_UNLOCK(runtime); return result; Fail: - HEAD_UNLOCK(); + HEAD_UNLOCK(runtime); Py_DECREF(result); return NULL; } @@ -1044,8 +1103,9 @@ static int PyThreadState_IsCurrent(PyThreadState *tstate) { /* Must be the tstate for this thread */ - assert(PyGILState_GetThisThreadState()==tstate); - return tstate == _PyThreadState_GET(); + struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; + assert(_PyGILState_GetThisThreadState(gilstate) == tstate); + return tstate == _PyRuntimeGILState_GetThreadState(gilstate); } /* Internal initialization/finalization functions called by @@ -1093,7 +1153,7 @@ void _PyGILState_Reinit(_PyRuntimeState *runtime) { struct _gilstate_runtime_state *gilstate = &runtime->gilstate; - PyThreadState *tstate = PyGILState_GetThisThreadState(); + PyThreadState *tstate = _PyGILState_GetThisThreadState(gilstate); PyThread_tss_delete(&gilstate->autoTSSkey); if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { @@ -1147,36 +1207,45 @@ _PyGILState_NoteThreadState(struct _gilstate_runtime_state *gilstate, PyThreadSt } /* The public functions */ +static PyThreadState * +_PyGILState_GetThisThreadState(struct _gilstate_runtime_state *gilstate) +{ + if (gilstate->autoInterpreterState == NULL) + return NULL; + return (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey); +} + PyThreadState * PyGILState_GetThisThreadState(void) { - if (_PyRuntime.gilstate.autoInterpreterState == NULL) - return NULL; - return (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey); + return _PyGILState_GetThisThreadState(&_PyRuntime.gilstate); } int PyGILState_Check(void) { - PyThreadState *tstate; - if (!_PyGILState_check_enabled) + if (!_PyGILState_check_enabled) { return 1; + } - if (!PyThread_tss_is_created(&_PyRuntime.gilstate.autoTSSkey)) { + struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; + if (!PyThread_tss_is_created(&gilstate->autoTSSkey)) { return 1; } - tstate = _PyThreadState_GET(); - if (tstate == NULL) + PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate); + if (tstate == NULL) { return 0; + } - return (tstate == PyGILState_GetThisThreadState()); + return (tstate == _PyGILState_GetThisThreadState(gilstate)); } PyGILState_STATE PyGILState_Ensure(void) { + struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; int current; PyThreadState *tcur; int need_init_threads = 0; @@ -1187,14 +1256,14 @@ PyGILState_Ensure(void) called Py_Initialize() and usually PyEval_InitThreads(). */ /* Py_Initialize() hasn't been called! */ - assert(_PyRuntime.gilstate.autoInterpreterState); + assert(gilstate->autoInterpreterState); - tcur = (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey); + tcur = (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey); if (tcur == NULL) { need_init_threads = 1; /* Create a new thread state for this thread */ - tcur = PyThreadState_New(_PyRuntime.gilstate.autoInterpreterState); + tcur = PyThreadState_New(gilstate->autoInterpreterState); if (tcur == NULL) Py_FatalError("Couldn't create thread-state for new thread"); /* This is our thread state! We'll need to delete it in the @@ -1230,18 +1299,21 @@ PyGILState_Ensure(void) void PyGILState_Release(PyGILState_STATE oldstate) { - PyThreadState *tcur = (PyThreadState *)PyThread_tss_get( - &_PyRuntime.gilstate.autoTSSkey); - if (tcur == NULL) + _PyRuntimeState *runtime = &_PyRuntime; + PyThreadState *tcur = PyThread_tss_get(&runtime->gilstate.autoTSSkey); + if (tcur == NULL) { Py_FatalError("auto-releasing thread-state, " "but no thread-state for this thread"); + } + /* We must hold the GIL and have our thread state current */ /* XXX - remove the check - the assert should be fine, but while this is very new (April 2003), the extra check by release-only users can't hurt. */ - if (! PyThreadState_IsCurrent(tcur)) + if (!PyThreadState_IsCurrent(tcur)) { Py_FatalError("This thread state must be current when releasing"); + } assert(PyThreadState_IsCurrent(tcur)); --tcur->gilstate_counter; assert(tcur->gilstate_counter >= 0); /* illegal counter value */ @@ -1258,7 +1330,7 @@ PyGILState_Release(PyGILState_STATE oldstate) * races; see bugs 225673 and 1061968 (that nasty bug has a * habit of coming back). */ - PyThreadState_DeleteCurrent(); + _PyThreadState_DeleteCurrent(runtime); } /* Release the lock if necessary */ else if (oldstate == PyGILState_UNLOCKED) @@ -1363,7 +1435,8 @@ _release_xidata(void *arg) } static void -_call_in_interpreter(PyInterpreterState *interp, +_call_in_interpreter(struct _gilstate_runtime_state *gilstate, + PyInterpreterState *interp, void (*func)(void *), void *arg) { /* We would use Py_AddPendingCall() if it weren't specific to the @@ -1371,18 +1444,18 @@ _call_in_interpreter(PyInterpreterState *interp, * naive approach. */ PyThreadState *save_tstate = NULL; - if (interp != _PyInterpreterState_Get()) { + if (interp != _PyRuntimeGILState_GetThreadState(gilstate)->interp) { // XXX Using the "head" thread isn't strictly correct. PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); // XXX Possible GILState issues? - save_tstate = PyThreadState_Swap(tstate); + save_tstate = _PyThreadState_Swap(gilstate, tstate); } func(arg); // Switch back. if (save_tstate != NULL) { - PyThreadState_Swap(save_tstate); + _PyThreadState_Swap(gilstate, save_tstate); } } @@ -1405,7 +1478,8 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) } // "Release" the data and/or the object. - _call_in_interpreter(interp, _release_xidata, data); + struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; + _call_in_interpreter(gilstate, interp, _release_xidata, data); } PyObject * @@ -1421,7 +1495,8 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data) crossinterpdatafunc. It would be simpler and more efficient. */ static int -_register_xidata(PyTypeObject *cls, crossinterpdatafunc getdata) +_register_xidata(struct _xidregistry *xidregistry, PyTypeObject *cls, + crossinterpdatafunc getdata) { // Note that we effectively replace already registered classes // rather than failing. @@ -1430,12 +1505,12 @@ _register_xidata(PyTypeObject *cls, crossinterpdatafunc getdata) return -1; newhead->cls = cls; newhead->getdata = getdata; - newhead->next = _PyRuntime.xidregistry.head; - _PyRuntime.xidregistry.head = newhead; + newhead->next = xidregistry->head; + xidregistry->head = newhead; return 0; } -static void _register_builtins_for_crossinterpreter_data(void); +static void _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry); int _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, @@ -1453,12 +1528,13 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, // Make sure the class isn't ever deallocated. Py_INCREF((PyObject *)cls); - PyThread_acquire_lock(_PyRuntime.xidregistry.mutex, WAIT_LOCK); - if (_PyRuntime.xidregistry.head == NULL) { - _register_builtins_for_crossinterpreter_data(); + struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ; + PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK); + if (xidregistry->head == NULL) { + _register_builtins_for_crossinterpreter_data(xidregistry); } - int res = _register_xidata(cls, getdata); - PyThread_release_lock(_PyRuntime.xidregistry.mutex); + int res = _register_xidata(xidregistry, cls, getdata); + PyThread_release_lock(xidregistry->mutex); return res; } @@ -1469,13 +1545,14 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, crossinterpdatafunc _PyCrossInterpreterData_Lookup(PyObject *obj) { + struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ; PyObject *cls = PyObject_Type(obj); crossinterpdatafunc getdata = NULL; - PyThread_acquire_lock(_PyRuntime.xidregistry.mutex, WAIT_LOCK); - struct _xidregitem *cur = _PyRuntime.xidregistry.head; + PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK); + struct _xidregitem *cur = xidregistry->head; if (cur == NULL) { - _register_builtins_for_crossinterpreter_data(); - cur = _PyRuntime.xidregistry.head; + _register_builtins_for_crossinterpreter_data(xidregistry); + cur = xidregistry->head; } for(; cur != NULL; cur = cur->next) { if (cur->cls == (PyTypeObject *)cls) { @@ -1484,7 +1561,7 @@ _PyCrossInterpreterData_Lookup(PyObject *obj) } } Py_DECREF(cls); - PyThread_release_lock(_PyRuntime.xidregistry.mutex); + PyThread_release_lock(xidregistry->mutex); return getdata; } @@ -1591,25 +1668,25 @@ _none_shared(PyObject *obj, _PyCrossInterpreterData *data) } static void -_register_builtins_for_crossinterpreter_data(void) +_register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry) { // None - if (_register_xidata((PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) { + if (_register_xidata(xidregistry, (PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) { Py_FatalError("could not register None for cross-interpreter sharing"); } // int - if (_register_xidata(&PyLong_Type, _long_shared) != 0) { + if (_register_xidata(xidregistry, &PyLong_Type, _long_shared) != 0) { Py_FatalError("could not register int for cross-interpreter sharing"); } // bytes - if (_register_xidata(&PyBytes_Type, _bytes_shared) != 0) { + if (_register_xidata(xidregistry, &PyBytes_Type, _bytes_shared) != 0) { Py_FatalError("could not register bytes for cross-interpreter sharing"); } // str - if (_register_xidata(&PyUnicode_Type, _str_shared) != 0) { + if (_register_xidata(xidregistry, &PyUnicode_Type, _str_shared) != 0) { Py_FatalError("could not register str for cross-interpreter sharing"); } } From 9db0324712f6982d89620b420f507a6aa5da152f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 02:32:01 +0200 Subject: [PATCH 082/212] bpo-36710: Add runtime parameter in gcmodule.c (GH-12958) Add 'state' or 'runtime' parameter to functions in gcmodule.c to avoid to rely directly on the global variable _PyRuntime. --- Include/internal/pycore_pylifecycle.h | 2 +- Modules/gcmodule.c | 302 ++++++++++++++------------ Python/import.c | 2 +- 3 files changed, 165 insertions(+), 141 deletions(-) diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 69709b10b8f842..24847f4f454e5b 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -83,7 +83,7 @@ extern void _PyGILState_Init( PyThreadState *tstate); extern void _PyGILState_Fini(_PyRuntimeState *runtime); -PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); +PyAPI_FUNC(void) _PyGC_DumpShutdownStats(_PyRuntimeState *runtime); PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromCoreConfig( const _PyCoreConfig *coreconfig); diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index f36c7f5d5e409e..be9b73a8446073 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -123,14 +123,14 @@ static PyObject *gc_str = NULL; DEBUG_UNCOLLECTABLE | \ DEBUG_SAVEALL -#define GEN_HEAD(n) (&_PyRuntime.gc.generations[n].head) +#define GEN_HEAD(state, n) (&(state)->generations[n].head) void _PyGC_Initialize(struct _gc_runtime_state *state) { state->enabled = 1; /* automatic collection enabled? */ -#define _GEN_HEAD(n) (&state->generations[n].head) +#define _GEN_HEAD(n) GEN_HEAD(state, n) struct gc_generation generations[NUM_GENERATIONS] = { /* PyGC_Head, threshold, count */ {{(uintptr_t)_GEN_HEAD(0), (uintptr_t)_GEN_HEAD(0)}, 700, 0}, @@ -140,7 +140,7 @@ _PyGC_Initialize(struct _gc_runtime_state *state) for (int i = 0; i < NUM_GENERATIONS; i++) { state->generations[i] = generations[i]; }; - state->generation0 = GEN_HEAD(0); + state->generation0 = GEN_HEAD(state, 0); struct gc_generation permanent_generation = { {(uintptr_t)&state->permanent_generation.head, (uintptr_t)&state->permanent_generation.head}, 0, 0 @@ -808,21 +808,22 @@ debug_cycle(const char *msg, PyObject *op) * merged into the old list regardless. */ static void -handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old) +handle_legacy_finalizers(struct _gc_runtime_state *state, + PyGC_Head *finalizers, PyGC_Head *old) { - PyGC_Head *gc = GC_NEXT(finalizers); - assert(!PyErr_Occurred()); - if (_PyRuntime.gc.garbage == NULL) { - _PyRuntime.gc.garbage = PyList_New(0); - if (_PyRuntime.gc.garbage == NULL) + + PyGC_Head *gc = GC_NEXT(finalizers); + if (state->garbage == NULL) { + state->garbage = PyList_New(0); + if (state->garbage == NULL) Py_FatalError("gc couldn't create gc.garbage list"); } for (; gc != finalizers; gc = GC_NEXT(gc)) { PyObject *op = FROM_GC(gc); - if ((_PyRuntime.gc.debug & DEBUG_SAVEALL) || has_legacy_finalizer(op)) { - if (PyList_Append(_PyRuntime.gc.garbage, op) < 0) { + if ((state->debug & DEBUG_SAVEALL) || has_legacy_finalizer(op)) { + if (PyList_Append(state->garbage, op) < 0) { PyErr_Clear(); break; } @@ -904,11 +905,11 @@ check_garbage(PyGC_Head *collectable) * objects may be freed. It is possible I screwed something up here. */ static void -delete_garbage(PyGC_Head *collectable, PyGC_Head *old) +delete_garbage(struct _gc_runtime_state *state, + PyGC_Head *collectable, PyGC_Head *old) { - inquiry clear; - assert(!PyErr_Occurred()); + while (!gc_list_is_empty(collectable)) { PyGC_Head *gc = GC_NEXT(collectable); PyObject *op = FROM_GC(gc); @@ -916,13 +917,14 @@ delete_garbage(PyGC_Head *collectable, PyGC_Head *old) _PyObject_ASSERT_WITH_MSG(op, Py_REFCNT(op) > 0, "refcount is too small"); - if (_PyRuntime.gc.debug & DEBUG_SAVEALL) { - assert(_PyRuntime.gc.garbage != NULL); - if (PyList_Append(_PyRuntime.gc.garbage, op) < 0) { + if (state->debug & DEBUG_SAVEALL) { + assert(state->garbage != NULL); + if (PyList_Append(state->garbage, op) < 0) { PyErr_Clear(); } } else { + inquiry clear; if ((clear = Py_TYPE(op)->tp_clear) != NULL) { Py_INCREF(op); (void) clear(op); @@ -965,8 +967,8 @@ clear_freelists(void) /* This is the main function. Read this to understand how the * collection process works. */ static Py_ssize_t -collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, - int nofail) +collect(struct _gc_runtime_state *state, int generation, + Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, int nofail) { int i; Py_ssize_t m = 0; /* # objects collected */ @@ -978,17 +980,15 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, PyGC_Head *gc; _PyTime_t t1 = 0; /* initialize to prevent a compiler warning */ - struct gc_generation_stats *stats = &_PyRuntime.gc.generation_stats[generation]; - - if (_PyRuntime.gc.debug & DEBUG_STATS) { + if (state->debug & DEBUG_STATS) { PySys_WriteStderr("gc: collecting generation %d...\n", generation); PySys_WriteStderr("gc: objects in each generation:"); for (i = 0; i < NUM_GENERATIONS; i++) PySys_FormatStderr(" %zd", - gc_list_size(GEN_HEAD(i))); + gc_list_size(GEN_HEAD(state, i))); PySys_WriteStderr("\ngc: objects in permanent generation: %zd", - gc_list_size(&_PyRuntime.gc.permanent_generation.head)); + gc_list_size(&state->permanent_generation.head)); t1 = _PyTime_GetMonotonicClock(); PySys_WriteStderr("\n"); @@ -999,19 +999,19 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, /* update collection and allocation counters */ if (generation+1 < NUM_GENERATIONS) - _PyRuntime.gc.generations[generation+1].count += 1; + state->generations[generation+1].count += 1; for (i = 0; i <= generation; i++) - _PyRuntime.gc.generations[i].count = 0; + state->generations[i].count = 0; /* merge younger generations with one we are currently collecting */ for (i = 0; i < generation; i++) { - gc_list_merge(GEN_HEAD(i), GEN_HEAD(generation)); + gc_list_merge(GEN_HEAD(state, i), GEN_HEAD(state, generation)); } /* handy references */ - young = GEN_HEAD(generation); + young = GEN_HEAD(state, generation); if (generation < NUM_GENERATIONS-1) - old = GEN_HEAD(generation+1); + old = GEN_HEAD(state, generation+1); else old = young; @@ -1039,7 +1039,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, /* Move reachable objects to next generation. */ if (young != old) { if (generation == NUM_GENERATIONS - 2) { - _PyRuntime.gc.long_lived_pending += gc_list_size(young); + state->long_lived_pending += gc_list_size(young); } gc_list_merge(young, old); } @@ -1047,8 +1047,8 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, /* We only untrack dicts in full collections, to avoid quadratic dict build-up. See issue #14775. */ untrack_dicts(young); - _PyRuntime.gc.long_lived_pending = 0; - _PyRuntime.gc.long_lived_total = gc_list_size(young); + state->long_lived_pending = 0; + state->long_lived_total = gc_list_size(young); } /* All objects in unreachable are trash, but objects reachable from @@ -1072,7 +1072,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, */ for (gc = GC_NEXT(&unreachable); gc != &unreachable; gc = GC_NEXT(gc)) { m++; - if (_PyRuntime.gc.debug & DEBUG_COLLECTABLE) { + if (state->debug & DEBUG_COLLECTABLE) { debug_cycle("collectable", FROM_GC(gc)); } } @@ -1094,17 +1094,17 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, * the reference cycles to be broken. It may also cause some objects * in finalizers to be freed. */ - delete_garbage(&unreachable, old); + delete_garbage(state, &unreachable, old); } /* Collect statistics on uncollectable objects found and print * debugging information. */ for (gc = GC_NEXT(&finalizers); gc != &finalizers; gc = GC_NEXT(gc)) { n++; - if (_PyRuntime.gc.debug & DEBUG_UNCOLLECTABLE) + if (state->debug & DEBUG_UNCOLLECTABLE) debug_cycle("uncollectable", FROM_GC(gc)); } - if (_PyRuntime.gc.debug & DEBUG_STATS) { + if (state->debug & DEBUG_STATS) { _PyTime_t t2 = _PyTime_GetMonotonicClock(); if (m == 0 && n == 0) @@ -1121,7 +1121,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, * reachable list of garbage. The programmer has to deal with * this if they insist on creating this type of structure. */ - handle_legacy_finalizers(&finalizers, old); + handle_legacy_finalizers(state, &finalizers, old); validate_list(old, 0); /* Clear free list only during the collection of the highest @@ -1143,16 +1143,21 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, } /* Update stats */ - if (n_collected) + if (n_collected) { *n_collected = m; - if (n_uncollectable) + } + if (n_uncollectable) { *n_uncollectable = n; + } + + struct gc_generation_stats *stats = &state->generation_stats[generation]; stats->collections++; stats->collected += m; stats->uncollectable += n; - if (PyDTrace_GC_DONE_ENABLED()) + if (PyDTrace_GC_DONE_ENABLED()) { PyDTrace_GC_DONE(n+m); + } assert(!PyErr_Occurred()); return n+m; @@ -1162,19 +1167,21 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, * is starting or stopping */ static void -invoke_gc_callback(const char *phase, int generation, - Py_ssize_t collected, Py_ssize_t uncollectable) +invoke_gc_callback(struct _gc_runtime_state *state, const char *phase, + int generation, Py_ssize_t collected, + Py_ssize_t uncollectable) { - Py_ssize_t i; - PyObject *info = NULL; - assert(!PyErr_Occurred()); + /* we may get called very early */ - if (_PyRuntime.gc.callbacks == NULL) + if (state->callbacks == NULL) { return; + } + /* The local variable cannot be rebound, check it for sanity */ - assert(PyList_CheckExact(_PyRuntime.gc.callbacks)); - if (PyList_GET_SIZE(_PyRuntime.gc.callbacks) != 0) { + assert(PyList_CheckExact(state->callbacks)); + PyObject *info = NULL; + if (PyList_GET_SIZE(state->callbacks) != 0) { info = Py_BuildValue("{sisnsn}", "generation", generation, "collected", collected, @@ -1184,8 +1191,8 @@ invoke_gc_callback(const char *phase, int generation, return; } } - for (i=0; icallbacks); i++) { + PyObject *r, *cb = PyList_GET_ITEM(state->callbacks, i); Py_INCREF(cb); /* make sure cb doesn't go away */ r = PyObject_CallFunction(cb, "sO", phase, info); if (r == NULL) { @@ -1204,36 +1211,34 @@ invoke_gc_callback(const char *phase, int generation, * progress callbacks. */ static Py_ssize_t -collect_with_callback(int generation) +collect_with_callback(struct _gc_runtime_state *state, int generation) { - Py_ssize_t result, collected, uncollectable; assert(!PyErr_Occurred()); - invoke_gc_callback("start", generation, 0, 0); - result = collect(generation, &collected, &uncollectable, 0); - invoke_gc_callback("stop", generation, collected, uncollectable); + Py_ssize_t result, collected, uncollectable; + invoke_gc_callback(state, "start", generation, 0, 0); + result = collect(state, generation, &collected, &uncollectable, 0); + invoke_gc_callback(state, "stop", generation, collected, uncollectable); assert(!PyErr_Occurred()); return result; } static Py_ssize_t -collect_generations(void) +collect_generations(struct _gc_runtime_state *state) { - int i; - Py_ssize_t n = 0; - /* Find the oldest generation (highest numbered) where the count * exceeds the threshold. Objects in the that generation and * generations younger than it will be collected. */ - for (i = NUM_GENERATIONS-1; i >= 0; i--) { - if (_PyRuntime.gc.generations[i].count > _PyRuntime.gc.generations[i].threshold) { + Py_ssize_t n = 0; + for (int i = NUM_GENERATIONS-1; i >= 0; i--) { + if (state->generations[i].count > state->generations[i].threshold) { /* Avoid quadratic performance degradation in number of tracked objects. See comments at the beginning of this file, and issue #4074. */ if (i == NUM_GENERATIONS - 1 - && _PyRuntime.gc.long_lived_pending < _PyRuntime.gc.long_lived_total / 4) + && state->long_lived_pending < state->long_lived_total / 4) continue; - n = collect_with_callback(i); + n = collect_with_callback(state, i); break; } } @@ -1301,21 +1306,23 @@ static Py_ssize_t gc_collect_impl(PyObject *module, int generation) /*[clinic end generated code: output=b697e633043233c7 input=40720128b682d879]*/ { - Py_ssize_t n; if (generation < 0 || generation >= NUM_GENERATIONS) { PyErr_SetString(PyExc_ValueError, "invalid generation"); return -1; } - if (_PyRuntime.gc.collecting) - n = 0; /* already collecting, don't do anything */ + struct _gc_runtime_state *state = &_PyRuntime.gc; + Py_ssize_t n; + if (state->collecting) { + /* already collecting, don't do anything */ + n = 0; + } else { - _PyRuntime.gc.collecting = 1; - n = collect_with_callback(generation); - _PyRuntime.gc.collecting = 0; + state->collecting = 1; + n = collect_with_callback(state, generation); + state->collecting = 0; } - return n; } @@ -1366,19 +1373,18 @@ PyDoc_STRVAR(gc_set_thresh__doc__, "collection.\n"); static PyObject * -gc_set_thresh(PyObject *self, PyObject *args) +gc_set_threshold(PyObject *self, PyObject *args) { - int i; + struct _gc_runtime_state *state = &_PyRuntime.gc; if (!PyArg_ParseTuple(args, "i|ii:set_threshold", - &_PyRuntime.gc.generations[0].threshold, - &_PyRuntime.gc.generations[1].threshold, - &_PyRuntime.gc.generations[2].threshold)) + &state->generations[0].threshold, + &state->generations[1].threshold, + &state->generations[2].threshold)) return NULL; - for (i = 3; i < NUM_GENERATIONS; i++) { + for (int i = 3; i < NUM_GENERATIONS; i++) { /* generations higher than 2 get the same threshold */ - _PyRuntime.gc.generations[i].threshold = _PyRuntime.gc.generations[2].threshold; + state->generations[i].threshold = state->generations[2].threshold; } - Py_RETURN_NONE; } @@ -1392,10 +1398,11 @@ static PyObject * gc_get_threshold_impl(PyObject *module) /*[clinic end generated code: output=7902bc9f41ecbbd8 input=286d79918034d6e6]*/ { + struct _gc_runtime_state *state = &_PyRuntime.gc; return Py_BuildValue("(iii)", - _PyRuntime.gc.generations[0].threshold, - _PyRuntime.gc.generations[1].threshold, - _PyRuntime.gc.generations[2].threshold); + state->generations[0].threshold, + state->generations[1].threshold, + state->generations[2].threshold); } /*[clinic input] @@ -1408,10 +1415,11 @@ static PyObject * gc_get_count_impl(PyObject *module) /*[clinic end generated code: output=354012e67b16398f input=a392794a08251751]*/ { + struct _gc_runtime_state *state = &_PyRuntime.gc; return Py_BuildValue("(iii)", - _PyRuntime.gc.generations[0].count, - _PyRuntime.gc.generations[1].count, - _PyRuntime.gc.generations[2].count); + state->generations[0].count, + state->generations[1].count, + state->generations[2].count); } static int @@ -1454,8 +1462,9 @@ gc_get_referrers(PyObject *self, PyObject *args) PyObject *result = PyList_New(0); if (!result) return NULL; + struct _gc_runtime_state *state = &_PyRuntime.gc; for (i = 0; i < NUM_GENERATIONS; i++) { - if (!(gc_referrers_for(args, GEN_HEAD(i), result))) { + if (!(gc_referrers_for(args, GEN_HEAD(state, i), result))) { Py_DECREF(result); return NULL; } @@ -1517,6 +1526,7 @@ gc_get_objects_impl(PyObject *module, Py_ssize_t generation) { int i; PyObject* result; + struct _gc_runtime_state *state = &_PyRuntime.gc; result = PyList_New(0); if (result == NULL) { @@ -1539,7 +1549,7 @@ gc_get_objects_impl(PyObject *module, Py_ssize_t generation) goto error; } - if (append_objects(result, GEN_HEAD(generation))) { + if (append_objects(result, GEN_HEAD(state, generation))) { goto error; } @@ -1548,7 +1558,7 @@ gc_get_objects_impl(PyObject *module, Py_ssize_t generation) /* If generation is not passed or None, get all objects from all generations */ for (i = 0; i < NUM_GENERATIONS; i++) { - if (append_objects(result, GEN_HEAD(i))) { + if (append_objects(result, GEN_HEAD(state, i))) { goto error; } } @@ -1570,16 +1580,16 @@ gc_get_stats_impl(PyObject *module) /*[clinic end generated code: output=a8ab1d8a5d26f3ab input=1ef4ed9d17b1a470]*/ { int i; - PyObject *result; struct gc_generation_stats stats[NUM_GENERATIONS], *st; /* To get consistent values despite allocations while constructing the result list, we use a snapshot of the running stats. */ + struct _gc_runtime_state *state = &_PyRuntime.gc; for (i = 0; i < NUM_GENERATIONS; i++) { - stats[i] = _PyRuntime.gc.generation_stats[i]; + stats[i] = state->generation_stats[i]; } - result = PyList_New(0); + PyObject *result = PyList_New(0); if (result == NULL) return NULL; @@ -1646,9 +1656,10 @@ static PyObject * gc_freeze_impl(PyObject *module) /*[clinic end generated code: output=502159d9cdc4c139 input=b602b16ac5febbe5]*/ { + struct _gc_runtime_state *state = &_PyRuntime.gc; for (int i = 0; i < NUM_GENERATIONS; ++i) { - gc_list_merge(GEN_HEAD(i), &_PyRuntime.gc.permanent_generation.head); - _PyRuntime.gc.generations[i].count = 0; + gc_list_merge(GEN_HEAD(state, i), &state->permanent_generation.head); + state->generations[i].count = 0; } Py_RETURN_NONE; } @@ -1665,7 +1676,8 @@ static PyObject * gc_unfreeze_impl(PyObject *module) /*[clinic end generated code: output=1c15f2043b25e169 input=2dd52b170f4cef6c]*/ { - gc_list_merge(&_PyRuntime.gc.permanent_generation.head, GEN_HEAD(NUM_GENERATIONS-1)); + struct _gc_runtime_state *state = &_PyRuntime.gc; + gc_list_merge(&state->permanent_generation.head, GEN_HEAD(state, NUM_GENERATIONS-1)); Py_RETURN_NONE; } @@ -1711,7 +1723,7 @@ static PyMethodDef GcMethods[] = { GC_SET_DEBUG_METHODDEF GC_GET_DEBUG_METHODDEF GC_GET_COUNT_METHODDEF - {"set_threshold", gc_set_thresh, METH_VARARGS, gc_set_thresh__doc__}, + {"set_threshold", gc_set_threshold, METH_VARARGS, gc_set_thresh__doc__}, GC_GET_THRESHOLD_METHODDEF GC_COLLECT_METHODDEF GC_GET_OBJECTS_METHODDEF @@ -1746,25 +1758,27 @@ PyInit_gc(void) m = PyModule_Create(&gcmodule); - if (m == NULL) + if (m == NULL) { return NULL; + } - if (_PyRuntime.gc.garbage == NULL) { - _PyRuntime.gc.garbage = PyList_New(0); - if (_PyRuntime.gc.garbage == NULL) + struct _gc_runtime_state *state = &_PyRuntime.gc; + if (state->garbage == NULL) { + state->garbage = PyList_New(0); + if (state->garbage == NULL) return NULL; } - Py_INCREF(_PyRuntime.gc.garbage); - if (PyModule_AddObject(m, "garbage", _PyRuntime.gc.garbage) < 0) + Py_INCREF(state->garbage); + if (PyModule_AddObject(m, "garbage", state->garbage) < 0) return NULL; - if (_PyRuntime.gc.callbacks == NULL) { - _PyRuntime.gc.callbacks = PyList_New(0); - if (_PyRuntime.gc.callbacks == NULL) + if (state->callbacks == NULL) { + state->callbacks = PyList_New(0); + if (state->callbacks == NULL) return NULL; } - Py_INCREF(_PyRuntime.gc.callbacks); - if (PyModule_AddObject(m, "callbacks", _PyRuntime.gc.callbacks) < 0) + Py_INCREF(state->callbacks); + if (PyModule_AddObject(m, "callbacks", state->callbacks) < 0) return NULL; #define ADD_INT(NAME) if (PyModule_AddIntConstant(m, #NAME, NAME) < 0) return NULL @@ -1781,17 +1795,23 @@ PyInit_gc(void) Py_ssize_t PyGC_Collect(void) { - Py_ssize_t n; + struct _gc_runtime_state *state = &_PyRuntime.gc; + if (!state->enabled) { + return 0; + } - if (_PyRuntime.gc.collecting) - n = 0; /* already collecting, don't do anything */ + Py_ssize_t n; + if (state->collecting) { + /* already collecting, don't do anything */ + n = 0; + } else { PyObject *exc, *value, *tb; - _PyRuntime.gc.collecting = 1; + state->collecting = 1; PyErr_Fetch(&exc, &value, &tb); - n = collect_with_callback(NUM_GENERATIONS - 1); + n = collect_with_callback(state, NUM_GENERATIONS - 1); PyErr_Restore(exc, value, tb); - _PyRuntime.gc.collecting = 0; + state->collecting = 0; } return n; @@ -1800,41 +1820,42 @@ PyGC_Collect(void) Py_ssize_t _PyGC_CollectIfEnabled(void) { - if (!_PyRuntime.gc.enabled) - return 0; - return PyGC_Collect(); } Py_ssize_t _PyGC_CollectNoFail(void) { + assert(!PyErr_Occurred()); + + struct _gc_runtime_state *state = &_PyRuntime.gc; Py_ssize_t n; - assert(!PyErr_Occurred()); /* Ideally, this function is only called on interpreter shutdown, and therefore not recursively. Unfortunately, when there are daemon threads, a daemon thread can start a cyclic garbage collection during interpreter shutdown (and then never finish it). See http://bugs.python.org/issue8713#msg195178 for an example. */ - if (_PyRuntime.gc.collecting) + if (state->collecting) { n = 0; + } else { - _PyRuntime.gc.collecting = 1; - n = collect(NUM_GENERATIONS - 1, NULL, NULL, 1); - _PyRuntime.gc.collecting = 0; + state->collecting = 1; + n = collect(state, NUM_GENERATIONS - 1, NULL, NULL, 1); + state->collecting = 0; } return n; } void -_PyGC_DumpShutdownStats(void) +_PyGC_DumpShutdownStats(_PyRuntimeState *runtime) { - if (!(_PyRuntime.gc.debug & DEBUG_SAVEALL) - && _PyRuntime.gc.garbage != NULL && PyList_GET_SIZE(_PyRuntime.gc.garbage) > 0) { + struct _gc_runtime_state *state = &runtime->gc; + if (!(state->debug & DEBUG_SAVEALL) + && state->garbage != NULL && PyList_GET_SIZE(state->garbage) > 0) { const char *message; - if (_PyRuntime.gc.debug & DEBUG_UNCOLLECTABLE) + if (state->debug & DEBUG_UNCOLLECTABLE) message = "gc: %zd uncollectable objects at " \ "shutdown"; else @@ -1845,13 +1866,13 @@ _PyGC_DumpShutdownStats(void) already. */ if (PyErr_WarnExplicitFormat(PyExc_ResourceWarning, "gc", 0, "gc", NULL, message, - PyList_GET_SIZE(_PyRuntime.gc.garbage))) + PyList_GET_SIZE(state->garbage))) PyErr_WriteUnraisable(NULL); - if (_PyRuntime.gc.debug & DEBUG_UNCOLLECTABLE) { + if (state->debug & DEBUG_UNCOLLECTABLE) { PyObject *repr = NULL, *bytes = NULL; - repr = PyObject_Repr(_PyRuntime.gc.garbage); + repr = PyObject_Repr(state->garbage); if (!repr || !(bytes = PyUnicode_EncodeFSDefault(repr))) - PyErr_WriteUnraisable(_PyRuntime.gc.garbage); + PyErr_WriteUnraisable(state->garbage); else { PySys_WriteStderr( " %s\n", @@ -1867,8 +1888,9 @@ _PyGC_DumpShutdownStats(void) void _PyGC_Fini(_PyRuntimeState *runtime) { - struct _gc_runtime_state *gc = &runtime->gc; - Py_CLEAR(gc->callbacks); + struct _gc_runtime_state *state = &runtime->gc; + Py_CLEAR(state->garbage); + Py_CLEAR(state->callbacks); } /* for debugging */ @@ -1908,6 +1930,7 @@ PyObject_GC_UnTrack(void *op_raw) static PyObject * _PyObject_GC_Alloc(int use_calloc, size_t basicsize) { + struct _gc_runtime_state *state = &_PyRuntime.gc; PyObject *op; PyGC_Head *g; size_t size; @@ -1923,15 +1946,15 @@ _PyObject_GC_Alloc(int use_calloc, size_t basicsize) assert(((uintptr_t)g & 3) == 0); // g must be aligned 4bytes boundary g->_gc_next = 0; g->_gc_prev = 0; - _PyRuntime.gc.generations[0].count++; /* number of allocated GC objects */ - if (_PyRuntime.gc.generations[0].count > _PyRuntime.gc.generations[0].threshold && - _PyRuntime.gc.enabled && - _PyRuntime.gc.generations[0].threshold && - !_PyRuntime.gc.collecting && + state->generations[0].count++; /* number of allocated GC objects */ + if (state->generations[0].count > state->generations[0].threshold && + state->enabled && + state->generations[0].threshold && + !state->collecting && !PyErr_Occurred()) { - _PyRuntime.gc.collecting = 1; - collect_generations(); - _PyRuntime.gc.collecting = 0; + state->collecting = 1; + collect_generations(state); + state->collecting = 0; } op = FROM_GC(g); return op; @@ -2000,8 +2023,9 @@ PyObject_GC_Del(void *op) if (_PyObject_GC_IS_TRACKED(op)) { gc_list_remove(g); } - if (_PyRuntime.gc.generations[0].count > 0) { - _PyRuntime.gc.generations[0].count--; + struct _gc_runtime_state *state = &_PyRuntime.gc; + if (state->generations[0].count > 0) { + state->generations[0].count--; } PyObject_FREE(g); } diff --git a/Python/import.c b/Python/import.c index c00c3aa640b078..3b2090b963ddc6 100644 --- a/Python/import.c +++ b/Python/import.c @@ -535,7 +535,7 @@ PyImport_Cleanup(void) _PyGC_CollectNoFail(); /* Dump GC stats before it's too late, since it uses the warnings machinery. */ - _PyGC_DumpShutdownStats(); + _PyGC_DumpShutdownStats(&_PyRuntime); /* Now, if there are any modules left alive, clear their globals to minimize potential leaks. All C extension modules actually end From 4d29983185bc12ca685a1eb3873bacb8a7b67416 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 04:08:53 +0200 Subject: [PATCH 083/212] bpo-36725: regrtest: add TestResult type (GH-12960) * Add TestResult and MultiprocessResult types to ensure that results always have the same fields. * runtest() now handles KeyboardInterrupt * accumulate_result() and format_test_result() now takes a TestResult * cleanup_test_droppings() is now called by runtest() and mark the test as ENV_CHANGED if the test leaks support.TESTFN file. * runtest() now includes code "around" the test in the test timing * Add print_warning() in test.libregrtest.utils to standardize how libregrtest logs warnings to ease parsing the test output. * support.unload() is now called with abstest rather than test_name * Rename 'test' variable/parameter to 'test_name' * dash_R(): remove unused the_module parameter * Remove unused imports --- Lib/test/libregrtest/main.py | 88 ++++----- Lib/test/libregrtest/refleak.py | 3 +- Lib/test/libregrtest/runtest.py | 274 ++++++++++++++++++----------- Lib/test/libregrtest/runtest_mp.py | 85 ++++----- Lib/test/libregrtest/save_env.py | 4 +- Lib/test/libregrtest/utils.py | 7 +- Lib/test/libregrtest/win_utils.py | 5 +- Lib/test/test_regrtest.py | 28 +-- 8 files changed, 286 insertions(+), 208 deletions(-) diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index d20e1746781f0a..ef1336a7e233d4 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -105,26 +105,30 @@ def __init__(self): # used by --junit-xml self.testsuite_xml = None - def accumulate_result(self, test, result): - ok, test_time, xml_data = result + def accumulate_result(self, result): + test_name = result.test_name + ok = result.result + if ok not in (CHILD_ERROR, INTERRUPTED): - self.test_times.append((test_time, test)) + self.test_times.append((result.test_time, test_name)) + if ok == PASSED: - self.good.append(test) + self.good.append(test_name) elif ok in (FAILED, CHILD_ERROR): - self.bad.append(test) + self.bad.append(test_name) elif ok == ENV_CHANGED: - self.environment_changed.append(test) + self.environment_changed.append(test_name) elif ok == SKIPPED: - self.skipped.append(test) + self.skipped.append(test_name) elif ok == RESOURCE_DENIED: - self.skipped.append(test) - self.resource_denieds.append(test) + self.skipped.append(test_name) + self.resource_denieds.append(test_name) elif ok == TEST_DID_NOT_RUN: - self.run_no_tests.append(test) + self.run_no_tests.append(test_name) elif ok != INTERRUPTED: raise ValueError("invalid test result: %r" % ok) + xml_data = result.xml_data if xml_data: import xml.etree.ElementTree as ET for e in xml_data: @@ -134,7 +138,7 @@ def accumulate_result(self, test, result): print(xml_data, file=sys.__stderr__) raise - def display_progress(self, test_index, test): + def display_progress(self, test_index, text): if self.ns.quiet: return @@ -143,7 +147,7 @@ def display_progress(self, test_index, test): fails = len(self.bad) + len(self.environment_changed) if fails and not self.ns.pgo: line = f"{line}/{fails}" - line = f"[{line}] {test}" + line = f"[{line}] {text}" # add the system load prefix: "load avg: 1.80 " if self.getloadavg: @@ -275,13 +279,13 @@ def list_cases(self): support.verbose = False support.set_match_tests(self.ns.match_tests) - for test in self.selected: - abstest = get_abs_module(self.ns, test) + for test_name in self.selected: + abstest = get_abs_module(self.ns, test_name) try: suite = unittest.defaultTestLoader.loadTestsFromName(abstest) self._list_cases(suite) except unittest.SkipTest: - self.skipped.append(test) + self.skipped.append(test_name) if self.skipped: print(file=sys.stderr) @@ -298,19 +302,19 @@ def rerun_failed_tests(self): print() print("Re-running failed tests in verbose mode") self.rerun = self.bad[:] - for test in self.rerun: - print("Re-running test %r in verbose mode" % test, flush=True) - try: - self.ns.verbose = True - ok = runtest(self.ns, test) - except KeyboardInterrupt: - self.interrupted = True + for test_name in self.rerun: + print("Re-running test %r in verbose mode" % test_name, flush=True) + self.ns.verbose = True + ok = runtest(self.ns, test_name) + + if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}: + self.bad.remove(test_name) + + if ok.result == INTERRUPTED: # print a newline separate from the ^C print() + self.interrupted = True break - else: - if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}: - self.bad.remove(test) else: if self.bad: print(count(len(self.bad), 'test'), "failed again:") @@ -348,8 +352,8 @@ def display_result(self): self.test_times.sort(reverse=True) print() print("10 slowest tests:") - for time, test in self.test_times[:10]: - print("- %s: %s" % (test, format_duration(time))) + for test_time, test in self.test_times[:10]: + print("- %s: %s" % (test, format_duration(test_time))) if self.bad: print() @@ -387,10 +391,10 @@ def run_tests_sequential(self): print("Run tests sequentially") previous_test = None - for test_index, test in enumerate(self.tests, 1): + for test_index, test_name in enumerate(self.tests, 1): start_time = time.monotonic() - text = test + text = test_name if previous_test: text = '%s -- %s' % (text, previous_test) self.display_progress(test_index, text) @@ -398,22 +402,20 @@ def run_tests_sequential(self): if self.tracer: # If we're tracing code coverage, then we don't exit with status # if on a false return value from main. - cmd = ('result = runtest(self.ns, test); ' - 'self.accumulate_result(test, result)') + cmd = ('result = runtest(self.ns, test_name); ' + 'self.accumulate_result(result)') ns = dict(locals()) self.tracer.runctx(cmd, globals=globals(), locals=ns) result = ns['result'] else: - try: - result = runtest(self.ns, test) - except KeyboardInterrupt: - self.interrupted = True - self.accumulate_result(test, (INTERRUPTED, None, None)) - break - else: - self.accumulate_result(test, result) - - previous_test = format_test_result(test, result[0]) + result = runtest(self.ns, test_name) + self.accumulate_result(result) + + if result.result == INTERRUPTED: + self.interrupted = True + break + + previous_test = format_test_result(result) test_time = time.monotonic() - start_time if test_time >= PROGRESS_MIN_TIME: previous_test = "%s in %s" % (previous_test, format_duration(test_time)) @@ -441,8 +443,8 @@ def run_tests_sequential(self): def _test_forever(self, tests): while True: - for test in tests: - yield test + for test_name in tests: + yield test_name if self.bad: return if self.ns.fail_env_changed and self.environment_changed: diff --git a/Lib/test/libregrtest/refleak.py b/Lib/test/libregrtest/refleak.py index 235d6bfd3af621..8d221232eb6ce7 100644 --- a/Lib/test/libregrtest/refleak.py +++ b/Lib/test/libregrtest/refleak.py @@ -1,4 +1,3 @@ -import errno import os import re import sys @@ -18,7 +17,7 @@ def _get_dump(cls): cls._abc_negative_cache, cls._abc_negative_cache_version) -def dash_R(ns, the_module, test_name, test_func): +def dash_R(ns, test_name, test_func): """Run a test multiple times, looking for reference leaks. Returns: diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index 0a9533c8a57378..55913b3842d7bd 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -1,4 +1,6 @@ +import collections import faulthandler +import functools import importlib import io import os @@ -9,6 +11,7 @@ from test import support from test.libregrtest.refleak import dash_R, clear_caches from test.libregrtest.save_env import saved_test_environment +from test.libregrtest.utils import print_warning # Test result constants. @@ -55,9 +58,17 @@ NOTTESTS = set() -def format_test_result(test_name, result): - fmt = _FORMAT_TEST_RESULT.get(result, "%s") - return fmt % test_name +# used by --findleaks, store for gc.garbage +found_garbage = [] + + +def format_test_result(result): + fmt = _FORMAT_TEST_RESULT.get(result.result, "%s") + return fmt % result.test_name + + +def findtestdir(path=None): + return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): @@ -73,48 +84,34 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): return stdtests + sorted(tests) -def get_abs_module(ns, test): - if test.startswith('test.') or ns.testdir: - return test +def get_abs_module(ns, test_name): + if test_name.startswith('test.') or ns.testdir: + return test_name else: - # Always import it from the test package - return 'test.' + test - + # Import it from the test package + return 'test.' + test_name -def runtest(ns, test): - """Run a single test. - - ns -- regrtest namespace of options - test -- the name of the test - Returns the tuple (result, test_time, xml_data), where result is one - of the constants: - - INTERRUPTED KeyboardInterrupt when run under -j - RESOURCE_DENIED test skipped because resource denied - SKIPPED test skipped for some other reason - ENV_CHANGED test failed because it changed the execution environment - FAILED test failed - PASSED test passed - EMPTY_TEST_SUITE test ran no subtests. +TestResult = collections.namedtuple('TestResult', + 'test_name result test_time xml_data') - If ns.xmlpath is not None, xml_data is a list containing each - generated testsuite element. - """ +def _runtest(ns, test_name): + # Handle faulthandler timeout, capture stdout+stderr, XML serialization + # and measure time. output_on_failure = ns.verbose3 use_timeout = (ns.timeout is not None) if use_timeout: faulthandler.dump_traceback_later(ns.timeout, exit=True) + + start_time = time.perf_counter() try: support.set_match_tests(ns.match_tests) - # reset the environment_altered flag to detect if a test altered - # the environment - support.environment_altered = False support.junit_xml_list = xml_list = [] if ns.xmlpath else None if ns.failfast: support.failfast = True + if output_on_failure: support.verbose = True @@ -124,8 +121,9 @@ def runtest(ns, test): try: sys.stdout = stream sys.stderr = stream - result = runtest_inner(ns, test, display_failure=False) - if result[0] != PASSED: + result = _runtest_inner(ns, test_name, + display_failure=False) + if result != PASSED: output = stream.getvalue() orig_stderr.write(output) orig_stderr.flush() @@ -133,98 +131,170 @@ def runtest(ns, test): sys.stdout = orig_stdout sys.stderr = orig_stderr else: - support.verbose = ns.verbose # Tell tests to be moderately quiet - result = runtest_inner(ns, test, display_failure=not ns.verbose) + # Tell tests to be moderately quiet + support.verbose = ns.verbose + + result = _runtest_inner(ns, test_name, + display_failure=not ns.verbose) if xml_list: import xml.etree.ElementTree as ET xml_data = [ET.tostring(x).decode('us-ascii') for x in xml_list] else: xml_data = None - return result + (xml_data,) + + test_time = time.perf_counter() - start_time + + return TestResult(test_name, result, test_time, xml_data) finally: if use_timeout: faulthandler.cancel_dump_traceback_later() - cleanup_test_droppings(test, ns.verbose) support.junit_xml_list = None +def runtest(ns, test_name): + """Run a single test. + + ns -- regrtest namespace of options + test_name -- the name of the test + + Returns the tuple (result, test_time, xml_data), where result is one + of the constants: + + INTERRUPTED KeyboardInterrupt + RESOURCE_DENIED test skipped because resource denied + SKIPPED test skipped for some other reason + ENV_CHANGED test failed because it changed the execution environment + FAILED test failed + PASSED test passed + EMPTY_TEST_SUITE test ran no subtests. + + If ns.xmlpath is not None, xml_data is a list containing each + generated testsuite element. + """ + try: + return _runtest(ns, test_name) + except: + if not ns.pgo: + msg = traceback.format_exc() + print(f"test {test_name} crashed -- {msg}", + file=sys.stderr, flush=True) + return TestResult(test_name, FAILED, 0.0, None) + + def post_test_cleanup(): + support.gc_collect() support.reap_children() -def runtest_inner(ns, test, display_failure=True): - support.unload(test) +def _test_module(the_module): + loader = unittest.TestLoader() + tests = loader.loadTestsFromModule(the_module) + for error in loader.errors: + print(error, file=sys.stderr) + if loader.errors: + raise Exception("errors while loading tests") + support.run_unittest(tests) + + +def _runtest_inner2(ns, test_name): + # Load the test function, run the test function, handle huntrleaks + # and findleaks to detect leaks + + abstest = get_abs_module(ns, test_name) + + # remove the module from sys.module to reload it if it was already imported + support.unload(abstest) + + the_module = importlib.import_module(abstest) + + # If the test has a test_main, that will run the appropriate + # tests. If not, use normal unittest test loading. + test_runner = getattr(the_module, "test_main", None) + if test_runner is None: + test_runner = functools.partial(_test_module, the_module) + + try: + if ns.huntrleaks: + # Return True if the test leaked references + refleak = dash_R(ns, test_name, test_runner) + else: + test_runner() + refleak = False + finally: + cleanup_test_droppings(test_name, ns.verbose) + + if ns.findleaks: + import gc + support.gc_collect() + if gc.garbage: + import gc + gc.garbage = [1] + print_warning(f"{test_name} created {len(gc.garbage)} " + f"uncollectable object(s).") + # move the uncollectable objects somewhere, + # so we don't see them again + found_garbage.extend(gc.garbage) + gc.garbage.clear() + support.environment_altered = True + + post_test_cleanup() + + return refleak + + +def _runtest_inner(ns, test_name, display_failure=True): + # Detect environment changes, handle exceptions. + + # Reset the environment_altered flag to detect if a test altered + # the environment + support.environment_altered = False + + if ns.pgo: + display_failure = False - test_time = 0.0 - refleak = False # True if the test leaked references. try: - abstest = get_abs_module(ns, test) clear_caches() - with saved_test_environment(test, ns.verbose, ns.quiet, pgo=ns.pgo) as environment: - start_time = time.perf_counter() - the_module = importlib.import_module(abstest) - # If the test has a test_main, that will run the appropriate - # tests. If not, use normal unittest test loading. - test_runner = getattr(the_module, "test_main", None) - if test_runner is None: - def test_runner(): - loader = unittest.TestLoader() - tests = loader.loadTestsFromModule(the_module) - for error in loader.errors: - print(error, file=sys.stderr) - if loader.errors: - raise Exception("errors while loading tests") - support.run_unittest(tests) - if ns.huntrleaks: - refleak = dash_R(ns, the_module, test, test_runner) - else: - test_runner() - test_time = time.perf_counter() - start_time - post_test_cleanup() + + with saved_test_environment(test_name, ns.verbose, ns.quiet, pgo=ns.pgo) as environment: + refleak = _runtest_inner2(ns, test_name) except support.ResourceDenied as msg: if not ns.quiet and not ns.pgo: - print(test, "skipped --", msg, flush=True) - return RESOURCE_DENIED, test_time + print(f"{test_name} skipped -- {msg}", flush=True) + return RESOURCE_DENIED except unittest.SkipTest as msg: if not ns.quiet and not ns.pgo: - print(test, "skipped --", msg, flush=True) - return SKIPPED, test_time - except KeyboardInterrupt: - raise - except support.TestFailed as msg: - if not ns.pgo: - if display_failure: - print("test", test, "failed --", msg, file=sys.stderr, - flush=True) - else: - print("test", test, "failed", file=sys.stderr, flush=True) - return FAILED, test_time + print(f"{test_name} skipped -- {msg}", flush=True) + return SKIPPED + except support.TestFailed as exc: + msg = f"test {test_name} failed" + if display_failure: + msg = f"{msg} -- {exc}" + print(msg, file=sys.stderr, flush=True) + return FAILED except support.TestDidNotRun: - return TEST_DID_NOT_RUN, test_time + return TEST_DID_NOT_RUN + except KeyboardInterrupt: + return INTERRUPTED except: - msg = traceback.format_exc() if not ns.pgo: - print("test", test, "crashed --", msg, file=sys.stderr, - flush=True) - return FAILED, test_time - else: - if refleak: - return FAILED, test_time - if environment.changed: - return ENV_CHANGED, test_time - return PASSED, test_time + msg = traceback.format_exc() + print(f"test {test_name} crashed -- {msg}", + file=sys.stderr, flush=True) + return FAILED + if refleak: + return FAILED + if environment.changed: + return ENV_CHANGED + return PASSED -def cleanup_test_droppings(testname, verbose): - import shutil - import stat - import gc +def cleanup_test_droppings(test_name, verbose): # First kill any dangling references to open files etc. # This can also issue some ResourceWarnings which would otherwise get # triggered during the following test run, and possibly produce failures. - gc.collect() + support.gc_collect() # Try to clean up junk commonly left behind. While tests shouldn't leave # any files or directories behind, when a test fails that can be tedious @@ -239,23 +309,23 @@ def cleanup_test_droppings(testname, verbose): continue if os.path.isdir(name): + import shutil kind, nuker = "directory", shutil.rmtree elif os.path.isfile(name): kind, nuker = "file", os.unlink else: - raise SystemError("os.path says %r exists but is neither " - "directory nor file" % name) + raise RuntimeError(f"os.path says {name!r} exists but is neither " + f"directory nor file") if verbose: - print("%r left behind %s %r" % (testname, kind, name)) + print_warning("%r left behind %s %r" % (test_name, kind, name)) + support.environment_altered = True + try: + import stat # fix possible permissions problems that might prevent cleanup os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) nuker(name) - except Exception as msg: - print(("%r left behind %s %r and it couldn't be " - "removed: %s" % (testname, kind, name, msg)), file=sys.stderr) - - -def findtestdir(path=None): - return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir + except Exception as exc: + print_warning(f"{test_name} left behind {kind} {name!r} " + f"and it couldn't be removed: {exc}") diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index 6190574afdf8b3..0a95bf622b059a 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -1,3 +1,4 @@ +import collections import faulthandler import json import os @@ -5,13 +6,12 @@ import sys import threading import time -import traceback import types from test import support from test.libregrtest.runtest import ( runtest, INTERRUPTED, CHILD_ERROR, PROGRESS_MIN_TIME, - format_test_result) + format_test_result, TestResult) from test.libregrtest.setup import setup_tests from test.libregrtest.utils import format_duration @@ -64,15 +64,9 @@ def run_tests_worker(worker_args): setup_tests(ns) - try: - result = runtest(ns, testname) - except KeyboardInterrupt: - result = INTERRUPTED, '', None - except BaseException as e: - traceback.print_exc() - result = CHILD_ERROR, str(e) - + result = runtest(ns, testname) print() # Force a newline (just in case) + print(json.dumps(result), flush=True) sys.exit(0) @@ -97,45 +91,51 @@ def __next__(self): return next(self.tests) +MultiprocessResult = collections.namedtuple('MultiprocessResult', + 'result stdout stderr error_msg') + class MultiprocessThread(threading.Thread): def __init__(self, pending, output, ns): super().__init__() self.pending = pending self.output = output self.ns = ns - self.current_test = None + self.current_test_name = None self.start_time = None def _runtest(self): try: - test = next(self.pending) + test_name = next(self.pending) except StopIteration: - self.output.put((None, None, None, None)) + self.output.put(None) return True try: self.start_time = time.monotonic() - self.current_test = test + self.current_test_name = test_name - retcode, stdout, stderr = run_test_in_subprocess(test, self.ns) + retcode, stdout, stderr = run_test_in_subprocess(test_name, self.ns) finally: - self.current_test = None + self.current_test_name = None if retcode != 0: - result = (CHILD_ERROR, "Exit code %s" % retcode, None) - self.output.put((test, stdout.rstrip(), stderr.rstrip(), - result)) + test_time = time.monotonic() - self.start_time + result = TestResult(test_name, CHILD_ERROR, test_time, None) + err_msg = "Exit code %s" % retcode + mp_result = MultiprocessResult(result, stdout.rstrip(), stderr.rstrip(), err_msg) + self.output.put(mp_result) return False stdout, _, result = stdout.strip().rpartition("\n") if not result: - self.output.put((None, None, None, None)) + self.output.put(None) return True + # deserialize run_tests_worker() output result = json.loads(result) - assert len(result) == 3, f"Invalid result tuple: {result!r}" - self.output.put((test, stdout.rstrip(), stderr.rstrip(), - result)) + result = TestResult(*result) + mp_result = MultiprocessResult(result, stdout.rstrip(), stderr.rstrip(), None) + self.output.put(mp_result) return False def run(self): @@ -144,7 +144,7 @@ def run(self): while not stop: stop = self._runtest() except BaseException: - self.output.put((None, None, None, None)) + self.output.put(None) raise @@ -164,12 +164,12 @@ def run_tests_multiprocess(regrtest): def get_running(workers): running = [] for worker in workers: - current_test = worker.current_test - if not current_test: + current_test_name = worker.current_test_name + if not current_test_name: continue dt = time.monotonic() - worker.start_time if dt >= PROGRESS_MIN_TIME: - text = '%s (%s)' % (current_test, format_duration(dt)) + text = '%s (%s)' % (current_test_name, format_duration(dt)) running.append(text) return running @@ -182,40 +182,41 @@ def get_running(workers): faulthandler.dump_traceback_later(test_timeout, exit=True) try: - item = output.get(timeout=get_timeout) + mp_result = output.get(timeout=get_timeout) except queue.Empty: running = get_running(workers) if running and not regrtest.ns.pgo: print('running: %s' % ', '.join(running), flush=True) continue - test, stdout, stderr, result = item - if test is None: + if mp_result is None: finished += 1 continue - regrtest.accumulate_result(test, result) + result = mp_result.result + regrtest.accumulate_result(result) # Display progress - ok, test_time, xml_data = result - text = format_test_result(test, ok) + ok = result.result + + text = format_test_result(result) if (ok not in (CHILD_ERROR, INTERRUPTED) - and test_time >= PROGRESS_MIN_TIME + and result.test_time >= PROGRESS_MIN_TIME and not regrtest.ns.pgo): - text += ' (%s)' % format_duration(test_time) + text += ' (%s)' % format_duration(result.test_time) elif ok == CHILD_ERROR: - text = '%s (%s)' % (text, test_time) + text = '%s (%s)' % (text, mp_result.error_msg) running = get_running(workers) if running and not regrtest.ns.pgo: text += ' -- running: %s' % ', '.join(running) regrtest.display_progress(test_index, text) # Copy stdout and stderr from the child process - if stdout: - print(stdout, flush=True) - if stderr and not regrtest.ns.pgo: - print(stderr, file=sys.stderr, flush=True) + if mp_result.stdout: + print(mp_result.stdout, flush=True) + if mp_result.stderr and not regrtest.ns.pgo: + print(mp_result.stderr, file=sys.stderr, flush=True) - if result[0] == INTERRUPTED: + if result.result == INTERRUPTED: raise KeyboardInterrupt test_index += 1 except KeyboardInterrupt: @@ -229,7 +230,7 @@ def get_running(workers): # If tests are interrupted, wait until tests complete wait_start = time.monotonic() while True: - running = [worker.current_test for worker in workers] + running = [worker.current_test_name for worker in workers] running = list(filter(bool, running)) if not running: break diff --git a/Lib/test/libregrtest/save_env.py b/Lib/test/libregrtest/save_env.py index 2313b71ec893b1..31931f2192f92b 100644 --- a/Lib/test/libregrtest/save_env.py +++ b/Lib/test/libregrtest/save_env.py @@ -9,6 +9,7 @@ import threading import warnings from test import support +from test.libregrtest.utils import print_warning try: import _multiprocessing, multiprocessing.process except ImportError: @@ -283,8 +284,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): self.changed = True restore(original) if not self.quiet and not self.pgo: - print(f"Warning -- {name} was modified by {self.testname}", - file=sys.stderr, flush=True) + print_warning(f"{name} was modified by {self.testname}") print(f" Before: {original}\n After: {current} ", file=sys.stderr, flush=True) return False diff --git a/Lib/test/libregrtest/utils.py b/Lib/test/libregrtest/utils.py index d36bf9196626db..fb9971a64f66c8 100644 --- a/Lib/test/libregrtest/utils.py +++ b/Lib/test/libregrtest/utils.py @@ -1,5 +1,6 @@ -import os.path import math +import os.path +import sys import textwrap @@ -54,3 +55,7 @@ def printlist(x, width=70, indent=4, file=None): print(textwrap.fill(' '.join(str(elt) for elt in sorted(x)), width, initial_indent=blanks, subsequent_indent=blanks), file=file) + + +def print_warning(msg): + print(f"Warning -- {msg}", file=sys.stderr, flush=True) diff --git a/Lib/test/libregrtest/win_utils.py b/Lib/test/libregrtest/win_utils.py index 2e6492289e15dc..ca27f3681f9e33 100644 --- a/Lib/test/libregrtest/win_utils.py +++ b/Lib/test/libregrtest/win_utils.py @@ -1,8 +1,7 @@ -import subprocess -import sys -import os import _winapi import msvcrt +import os +import subprocess import uuid from test import support diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index a9febd00eda096..5c65e6dd852037 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -26,8 +26,9 @@ ROOT_DIR = os.path.abspath(os.path.normpath(ROOT_DIR)) TEST_INTERRUPTED = textwrap.dedent(""" - from signal import SIGINT, raise_signal + from signal import SIGINT try: + from signal import raise_signal raise_signal(SIGINT) except ImportError: import os @@ -108,7 +109,7 @@ def test_quiet(self): self.assertTrue(ns.quiet) self.assertEqual(ns.verbose, 0) - def test_slow(self): + def test_slowest(self): for opt in '-o', '--slowest': with self.subTest(opt=opt): ns = libregrtest._parse_args([opt]) @@ -780,22 +781,23 @@ def test_slowest(self): % (self.TESTNAME_REGEX, len(tests))) self.check_line(output, regex) - def test_slow_interrupted(self): + def test_slowest_interrupted(self): # Issue #25373: test --slowest with an interrupted test code = TEST_INTERRUPTED test = self.create_test("sigint", code=code) for multiprocessing in (False, True): - if multiprocessing: - args = ("--slowest", "-j2", test) - else: - args = ("--slowest", test) - output = self.run_tests(*args, exitcode=130) - self.check_executed_tests(output, test, - omitted=test, interrupted=True) - - regex = ('10 slowest tests:\n') - self.check_line(output, regex) + with self.subTest(multiprocessing=multiprocessing): + if multiprocessing: + args = ("--slowest", "-j2", test) + else: + args = ("--slowest", test) + output = self.run_tests(*args, exitcode=130) + self.check_executed_tests(output, test, + omitted=test, interrupted=True) + + regex = ('10 slowest tests:\n') + self.check_line(output, regex) def test_coverage(self): # test --coverage From 99e69d44f499625786a2e6461a954adcd0037d69 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 05:48:51 +0200 Subject: [PATCH 084/212] bpo-36710: Fix compiler warning on PyThreadState_Delete() (GH-12962) _PyThreadState_Delete() has no return value. --- Python/pystate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/pystate.c b/Python/pystate.c index f964f4951b9cfd..e9c4c7d8376bf7 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -826,7 +826,7 @@ _PyThreadState_Delete(_PyRuntimeState *runtime, PyThreadState *tstate) void PyThreadState_Delete(PyThreadState *tstate) { - return _PyThreadState_Delete(&_PyRuntime, tstate); + _PyThreadState_Delete(&_PyRuntime, tstate); } From 87d23a041d9efb743c5680ac23305ddddf300e51 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 05:49:26 +0200 Subject: [PATCH 085/212] bpo-36724: Add _PyWarnings_Fini() (#12963) Py_FinalizeEx() now clears _PyRuntime.warnings variables and _PyRuntime.exitfuncs. Changes: * Add _PyWarnings_Fini(): called by Py_FinalizeEx() * call_ll_exitfuncs() now clears _PyRuntime.exitfuncs while iterating on it (on backward order). --- Include/internal/pycore_pylifecycle.h | 1 + Python/_warnings.c | 43 +++++++++++++++++---------- Python/pylifecycle.c | 8 ++++- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 24847f4f454e5b..f5da1431d94cc9 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -76,6 +76,7 @@ extern void PyLong_Fini(void); extern void _PyFaulthandler_Fini(void); extern void _PyHash_Fini(void); extern int _PyTraceMalloc_Fini(void); +extern void _PyWarnings_Fini(_PyRuntimeState *runtime); extern void _PyGILState_Init( _PyRuntimeState *runtime, diff --git a/Python/_warnings.c b/Python/_warnings.c index 33b461511585e5..388b29954081eb 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1259,35 +1259,46 @@ _PyWarnings_Init(void) if (m == NULL) return NULL; - if (_PyRuntime.warnings.filters == NULL) { - _PyRuntime.warnings.filters = init_filters(); - if (_PyRuntime.warnings.filters == NULL) + struct _warnings_runtime_state *state = &_PyRuntime.warnings; + if (state->filters == NULL) { + state->filters = init_filters(); + if (state->filters == NULL) return NULL; } - Py_INCREF(_PyRuntime.warnings.filters); - if (PyModule_AddObject(m, "filters", _PyRuntime.warnings.filters) < 0) + Py_INCREF(state->filters); + if (PyModule_AddObject(m, "filters", state->filters) < 0) return NULL; - if (_PyRuntime.warnings.once_registry == NULL) { - _PyRuntime.warnings.once_registry = PyDict_New(); - if (_PyRuntime.warnings.once_registry == NULL) + if (state->once_registry == NULL) { + state->once_registry = PyDict_New(); + if (state->once_registry == NULL) return NULL; } - Py_INCREF(_PyRuntime.warnings.once_registry); + Py_INCREF(state->once_registry); if (PyModule_AddObject(m, "_onceregistry", - _PyRuntime.warnings.once_registry) < 0) + state->once_registry) < 0) return NULL; - if (_PyRuntime.warnings.default_action == NULL) { - _PyRuntime.warnings.default_action = PyUnicode_FromString("default"); - if (_PyRuntime.warnings.default_action == NULL) + if (state->default_action == NULL) { + state->default_action = PyUnicode_FromString("default"); + if (state->default_action == NULL) return NULL; } - Py_INCREF(_PyRuntime.warnings.default_action); + Py_INCREF(state->default_action); if (PyModule_AddObject(m, "_defaultaction", - _PyRuntime.warnings.default_action) < 0) + state->default_action) < 0) return NULL; - _PyRuntime.warnings.filters_version = 0; + state->filters_version = 0; return m; } + + +void +_PyWarnings_Fini(_PyRuntimeState *runtime) +{ + struct _warnings_runtime_state *state = &runtime->warnings; + Py_CLEAR(state->filters); + Py_CLEAR(state->once_registry); + Py_CLEAR(state->default_action); +} diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 03486c3b195a52..ae2d0bf92c6e1f 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1313,6 +1313,7 @@ Py_FinalizeEx(void) PyDict_Fini(); PySlice_Fini(); _PyGC_Fini(runtime); + _PyWarnings_Fini(runtime); _Py_HashRandomization_Fini(); _PyArg_Fini(); PyAsyncGen_Fini(); @@ -2248,7 +2249,12 @@ static void call_ll_exitfuncs(_PyRuntimeState *runtime) { while (runtime->nexitfuncs > 0) { - (*runtime->exitfuncs[--runtime->nexitfuncs])(); + /* pop last function from the list */ + runtime->nexitfuncs--; + void (*exitfunc)(void) = runtime->exitfuncs[runtime->nexitfuncs]; + runtime->exitfuncs[runtime->nexitfuncs] = NULL; + + exitfunc(); } fflush(stdout); From 3cde440f20a9db75fb2c4e65e8e4d04a53216a2d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 08:40:25 +0200 Subject: [PATCH 086/212] bpo-36725: Refactor regrtest multiprocessing code (GH-12961) Rewrite run_tests_multiprocess() function as a new MultiprocessRunner class with multiple methods to better report errors and stop immediately when needed. Changes: * Worker processes are now killed immediately if tests are interrupted or if a test does crash (CHILD_ERROR): worker processes are killed. * Rewrite how errors in a worker thread are reported to the main thread. No longer ignore BaseException or parsing errors silently. * Remove 'finished' variable: use worker.is_alive() instead * Always compute omitted tests. Add Regrtest.get_executed() method. --- Lib/test/libregrtest/main.py | 17 +- Lib/test/libregrtest/runtest.py | 1 + Lib/test/libregrtest/runtest_mp.py | 332 ++++++++++-------- Lib/test/test_regrtest.py | 4 +- .../2019-04-26-04-12-29.bpo-36725.B8-ghi.rst | 3 + 5 files changed, 205 insertions(+), 152 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-04-26-04-12-29.bpo-36725.B8-ghi.rst diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index ef1336a7e233d4..606dc268ae3fa8 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -79,8 +79,8 @@ def __init__(self): self.skipped = [] self.resource_denieds = [] self.environment_changed = [] - self.rerun = [] self.run_no_tests = [] + self.rerun = [] self.first_result = None self.interrupted = False @@ -105,6 +105,11 @@ def __init__(self): # used by --junit-xml self.testsuite_xml = None + def get_executed(self): + return (set(self.good) | set(self.bad) | set(self.skipped) + | set(self.resource_denieds) | set(self.environment_changed) + | set(self.run_no_tests)) + def accumulate_result(self, result): test_name = result.test_name ok = result.result @@ -311,8 +316,6 @@ def rerun_failed_tests(self): self.bad.remove(test_name) if ok.result == INTERRUPTED: - # print a newline separate from the ^C - print() self.interrupted = True break else: @@ -331,11 +334,11 @@ def display_result(self): print("== Tests result: %s ==" % self.get_tests_result()) if self.interrupted: - print() - # print a newline after ^C print("Test suite interrupted by signal SIGINT.") - executed = set(self.good) | set(self.bad) | set(self.skipped) - omitted = set(self.selected) - executed + + omitted = set(self.selected) - self.get_executed() + if omitted: + print() print(count(len(omitted), "test"), "omitted:") printlist(omitted) diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index 55913b3842d7bd..c0cfa5312f7057 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -275,6 +275,7 @@ def _runtest_inner(ns, test_name, display_failure=True): except support.TestDidNotRun: return TEST_DID_NOT_RUN except KeyboardInterrupt: + print() return INTERRUPTED except: if not ns.pgo: diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index 0a95bf622b059a..e6c4f4f74a1ec4 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -3,9 +3,11 @@ import json import os import queue +import subprocess import sys import threading import time +import traceback import types from test import support @@ -19,20 +21,12 @@ # Display the running tests if nothing happened last N seconds PROGRESS_UPDATE = 30.0 # seconds -# If interrupted, display the wait progress every N seconds -WAIT_PROGRESS = 2.0 # seconds +def must_stop(result): + return result.result in (INTERRUPTED, CHILD_ERROR) -def run_test_in_subprocess(testname, ns): - """Run the given test in a subprocess with --worker-args. - - ns is the option Namespace parsed from command-line arguments. regrtest - is invoked in a subprocess with the --worker-args argument; when the - subprocess exits, its return code, stdout and stderr are returned as a - 3-tuple. - """ - from subprocess import Popen, PIPE +def run_test_in_subprocess(testname, ns): ns_dict = vars(ns) worker_args = (ns_dict, testname) worker_args = json.dumps(worker_args) @@ -47,15 +41,12 @@ def run_test_in_subprocess(testname, ns): # Running the child from the same working directory as regrtest's original # invocation ensures that TEMPDIR for the child is the same when # sysconfig.is_python_build() is true. See issue 15300. - popen = Popen(cmd, - stdout=PIPE, stderr=PIPE, - universal_newlines=True, - close_fds=(os.name != 'nt'), - cwd=support.SAVEDCWD) - with popen: - stdout, stderr = popen.communicate() - retcode = popen.wait() - return retcode, stdout, stderr + return subprocess.Popen(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + close_fds=(os.name != 'nt'), + cwd=support.SAVEDCWD) def run_tests_worker(worker_args): @@ -66,7 +57,6 @@ def run_tests_worker(worker_args): result = runtest(ns, testname) print() # Force a newline (just in case) - print(json.dumps(result), flush=True) sys.exit(0) @@ -77,7 +67,6 @@ class MultiprocessIterator: """A thread-safe iterator over tests for multiprocess mode.""" def __init__(self, tests): - self.interrupted = False self.lock = threading.Lock() self.tests = tests @@ -86,8 +75,6 @@ def __iter__(self): def __next__(self): with self.lock: - if self.interrupted: - raise StopIteration('tests interrupted') return next(self.tests) @@ -102,143 +89,202 @@ def __init__(self, pending, output, ns): self.ns = ns self.current_test_name = None self.start_time = None + self._popen = None - def _runtest(self): - try: - test_name = next(self.pending) - except StopIteration: - self.output.put(None) - return True + def kill(self): + if not self.is_alive(): + return + if self._popen is not None: + self._popen.kill() + def _runtest(self, test_name): try: self.start_time = time.monotonic() self.current_test_name = test_name - retcode, stdout, stderr = run_test_in_subprocess(test_name, self.ns) + popen = run_test_in_subprocess(test_name, self.ns) + self._popen = popen + with popen: + try: + stdout, stderr = popen.communicate() + except: + popen.kill() + popen.wait() + raise + + retcode = popen.wait() finally: self.current_test_name = None + self._popen = None + + stdout = stdout.strip() + stderr = stderr.rstrip() + err_msg = None if retcode != 0: + err_msg = "Exit code %s" % retcode + else: + stdout, _, result = stdout.rpartition("\n") + stdout = stdout.rstrip() + if not result: + err_msg = "Failed to parse worker stdout" + else: + try: + # deserialize run_tests_worker() output + result = json.loads(result) + result = TestResult(*result) + except Exception as exc: + err_msg = "Failed to parse worker JSON: %s" % exc + + if err_msg is not None: test_time = time.monotonic() - self.start_time result = TestResult(test_name, CHILD_ERROR, test_time, None) - err_msg = "Exit code %s" % retcode - mp_result = MultiprocessResult(result, stdout.rstrip(), stderr.rstrip(), err_msg) - self.output.put(mp_result) - return False - stdout, _, result = stdout.strip().rpartition("\n") - if not result: - self.output.put(None) - return True - - # deserialize run_tests_worker() output - result = json.loads(result) - result = TestResult(*result) - mp_result = MultiprocessResult(result, stdout.rstrip(), stderr.rstrip(), None) - self.output.put(mp_result) - return False + return MultiprocessResult(result, stdout, stderr, err_msg) def run(self): - try: - stop = False - while not stop: - stop = self._runtest() - except BaseException: - self.output.put(None) - raise + while True: + try: + try: + test_name = next(self.pending) + except StopIteration: + break + mp_result = self._runtest(test_name) + self.output.put((False, mp_result)) -def run_tests_multiprocess(regrtest): - output = queue.Queue() - pending = MultiprocessIterator(regrtest.tests) - test_timeout = regrtest.ns.timeout - use_timeout = (test_timeout is not None) - - workers = [MultiprocessThread(pending, output, regrtest.ns) - for i in range(regrtest.ns.use_mp)] - print("Run tests in parallel using %s child processes" - % len(workers)) + if must_stop(mp_result.result): + break + except BaseException: + self.output.put((True, traceback.format_exc())) + break + + +def get_running(workers): + running = [] for worker in workers: - worker.start() - - def get_running(workers): - running = [] - for worker in workers: - current_test_name = worker.current_test_name - if not current_test_name: - continue - dt = time.monotonic() - worker.start_time - if dt >= PROGRESS_MIN_TIME: - text = '%s (%s)' % (current_test_name, format_duration(dt)) - running.append(text) - return running - - finished = 0 - test_index = 1 - get_timeout = max(PROGRESS_UPDATE, PROGRESS_MIN_TIME) - try: - while finished < regrtest.ns.use_mp: - if use_timeout: - faulthandler.dump_traceback_later(test_timeout, exit=True) + current_test_name = worker.current_test_name + if not current_test_name: + continue + dt = time.monotonic() - worker.start_time + if dt >= PROGRESS_MIN_TIME: + text = '%s (%s)' % (current_test_name, format_duration(dt)) + running.append(text) + return running + + +class MultiprocessRunner: + def __init__(self, regrtest): + self.regrtest = regrtest + self.ns = regrtest.ns + self.output = queue.Queue() + self.pending = MultiprocessIterator(self.regrtest.tests) + if self.ns.timeout is not None: + self.test_timeout = self.ns.timeout * 1.5 + else: + self.test_timeout = None + self.workers = None + + def start_workers(self): + self.workers = [MultiprocessThread(self.pending, self.output, self.ns) + for _ in range(self.ns.use_mp)] + print("Run tests in parallel using %s child processes" + % len(self.workers)) + for worker in self.workers: + worker.start() + + def wait_workers(self): + for worker in self.workers: + worker.kill() + for worker in self.workers: + worker.join() + + def _get_result(self): + if not any(worker.is_alive() for worker in self.workers): + # all worker threads are done: consume pending results + try: + return self.output.get(timeout=0) + except queue.Empty: + return None + + while True: + if self.test_timeout is not None: + faulthandler.dump_traceback_later(self.test_timeout, exit=True) + # wait for a thread + timeout = max(PROGRESS_UPDATE, PROGRESS_MIN_TIME) try: - mp_result = output.get(timeout=get_timeout) + return self.output.get(timeout=timeout) except queue.Empty: - running = get_running(workers) - if running and not regrtest.ns.pgo: - print('running: %s' % ', '.join(running), flush=True) - continue - - if mp_result is None: - finished += 1 - continue - result = mp_result.result - regrtest.accumulate_result(result) - - # Display progress - ok = result.result - - text = format_test_result(result) - if (ok not in (CHILD_ERROR, INTERRUPTED) - and result.test_time >= PROGRESS_MIN_TIME - and not regrtest.ns.pgo): - text += ' (%s)' % format_duration(result.test_time) - elif ok == CHILD_ERROR: - text = '%s (%s)' % (text, mp_result.error_msg) - running = get_running(workers) - if running and not regrtest.ns.pgo: - text += ' -- running: %s' % ', '.join(running) - regrtest.display_progress(test_index, text) - - # Copy stdout and stderr from the child process - if mp_result.stdout: - print(mp_result.stdout, flush=True) - if mp_result.stderr and not regrtest.ns.pgo: - print(mp_result.stderr, file=sys.stderr, flush=True) - - if result.result == INTERRUPTED: - raise KeyboardInterrupt - test_index += 1 - except KeyboardInterrupt: - regrtest.interrupted = True - pending.interrupted = True - print() - finally: - if use_timeout: - faulthandler.cancel_dump_traceback_later() - - # If tests are interrupted, wait until tests complete - wait_start = time.monotonic() - while True: - running = [worker.current_test_name for worker in workers] - running = list(filter(bool, running)) - if not running: - break - - dt = time.monotonic() - wait_start - line = "Waiting for %s (%s tests)" % (', '.join(running), len(running)) - if dt >= WAIT_PROGRESS: - line = "%s since %.0f sec" % (line, dt) - print(line, flush=True) - for worker in workers: - worker.join(WAIT_PROGRESS) + pass + + # display progress + running = get_running(self.workers) + if running and not self.ns.pgo: + print('running: %s' % ', '.join(running), flush=True) + + def display_result(self, mp_result): + result = mp_result.result + + text = format_test_result(result) + if mp_result.error_msg is not None: + # CHILD_ERROR + text += ' (%s)' % mp_result.error_msg + elif (result.test_time >= PROGRESS_MIN_TIME and not self.ns.pgo): + text += ' (%s)' % format_duration(result.test_time) + running = get_running(self.workers) + if running and not self.ns.pgo: + text += ' -- running: %s' % ', '.join(running) + self.regrtest.display_progress(self.test_index, text) + + def _process_result(self, item): + if item[0]: + # Thread got an exception + format_exc = item[1] + print(f"regrtest worker thread failed: {format_exc}", + file=sys.stderr, flush=True) + return True + + self.test_index += 1 + mp_result = item[1] + self.regrtest.accumulate_result(mp_result.result) + self.display_result(mp_result) + + if mp_result.stdout: + print(mp_result.stdout, flush=True) + if mp_result.stderr and not self.ns.pgo: + print(mp_result.stderr, file=sys.stderr, flush=True) + + if mp_result.result.result == INTERRUPTED: + self.regrtest.interrupted = True + + if must_stop(mp_result.result): + return True + + return False + + def run_tests(self): + self.start_workers() + + self.test_index = 0 + try: + while True: + item = self._get_result() + if item is None: + break + + stop = self._process_result(item) + if stop: + break + except KeyboardInterrupt: + print() + self.regrtest.interrupted = True + finally: + if self.test_timeout is not None: + faulthandler.cancel_dump_traceback_later() + + self.wait_workers() + + +def run_tests_multiprocess(regrtest): + MultiprocessRunner(regrtest).run_tests() diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 5c65e6dd852037..e0d1d3cec7c26a 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -916,13 +916,13 @@ def test_method2(self): testname) self.assertEqual(output.splitlines(), all_methods) + @support.cpython_only def test_crashed(self): # Any code which causes a crash code = 'import faulthandler; faulthandler._sigsegv()' crash_test = self.create_test(name="crash", code=code) - ok_test = self.create_test(name="ok") - tests = [crash_test, ok_test] + tests = [crash_test] output = self.run_tests("-j2", *tests, exitcode=2) self.check_executed_tests(output, tests, failed=crash_test, randomize=True) diff --git a/Misc/NEWS.d/next/Tests/2019-04-26-04-12-29.bpo-36725.B8-ghi.rst b/Misc/NEWS.d/next/Tests/2019-04-26-04-12-29.bpo-36725.B8-ghi.rst new file mode 100644 index 00000000000000..b632c46d2b674f --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-04-26-04-12-29.bpo-36725.B8-ghi.rst @@ -0,0 +1,3 @@ +When using mulitprocessing mode (-jN), regrtest now better reports errors if +a worker process fails, and it exits immediately on a worker thread failure +or when interrupted. From 7abb6c05afd02c17c7a941b64db5756b161b3cf7 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Fri, 26 Apr 2019 15:56:15 +0900 Subject: [PATCH 087/212] bpo-36669: add matmul support to weakref.proxy (GH-12932) --- Doc/library/weakref.rst | 4 ++++ Doc/whatsnew/3.8.rst | 7 +++++++ Lib/test/test_weakref.py | 15 +++++++++++++++ .../2019-04-24-17-08-45.bpo-36669.X4g0fu.rst | 1 + Objects/weakrefobject.c | 4 ++++ 5 files changed, 31 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2019-04-24-17-08-45.bpo-36669.X4g0fu.rst diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst index 7f3d267d74c2ec..80a908bbd83b0a 100644 --- a/Doc/library/weakref.rst +++ b/Doc/library/weakref.rst @@ -139,6 +139,10 @@ Extension types can easily be made to support weak references; see prevent their use as dictionary keys. *callback* is the same as the parameter of the same name to the :func:`ref` function. + .. versionchanged:: 3.8 + Extended the operator support on proxy objects to include the matrix + multiplication operators ``@`` and ``@=``. + .. function:: getweakrefcount(object) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 2270334a281b08..4cb9c4f0f20e94 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -450,6 +450,13 @@ venv activating virtual environments under PowerShell Core 6.1. (Contributed by Brett Cannon in :issue:`32718`.) +weakref +------- + +* The proxy objects returned by :func:`weakref.proxy` now support the matrix + multiplication operators ``@`` and ``@=`` in addition to the other + numeric operators. (Contributed by Mark Dickinson in :issue:`36669`.) + xml --- diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index 50a46f817f9ffe..6f15c03ac5292f 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -285,6 +285,21 @@ def __ifloordiv__(self, other): p //= 5 self.assertEqual(p, 21) + def test_proxy_matmul(self): + class C: + def __matmul__(self, other): + return 1729 + def __rmatmul__(self, other): + return -163 + def __imatmul__(self, other): + return 561 + o = C() + p = weakref.proxy(o) + self.assertEqual(p @ 5, 1729) + self.assertEqual(5 @ p, -163) + p @= 5 + self.assertEqual(p, 561) + # The PyWeakref_* C API is documented as allowing either NULL or # None as the value for the callback, where either means "no # callback". The "no callback" ref and proxy objects are supposed diff --git a/Misc/NEWS.d/next/Library/2019-04-24-17-08-45.bpo-36669.X4g0fu.rst b/Misc/NEWS.d/next/Library/2019-04-24-17-08-45.bpo-36669.X4g0fu.rst new file mode 100644 index 00000000000000..53bdefee12f2c5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-24-17-08-45.bpo-36669.X4g0fu.rst @@ -0,0 +1 @@ +Add missing matrix multiplication operator support to weakref.proxy. diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index 9227aa688f47e1..ff6d92254f7fe2 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -525,6 +525,8 @@ WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd) WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor) WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr) WRAP_UNARY(proxy_index, PyNumber_Index) +WRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply) +WRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply) static int proxy_bool(PyWeakReference *proxy) @@ -642,6 +644,8 @@ static PyNumberMethods proxy_as_number = { proxy_ifloor_div, /*nb_inplace_floor_divide*/ proxy_itrue_div, /*nb_inplace_true_divide*/ proxy_index, /*nb_index*/ + proxy_matmul, /*nb_matrix_multiply*/ + proxy_imatmul, /*nb_inplace_matrix_multiply*/ }; static PySequenceMethods proxy_as_sequence = { From 75120d2205af086140e5e4e2dc620eb19cdf9078 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 09:28:53 +0200 Subject: [PATCH 088/212] bpo-36719: regrtest always detect uncollectable objects (GH-12951) regrtest now always detects uncollectable objects. Previously, the check was only enabled by --findleaks. The check now also works with -jN/--multiprocess N. --findleaks becomes a deprecated alias to --fail-env-changed. --- Lib/test/libregrtest/cmdline.py | 12 +++--- Lib/test/libregrtest/main.py | 43 +++---------------- Lib/test/libregrtest/runtest.py | 35 +++++++-------- Lib/test/test_regrtest.py | 41 +++++++++++++++--- .../2019-04-26-09-02-49.bpo-36719.ys2uqH.rst | 4 ++ 5 files changed, 66 insertions(+), 69 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-04-26-09-02-49.bpo-36719.ys2uqH.rst diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py index 7cd85bf2803aa1..cb09ee0e03b30c 100644 --- a/Lib/test/libregrtest/cmdline.py +++ b/Lib/test/libregrtest/cmdline.py @@ -226,8 +226,9 @@ def _create_parser(): '(instead of the Python stdlib test suite)') group = parser.add_argument_group('Special runs') - group.add_argument('-l', '--findleaks', action='store_true', - help='if GC is available detect tests that leak memory') + group.add_argument('-l', '--findleaks', action='store_const', const=2, + default=1, + help='deprecated alias to --fail-env-changed') group.add_argument('-L', '--runleaks', action='store_true', help='run the leaks(1) command just before exit.' + more_details) @@ -309,7 +310,7 @@ def _parse_args(args, **kwargs): # Defaults ns = argparse.Namespace(testdir=None, verbose=0, quiet=False, exclude=False, single=False, randomize=False, fromfile=None, - findleaks=False, use_resources=None, trace=False, coverdir='coverage', + findleaks=1, use_resources=None, trace=False, coverdir='coverage', runleaks=False, huntrleaks=False, verbose2=False, print_slow=False, random_seed=None, use_mp=None, verbose3=False, forever=False, header=False, failfast=False, match_tests=None, pgo=False) @@ -330,12 +331,13 @@ def _parse_args(args, **kwargs): parser.error("unrecognized arguments: %s" % arg) sys.exit(1) + if ns.findleaks > 1: + # --findleaks implies --fail-env-changed + ns.fail_env_changed = True if ns.single and ns.fromfile: parser.error("-s and -f don't go together!") if ns.use_mp is not None and ns.trace: parser.error("-T and -j don't go together!") - if ns.use_mp is not None and ns.findleaks: - parser.error("-l and -j don't go together!") if ns.failfast and not (ns.verbose or ns.verbose3): parser.error("-G/--failfast needs either -v or -W") if ns.pgo and (ns.verbose or ns.verbose2 or ns.verbose3): diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 606dc268ae3fa8..def6532b623f91 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -20,10 +20,6 @@ from test.libregrtest.setup import setup_tests from test.libregrtest.utils import removepy, count, format_duration, printlist from test import support -try: - import gc -except ImportError: - gc = None # When tests are run from the Python build directory, it is best practice @@ -90,9 +86,6 @@ def __init__(self): # used by --coverage, trace.Trace instance self.tracer = None - # used by --findleaks, store for gc.garbage - self.found_garbage = [] - # used to display the progress bar "[ 3/100]" self.start_time = time.monotonic() self.test_count = '' @@ -173,22 +166,6 @@ def parse_args(self, kwargs): "faulthandler.dump_traceback_later", file=sys.stderr) ns.timeout = None - if ns.threshold is not None and gc is None: - print('No GC available, ignore --threshold.', file=sys.stderr) - ns.threshold = None - - if ns.findleaks: - if gc is not None: - # Uncomment the line below to report garbage that is not - # freeable by reference counting alone. By default only - # garbage that is not collectable by the GC is reported. - pass - #gc.set_debug(gc.DEBUG_SAVEALL) - else: - print('No GC available, disabling --findleaks', - file=sys.stderr) - ns.findleaks = False - if ns.xmlpath: support.junit_xml_list = self.testsuite_xml = [] @@ -308,7 +285,7 @@ def rerun_failed_tests(self): print("Re-running failed tests in verbose mode") self.rerun = self.bad[:] for test_name in self.rerun: - print("Re-running test %r in verbose mode" % test_name, flush=True) + print(f"Re-running {test_name} in verbose mode", flush=True) self.ns.verbose = True ok = runtest(self.ns, test_name) @@ -318,10 +295,10 @@ def rerun_failed_tests(self): if ok.result == INTERRUPTED: self.interrupted = True break - else: - if self.bad: - print(count(len(self.bad), 'test'), "failed again:") - printlist(self.bad) + + if self.bad: + print(count(len(self.bad), 'test'), "failed again:") + printlist(self.bad) self.display_result() @@ -426,16 +403,6 @@ def run_tests_sequential(self): # be quiet: say nothing if the test passed shortly previous_test = None - if self.ns.findleaks: - gc.collect() - if gc.garbage: - print("Warning: test created", len(gc.garbage), end=' ') - print("uncollectable object(s).") - # move the uncollectable objects somewhere so we don't see - # them again - self.found_garbage.extend(gc.garbage) - del gc.garbage[:] - # Unload the newly imported modules (best effort finalization) for module in sys.modules.keys(): if module not in save_modules and module.startswith("test."): diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index c0cfa5312f7057..a9574929a4cda6 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -1,6 +1,7 @@ import collections import faulthandler import functools +import gc import importlib import io import os @@ -8,6 +9,7 @@ import time import traceback import unittest + from test import support from test.libregrtest.refleak import dash_R, clear_caches from test.libregrtest.save_env import saved_test_environment @@ -59,7 +61,7 @@ # used by --findleaks, store for gc.garbage -found_garbage = [] +FOUND_GARBAGE = [] def format_test_result(result): @@ -182,11 +184,6 @@ def runtest(ns, test_name): return TestResult(test_name, FAILED, 0.0, None) -def post_test_cleanup(): - support.gc_collect() - support.reap_children() - - def _test_module(the_module): loader = unittest.TestLoader() tests = loader.loadTestsFromModule(the_module) @@ -224,21 +221,19 @@ def _runtest_inner2(ns, test_name): finally: cleanup_test_droppings(test_name, ns.verbose) - if ns.findleaks: - import gc - support.gc_collect() - if gc.garbage: - import gc - gc.garbage = [1] - print_warning(f"{test_name} created {len(gc.garbage)} " - f"uncollectable object(s).") - # move the uncollectable objects somewhere, - # so we don't see them again - found_garbage.extend(gc.garbage) - gc.garbage.clear() - support.environment_altered = True + support.gc_collect() + + if gc.garbage: + support.environment_altered = True + print_warning(f"{test_name} created {len(gc.garbage)} " + f"uncollectable object(s).") - post_test_cleanup() + # move the uncollectable objects somewhere, + # so we don't see them again + FOUND_GARBAGE.extend(gc.garbage) + gc.garbage.clear() + + support.reap_children() return refleak diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index e0d1d3cec7c26a..7ff2dde5aa1cd5 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -26,9 +26,8 @@ ROOT_DIR = os.path.abspath(os.path.normpath(ROOT_DIR)) TEST_INTERRUPTED = textwrap.dedent(""" - from signal import SIGINT + from signal import SIGINT, raise_signal try: - from signal import raise_signal raise_signal(SIGINT) except ImportError: import os @@ -255,9 +254,7 @@ def test_multiprocess(self): self.checkError([opt], 'expected one argument') self.checkError([opt, 'foo'], 'invalid int value') self.checkError([opt, '2', '-T'], "don't go together") - self.checkError([opt, '2', '-l'], "don't go together") self.checkError([opt, '0', '-T'], "don't go together") - self.checkError([opt, '0', '-l'], "don't go together") def test_coverage(self): for opt in '-T', '--coverage': @@ -454,8 +451,8 @@ def list_regex(line_format, tests): regex = list_regex('%s re-run test%s', rerun) self.check_line(output, regex) self.check_line(output, "Re-running failed tests in verbose mode") - for name in rerun: - regex = "Re-running test %r in verbose mode" % name + for test_name in rerun: + regex = f"Re-running {test_name} in verbose mode" self.check_line(output, regex) if no_test_ran: @@ -1070,6 +1067,38 @@ def test_other_bug(self): self.check_executed_tests(output, [testname, testname2], no_test_ran=[testname]) + @support.cpython_only + def test_findleaks(self): + code = textwrap.dedent(r""" + import _testcapi + import gc + import unittest + + @_testcapi.with_tp_del + class Garbage: + def __tp_del__(self): + pass + + class Tests(unittest.TestCase): + def test_garbage(self): + # create an uncollectable object + obj = Garbage() + obj.ref_cycle = obj + obj = None + """) + testname = self.create_test(code=code) + + output = self.run_tests("--fail-env-changed", testname, exitcode=3) + self.check_executed_tests(output, [testname], + env_changed=[testname], + fail_env_changed=True) + + # --findleaks is now basically an alias to --fail-env-changed + output = self.run_tests("--findleaks", testname, exitcode=3) + self.check_executed_tests(output, [testname], + env_changed=[testname], + fail_env_changed=True) + class TestUtils(unittest.TestCase): def test_format_duration(self): diff --git a/Misc/NEWS.d/next/Tests/2019-04-26-09-02-49.bpo-36719.ys2uqH.rst b/Misc/NEWS.d/next/Tests/2019-04-26-09-02-49.bpo-36719.ys2uqH.rst new file mode 100644 index 00000000000000..4b6ef76bc6d69a --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-04-26-09-02-49.bpo-36719.ys2uqH.rst @@ -0,0 +1,4 @@ +regrtest now always detects uncollectable objects. Previously, the check was +only enabled by ``--findleaks``. The check now also works with +``-jN/--multiprocess N``. ``--findleaks`` becomes a deprecated alias to +``--fail-env-changed``. From 837acc1957d86ca950433f5064fd06d09b57d23b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 09:56:37 +0200 Subject: [PATCH 089/212] bpo-36719: Fix regrtest re-run (GH-12964) Properly handle a test which fail but then pass. Add test_rerun_success() unit test. --- Lib/test/libregrtest/main.py | 23 +++++++++++++---------- Lib/test/libregrtest/runtest_mp.py | 3 --- Lib/test/test_regrtest.py | 23 ++++++++++++++++++++++- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index def6532b623f91..691fb528cdd5fd 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -103,17 +103,18 @@ def get_executed(self): | set(self.resource_denieds) | set(self.environment_changed) | set(self.run_no_tests)) - def accumulate_result(self, result): + def accumulate_result(self, result, rerun=False): test_name = result.test_name ok = result.result - if ok not in (CHILD_ERROR, INTERRUPTED): + if ok not in (CHILD_ERROR, INTERRUPTED) and not rerun: self.test_times.append((result.test_time, test_name)) if ok == PASSED: self.good.append(test_name) elif ok in (FAILED, CHILD_ERROR): - self.bad.append(test_name) + if not rerun: + self.bad.append(test_name) elif ok == ENV_CHANGED: self.environment_changed.append(test_name) elif ok == SKIPPED: @@ -123,9 +124,14 @@ def accumulate_result(self, result): self.resource_denieds.append(test_name) elif ok == TEST_DID_NOT_RUN: self.run_no_tests.append(test_name) - elif ok != INTERRUPTED: + elif ok == INTERRUPTED: + self.interrupted = True + else: raise ValueError("invalid test result: %r" % ok) + if rerun and ok not in {FAILED, CHILD_ERROR, INTERRUPTED}: + self.bad.remove(test_name) + xml_data = result.xml_data if xml_data: import xml.etree.ElementTree as ET @@ -287,13 +293,11 @@ def rerun_failed_tests(self): for test_name in self.rerun: print(f"Re-running {test_name} in verbose mode", flush=True) self.ns.verbose = True - ok = runtest(self.ns, test_name) + result = runtest(self.ns, test_name) - if ok[0] in {PASSED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED}: - self.bad.remove(test_name) + self.accumulate_result(result, rerun=True) - if ok.result == INTERRUPTED: - self.interrupted = True + if result.result == INTERRUPTED: break if self.bad: @@ -392,7 +396,6 @@ def run_tests_sequential(self): self.accumulate_result(result) if result.result == INTERRUPTED: - self.interrupted = True break previous_test = format_test_result(result) diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index e6c4f4f74a1ec4..dbab6954de867f 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -255,9 +255,6 @@ def _process_result(self, item): if mp_result.stderr and not self.ns.pgo: print(mp_result.stderr, file=sys.stderr, flush=True) - if mp_result.result.result == INTERRUPTED: - self.regrtest.interrupted = True - if must_stop(mp_result.result): return True diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 7ff2dde5aa1cd5..9155522c273d88 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -484,7 +484,7 @@ def list_regex(line_format, tests): result.append('SUCCESS') result = ', '.join(result) if rerun: - self.check_line(output, 'Tests result: %s' % result) + self.check_line(output, 'Tests result: FAILURE') result = 'FAILURE then %s' % result self.check_line(output, 'Tests result: %s' % result) @@ -989,6 +989,7 @@ def test_env_changed(self): fail_env_changed=True) def test_rerun_fail(self): + # FAILURE then FAILURE code = textwrap.dedent(""" import unittest @@ -1003,6 +1004,26 @@ def test_bug(self): self.check_executed_tests(output, [testname], failed=testname, rerun=testname) + def test_rerun_success(self): + # FAILURE then SUCCESS + code = textwrap.dedent(""" + import builtins + import unittest + + class Tests(unittest.TestCase): + failed = False + + def test_fail_once(self): + if not hasattr(builtins, '_test_failed'): + builtins._test_failed = True + self.fail("bug") + """) + testname = self.create_test(code=code) + + output = self.run_tests("-w", testname, exitcode=0) + self.check_executed_tests(output, [testname], + rerun=testname) + def test_no_tests_ran(self): code = textwrap.dedent(""" import unittest From 00db7c73af4f60df61e9df87cde7401c3ed9df69 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 11:12:26 +0200 Subject: [PATCH 090/212] bpo-36719: regrtest closes explicitly WindowsLoadTracker (GH-12965) Regrtest.finalize() now closes explicitly the WindowsLoadTracker instance. --- Lib/test/libregrtest/main.py | 35 +++++++++++++++++++------------ Lib/test/libregrtest/win_utils.py | 8 ++++++- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 691fb528cdd5fd..c19ea44db9b287 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -98,6 +98,8 @@ def __init__(self): # used by --junit-xml self.testsuite_xml = None + self.win_load_tracker = None + def get_executed(self): return (set(self.good) | set(self.bad) | set(self.skipped) | set(self.resource_denieds) | set(self.environment_changed) @@ -154,9 +156,9 @@ def display_progress(self, test_index, text): line = f"[{line}] {text}" # add the system load prefix: "load avg: 1.80 " - if self.getloadavg: - load_avg_1min = self.getloadavg() - line = f"load avg: {load_avg_1min:.2f} {line}" + load_avg = self.getloadavg() + if load_avg is not None: + line = f"load avg: {load_avg:.2f} {line}" # add the timestamp prefix: "0:01:05 " test_time = time.monotonic() - self.start_time @@ -490,6 +492,10 @@ def run_tests(self): self.run_tests_sequential() def finalize(self): + if self.win_load_tracker is not None: + self.win_load_tracker.close() + self.win_load_tracker = None + if self.next_single_filename: if self.next_single_test: with open(self.next_single_filename, 'w') as fp: @@ -560,6 +566,15 @@ def main(self, tests=None, **kwargs): with support.temp_cwd(test_cwd, quiet=True): self._main(tests, kwargs) + def getloadavg(self): + if self.win_load_tracker is not None: + return self.win_load_tracker.getloadavg() + + if hasattr(os, 'getloadavg'): + return os.getloadavg()[0] + + return None + def _main(self, tests, kwargs): if self.ns.huntrleaks: warmup, repetitions, _ = self.ns.huntrleaks @@ -591,23 +606,17 @@ def _main(self, tests, kwargs): self.list_cases() sys.exit(0) - self.getloadavg = None # If we're on windows and this is the parent runner (not a worker), - # report the load average. - if hasattr(os, 'getloadavg'): - def getloadavg_1m(): - return os.getloadavg()[0] - self.getloadavg = getloadavg_1m - elif sys.platform == 'win32' and (self.ns.worker_args is None): + # track the load average. + if sys.platform == 'win32' and (self.ns.worker_args is None): from test.libregrtest.win_utils import WindowsLoadTracker try: - load_tracker = WindowsLoadTracker() - self.getloadavg = load_tracker.getloadavg + self.win_load_tracker = WindowsLoadTracker() except FileNotFoundError as error: # Windows IoT Core and Windows Nano Server do not provide # typeperf.exe for x64, x86 or ARM - print('Failed to create WindowsLoadTracker: {}'.format(error)) + print(f'Failed to create WindowsLoadTracker: {error}') self.run_tests() self.display_result() diff --git a/Lib/test/libregrtest/win_utils.py b/Lib/test/libregrtest/win_utils.py index ca27f3681f9e33..adfe278ba39bf2 100644 --- a/Lib/test/libregrtest/win_utils.py +++ b/Lib/test/libregrtest/win_utils.py @@ -60,9 +60,15 @@ def start(self): # Close our copy of the write end of the pipe os.close(command_stdout) - def __del__(self): + def close(self): + if self.p is None: + return self.p.kill() self.p.wait() + self.p = None + + def __del__(self): + self.close() def read_output(self): import _winapi From 4cb525a1f0cba152d1da61e531f2ad5db633120a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 13:05:47 +0200 Subject: [PATCH 091/212] bpo-36356: pymain_exit_error() only call pymain_free() for exit (GH-12968) Add _Py_INIT_HAS_EXITCODE() macro. --- Include/cpython/coreconfig.h | 4 +++- Modules/main.c | 7 ++++++- Python/pylifecycle.c | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index c1a72989a5e979..ed2f09f933b23a 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -33,8 +33,10 @@ typedef struct { #define _Py_INIT_NO_MEMORY() _Py_INIT_USER_ERR("memory allocation failed") #define _Py_INIT_EXIT(EXITCODE) \ (_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0, .exitcode = (EXITCODE)} +#define _Py_INIT_HAS_EXITCODE(err) \ + (err.exitcode != -1) #define _Py_INIT_FAILED(err) \ - (err.msg != NULL || err.exitcode != -1) + (err.msg != NULL || _Py_INIT_HAS_EXITCODE(err)) /* --- _PyWstrList ------------------------------------------------ */ diff --git a/Modules/main.c b/Modules/main.c index 6a7f735ed692af..68f0b99c9fbbf4 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -570,7 +570,12 @@ exit_sigint(void) static void _Py_NO_RETURN pymain_exit_error(_PyInitError err) { - pymain_free(); + if (_Py_INIT_HAS_EXITCODE(err)) { + /* If it's an error rather than a regular exit, leave Python runtime + alive: _Py_ExitInitError() uses the current exception and use + sys.stdout in this case. */ + pymain_free(); + } _Py_ExitInitError(err); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index ae2d0bf92c6e1f..d93fe065558aa3 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2172,7 +2172,7 @@ Py_FatalError(const char *msg) void _Py_NO_RETURN _Py_ExitInitError(_PyInitError err) { - if (err.exitcode >= 0) { + if (_Py_INIT_HAS_EXITCODE(err)) { exit(err.exitcode); } else { From 06d04e77ca36133e82bf6c363c09ba82e07a9c75 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 13:09:47 +0200 Subject: [PATCH 092/212] bpo-36733: Fix PYTHONPATH for make regen-add (GH-12969) Add PYTHONPATH=$(srcdir) to run $(PYTHON_FOR_REGEN) -m Parser.pgen, so it's possible to build Python from a different directory. --- Makefile.pre.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index 68ac7723556e4e..d06ad0bc939c35 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -791,7 +791,7 @@ regen-grammar: regen-token # Regenerate Include/graminit.h and Python/graminit.c # from Grammar/Grammar using pgen @$(MKDIR_P) Include - $(PYTHON_FOR_REGEN) -m Parser.pgen $(srcdir)/Grammar/Grammar \ + PYTHONPATH=$(srcdir) $(PYTHON_FOR_REGEN) -m Parser.pgen $(srcdir)/Grammar/Grammar \ $(srcdir)/Grammar/Tokens \ $(srcdir)/Include/graminit.h.new \ $(srcdir)/Python/graminit.c.new @@ -849,7 +849,7 @@ regen-token: regen-keyword: # Regenerate Lib/keyword.py from Grammar/Grammar and Grammar/Tokens # using Parser/pgen - $(PYTHON_FOR_REGEN) -m Parser.pgen.keywordgen $(srcdir)/Grammar/Grammar \ + PYTHONPATH=$(srcdir) $(PYTHON_FOR_REGEN) -m Parser.pgen.keywordgen $(srcdir)/Grammar/Grammar \ $(srcdir)/Grammar/Tokens \ $(srcdir)/Lib/keyword.py.new $(UPDATE_FILE) $(srcdir)/Lib/keyword.py $(srcdir)/Lib/keyword.py.new From ad0daf5b374dc43540d4ffcf32ca30e5c5147b90 Mon Sep 17 00:00:00 2001 From: Charles Pigott Date: Fri, 26 Apr 2019 16:38:12 +0100 Subject: [PATCH 093/212] bpo-31525: Increase minimum sqlite version number check (GH-12923) --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 58c16e8ba49d5c..96a49b4e353c72 100644 --- a/setup.py +++ b/setup.py @@ -1299,7 +1299,7 @@ def detect_sqlite(self): sqlite_setup_debug = False # verbose debug prints from this script? # We hunt for #define SQLITE_VERSION "n.n.n" - # We need to find >= sqlite version 3.0.8 + # We need to find >= sqlite version 3.3.9, for sqlite3_prepare_v2 sqlite_incdir = sqlite_libdir = None sqlite_inc_paths = [ '/usr/include', '/usr/include/sqlite', @@ -1310,7 +1310,7 @@ def detect_sqlite(self): ] if CROSS_COMPILING: sqlite_inc_paths = [] - MIN_SQLITE_VERSION_NUMBER = (3, 0, 8) + MIN_SQLITE_VERSION_NUMBER = (3, 3, 9) MIN_SQLITE_VERSION = ".".join([str(x) for x in MIN_SQLITE_VERSION_NUMBER]) @@ -1344,7 +1344,7 @@ def detect_sqlite(self): break else: if sqlite_setup_debug: - print("%s: version %d is too old, need >= %s"%(d, + print("%s: version %s is too old, need >= %s"%(d, sqlite_version, MIN_SQLITE_VERSION)) elif sqlite_setup_debug: print("sqlite: %s had no SQLITE_VERSION"%(f,)) From 01f073f5e43329547471c846c37e23157255e30a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 17:55:17 +0200 Subject: [PATCH 094/212] bpo-21536: Revert Makefile change on python-config (GH-12971) Misc/python-config.sh lives in the build directory, not in the source directory. --- Makefile.pre.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index d06ad0bc939c35..89479ee7f1a36c 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1460,7 +1460,9 @@ libinstall: build_all $(srcdir)/Modules/xxmodule.c -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/PatternGrammar.txt -python-config: $(srcdir)/Misc/python-config.in $(srcdir)/Misc/python-config.sh +# bpo-21536: Misc/python-config.sh is generated in the build directory +# from $(srcdir)Misc/python-config.sh.in. +python-config: $(srcdir)/Misc/python-config.in Misc/python-config.sh @ # Substitution happens here, as the completely-expanded BINDIR @ # is not available in configure sed -e "s,@EXENAME@,$(BINDIR)/python$(LDVERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config.py From 404606974051c5ec093312aa57cf1bcbc52e1d85 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 17:56:44 +0200 Subject: [PATCH 095/212] bpo-36722: Add What's New entry for debug ABI (GH-12957) --- Doc/whatsnew/3.8.rst | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 4cb9c4f0f20e94..444625040afb2e 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -98,6 +98,30 @@ subdirectories). (Contributed by Carl Meyer in :issue:`33499`.) +Debug build uses the same ABI as release build +----------------------------------------------- + +Python now uses the same ABI when built in release and in debug mode. On Unix, +when Python is build in debug mode, it is now possible to load C extensions +built in release mode and C extensions built using the stable ABI. + +Release build and debug build are now ABI compatible: the ``Py_DEBUG`` define +no longer implies the ``Py_TRACE_REFS`` define which introduces the only ABI +incompatibility. A new ``./configure --with-trace-refs`` build option is now +required to get ``Py_TRACE_REFS`` define which adds :func:`sys.getobjects` +function and :envvar:`PYTHONDUMPREFS` environment variable. +(Contributed by Victor Stinner in :issue:`36465`.) + +On Unix, C extensions are no longer linked to libpython. It is now possible to +load a C extension built using a shared library Python +with a statically linked Python. +(Contributed by Victor Stinner in :issue:`21536`.) + +On Unix, when Python is built in debug mode, import now also looks for C +extensions compiled in release mode and for C extensions compiled with the +stable ABI. +(Contributed by Victor Stinner in :issue:`36722`.) + Other Language Changes ====================== From 6d13e5b35ba7165db3f38fccdd6e1e5283f96a74 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Apr 2019 18:56:19 +0200 Subject: [PATCH 096/212] bpo-36722: Don't define ALT_SOABI for Py_TRACE_REFS build (GH-12973) Py_TRACE_REFS ABI is incompatible with release and debug (Py_DEBUG) ABI. --- Include/pyport.h | 14 ++++++++++---- configure | 3 ++- configure.ac | 3 ++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Include/pyport.h b/Include/pyport.h index acbae5bafeb512..568ab8f757d217 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -797,9 +797,9 @@ extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler; #endif /* Py_BUILD_CORE */ #ifdef __ANDROID__ -/* The Android langinfo.h header is not used. */ -#undef HAVE_LANGINFO_H -#undef CODESET + /* The Android langinfo.h header is not used. */ +# undef HAVE_LANGINFO_H +# undef CODESET #endif /* Maximum value of the Windows DWORD type */ @@ -810,7 +810,13 @@ extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler; * for compatibility. */ #ifndef WITH_THREAD -#define WITH_THREAD +# define WITH_THREAD +#endif + +/* Check that ALT_SOABI is consistent with Py_TRACE_REFS: + ./configure --with-trace-refs should must be used to define Py_TRACE_REFS */ +#if defined(ALT_SOABI) && defined(Py_TRACE_REFS) +# error "Py_TRACE_REFS ABI is not compatible with release and debug ABI" #endif #endif /* Py_PYPORT_H */ diff --git a/configure b/configure index b2775cf04000fd..7f26fab81fe5dd 100755 --- a/configure +++ b/configure @@ -15128,7 +15128,8 @@ SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${PLATFORM_TRIPLET:+-$PLATFO { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SOABI" >&5 $as_echo "$SOABI" >&6; } -if test "$Py_DEBUG" = 'true'; then +# Release and debug (Py_DEBUG) ABI are compatible, but not Py_TRACE_REFS ABI +if test "$Py_DEBUG" = 'true' -a "$with_trace_refs" != "yes"; then # Similar to SOABI but remove "d" flag from ABIFLAGS ALT_SOABI='cpython-'`echo $VERSION | tr -d .``echo $ABIFLAGS | tr -d d`${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} diff --git a/configure.ac b/configure.ac index 312758788e4d7a..157e9bf4067943 100644 --- a/configure.ac +++ b/configure.ac @@ -4627,7 +4627,8 @@ AC_MSG_CHECKING(SOABI) SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} AC_MSG_RESULT($SOABI) -if test "$Py_DEBUG" = 'true'; then +# Release and debug (Py_DEBUG) ABI are compatible, but not Py_TRACE_REFS ABI +if test "$Py_DEBUG" = 'true' -a "$with_trace_refs" != "yes"; then # Similar to SOABI but remove "d" flag from ABIFLAGS AC_SUBST(ALT_SOABI) ALT_SOABI='cpython-'`echo $VERSION | tr -d .``echo $ABIFLAGS | tr -d d`${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} From 55d035113dfb1bd90495c8571758f504ae8d4802 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Fri, 26 Apr 2019 23:22:36 -0400 Subject: [PATCH 097/212] Syntax highlight IDLE html doc code example. (GH-12981) The new markup is currently ignored by IDLE's tk doc display. --- Doc/library/idle.rst | 6 ++---- Lib/idlelib/help.html | 48 +++++++++++++++++++++---------------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index 11e137bf1092ed..ad449112832671 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -724,11 +724,9 @@ to begin after the next tab stop. (They occur every 8 'characters'). Newline characters cause following text to appear on a new line. Other control characters are ignored or displayed as a space, box, or something else, depending on the operating system and font. (Moving the text cursor through -such output with arrow keys may exhibit some surprising spacing behavior.) +such output with arrow keys may exhibit some surprising spacing behavior.) :: -.. code-block:: none - - >>> s = 'a\tb\a<\x02><\r>\bc\nd' + >>> s = 'a\tb\a<\x02><\r>\bc\nd' # Enter 22 chars. >>> len(s) 14 >>> s # Display repr(s) diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index b654ab7f2c5f86..7e743e6d8137b5 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -6,7 +6,7 @@ - IDLE — Python 3.8.0a1 documentation + IDLE — Python 3.8.0a3 documentation @@ -19,7 +19,7 @@ @@ -72,7 +72,7 @@

Navigation

  • - 3.8.0a1 Documentation » + 3.8.0a3 Documentation »
  • @@ -372,8 +372,8 @@

    Help menu (Shell and Editor)
    Squeeze
    If the cursor is over an output line, squeeze all the output between @@ -673,24 +673,22 @@

    User output in Shell -

    A Tk Text widget, and hence IDLE’s Shell, displays characters (codepoints) -in the the BMP (Basic Multilingual Plane) subset of Unicode. -Which characters are displayed with a proper glyph and which with a -replacement box depends on the operating system and installed fonts. -Tab characters cause the following text to begin after -the next tab stop. (They occur every 8 ‘characters’). -Newline characters cause following text to appear on a new line. -Other control characters are ignored or displayed as a space, box, or -something else, depending on the operating system and font. -(Moving the text cursor through such output with arrow keys may exhibit -some surprising spacing behavior.)

    -
    >>> s = 'a\tb\a<\x02><\r>\bc\nd'
    ->>> len(s)
    -14
    ->>> s  # Display repr(s)
    -'a\tb\x07<\x02><\r>\x08c\nd'
    ->>> print(s, end='')  # Display s as is.
    -# Result varies by OS and font.  Try it.
    +

    A Tk Text widget, and hence IDLE’s Shell, displays characters (codepoints) in +the BMP (Basic Multilingual Plane) subset of Unicode. Which characters are +displayed with a proper glyph and which with a replacement box depends on the +operating system and installed fonts. Tab characters cause the following text +to begin after the next tab stop. (They occur every 8 ‘characters’). Newline +characters cause following text to appear on a new line. Other control +characters are ignored or displayed as a space, box, or something else, +depending on the operating system and font. (Moving the text cursor through +such output with arrow keys may exhibit some surprising spacing behavior.)

    +
    >>> s = 'a\tb\a<\x02><\r>\bc\nd'  # Enter 22 chars.
    +>>> len(s)
    +14
    +>>> s  # Display repr(s)
    +'a\tb\x07<\x02><\r>\x08c\nd'
    +>>> print(s, end='')  # Display s as is.
    +# Result varies by OS and font.  Try it.
     

    The repr function is used for interactive echo of expression @@ -912,7 +910,7 @@

    Navigation

  • - 3.8.0a1 Documentation » + 3.8.0a3 Documentation »
  • @@ -943,7 +941,7 @@

    Navigation



    - Last updated on Feb 23, 2019. + Last updated on Apr 26, 2019. Found a bug?
    From 5c403b203510549a3f89d138d3265c5cc0cc12af Mon Sep 17 00:00:00 2001 From: Paul Ganssle Date: Sat, 27 Apr 2019 14:14:35 -0400 Subject: [PATCH 098/212] bpo-36722: Style and grammar edits for ABI news entries (GH-12979) --- Doc/whatsnew/3.8.rst | 25 ++++++++++--------- .../2019-04-09-18-19-43.bpo-36465.-w6vx6.rst | 11 ++++---- .../2019-04-25-01-51-52.bpo-21536.ACQkiC.rst | 8 +++--- Misc/SpecialBuilds.txt | 2 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 444625040afb2e..8d94a9ff544186 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -101,20 +101,21 @@ subdirectories). Debug build uses the same ABI as release build ----------------------------------------------- -Python now uses the same ABI when built in release and in debug mode. On Unix, -when Python is build in debug mode, it is now possible to load C extensions -built in release mode and C extensions built using the stable ABI. - -Release build and debug build are now ABI compatible: the ``Py_DEBUG`` define -no longer implies the ``Py_TRACE_REFS`` define which introduces the only ABI -incompatibility. A new ``./configure --with-trace-refs`` build option is now -required to get ``Py_TRACE_REFS`` define which adds :func:`sys.getobjects` -function and :envvar:`PYTHONDUMPREFS` environment variable. +Python now uses the same ABI whether it built in release or debug mode. On +Unix, when Python is built in debug mode, it is now possible to load C +extensions built in release mode and C extensions built using the stable ABI. + +Release builds and debug builds are now ABI compatible: defining the +``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro, which +introduces the only ABI incompatibility. The ``Py_TRACE_REFS`` macro, which +adds the :func:`sys.getobjects` function and the :envvar:`PYTHONDUMPREFS` +environment variable, can be set using the new ``./configure --with-trace-refs`` +build option. (Contributed by Victor Stinner in :issue:`36465`.) -On Unix, C extensions are no longer linked to libpython. It is now possible to -load a C extension built using a shared library Python -with a statically linked Python. +On Unix, C extensions are no longer linked to libpython. It is now possible +for a statically linked Python to load a C extension built using a shared +library Python. (Contributed by Victor Stinner in :issue:`21536`.) On Unix, when Python is built in debug mode, import now also looks for C diff --git a/Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst b/Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst index 52de1ef44830be..8969d3c4df1872 100644 --- a/Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst +++ b/Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst @@ -1,5 +1,6 @@ -Release build and debug build are now ABI compatible: the ``Py_DEBUG`` define -no longer implies ``Py_TRACE_REFS`` define which introduces the only ABI -incompatibility. A new ``./configure --with-trace-refs`` build option is now -required to get ``Py_TRACE_REFS`` define which adds :func:`sys.getobjects` -function and ``PYTHONDUMPREFS`` environment variable. +Release builds and debug builds are now ABI compatible: defining the +``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro, which +introduces the only ABI incompatibility. The ``Py_TRACE_REFS`` macro, which +adds the :func:`sys.getobjects` function and the :envvar:`PYTHONDUMPREFS` +environment variable, can be set using the new ``./configure --with-trace-refs`` +build option. diff --git a/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst b/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst index 5e1e717b1ea885..8cfad76ab172f9 100644 --- a/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst +++ b/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst @@ -1,12 +1,12 @@ On Unix, C extensions are no longer linked to libpython. -It is now possible to load a C extension built using a shared library Python -with a statically linked Python. +It is now possible for a statically linked Python to load a C extension built +using a shared library Python. When Python is embedded, ``libpython`` must not be loaded with ``RTLD_LOCAL``, but ``RTLD_GLOBAL`` instead. Previously, using ``RTLD_LOCAL``, it was already -not possible to load C extensions which were not linked to ``libpython``, like -C extensions of the standard library built by the ``*shared*`` section of +not possible to load C extensions which were not linked to ``libpython``, such +as C extensions of the standard library built by the ``*shared*`` section of ``Modules/Setup``. distutils, python-config and python-config.py have been modified. diff --git a/Misc/SpecialBuilds.txt b/Misc/SpecialBuilds.txt index 193de57b0850bd..d1a032165f8520 100644 --- a/Misc/SpecialBuilds.txt +++ b/Misc/SpecialBuilds.txt @@ -1,5 +1,5 @@ This file describes some special Python build types enabled via compile-time -preprocessor defines. +preprocessor directives. IMPORTANT: if you want to build a debug-enabled Python, it is recommended that you use ``./configure --with-pydebug``, rather than the options listed here. From 4d8c8c0ad6163c24136d3419eb04f310b31f7e64 Mon Sep 17 00:00:00 2001 From: Paul Ganssle Date: Sat, 27 Apr 2019 15:39:40 -0400 Subject: [PATCH 099/212] bpo-36025: Fix PyDate_FromTimestamp API (GH-11922) In the process of converting the date.fromtimestamp function to use argument clinic in GH-8535, the C API for PyDate_FromTimestamp was inadvertently changed to expect a timestamp object rather than an argument tuple. This PR fixes this backwards-incompatible change by adding a new wrapper function for the C API function that unwraps the argument tuple and passes it to the underlying function. This PR also adds tests for both PyDate_FromTimestamp and PyDateTime_FromTimestamp to prevent any further regressions. --- Lib/test/datetimetester.py | 35 ++++++++++ .../2019-02-19-08-23-42.bpo-36025.tnwylQ.rst | 5 ++ Modules/_datetimemodule.c | 19 ++++- Modules/_testcapimodule.c | 69 ++++++++++++++++++- 4 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2019-02-19-08-23-42.bpo-36025.tnwylQ.rst diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 715f0ea6b40d23..617bf9a25587dc 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -5942,6 +5942,41 @@ class TZInfoSubclass(tzinfo): with self.subTest(arg=arg, exact=exact): self.assertFalse(is_tzinfo(arg, exact)) + def test_date_from_timestamp(self): + ts = datetime(1995, 4, 12).timestamp() + + for macro in [0, 1]: + with self.subTest(macro=macro): + d = _testcapi.get_date_fromtimestamp(int(ts), macro) + + self.assertEqual(d, date(1995, 4, 12)) + + def test_datetime_from_timestamp(self): + ts0 = datetime(1995, 4, 12).timestamp() + ts1 = datetime(1995, 4, 12, 12, 30).timestamp() + + cases = [ + ((1995, 4, 12), None, False), + ((1995, 4, 12), None, True), + ((1995, 4, 12), timezone(timedelta(hours=1)), True), + ((1995, 4, 12, 14, 30), None, False), + ((1995, 4, 12, 14, 30), None, True), + ((1995, 4, 12, 14, 30), timezone(timedelta(hours=1)), True), + ] + + from_timestamp = _testcapi.get_datetime_fromtimestamp + for case in cases: + for macro in [0, 1]: + with self.subTest(case=case, macro=macro): + dtup, tzinfo, usetz = case + dt_orig = datetime(*dtup, tzinfo=tzinfo) + ts = int(dt_orig.timestamp()) + + dt_rt = from_timestamp(ts, tzinfo, usetz, macro) + + self.assertEqual(dt_orig, dt_rt) + + def load_tests(loader, standard_tests, pattern): standard_tests.addTest(ZoneInfoCompleteTest()) return standard_tests diff --git a/Misc/NEWS.d/next/C API/2019-02-19-08-23-42.bpo-36025.tnwylQ.rst b/Misc/NEWS.d/next/C API/2019-02-19-08-23-42.bpo-36025.tnwylQ.rst new file mode 100644 index 00000000000000..b00a33d109c255 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-02-19-08-23-42.bpo-36025.tnwylQ.rst @@ -0,0 +1,5 @@ +Fixed an accidental change to the datetime C API where the arguments to the +:c:func:`PyDate_FromTimestamp` function were incorrectly interpreted as a +single timestamp rather than an arguments tuple, which causes existing code to +start raising :exc:`TypeError`. The backwards-incompatible change was only +present in alpha releases of Python 3.8. Patch by Paul Ganssle. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index c1557b5e6f491d..b3954c98ee7df3 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -2921,6 +2921,23 @@ datetime_date_fromtimestamp(PyTypeObject *type, PyObject *timestamp) return date_fromtimestamp((PyObject *) type, timestamp); } +/* bpo-36025: This is a wrapper for API compatibility with the public C API, + * which expects a function that takes an *args tuple, whereas the argument + * clinic generates code that takes METH_O. + */ +static PyObject * +datetime_date_fromtimestamp_capi(PyObject *cls, PyObject *args) +{ + PyObject *timestamp; + PyObject *result = NULL; + + if (PyArg_UnpackTuple(args, "fromtimestamp", 1, 1, ×tamp)) { + result = date_fromtimestamp(cls, timestamp); + } + + return result; +} + /* Return new date from proleptic Gregorian ordinal. Raises ValueError if * the ordinal is out of range. */ @@ -6275,7 +6292,7 @@ static PyDateTime_CAPI CAPI = { new_delta_ex, new_timezone, datetime_fromtimestamp, - date_fromtimestamp, + datetime_date_fromtimestamp_capi, new_datetime_ex2, new_time_ex2 }; diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 6f4eb53d7e9239..c52e34996385de 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2340,6 +2340,71 @@ get_timezone_utc_capi(PyObject* self, PyObject *args) { } } +static PyObject * +get_date_fromtimestamp(PyObject* self, PyObject *args) +{ + PyObject *tsargs = NULL, *ts = NULL, *rv = NULL; + int macro = 0; + + if (!PyArg_ParseTuple(args, "O|p", &ts, ¯o)) { + return NULL; + } + + // Construct the argument tuple + if ((tsargs = PyTuple_Pack(1, ts)) == NULL) { + return NULL; + } + + // Pass along to the API function + if (macro) { + rv = PyDate_FromTimestamp(tsargs); + } + else { + rv = PyDateTimeAPI->Date_FromTimestamp( + (PyObject *)PyDateTimeAPI->DateType, tsargs + ); + } + + Py_DECREF(tsargs); + return rv; +} + +static PyObject * +get_datetime_fromtimestamp(PyObject* self, PyObject *args) +{ + int macro = 0; + int usetz = 0; + PyObject *tsargs = NULL, *ts = NULL, *tzinfo = Py_None, *rv = NULL; + if (!PyArg_ParseTuple(args, "OO|pp", &ts, &tzinfo, &usetz, ¯o)) { + return NULL; + } + + // Construct the argument tuple + if (usetz) { + tsargs = PyTuple_Pack(2, ts, tzinfo); + } + else { + tsargs = PyTuple_Pack(1, ts); + } + + if (tsargs == NULL) { + return NULL; + } + + // Pass along to the API function + if (macro) { + rv = PyDateTime_FromTimestamp(tsargs); + } + else { + rv = PyDateTimeAPI->DateTime_FromTimestamp( + (PyObject *)PyDateTimeAPI->DateTimeType, tsargs, NULL + ); + } + + Py_DECREF(tsargs); + return rv; +} + /* test_thread_state spawns a thread of its own, and that thread releases * `thread_done` when it's finished. The driver code has to know when the @@ -4769,7 +4834,9 @@ static PyMethodDef TestMethods[] = { {"datetime_check_tzinfo", datetime_check_tzinfo, METH_VARARGS}, {"make_timezones_capi", make_timezones_capi, METH_NOARGS}, {"get_timezones_offset_zero", get_timezones_offset_zero, METH_NOARGS}, - {"get_timezone_utc_capi", get_timezone_utc_capi, METH_VARARGS}, + {"get_timezone_utc_capi", get_timezone_utc_capi, METH_VARARGS}, + {"get_date_fromtimestamp", get_date_fromtimestamp, METH_VARARGS}, + {"get_datetime_fromtimestamp", get_datetime_fromtimestamp, METH_VARARGS}, {"test_list_api", test_list_api, METH_NOARGS}, {"test_dict_iteration", test_dict_iteration, METH_NOARGS}, {"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS}, From 21a9ba1992775b5a833da28bfa0a9f028d1b6761 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sat, 27 Apr 2019 22:40:45 +0300 Subject: [PATCH 100/212] bpo-2091: Fix typo in exception message (GH-12987) --- Modules/_io/_iomodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 965c4846bdb8b4..d482142d080404 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -324,7 +324,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, if (universal) { if (creating || writing || appending || updating) { PyErr_SetString(PyExc_ValueError, - "mode U cannot be combined with x', 'w', 'a', or '+'"); + "mode U cannot be combined with 'x', 'w', 'a', or '+'"); goto error; } if (PyErr_WarnEx(PyExc_DeprecationWarning, From 50fed0b64faa3053300008ef5607b570fe209de6 Mon Sep 17 00:00:00 2001 From: "Gordon P. Hemsley" Date: Sun, 28 Apr 2019 00:41:43 -0400 Subject: [PATCH 101/212] bpo-32424: Improve test coverage for xml.etree.ElementTree (GH-12891) * Fix typo in test_cyclic_gc subtest * Improve test coverage for xml.etree.ElementTree --- Lib/test/test_xml_etree.py | 87 ++++++++++++++++++- Misc/ACKS | 1 + .../2019-04-21-17-53-50.bpo-32424.Q4rBmn.rst | 2 + .../2019-04-21-17-55-18.bpo-32424.yDy49h.rst | 1 + 4 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-04-21-17-53-50.bpo-32424.Q4rBmn.rst create mode 100644 Misc/NEWS.d/next/Tests/2019-04-21-17-55-18.bpo-32424.yDy49h.rst diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 14ce32af802624..e0d2cb7b995231 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -9,6 +9,7 @@ import functools import html import io +import itertools import locale import operator import pickle @@ -1929,6 +1930,88 @@ def test_expat224_utf8_bug_file(self): class BasicElementTest(ElementTestCase, unittest.TestCase): + + def test___init__(self): + tag = "foo" + attrib = { "zix": "wyp" } + + element_foo = ET.Element(tag, attrib) + + # traits of an element + self.assertIsInstance(element_foo, ET.Element) + self.assertIn("tag", dir(element_foo)) + self.assertIn("attrib", dir(element_foo)) + self.assertIn("text", dir(element_foo)) + self.assertIn("tail", dir(element_foo)) + + # string attributes have expected values + self.assertEqual(element_foo.tag, tag) + self.assertIsNone(element_foo.text) + self.assertIsNone(element_foo.tail) + + # attrib is a copy + self.assertIsNot(element_foo.attrib, attrib) + self.assertEqual(element_foo.attrib, attrib) + + # attrib isn't linked + attrib["bar"] = "baz" + self.assertIsNot(element_foo.attrib, attrib) + self.assertNotEqual(element_foo.attrib, attrib) + + def test___copy__(self): + element_foo = ET.Element("foo", { "zix": "wyp" }) + element_foo.append(ET.Element("bar", { "baz": "qix" })) + + element_foo2 = copy.copy(element_foo) + + # elements are not the same + self.assertIsNot(element_foo2, element_foo) + + # string attributes are equal + self.assertEqual(element_foo2.tag, element_foo.tag) + self.assertEqual(element_foo2.text, element_foo.text) + self.assertEqual(element_foo2.tail, element_foo.tail) + + # number of children is the same + self.assertEqual(len(element_foo2), len(element_foo)) + + # children are the same + for (child1, child2) in itertools.zip_longest(element_foo, element_foo2): + self.assertIs(child1, child2) + + # attrib is a copy + self.assertEqual(element_foo2.attrib, element_foo.attrib) + + def test___deepcopy__(self): + element_foo = ET.Element("foo", { "zix": "wyp" }) + element_foo.append(ET.Element("bar", { "baz": "qix" })) + + element_foo2 = copy.deepcopy(element_foo) + + # elements are not the same + self.assertIsNot(element_foo2, element_foo) + + # string attributes are equal + self.assertEqual(element_foo2.tag, element_foo.tag) + self.assertEqual(element_foo2.text, element_foo.text) + self.assertEqual(element_foo2.tail, element_foo.tail) + + # number of children is the same + self.assertEqual(len(element_foo2), len(element_foo)) + + # children are not the same + for (child1, child2) in itertools.zip_longest(element_foo, element_foo2): + self.assertIsNot(child1, child2) + + # attrib is a copy + self.assertIsNot(element_foo2.attrib, element_foo.attrib) + self.assertEqual(element_foo2.attrib, element_foo.attrib) + + # attrib isn't linked + element_foo.attrib["bar"] = "baz" + self.assertIsNot(element_foo2.attrib, element_foo.attrib) + self.assertNotEqual(element_foo2.attrib, element_foo.attrib) + def test_augmentation_type_errors(self): e = ET.Element('joe') self.assertRaises(TypeError, e.append, 'b') @@ -1984,9 +2067,9 @@ class Dummy: e1 = ET.Element('e1') e2 = ET.Element('e2') e3 = ET.Element('e3') - e1.append(e2) - e2.append(e2) e3.append(e1) + e2.append(e3) + e1.append(e2) wref = weakref.ref(e1) del e1, e2, e3 gc_collect() diff --git a/Misc/ACKS b/Misc/ACKS index 393ea205ac1d76..300e788940787e 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -647,6 +647,7 @@ Christian Heimes Thomas Heller Malte Helmert Lance Finn Helsten +Gordon P. Hemsley Jonathan Hendry Nathan Henrie Michael Henry diff --git a/Misc/NEWS.d/next/Tests/2019-04-21-17-53-50.bpo-32424.Q4rBmn.rst b/Misc/NEWS.d/next/Tests/2019-04-21-17-53-50.bpo-32424.Q4rBmn.rst new file mode 100644 index 00000000000000..f057d7e7730ecf --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-04-21-17-53-50.bpo-32424.Q4rBmn.rst @@ -0,0 +1,2 @@ +Fix typo in test_cyclic_gc() test for xml.etree.ElementTree. Patch by Gordon +P. Hemsley. diff --git a/Misc/NEWS.d/next/Tests/2019-04-21-17-55-18.bpo-32424.yDy49h.rst b/Misc/NEWS.d/next/Tests/2019-04-21-17-55-18.bpo-32424.yDy49h.rst new file mode 100644 index 00000000000000..bb0839f7a31829 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-04-21-17-55-18.bpo-32424.yDy49h.rst @@ -0,0 +1 @@ +Improve test coverage for xml.etree.ElementTree. Patch by Gordon P. Hemsley. From da63b321f63b697f75e7ab2f88f55d907f56c187 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sun, 28 Apr 2019 00:22:36 -0700 Subject: [PATCH 102/212] bpo-36715: Add usage note for dict.fromkeys() (GH-12974) --- Doc/library/stdtypes.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index aeecdbb24a57b1..0a6bb149075f47 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4254,7 +4254,10 @@ pairs within braces, for example: ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098: Create a new dictionary with keys from *iterable* and values set to *value*. :meth:`fromkeys` is a class method that returns a new dictionary. *value* - defaults to ``None``. + defaults to ``None``. All of the values refer to just a single instance, + so it generally doesn't make sense for *value* to be a mutable object + such as an empty list. To get distinct values, use a :ref:`dict + comprehension ` instead. .. method:: get(key[, default]) From e0dcb85b7d64153d1741698c04a6736c9669603a Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Sun, 28 Apr 2019 06:58:52 -0600 Subject: [PATCH 103/212] bpo-36745: Fix a possible reference leak in PyObject_SetAttr() (GH-12993) https://bugs.python.org/issue36745 --- Objects/object.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Objects/object.c b/Objects/object.c index e7ec7aec490f8b..589bf365e870fd 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1044,8 +1044,10 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value) } if (tp->tp_setattr != NULL) { const char *name_str = PyUnicode_AsUTF8(name); - if (name_str == NULL) + if (name_str == NULL) { + Py_DECREF(name); return -1; + } err = (*tp->tp_setattr)(v, (char *)name_str, value); Py_DECREF(name); return err; From 86f0c8215c2fdaeef58d185ff00b854a45971f84 Mon Sep 17 00:00:00 2001 From: Emmanuel Arias Date: Sun, 28 Apr 2019 23:24:24 -0300 Subject: [PATCH 104/212] bpo-36729: Delete unused text variable on tests. (GH-12959) --- Lib/test/test_pydoc.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index c2bd9f3012c1ae..67c6c5d42d48b4 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -1250,7 +1250,6 @@ def __get__(self, obj, cls): class X: attr = Descr() - text = pydoc.plain(pydoc.render_doc(X.attr)) self.assertEqual(self._get_summary_lines(X.attr), """\ .Descr object>""") @@ -1276,17 +1275,14 @@ def __set__(self, obj, cls): class X: attr = Descr() - text = pydoc.plain(pydoc.render_doc(X.attr)) self.assertEqual(self._get_summary_lines(X.attr), "") X.attr.__doc__ = 'Custom descriptor' - text = pydoc.plain(pydoc.render_doc(X.attr)) self.assertEqual(self._get_summary_lines(X.attr), """\ Custom descriptor """) X.attr.__name__ = 'foo' - text = pydoc.plain(pydoc.render_doc(X.attr)) self.assertEqual(self._get_summary_lines(X.attr), """\ foo Custom descriptor From db81ba1393af40ba920a996651e2c11943c3663c Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sun, 28 Apr 2019 21:31:55 -0700 Subject: [PATCH 105/212] bpo-36546: More tests: type preservation and equal inputs (#13000) --- Lib/test/test_statistics.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index c988d7fd8be7b7..0a967055f0fe6c 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -2153,12 +2153,11 @@ def test_specific_cases(self): ]: self.assertEqual(expected, quantiles(data, n=n)) self.assertEqual(len(quantiles(data, n=n)), n - 1) - self.assertEqual(list(map(float, expected)), - quantiles(map(Decimal, data), n=n)) - self.assertEqual(list(map(Decimal, expected)), - quantiles(map(Decimal, data), n=n)) - self.assertEqual(list(map(Fraction, expected)), - quantiles(map(Fraction, data), n=n)) + # Preserve datatype when possible + for datatype in (float, Decimal, Fraction): + result = quantiles(map(datatype, data), n=n) + self.assertTrue(all(type(x) == datatype) for x in result) + self.assertEqual(result, list(map(datatype, expected))) # Invariant under tranlation and scaling def f(x): return 3.5 * x - 1234.675 @@ -2199,12 +2198,11 @@ def test_specific_cases_inclusive(self): ]: self.assertEqual(expected, quantiles(data, n=n, method="inclusive")) self.assertEqual(len(quantiles(data, n=n, method="inclusive")), n - 1) - self.assertEqual(list(map(float, expected)), - quantiles(map(Decimal, data), n=n, method="inclusive")) - self.assertEqual(list(map(Decimal, expected)), - quantiles(map(Decimal, data), n=n, method="inclusive")) - self.assertEqual(list(map(Fraction, expected)), - quantiles(map(Fraction, data), n=n, method="inclusive")) + # Preserve datatype when possible + for datatype in (float, Decimal, Fraction): + result = quantiles(map(datatype, data), n=n, method="inclusive") + self.assertTrue(all(type(x) == datatype) for x in result) + self.assertEqual(result, list(map(datatype, expected))) # Invariant under tranlation and scaling def f(x): return 3.5 * x - 1234.675 @@ -2222,6 +2220,14 @@ def f(x): self.assertTrue(all(math.isclose(e, a, abs_tol=0.0001) for e, a in zip(expected, actual))) + def test_equal_inputs(self): + quantiles = statistics.quantiles + for n in range(2, 10): + data = [10.0] * n + self.assertEqual(quantiles(data), [10.0, 10.0, 10.0]) + self.assertEqual(quantiles(data, method='inclusive'), + [10.0, 10.0, 10.0]) + def test_equal_sized_groups(self): quantiles = statistics.quantiles total = 10_000 From b021ba50284cdfc200b5d18dc4dea80218fcbe91 Mon Sep 17 00:00:00 2001 From: Andrey <45011689+heckad@users.noreply.github.com> Date: Mon, 29 Apr 2019 14:33:26 +1000 Subject: [PATCH 106/212] Fix typo in 'tandem' word (GH-12998) (GH-12998) --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/ceval.c b/Python/ceval.c index 342dc10af6a629..4e165c3311d4a6 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3207,7 +3207,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) } case TARGET(LOAD_METHOD): { - /* Designed to work in tamdem with CALL_METHOD. */ + /* Designed to work in tandem with CALL_METHOD. */ PyObject *name = GETITEM(names, oparg); PyObject *obj = TOP(); PyObject *meth = NULL; From 254b309c801f82509597e3d7d4be56885ef94c11 Mon Sep 17 00:00:00 2001 From: xdegaye Date: Mon, 29 Apr 2019 09:27:40 +0200 Subject: [PATCH 107/212] bpo-21536: On Android, C extensions are linked to libpython (GH-12989) --- Doc/distutils/apiref.rst | 3 ++- Doc/whatsnew/3.8.rst | 12 ++++++------ Lib/distutils/command/build_ext.py | 15 +++++++++++++++ Makefile.pre.in | 1 + .../2019-04-25-01-51-52.bpo-21536.ACQkiC.rst | 2 +- Misc/python-config.in | 5 ++++- Misc/python-config.sh.in | 2 +- configure | 9 +++++++++ configure.ac | 8 ++++++++ 9 files changed, 47 insertions(+), 10 deletions(-) diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index c3cdfc8a0a8ec6..1facc0408d5b0f 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -279,7 +279,8 @@ the full reference. .. versionchanged:: 3.8 - On Unix, C extensions are no longer linked to libpython. + On Unix, C extensions are no longer linked to libpython except on + Android. .. class:: Distribution diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 8d94a9ff544186..8df7538f1c435e 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -883,12 +883,12 @@ Changes in the Python API Changes in the C API -------------------- -* On Unix, C extensions are no longer linked to libpython. When Python is - embedded, ``libpython`` must not be loaded with ``RTLD_LOCAL``, but - ``RTLD_GLOBAL`` instead. Previously, using ``RTLD_LOCAL``, it was already not - possible to load C extensions which were not linked to ``libpython``, like C - extensions of the standard library built by the ``*shared*`` section of - ``Modules/Setup``. +* On Unix, C extensions are no longer linked to libpython except on + Android. When Python is embedded, ``libpython`` must not be loaded with + ``RTLD_LOCAL``, but ``RTLD_GLOBAL`` instead. Previously, using + ``RTLD_LOCAL``, it was already not possible to load C extensions which were + not linked to ``libpython``, like C extensions of the standard library built + by the ``*shared*`` section of ``Modules/Setup``. * Use of ``#`` variants of formats in parsing or building value (e.g. :c:func:`PyArg_ParseTuple`, :c:func:`Py_BuildValue`, :c:func:`PyObject_CallFunction`, diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py index 1672d02acf1f7a..c3b9602461f93a 100644 --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py @@ -714,5 +714,20 @@ def get_libraries(self, ext): # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] + # On Android only the main executable and LD_PRELOADs are considered + # to be RTLD_GLOBAL, all the dependencies of the main executable + # remain RTLD_LOCAL and so the shared libraries must be linked with + # libpython when python is built with a shared python library (issue + # bpo-21536). + else: + from distutils.sysconfig import get_config_var + if get_config_var('Py_ENABLE_SHARED'): + # Either a native build on an Android device or the + # cross-compilation of Python. + if (hasattr(sys, 'getandroidapilevel') or + ('_PYTHON_HOST_PLATFORM' in os.environ and + get_config_var('ANDROID_API_LEVEL') != 0)): + ldversion = get_config_var('LDVERSION') + return ext.libraries + ['python' + ldversion] return ext.libraries diff --git a/Makefile.pre.in b/Makefile.pre.in index 89479ee7f1a36c..7f0d8d44b3d172 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -41,6 +41,7 @@ AR= @AR@ READELF= @READELF@ SOABI= @SOABI@ LDVERSION= @LDVERSION@ +LIBPYTHON= @LIBPYTHON@ GITVERSION= @GITVERSION@ GITTAG= @GITTAG@ GITBRANCH= @GITBRANCH@ diff --git a/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst b/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst index 8cfad76ab172f9..59efab83265f4b 100644 --- a/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst +++ b/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst @@ -1,4 +1,4 @@ -On Unix, C extensions are no longer linked to libpython. +On Unix, C extensions are no longer linked to libpython except on Android. It is now possible for a statically linked Python to load a C extension built using a shared library Python. diff --git a/Misc/python-config.in b/Misc/python-config.in index 31ad55822e55a2..1df30d261d8ebb 100644 --- a/Misc/python-config.in +++ b/Misc/python-config.in @@ -47,7 +47,10 @@ for opt in opt_flags: print(' '.join(flags)) elif opt in ('--libs', '--ldflags'): - libs = getvar('LIBS').split() + getvar('SYSLIBS').split() + libpython = getvar('LIBPYTHON') + libs = [libpython] if libpython else [] + libs.extend(getvar('LIBS').split() + getvar('SYSLIBS').split()) + # add the prefix/lib/pythonX.Y/config dir, but only if there is no # shared library in prefix/lib/. if opt == '--ldflags': diff --git a/Misc/python-config.sh.in b/Misc/python-config.sh.in index ac1a467678e44b..33991ef0c5d49a 100644 --- a/Misc/python-config.sh.in +++ b/Misc/python-config.sh.in @@ -41,7 +41,7 @@ LIBM="@LIBM@" LIBC="@LIBC@" SYSLIBS="$LIBM $LIBC" ABIFLAGS="@ABIFLAGS@" -LIBS="@LIBS@ $SYSLIBS" +LIBS="@LIBPYTHON@ @LIBS@ $SYSLIBS" BASECFLAGS="@BASECFLAGS@" LDLIBRARY="@LDLIBRARY@" OPT="@OPT@" diff --git a/configure b/configure index 7f26fab81fe5dd..8d9c73d1c386bd 100755 --- a/configure +++ b/configure @@ -631,6 +631,7 @@ SRCDIRS THREADHEADERS LIBPL PY_ENABLE_SHARED +LIBPYTHON EXT_SUFFIX ALT_SOABI SOABI @@ -15154,6 +15155,14 @@ LDVERSION='$(VERSION)$(ABIFLAGS)' { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LDVERSION" >&5 $as_echo "$LDVERSION" >&6; } +# On Android the shared libraries must be linked with libpython. + +if test -z "$ANDROID_API_LEVEL"; then + LIBPYTHON='' +else + LIBPYTHON="-lpython${VERSION}${ABIFLAGS}" +fi + if test x$PLATFORM_TRIPLET = x; then LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}" diff --git a/configure.ac b/configure.ac index 157e9bf4067943..7d2eff0d94c34f 100644 --- a/configure.ac +++ b/configure.ac @@ -4648,6 +4648,14 @@ AC_MSG_CHECKING(LDVERSION) LDVERSION='$(VERSION)$(ABIFLAGS)' AC_MSG_RESULT($LDVERSION) +# On Android the shared libraries must be linked with libpython. +AC_SUBST(LIBPYTHON) +if test -z "$ANDROID_API_LEVEL"; then + LIBPYTHON='' +else + LIBPYTHON="-lpython${VERSION}${ABIFLAGS}" +fi + dnl define LIBPL after ABIFLAGS and LDVERSION is defined. AC_SUBST(PY_ENABLE_SHARED) if test x$PLATFORM_TRIPLET = x; then From f781d202a2382731b43bade845a58d28a02e9ea1 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com> Date: Mon, 29 Apr 2019 04:38:45 -0400 Subject: [PATCH 108/212] bpo-36475: Finalize PyEval_AcquireLock() and PyEval_AcquireThread() properly (GH-12667) PyEval_AcquireLock() and PyEval_AcquireThread() now terminate the current thread if called while the interpreter is finalizing, making them consistent with PyEval_RestoreThread(), Py_END_ALLOW_THREADS, and PyGILState_Ensure(). --- Doc/c-api/init.rst | 24 ++++++++++++++++ Doc/whatsnew/3.8.rst | 7 +++++ .../2019-04-02-20-02-22.bpo-36475.CjRps3.rst | 4 +++ Python/ceval.c | 28 +++++++++++-------- 4 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-02-20-02-22.bpo-36475.CjRps3.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 7ef11228a33dcf..367c069a7ff4cd 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -1080,6 +1080,18 @@ All of the following functions must be called after :c:func:`Py_Initialize`. *tstate*, which should not be *NULL*. The lock must have been created earlier. If this thread already has the lock, deadlock ensues. + .. note:: + Calling this function from a thread when the runtime is finalizing + will terminate the thread, even if the thread was not created by Python. + You can use :c:func:`_Py_IsFinalizing` or :func:`sys.is_finalizing` to + check if the interpreter is in process of being finalized before calling + this function to avoid unwanted termination. + + .. versionchanged:: 3.8 + Updated to be consistent with :c:func:`PyEval_RestoreThread`, + :c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`, + and terminate the current thread if called while the interpreter is finalizing. + :c:func:`PyEval_RestoreThread` is a higher-level function which is always available (even when threads have not been initialized). @@ -1106,6 +1118,18 @@ All of the following functions must be called after :c:func:`Py_Initialize`. :c:func:`PyEval_RestoreThread` or :c:func:`PyEval_AcquireThread` instead. + .. note:: + Calling this function from a thread when the runtime is finalizing + will terminate the thread, even if the thread was not created by Python. + You can use :c:func:`_Py_IsFinalizing` or :func:`sys.is_finalizing` to + check if the interpreter is in process of being finalized before calling + this function to avoid unwanted termination. + + .. versionchanged:: 3.8 + Updated to be consistent with :c:func:`PyEval_RestoreThread`, + :c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`, + and terminate the current thread if called while the interpreter is finalizing. + .. c:function:: void PyEval_ReleaseLock() diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 8df7538f1c435e..90ff72f67ff434 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -758,6 +758,13 @@ Changes in Python behavior always use the ``sys.platform.startswith('aix')``. (Contributed by M. Felt in :issue:`36588`.) +* :c:func:`PyEval_AcquireLock` and :c:func:`PyEval_AcquireThread` now + terminate the current thread if called while the interpreter is + finalizing, making them consistent with :c:func:`PyEval_RestoreThread`, + :c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`. If this + behaviour is not desired, guard the call by checking :c:func:`_Py_IsFinalizing` + or :c:func:`sys.is_finalizing`. + Changes in the Python API ------------------------- diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-02-20-02-22.bpo-36475.CjRps3.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-02-20-02-22.bpo-36475.CjRps3.rst new file mode 100644 index 00000000000000..6f0975107fa281 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-04-02-20-02-22.bpo-36475.CjRps3.rst @@ -0,0 +1,4 @@ +:c:func:`PyEval_AcquireLock` and :c:func:`PyEval_AcquireThread` now +terminate the current thread if called while the interpreter is +finalizing, making them consistent with :c:func:`PyEval_RestoreThread`, +:c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`. \ No newline at end of file diff --git a/Python/ceval.c b/Python/ceval.c index 4e165c3311d4a6..ccd0427a142936 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -76,6 +76,7 @@ static PyObject * special_lookup(PyObject *, _Py_Identifier *); static int check_args_iterable(PyObject *func, PyObject *vararg); static void format_kwargs_error(PyObject *func, PyObject *kwargs); static void format_awaitable_error(PyTypeObject *, int); +static inline void exit_thread_if_finalizing(PyThreadState *); #define NAME_ERROR_MSG \ "name '%.200s' is not defined" @@ -203,6 +204,17 @@ _PyEval_FiniThreads(void) } } +static inline void +exit_thread_if_finalizing(PyThreadState *tstate) +{ + /* _Py_Finalizing is protected by the GIL */ + if (_Py_IsFinalizing() && !_Py_CURRENTLY_FINALIZING(tstate)) { + drop_gil(tstate); + PyThread_exit_thread(); + Py_UNREACHABLE(); + } +} + void PyEval_AcquireLock(void) { @@ -210,6 +222,7 @@ PyEval_AcquireLock(void) if (tstate == NULL) Py_FatalError("PyEval_AcquireLock: current thread state is NULL"); take_gil(tstate); + exit_thread_if_finalizing(tstate); } void @@ -230,6 +243,7 @@ PyEval_AcquireThread(PyThreadState *tstate) /* Check someone has called PyEval_InitThreads() to create the lock */ assert(gil_created()); take_gil(tstate); + exit_thread_if_finalizing(tstate); if (PyThreadState_Swap(tstate) != NULL) Py_FatalError( "PyEval_AcquireThread: non-NULL old thread state"); @@ -298,12 +312,7 @@ PyEval_RestoreThread(PyThreadState *tstate) int err = errno; take_gil(tstate); - /* _Py_Finalizing is protected by the GIL */ - if (_Py_IsFinalizing() && !_Py_CURRENTLY_FINALIZING(tstate)) { - drop_gil(tstate); - PyThread_exit_thread(); - Py_UNREACHABLE(); - } + exit_thread_if_finalizing(tstate); errno = err; PyThreadState_Swap(tstate); @@ -1083,12 +1092,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) take_gil(tstate); /* Check if we should make a quick exit. */ - if (_Py_IsFinalizing() && - !_Py_CURRENTLY_FINALIZING(tstate)) - { - drop_gil(tstate); - PyThread_exit_thread(); - } + exit_thread_if_finalizing(tstate); if (PyThreadState_Swap(tstate) != NULL) Py_FatalError("ceval: orphan tstate"); From 7a5a1cfe04892351bba8e8d7d21ae2262fa35b67 Mon Sep 17 00:00:00 2001 From: xdegaye Date: Mon, 29 Apr 2019 11:01:42 +0200 Subject: [PATCH 109/212] bpo-36747: Remove the stale scriptsinstall Makefile target (GH-13003) --- Makefile.pre.in | 8 -------- .../next/Build/2019-04-29-09-57-20.bpo-36747.1YEyu-.rst | 1 + 2 files changed, 1 insertion(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2019-04-29-09-57-20.bpo-36747.1YEyu-.rst diff --git a/Makefile.pre.in b/Makefile.pre.in index 7f0d8d44b3d172..619e3fb3645e23 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1653,14 +1653,6 @@ frameworkaltinstallunixtools: frameworkinstallextras: cd Mac && $(MAKE) installextras DESTDIR="$(DESTDIR)" -# This installs a few of the useful scripts in Tools/scripts -scriptsinstall: - SRCDIR=$(srcdir) $(RUNSHARED) \ - $(PYTHON_FOR_BUILD) $(srcdir)/Tools/scripts/setup.py install \ - --prefix=$(prefix) \ - --install-scripts=$(BINDIR) \ - --root=$(DESTDIR)/ - # Build the toplevel Makefile Makefile.pre: $(srcdir)/Makefile.pre.in config.status CONFIG_FILES=Makefile.pre CONFIG_HEADERS= $(SHELL) config.status diff --git a/Misc/NEWS.d/next/Build/2019-04-29-09-57-20.bpo-36747.1YEyu-.rst b/Misc/NEWS.d/next/Build/2019-04-29-09-57-20.bpo-36747.1YEyu-.rst new file mode 100644 index 00000000000000..dd5a00801a9313 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2019-04-29-09-57-20.bpo-36747.1YEyu-.rst @@ -0,0 +1 @@ +Remove the stale scriptsinstall Makefile target. From b36e5d627d4232a01850707eb78a5067f3fd77f4 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 29 Apr 2019 11:15:56 +0200 Subject: [PATCH 110/212] bpo-36356: Destroy the GIL at exit (GH-12453) * Add _PyEval_FiniThreads2(). _PyEval_FiniThreads() now only clears the pending lock, whereas _PyEval_FiniThreads2() destroys the GIL. * pymain_free() now calls _PyEval_FiniThreads2(). * Py_FinalizeEx() now calls _PyEval_FiniThreads(). --- Include/ceval.h | 3 --- Include/internal/pycore_ceval.h | 3 +++ Modules/main.c | 11 ++++++----- Python/ceval.c | 16 +++++++++++----- Python/pylifecycle.c | 11 ++++++----- 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/Include/ceval.h b/Include/ceval.h index 11283c0a570b7e..98e873d2c8b234 100644 --- a/Include/ceval.h +++ b/Include/ceval.h @@ -192,9 +192,6 @@ PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *); PyAPI_FUNC(int) PyEval_ThreadsInitialized(void); PyAPI_FUNC(void) PyEval_InitThreads(void); -#ifndef Py_LIMITED_API -PyAPI_FUNC(void) _PyEval_FiniThreads(void); -#endif /* !Py_LIMITED_API */ PyAPI_FUNC(void) PyEval_AcquireLock(void) Py_DEPRECATED(3.2); PyAPI_FUNC(void) PyEval_ReleaseLock(void) /* Py_DEPRECATED(3.2) */; PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate); diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 0bb19f1aa3b642..ae3d83239227f2 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -54,6 +54,9 @@ struct _ceval_runtime_state { PyAPI_FUNC(void) _PyEval_Initialize(struct _ceval_runtime_state *); +PyAPI_FUNC(void) _PyEval_FiniThreads(void); +PyAPI_FUNC(void) _PyEval_FiniThreads2(void); + #ifdef __cplusplus } #endif diff --git a/Modules/main.c b/Modules/main.c index 68f0b99c9fbbf4..f77bbd2f41c442 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1,6 +1,7 @@ /* Python interpreter main program */ #include "Python.h" +#include "pycore_ceval.h" /* _PyEval_FiniThreads2() */ #include "pycore_coreconfig.h" #include "pycore_pylifecycle.h" #include "pycore_pymem.h" @@ -525,15 +526,15 @@ pymain_run_python(int *exitcode) /* --- pymain_main() ---------------------------------------------- */ +/* Free global variables which cannot be freed in Py_Finalize(): + configuration options set before Py_Initialize() which should + remain valid after Py_Finalize(), since + Py_Initialize()-Py_Finalize() can be called multiple times. */ static void pymain_free(void) { _PyImport_Fini2(); - - /* Free global variables which cannot be freed in Py_Finalize(): - configuration options set before Py_Initialize() which should - remain valid after Py_Finalize(), since - Py_Initialize()-Py_Finalize() can be called multiple times. */ + _PyEval_FiniThreads2(); _PyPathConfig_ClearGlobal(); _Py_ClearStandardStreamEncoding(); _Py_ClearArgcArgv(); diff --git a/Python/ceval.c b/Python/ceval.c index ccd0427a142936..5480fbacaf4d74 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -188,8 +188,19 @@ PyEval_InitThreads(void) } } + void _PyEval_FiniThreads(void) +{ + if (_PyRuntime.ceval.pending.lock != NULL) { + PyThread_free_lock(_PyRuntime.ceval.pending.lock); + _PyRuntime.ceval.pending.lock = NULL; + } +} + + +void +_PyEval_FiniThreads2(void) { if (!gil_created()) { return; @@ -197,11 +208,6 @@ _PyEval_FiniThreads(void) destroy_gil(); assert(!gil_created()); - - if (_PyRuntime.ceval.pending.lock != NULL) { - PyThread_free_lock(_PyRuntime.ceval.pending.lock); - _PyRuntime.ceval.pending.lock = NULL; - } } static inline void diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index d93fe065558aa3..0836e18f9d1ce7 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -4,8 +4,9 @@ #include "Python-ast.h" #undef Yield /* undefine macro conflicting with */ -#include "pycore_coreconfig.h" +#include "pycore_ceval.h" /* _PyEval_FiniThreads() */ #include "pycore_context.h" +#include "pycore_coreconfig.h" #include "pycore_fileutils.h" #include "pycore_hamt.h" #include "pycore_pathconfig.h" @@ -555,12 +556,11 @@ pycore_create_interpreter(_PyRuntimeState *runtime, return _Py_INIT_ERR("can't make first thread"); (void) PyThreadState_Swap(tstate); - /* We can't call _PyEval_FiniThreads() in Py_FinalizeEx because - destroying the GIL might fail when it is being referenced from - another running thread (see issue #9901). + /* Destroying the GIL in Py_FinalizeEx might fail when it is being + referenced from another running thread (see bpo-9901). Instead we destroy the previously created GIL here, which ensures that we can call Py_Initialize / Py_FinalizeEx multiple times. */ - _PyEval_FiniThreads(); + _PyEval_FiniThreads2(); /* Auto-thread-state API */ _PyGILState_Init(runtime, interp, tstate); @@ -1357,6 +1357,7 @@ Py_FinalizeEx(void) call_ll_exitfuncs(runtime); + _PyEval_FiniThreads(); _PyRuntime_Finalize(); return status; } From 99fcc616d400cd31af0733c3f8cc93bcc1d32a44 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 29 Apr 2019 13:04:07 +0200 Subject: [PATCH 111/212] Revert "bpo-36356: Destroy the GIL at exit (GH-12453)" (GH613006) This reverts commit b36e5d627d4232a01850707eb78a5067f3fd77f4. --- Include/ceval.h | 3 +++ Include/internal/pycore_ceval.h | 3 --- Modules/main.c | 11 +++++------ Python/ceval.c | 16 +++++----------- Python/pylifecycle.c | 11 +++++------ 5 files changed, 18 insertions(+), 26 deletions(-) diff --git a/Include/ceval.h b/Include/ceval.h index 98e873d2c8b234..11283c0a570b7e 100644 --- a/Include/ceval.h +++ b/Include/ceval.h @@ -192,6 +192,9 @@ PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *); PyAPI_FUNC(int) PyEval_ThreadsInitialized(void); PyAPI_FUNC(void) PyEval_InitThreads(void); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyEval_FiniThreads(void); +#endif /* !Py_LIMITED_API */ PyAPI_FUNC(void) PyEval_AcquireLock(void) Py_DEPRECATED(3.2); PyAPI_FUNC(void) PyEval_ReleaseLock(void) /* Py_DEPRECATED(3.2) */; PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate); diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index ae3d83239227f2..0bb19f1aa3b642 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -54,9 +54,6 @@ struct _ceval_runtime_state { PyAPI_FUNC(void) _PyEval_Initialize(struct _ceval_runtime_state *); -PyAPI_FUNC(void) _PyEval_FiniThreads(void); -PyAPI_FUNC(void) _PyEval_FiniThreads2(void); - #ifdef __cplusplus } #endif diff --git a/Modules/main.c b/Modules/main.c index f77bbd2f41c442..68f0b99c9fbbf4 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1,7 +1,6 @@ /* Python interpreter main program */ #include "Python.h" -#include "pycore_ceval.h" /* _PyEval_FiniThreads2() */ #include "pycore_coreconfig.h" #include "pycore_pylifecycle.h" #include "pycore_pymem.h" @@ -526,15 +525,15 @@ pymain_run_python(int *exitcode) /* --- pymain_main() ---------------------------------------------- */ -/* Free global variables which cannot be freed in Py_Finalize(): - configuration options set before Py_Initialize() which should - remain valid after Py_Finalize(), since - Py_Initialize()-Py_Finalize() can be called multiple times. */ static void pymain_free(void) { _PyImport_Fini2(); - _PyEval_FiniThreads2(); + + /* Free global variables which cannot be freed in Py_Finalize(): + configuration options set before Py_Initialize() which should + remain valid after Py_Finalize(), since + Py_Initialize()-Py_Finalize() can be called multiple times. */ _PyPathConfig_ClearGlobal(); _Py_ClearStandardStreamEncoding(); _Py_ClearArgcArgv(); diff --git a/Python/ceval.c b/Python/ceval.c index 5480fbacaf4d74..ccd0427a142936 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -188,19 +188,8 @@ PyEval_InitThreads(void) } } - void _PyEval_FiniThreads(void) -{ - if (_PyRuntime.ceval.pending.lock != NULL) { - PyThread_free_lock(_PyRuntime.ceval.pending.lock); - _PyRuntime.ceval.pending.lock = NULL; - } -} - - -void -_PyEval_FiniThreads2(void) { if (!gil_created()) { return; @@ -208,6 +197,11 @@ _PyEval_FiniThreads2(void) destroy_gil(); assert(!gil_created()); + + if (_PyRuntime.ceval.pending.lock != NULL) { + PyThread_free_lock(_PyRuntime.ceval.pending.lock); + _PyRuntime.ceval.pending.lock = NULL; + } } static inline void diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 0836e18f9d1ce7..d93fe065558aa3 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -4,9 +4,8 @@ #include "Python-ast.h" #undef Yield /* undefine macro conflicting with */ -#include "pycore_ceval.h" /* _PyEval_FiniThreads() */ -#include "pycore_context.h" #include "pycore_coreconfig.h" +#include "pycore_context.h" #include "pycore_fileutils.h" #include "pycore_hamt.h" #include "pycore_pathconfig.h" @@ -556,11 +555,12 @@ pycore_create_interpreter(_PyRuntimeState *runtime, return _Py_INIT_ERR("can't make first thread"); (void) PyThreadState_Swap(tstate); - /* Destroying the GIL in Py_FinalizeEx might fail when it is being - referenced from another running thread (see bpo-9901). + /* We can't call _PyEval_FiniThreads() in Py_FinalizeEx because + destroying the GIL might fail when it is being referenced from + another running thread (see issue #9901). Instead we destroy the previously created GIL here, which ensures that we can call Py_Initialize / Py_FinalizeEx multiple times. */ - _PyEval_FiniThreads2(); + _PyEval_FiniThreads(); /* Auto-thread-state API */ _PyGILState_Init(runtime, interp, tstate); @@ -1357,7 +1357,6 @@ Py_FinalizeEx(void) call_ll_exitfuncs(runtime); - _PyEval_FiniThreads(); _PyRuntime_Finalize(); return status; } From 8c77b8cb9188165a123f2512026e3629bf03dc9b Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Mon, 29 Apr 2019 13:36:57 +0100 Subject: [PATCH 112/212] bpo-36540: PEP 570 -- Implementation (GH-12701) This commit contains the implementation of PEP570: Python positional-only parameters. * Update Grammar/Grammar with new typedarglist and varargslist * Regenerate grammar files * Update and regenerate AST related files * Update code object * Update marshal.c * Update compiler and symtable * Regenerate importlib files * Update callable objects * Implement positional-only args logic in ceval.c * Regenerate frozen data * Update standard library to account for positional-only args * Add test file for positional-only args * Update other test files to account for positional-only args * Add News entry * Update inspect module and related tests --- Grammar/Grammar | 46 +- Include/Python-ast.h | 10 +- Include/code.h | 3 +- Lib/ctypes/test/test_values.py | 6 +- Lib/dis.py | 1 + Lib/importlib/_bootstrap_external.py | 3 +- Lib/inspect.py | 96 +- Lib/modulefinder.py | 5 +- Lib/test/inspect_fodder.py | 2 +- Lib/test/inspect_fodder2.py | 16 + Lib/test/test_ast.py | 51 +- Lib/test/test_code.py | 28 +- Lib/test/test_dis.py | 62 +- Lib/test/test_functools.py | 7 + Lib/test/test_import/__init__.py | 3 +- Lib/test/test_importlib/test_util.py | 2 +- Lib/test/test_inspect.py | 45 +- Lib/test/test_parser.py | 12 + Lib/test/test_positional_only_arg.py | 403 ++ Lib/test/test_type_comments.py | 2 +- Lib/types.py | 2 +- .../2019-04-06-20-59-19.bpo-36540.SzVUfC.rst | 2 + Objects/call.c | 8 +- Objects/codeobject.c | 73 +- PC/launcher.c | 2 +- Parser/Python.asdl | 4 +- Python/Python-ast.c | 50 +- Python/ast.c | 100 +- Python/ceval.c | 118 +- Python/compile.c | 9 +- Python/frozen.c | 18 +- Python/graminit.c | 622 ++- Python/importlib.h | 2781 +++++------ Python/importlib_external.h | 4216 +++++++++-------- Python/importlib_zipimport.h | 1647 +++---- Python/marshal.c | 8 +- Python/symtable.c | 2 + Tools/parser/unparse.py | 8 +- 38 files changed, 5767 insertions(+), 4706 deletions(-) create mode 100644 Lib/test/test_positional_only_arg.py create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-06-20-59-19.bpo-36540.SzVUfC.rst diff --git a/Grammar/Grammar b/Grammar/Grammar index eaebdc4340f41c..0cacfb648e9abb 100644 --- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -22,13 +22,55 @@ async_funcdef: ASYNC funcdef funcdef: 'def' NAME parameters ['->' test] ':' [TYPE_COMMENT] func_body_suite parameters: '(' [typedargslist] ')' -typedargslist: (tfpdef ['=' test] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] [ + +# The following definition for typedarglist is equivalent to this set of rules: +# +# arguments = argument (',' [TYPE_COMMENT] argument)* +# argument = tfpdef ['=' test] +# kwargs = '**' tfpdef [','] [TYPE_COMMENT] +# args = '*' [tfpdef] +# kwonly_kwargs = (',' [TYPE_COMMENT] argument)* (TYPE_COMMENT | [',' [TYPE_COMMENT] [kwargs]]) +# args_kwonly_kwargs = args kwonly_kwargs | kwargs +# poskeyword_args_kwonly_kwargs = arguments ( TYPE_COMMENT | [',' [TYPE_COMMENT] [args_kwonly_kwargs]]) +# typedargslist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs +# typedarglist = (arguments ',' [TYPE_COMMENT] '/' [',' [[TYPE_COMMENT] typedargslist_no_posonly]])|(typedargslist_no_posonly)" +# +# It needs to be fully expanded to allow our LL(1) parser to work on it. + +typedargslist: ( + (tfpdef ['=' test] (',' [TYPE_COMMENT] tfpdef ['=' test])* ',' [TYPE_COMMENT] '/' [',' [ [TYPE_COMMENT] tfpdef ['=' test] ( + ',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] [ '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | '**' tfpdef [','] [TYPE_COMMENT]]]) | '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) + | '**' tfpdef [','] [TYPE_COMMENT]]] ) +| (tfpdef ['=' test] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] [ + '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) + | '**' tfpdef [','] [TYPE_COMMENT]]]) + | '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | '**' tfpdef [','] [TYPE_COMMENT]) +) tfpdef: NAME [':' test] -varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [ + +# The following definition for varargslist is equivalent to this set of rules: +# +# arguments = argument (',' argument )* +# argument = vfpdef ['=' test] +# kwargs = '**' vfpdef [','] +# args = '*' [vfpdef] +# kwonly_kwargs = (',' argument )* [',' [kwargs]] +# args_kwonly_kwargs = args kwonly_kwargs | kwargs +# poskeyword_args_kwonly_kwargs = arguments [',' [args_kwonly_kwargs]] +# vararglist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs +# varargslist = arguments ',' '/' [','[(vararglist_no_posonly)]] | (vararglist_no_posonly) +# +# It needs to be fully expanded to allow our LL(1) parser to work on it. + +varargslist: vfpdef ['=' test ](',' vfpdef ['=' test])* ',' '/' [',' [ (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [ + '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] + | '**' vfpdef [',']]] + | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] + | '**' vfpdef [',']) ]] | (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [ '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] | '**' vfpdef [',']]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] diff --git a/Include/Python-ast.h b/Include/Python-ast.h index a5742ff0485b89..0c739db6d14124 100644 --- a/Include/Python-ast.h +++ b/Include/Python-ast.h @@ -427,6 +427,7 @@ struct _excepthandler { struct _arguments { asdl_seq *args; + asdl_seq *posonlyargs; arg_ty vararg; asdl_seq *kwonlyargs; asdl_seq *kw_defaults; @@ -684,10 +685,11 @@ excepthandler_ty _Py_ExceptHandler(expr_ty type, identifier name, asdl_seq * body, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); -#define arguments(a0, a1, a2, a3, a4, a5, a6) _Py_arguments(a0, a1, a2, a3, a4, a5, a6) -arguments_ty _Py_arguments(asdl_seq * args, arg_ty vararg, asdl_seq * - kwonlyargs, asdl_seq * kw_defaults, arg_ty kwarg, - asdl_seq * defaults, PyArena *arena); +#define arguments(a0, a1, a2, a3, a4, a5, a6, a7) _Py_arguments(a0, a1, a2, a3, a4, a5, a6, a7) +arguments_ty _Py_arguments(asdl_seq * args, asdl_seq * posonlyargs, arg_ty + vararg, asdl_seq * kwonlyargs, asdl_seq * + kw_defaults, arg_ty kwarg, asdl_seq * defaults, + PyArena *arena); #define arg(a0, a1, a2, a3, a4, a5, a6, a7) _Py_arg(a0, a1, a2, a3, a4, a5, a6, a7) arg_ty _Py_arg(identifier arg, expr_ty annotation, string type_comment, int lineno, int col_offset, int end_lineno, int end_col_offset, diff --git a/Include/code.h b/Include/code.h index 2e661e8b36b7f7..933de97d078282 100644 --- a/Include/code.h +++ b/Include/code.h @@ -21,6 +21,7 @@ typedef uint16_t _Py_CODEUNIT; typedef struct { PyObject_HEAD int co_argcount; /* #arguments, except *args */ + int co_posonlyargcount; /* #positional only arguments */ int co_kwonlyargcount; /* #keyword only arguments */ int co_nlocals; /* #local variables */ int co_stacksize; /* #entries needed for evaluation stack */ @@ -102,7 +103,7 @@ PyAPI_DATA(PyTypeObject) PyCode_Type; /* Public interface */ PyAPI_FUNC(PyCodeObject *) PyCode_New( - int, int, int, int, int, PyObject *, PyObject *, + int, int, int, int, int, int, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *, int, PyObject *); /* same as struct above */ diff --git a/Lib/ctypes/test/test_values.py b/Lib/ctypes/test/test_values.py index b38b63f870a653..87eb9198ade0c7 100644 --- a/Lib/ctypes/test/test_values.py +++ b/Lib/ctypes/test/test_values.py @@ -80,9 +80,9 @@ class struct_frozen(Structure): continue items.append((entry.name.decode("ascii"), entry.size)) - expected = [("__hello__", 139), - ("__phello__", -139), - ("__phello__.spam", 139), + expected = [("__hello__", 141), + ("__phello__", -141), + ("__phello__.spam", 141), ] self.assertEqual(items, expected, "PyImport_FrozenModules example " "in Doc/library/ctypes.rst may be out of date") diff --git a/Lib/dis.py b/Lib/dis.py index b2b0003203a44f..a25fb2b417643d 100644 --- a/Lib/dis.py +++ b/Lib/dis.py @@ -157,6 +157,7 @@ def _format_code_info(co): lines.append("Name: %s" % co.co_name) lines.append("Filename: %s" % co.co_filename) lines.append("Argument count: %s" % co.co_argcount) + lines.append("Positional-only arguments: %s" % co.co_posonlyargcount) lines.append("Kw-only arguments: %s" % co.co_kwonlyargcount) lines.append("Number of locals: %s" % co.co_nlocals) lines.append("Stack size: %s" % co.co_stacksize) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 146c6472f70610..f8ff5f4f2c5c69 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -265,6 +265,7 @@ def _write_atomic(path, data, mode=0o666): # this might affected the first line number #32911) # Python 3.8a1 3400 (move frame block handling to compiler #17611) # Python 3.8a1 3401 (add END_ASYNC_FOR #33041) +# Python 3.8a1 3410 (PEP570 Python Positional-Only Parameters #36540) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually @@ -273,7 +274,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3401).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3410).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/inspect.py b/Lib/inspect.py index d8475c63f9017f..3201e794fb37f7 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -272,6 +272,7 @@ def iscode(object): | 16=nested | 32=generator | 64=nofree | 128=coroutine | 256=iterable_coroutine | 512=async_generator co_freevars tuple of names of free variables + co_posonlyargcount number of positional only arguments 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 @@ -1031,26 +1032,20 @@ def getargs(co): 'args' is the list of argument names. Keyword-only arguments are appended. 'varargs' and 'varkw' are the names of the * and ** arguments or None.""" - args, varargs, kwonlyargs, varkw = _getfullargs(co) - return Arguments(args + kwonlyargs, varargs, varkw) - -def _getfullargs(co): - """Get information about the arguments accepted by a code object. - - Four things are returned: (args, varargs, kwonlyargs, varkw), where - 'args' and 'kwonlyargs' are lists of argument names, and 'varargs' - and 'varkw' are the names of the * and ** arguments or None.""" - if not iscode(co): raise TypeError('{!r} is not a code object'.format(co)) - nargs = co.co_argcount names = co.co_varnames + nargs = co.co_argcount + nposonlyargs = co.co_posonlyargcount nkwargs = co.co_kwonlyargcount - args = list(names[:nargs]) - kwonlyargs = list(names[nargs:nargs+nkwargs]) + nposargs = nargs + nposonlyargs + posonlyargs = list(names[:nposonlyargs]) + args = list(names[nposonlyargs:nposonlyargs+nargs]) + kwonlyargs = list(names[nposargs:nposargs+nkwargs]) step = 0 + nargs += nposonlyargs nargs += nkwargs varargs = None if co.co_flags & CO_VARARGS: @@ -1059,8 +1054,7 @@ def _getfullargs(co): varkw = None if co.co_flags & CO_VARKEYWORDS: varkw = co.co_varnames[nargs] - return args, varargs, kwonlyargs, varkw - + return Arguments(posonlyargs + args + kwonlyargs, varargs, varkw) ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults') @@ -1087,15 +1081,16 @@ def getargspec(func): warnings.warn("inspect.getargspec() is deprecated since Python 3.0, " "use inspect.signature() or inspect.getfullargspec()", DeprecationWarning, stacklevel=2) - args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ - getfullargspec(func) - if kwonlyargs or ann: - raise ValueError("Function has keyword-only parameters or annotations" - ", use getfullargspec() API which can support them") + args, varargs, varkw, defaults, posonlyargs, kwonlyargs, \ + kwonlydefaults, ann = getfullargspec(func) + if posonlyargs or kwonlyargs or ann: + raise ValueError("Function has positional-only, keyword-only parameters" + " or annotations, use getfullargspec() API which can" + " support them") return ArgSpec(args, varargs, varkw, defaults) FullArgSpec = namedtuple('FullArgSpec', - 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations') + 'args, varargs, varkw, defaults, posonlyargs, kwonlyargs, kwonlydefaults, annotations') def getfullargspec(func): """Get the names and default values of a callable object's parameters. @@ -1145,6 +1140,7 @@ def getfullargspec(func): args = [] varargs = None varkw = None + posonlyargs = [] kwonlyargs = [] defaults = () annotations = {} @@ -1159,7 +1155,9 @@ def getfullargspec(func): name = param.name if kind is _POSITIONAL_ONLY: - args.append(name) + posonlyargs.append(name) + if param.default is not param.empty: + defaults += (param.default,) elif kind is _POSITIONAL_OR_KEYWORD: args.append(name) if param.default is not param.empty: @@ -1185,7 +1183,7 @@ def getfullargspec(func): defaults = None return FullArgSpec(args, varargs, varkw, defaults, - kwonlyargs, kwdefaults, annotations) + posonlyargs, kwonlyargs, kwdefaults, annotations) ArgInfo = namedtuple('ArgInfo', 'args varargs keywords locals') @@ -1216,7 +1214,8 @@ def _formatannotation(annotation): return _formatannotation def formatargspec(args, varargs=None, varkw=None, defaults=None, - kwonlyargs=(), kwonlydefaults={}, annotations={}, + posonlyargs=(), kwonlyargs=(), kwonlydefaults={}, + annotations={}, formatarg=str, formatvarargs=lambda name: '*' + name, formatvarkw=lambda name: '**' + name, @@ -1249,12 +1248,17 @@ def formatargandannotation(arg): return result specs = [] if defaults: - firstdefault = len(args) - len(defaults) - for i, arg in enumerate(args): + firstdefault = len(posonlyargs) + len(args) - len(defaults) + posonly_left = len(posonlyargs) + for i, arg in enumerate([*posonlyargs, *args]): spec = formatargandannotation(arg) if defaults and i >= firstdefault: spec = spec + formatvalue(defaults[i - firstdefault]) specs.append(spec) + posonly_left -= 1 + if posonlyargs and posonly_left == 0: + specs.append('/') + if varargs is not None: specs.append(formatvarargs(formatargandannotation(varargs))) else: @@ -1342,7 +1346,8 @@ def getcallargs(*func_and_positional, **named): func = func_and_positional[0] positional = func_and_positional[1:] spec = getfullargspec(func) - args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = spec + (args, varargs, varkw, defaults, posonlyargs, + kwonlyargs, kwonlydefaults, ann) = spec f_name = func.__name__ arg2value = {} @@ -1351,12 +1356,16 @@ def getcallargs(*func_and_positional, **named): # implicit 'self' (or 'cls' for classmethods) argument positional = (func.__self__,) + positional num_pos = len(positional) + num_posonlyargs = len(posonlyargs) num_args = len(args) num_defaults = len(defaults) if defaults else 0 + n = min(num_pos, num_posonlyargs) + for i in range(num_posonlyargs): + arg2value[posonlyargs[i]] = positional[i] n = min(num_pos, num_args) for i in range(n): - arg2value[args[i]] = positional[i] + arg2value[args[i]] = positional[num_posonlyargs+i] if varargs: arg2value[varargs] = tuple(positional[n:]) possible_kwargs = set(args + kwonlyargs) @@ -2137,9 +2146,12 @@ def _signature_from_function(cls, func): func_code = func.__code__ pos_count = func_code.co_argcount arg_names = func_code.co_varnames - positional = tuple(arg_names[:pos_count]) + posonly_count = func_code.co_posonlyargcount + positional_count = posonly_count + pos_count + positional_only = tuple(arg_names[:posonly_count]) + positional = tuple(arg_names[posonly_count:positional_count]) keyword_only_count = func_code.co_kwonlyargcount - keyword_only = arg_names[pos_count:(pos_count + keyword_only_count)] + keyword_only = arg_names[positional_count:(positional_count + keyword_only_count)] annotations = func.__annotations__ defaults = func.__defaults__ kwdefaults = func.__kwdefaults__ @@ -2151,23 +2163,33 @@ def _signature_from_function(cls, func): parameters = [] + non_default_count = positional_count - pos_default_count + all_positional = positional_only + positional + + posonly_left = posonly_count + # Non-keyword-only parameters w/o defaults. - non_default_count = pos_count - pos_default_count - for name in positional[:non_default_count]: + for name in all_positional[:non_default_count]: + kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD annotation = annotations.get(name, _empty) parameters.append(Parameter(name, annotation=annotation, - kind=_POSITIONAL_OR_KEYWORD)) + kind=kind)) + if posonly_left: + posonly_left -= 1 # ... w/ defaults. - for offset, name in enumerate(positional[non_default_count:]): + for offset, name in enumerate(all_positional[non_default_count:]): + kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD annotation = annotations.get(name, _empty) parameters.append(Parameter(name, annotation=annotation, - kind=_POSITIONAL_OR_KEYWORD, + kind=kind, default=defaults[offset])) + if posonly_left: + posonly_left -= 1 # *args if func_code.co_flags & CO_VARARGS: - name = arg_names[pos_count + keyword_only_count] + name = arg_names[positional_count + keyword_only_count] annotation = annotations.get(name, _empty) parameters.append(Parameter(name, annotation=annotation, kind=_VAR_POSITIONAL)) @@ -2184,7 +2206,7 @@ def _signature_from_function(cls, func): default=default)) # **kwargs if func_code.co_flags & CO_VARKEYWORDS: - index = pos_count + keyword_only_count + index = positional_count + keyword_only_count if func_code.co_flags & CO_VARARGS: index += 1 diff --git a/Lib/modulefinder.py b/Lib/modulefinder.py index 0061ef415ce322..a36f1b6d58c446 100644 --- a/Lib/modulefinder.py +++ b/Lib/modulefinder.py @@ -619,8 +619,9 @@ def replace_paths_in_code(self, co): if isinstance(consts[i], type(co)): consts[i] = self.replace_paths_in_code(consts[i]) - return types.CodeType(co.co_argcount, co.co_kwonlyargcount, - co.co_nlocals, co.co_stacksize, co.co_flags, + return types.CodeType(co.co_argcount, co.co_posonlyargcount, + co.co_kwonlyargcount, co.co_nlocals, + co.co_stacksize, co.co_flags, co.co_code, tuple(consts), co.co_names, co.co_varnames, new_filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, diff --git a/Lib/test/inspect_fodder.py b/Lib/test/inspect_fodder.py index 667507768ccb69..96a0257bfdf03e 100644 --- a/Lib/test/inspect_fodder.py +++ b/Lib/test/inspect_fodder.py @@ -5,7 +5,7 @@ # line 5 # line 7 -def spam(a, b, c, d=3, e=4, f=5, *g, **h): +def spam(a, /, b, c, d=3, e=4, f=5, *g, **h): eggs(b + d, c + f) # line 11 diff --git a/Lib/test/inspect_fodder2.py b/Lib/test/inspect_fodder2.py index c6987ea2c9e485..5a7b559d07d762 100644 --- a/Lib/test/inspect_fodder2.py +++ b/Lib/test/inspect_fodder2.py @@ -137,3 +137,19 @@ def func136(): def func137(): never_reached1 never_reached2 + +#line 141 +def positional_only_arg(a, /): + pass + +#line 145 +def all_markers(a, b, /, c, d, *, e, f): + pass + +# line 149 +def all_markers_with_args_and_kwargs(a, b, /, c, d, *args, e, f, **kwargs): + pass + +#line 153 +def all_markers_with_defaults(a, b=1, /, c=2, d=3, *, e=4, f=5): + pass diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index e39d1f2e17a89e..0c5bbf6752a48e 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -319,14 +319,14 @@ def test_field_attr_existence(self): def test_arguments(self): x = ast.arguments() - self.assertEqual(x._fields, ('args', 'vararg', 'kwonlyargs', + self.assertEqual(x._fields, ('args', 'posonlyargs', 'vararg', 'kwonlyargs', 'kw_defaults', 'kwarg', 'defaults')) with self.assertRaises(AttributeError): x.vararg - x = ast.arguments(*range(1, 7)) - self.assertEqual(x.vararg, 2) + x = ast.arguments(*range(1, 8)) + self.assertEqual(x.vararg, 3) def test_field_attr_writable(self): x = ast.Num() @@ -816,22 +816,25 @@ def test_module(self): self.mod(m, "must have Load context", "eval") def _check_arguments(self, fac, check): - def arguments(args=None, vararg=None, + def arguments(args=None, posonlyargs=None, vararg=None, kwonlyargs=None, kwarg=None, defaults=None, kw_defaults=None): if args is None: args = [] + if posonlyargs is None: + posonlyargs = [] if kwonlyargs is None: kwonlyargs = [] if defaults is None: defaults = [] if kw_defaults is None: kw_defaults = [] - args = ast.arguments(args, vararg, kwonlyargs, kw_defaults, - kwarg, defaults) + args = ast.arguments(args, posonlyargs, vararg, kwonlyargs, + kw_defaults, kwarg, defaults) return fac(args) args = [ast.arg("x", ast.Name("x", ast.Store()))] check(arguments(args=args), "must have Load context") + check(arguments(posonlyargs=args), "must have Load context") check(arguments(kwonlyargs=args), "must have Load context") check(arguments(defaults=[ast.Num(3)]), "more positional defaults than args") @@ -847,7 +850,7 @@ def arguments(args=None, vararg=None, "must have Load context") def test_funcdef(self): - a = ast.arguments([], None, [], [], None, []) + a = ast.arguments([], [], None, [], [], None, []) f = ast.FunctionDef("x", a, [], [], None) self.stmt(f, "empty body on FunctionDef") f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())], @@ -1013,7 +1016,7 @@ def test_unaryop(self): self.expr(u, "must have Load context") def test_lambda(self): - a = ast.arguments([], None, [], [], None, []) + a = ast.arguments([], [], None, [], [], None, []) self.expr(ast.Lambda(a, ast.Name("x", ast.Store())), "must have Load context") def fac(args): @@ -1636,17 +1639,17 @@ def main(): exec_results = [ ('Module', [('Expr', (1, 0), ('Constant', (1, 0), None, None))], []), ('Module', [('Expr', (1, 0), ('Constant', (1, 0), 'module docstring', None))], []), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (1, 9), ('Constant', (1, 9), 'function docstring', None))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], None, [], [], None, [('Constant', (1, 8), 0, None)]), [('Pass', (1, 12))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None, None), [], [], None, []), [('Pass', (1, 14))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None, None), []), [('Pass', (1, 17))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None), ('arg', (1, 9), 'b', None, None), ('arg', (1, 14), 'c', None, None), ('arg', (1, 22), 'd', None, None), ('arg', (1, 28), 'e', None, None)], ('arg', (1, 35), 'args', None, None), [('arg', (1, 41), 'f', None, None)], [('Constant', (1, 43), 42, None)], ('arg', (1, 49), 'kwargs', None, None), [('Constant', (1, 11), 1, None), ('Constant', (1, 16), None, None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Expr', (1, 58), ('Constant', (1, 58), 'doc for f()', None))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9), ('Constant', (1, 9), 'function docstring', None))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 10))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8), 0, None)]), [('Pass', (1, 12))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [], ('arg', (1, 7), 'args', None, None), [], [], None, []), [('Pass', (1, 14))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], ('arg', (1, 8), 'kwargs', None, None), []), [('Pass', (1, 17))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None, None), ('arg', (1, 9), 'b', None, None), ('arg', (1, 14), 'c', None, None), ('arg', (1, 22), 'd', None, None), ('arg', (1, 28), 'e', None, None)], [], ('arg', (1, 35), 'args', None, None), [('arg', (1, 41), 'f', None, None)], [('Constant', (1, 43), 42, None)], ('arg', (1, 49), 'kwargs', None, None), [('Constant', (1, 11), 1, None), ('Constant', (1, 16), None, None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Expr', (1, 58), ('Constant', (1, 58), 'doc for f()', None))], [], None, None)], []), ('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [])], []), ('Module', [('ClassDef', (1, 0), 'C', [], [], [('Expr', (1, 9), ('Constant', (1, 9), 'docstring for class C', None))], [])], []), ('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [])], []), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Constant', (1, 15), 1, None))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8), ('Constant', (1, 15), 1, None))], [], None, None)], []), ('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])], []), ('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Constant', (1, 4), 1, None), None)], []), ('Module', [('Assign', (1, 0), [('Tuple', (1, 0), [('Name', (1, 0), 'a', ('Store',)), ('Name', (1, 2), 'b', ('Store',))], ('Store',))], ('Name', (1, 6), 'c', ('Load',)), None)], []), @@ -1677,16 +1680,16 @@ def main(): ('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [], 0)]))], []), ('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))], 0)]))], []), ('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [], 0)]))], []), -('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('Constant', (2, 1), 'async function', None)), ('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None, None)], []), -('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('AsyncFor', (2, 1), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Constant', (2, 19), 1, None))], [('Expr', (3, 7), ('Constant', (3, 7), 2, None))], None)], [], None, None)], []), -('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('AsyncWith', (2, 1), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Constant', (2, 20), 1, None))], None)], [], None, None)], []), +('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1), ('Constant', (2, 1), 'async function', None)), ('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None, None)], []), +('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Constant', (2, 19), 1, None))], [('Expr', (3, 7), ('Constant', (3, 7), 2, None))], None)], [], None, None)], []), +('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Constant', (2, 20), 1, None))], None)], [], None, None)], []), ('Module', [('Expr', (1, 0), ('Dict', (1, 0), [None, ('Constant', (1, 10), 2, None)], [('Dict', (1, 3), [('Constant', (1, 4), 1, None)], [('Constant', (1, 6), 2, None)]), ('Constant', (1, 12), 3, None)]))], []), ('Module', [('Expr', (1, 0), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Constant', (1, 3), 1, None), ('Constant', (1, 6), 2, None)]), ('Load',)), ('Constant', (1, 10), 3, None)]))], []), -('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 1), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None, None)], []), -('Module', [('FunctionDef', (3, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (3, 9))], [('Name', (1, 1), 'deco1', ('Load',)), ('Call', (2, 0), ('Name', (2, 1), 'deco2', ('Load',)), [], [])], None, None)], []), -('Module', [('AsyncFunctionDef', (3, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (3, 15))], [('Name', (1, 1), 'deco1', ('Load',)), ('Call', (2, 0), ('Name', (2, 1), 'deco2', ('Load',)), [], [])], None, None)], []), +('Module', [('AsyncFunctionDef', (1, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 1), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None, None)], []), +('Module', [('FunctionDef', (3, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (3, 9))], [('Name', (1, 1), 'deco1', ('Load',)), ('Call', (2, 0), ('Name', (2, 1), 'deco2', ('Load',)), [], [])], None, None)], []), +('Module', [('AsyncFunctionDef', (3, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (3, 15))], [('Name', (1, 1), 'deco1', ('Load',)), ('Call', (2, 0), ('Name', (2, 1), 'deco2', ('Load',)), [], [])], None, None)], []), ('Module', [('ClassDef', (3, 0), 'C', [], [], [('Pass', (3, 9))], [('Name', (1, 1), 'deco1', ('Load',)), ('Call', (2, 0), ('Name', (2, 1), 'deco2', ('Load',)), [], [])])], []), -('Module', [('FunctionDef', (2, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (2, 9))], [('Call', (1, 1), ('Name', (1, 1), 'deco', ('Load',)), [('GeneratorExp', (1, 5), ('Name', (1, 6), 'a', ('Load',)), [('comprehension', ('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 17), 'b', ('Load',)), [], 0)])], [])], None, None)], []), +('Module', [('FunctionDef', (2, 0), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9))], [('Call', (1, 1), ('Name', (1, 1), 'deco', ('Load',)), [('GeneratorExp', (1, 5), ('Name', (1, 6), 'a', ('Load',)), [('comprehension', ('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 17), 'b', ('Load',)), [], 0)])], [])], None, None)], []), ('Module', [('Expr', (1, 0), ('NamedExpr', (1, 1), ('Name', (1, 1), 'a', ('Store',)), ('Constant', (1, 6), 1, None)))], []), ] single_results = [ @@ -1697,7 +1700,7 @@ def main(): ('Expression', ('BoolOp', (1, 0), ('And',), [('Name', (1, 0), 'a', ('Load',)), ('Name', (1, 6), 'b', ('Load',))])), ('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))), ('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))), -('Expression', ('Lambda', (1, 0), ('arguments', [], None, [], [], None, []), ('Constant', (1, 7), None, None))), +('Expression', ('Lambda', (1, 0), ('arguments', [], [], None, [], [], None, []), ('Constant', (1, 7), None, None))), ('Expression', ('Dict', (1, 0), [('Constant', (1, 2), 1, None)], [('Constant', (1, 4), 2, None)])), ('Expression', ('Dict', (1, 0), [], [])), ('Expression', ('Set', (1, 0), [('Constant', (1, 1), None, None)])), diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index 55faf4c4279fb6..e49121ef16988c 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -9,6 +9,7 @@ >>> dump(f.__code__) name: f argcount: 1 +posonlyargcount: 0 kwonlyargcount: 0 names: () varnames: ('x', 'g') @@ -21,6 +22,7 @@ >>> dump(f(4).__code__) name: g argcount: 1 +posonlyargcount: 0 kwonlyargcount: 0 names: () varnames: ('y',) @@ -40,6 +42,7 @@ >>> dump(h.__code__) name: h argcount: 2 +posonlyargcount: 0 kwonlyargcount: 0 names: () varnames: ('x', 'y', 'a', 'b', 'c') @@ -57,6 +60,7 @@ >>> dump(attrs.__code__) name: attrs argcount: 1 +posonlyargcount: 0 kwonlyargcount: 0 names: ('print', 'attr1', 'attr2', 'attr3') varnames: ('obj',) @@ -75,6 +79,7 @@ >>> dump(optimize_away.__code__) name: optimize_away argcount: 0 +posonlyargcount: 0 kwonlyargcount: 0 names: () varnames: () @@ -91,6 +96,7 @@ >>> dump(keywordonly_args.__code__) name: keywordonly_args argcount: 2 +posonlyargcount: 0 kwonlyargcount: 1 names: () varnames: ('a', 'b', 'k1') @@ -100,6 +106,23 @@ flags: 67 consts: ('None',) +>>> def posonly_args(a,b,/,c): +... return a,b,c +... + +>>> dump(posonly_args.__code__) +name: posonly_args +argcount: 1 +posonlyargcount: 2 +kwonlyargcount: 0 +names: () +varnames: ('a', 'b', 'c') +cellvars: () +freevars: () +nlocals: 3 +flags: 67 +consts: ('None',) + """ import inspect @@ -126,7 +149,8 @@ def consts(t): def dump(co): """Print out a text representation of a code object.""" - for attr in ["name", "argcount", "kwonlyargcount", "names", "varnames", + for attr in ["name", "argcount", "posonlyargcount", + "kwonlyargcount", "names", "varnames", "cellvars", "freevars", "nlocals", "flags"]: print("%s: %s" % (attr, getattr(co, "co_" + attr))) print("consts:", tuple(consts(co.co_consts))) @@ -157,7 +181,7 @@ def create_closure(__class__): def new_code(c): '''A new code object with a __class__ cell added to freevars''' return CodeType( - c.co_argcount, c.co_kwonlyargcount, c.co_nlocals, + c.co_argcount, c.co_posonlyargcount, c.co_kwonlyargcount, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code, c.co_consts, c.co_names, c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno, c.co_lnotab, c.co_freevars + ('__class__',), c.co_cellvars) diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 8d1912b6ee5881..1561021f5bc732 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -617,6 +617,7 @@ def get_disassembly(self, func, lasti=-1, wrapper=True, **kwargs): Name: code_info Filename: (.*) Argument count: 1 +Positional-only arguments: 0 Kw-only arguments: 0 Number of locals: 1 Stack size: 3 @@ -631,50 +632,53 @@ def get_disassembly(self, func, lasti=-1, wrapper=True, **kwargs): if sys.flags.optimize < 2 else (None,)) @staticmethod -def tricky(x, y, z=True, *args, c, d, e=[], **kwds): +def tricky(a, b, /, x, y, z=True, *args, c, d, e=[], **kwds): def f(c=c): - print(x, y, z, c, d, e, f) - yield x, y, z, c, d, e, f + print(a, b, x, y, z, c, d, e, f) + yield a, b, x, y, z, c, d, e, f code_info_tricky = """\ Name: tricky Filename: (.*) Argument count: 3 +Positional-only arguments: 2 Kw-only arguments: 3 -Number of locals: 8 -Stack size: 7 +Number of locals: 10 +Stack size: 9 Flags: OPTIMIZED, NEWLOCALS, VARARGS, VARKEYWORDS, GENERATOR Constants: 0: None 1: 2: 'tricky..f' Variable names: - 0: x - 1: y - 2: z - 3: c - 4: d - 5: e - 6: args - 7: kwds + 0: a + 1: b + 2: x + 3: y + 4: z + 5: c + 6: d + 7: e + 8: args + 9: kwds Cell variables: - 0: [edfxyz] - 1: [edfxyz] - 2: [edfxyz] - 3: [edfxyz] - 4: [edfxyz] - 5: [edfxyz]""" + 0: [abedfxyz] + 1: [abedfxyz] + 2: [abedfxyz] + 3: [abedfxyz] + 4: [abedfxyz] + 5: [abedfxyz]""" # NOTE: the order of the cell variables above depends on dictionary order! co_tricky_nested_f = tricky.__func__.__code__.co_consts[1] code_info_tricky_nested_f = """\ -Name: f Filename: (.*) Argument count: 1 +Positional-only arguments: 0 Kw-only arguments: 0 Number of locals: 1 -Stack size: 8 +Stack size: 10 Flags: OPTIMIZED, NEWLOCALS, NESTED Constants: 0: None @@ -683,17 +687,18 @@ def f(c=c): Variable names: 0: c Free variables: - 0: [edfxyz] - 1: [edfxyz] - 2: [edfxyz] - 3: [edfxyz] - 4: [edfxyz] - 5: [edfxyz]""" + 0: [abedfxyz] + 1: [abedfxyz] + 2: [abedfxyz] + 3: [abedfxyz] + 4: [abedfxyz] + 5: [abedfxyz]""" code_info_expr_str = """\ Name: Filename: Argument count: 0 +Positional-only arguments: 0 Kw-only arguments: 0 Number of locals: 0 Stack size: 2 @@ -707,6 +712,7 @@ def f(c=c): Name: Filename: Argument count: 0 +Positional-only arguments: 0 Kw-only arguments: 0 Number of locals: 0 Stack size: 2 @@ -721,6 +727,7 @@ def f(c=c): Name: Filename: Argument count: 0 +Positional-only arguments: 0 Kw-only arguments: 0 Number of locals: 0 Stack size: 2 @@ -742,6 +749,7 @@ async def async_def(): Name: async_def Filename: (.*) Argument count: 0 +Positional-only arguments: 0 Kw-only arguments: 0 Number of locals: 2 Stack size: 10 diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 98908405e1401a..85c65d18326067 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -581,6 +581,13 @@ def add(self, x, y): for func in [self.A.static, self.A.cls, self.A.over_partial, self.A.nested, self.A.both]: self.assertFalse(getattr(func, '__isabstractmethod__', False)) + def test_positional_only(self): + def f(a, b, /): + return a + b + + p = functools.partial(f, 1) + self.assertEqual(p(2), f(1, 2)) + class TestUpdateWrapper(unittest.TestCase): diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index a0bfe1a6c19b3e..109b01413b2d84 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -674,7 +674,8 @@ def test_foreign_code(self): foreign_code = importlib.import_module.__code__ pos = constants.index(1) constants[pos] = foreign_code - code = type(code)(code.co_argcount, code.co_kwonlyargcount, + code = type(code)(code.co_argcount, code.co_posonlyargcount, + code.co_kwonlyargcount, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, tuple(constants), code.co_names, code.co_varnames, code.co_filename, diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py index 8739eea841d051..db0899aff6b99f 100644 --- a/Lib/test/test_importlib/test_util.py +++ b/Lib/test/test_importlib/test_util.py @@ -862,7 +862,7 @@ def test_magic_number(self): in advance. Such exceptional releases will then require an adjustment to this test case. """ - EXPECTED_MAGIC_NUMBER = 3400 + EXPECTED_MAGIC_NUMBER = 3410 actual = int.from_bytes(importlib.util.MAGIC_NUMBER[:2], 'little') msg = ( diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 7d74746b48b499..06f8d69a579f0e 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -763,30 +763,31 @@ def assertArgSpecEquals(self, routine, args_e, varargs_e=None, def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None, varkw_e=None, defaults_e=None, - kwonlyargs_e=[], kwonlydefaults_e=None, + posonlyargs_e=[], kwonlyargs_e=[], + kwonlydefaults_e=None, ann_e={}, formatted=None): - args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ + args, varargs, varkw, defaults, posonlyargs, kwonlyargs, kwonlydefaults, ann = \ inspect.getfullargspec(routine) self.assertEqual(args, args_e) self.assertEqual(varargs, varargs_e) self.assertEqual(varkw, varkw_e) self.assertEqual(defaults, defaults_e) + self.assertEqual(posonlyargs, posonlyargs_e) self.assertEqual(kwonlyargs, kwonlyargs_e) self.assertEqual(kwonlydefaults, kwonlydefaults_e) self.assertEqual(ann, ann_e) if formatted is not None: with self.assertWarns(DeprecationWarning): self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults, - kwonlyargs, kwonlydefaults, ann), + posonlyargs, kwonlyargs, + kwonlydefaults, ann), formatted) def test_getargspec(self): self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)') - self.assertArgSpecEquals(mod.spam, - ['a', 'b', 'c', 'd', 'e', 'f'], - 'g', 'h', (3, 4, 5), - '(a, b, c, d=3, e=4, f=5, *g, **h)') + self.assertRaises(ValueError, self.assertArgSpecEquals, + mod.spam, []) self.assertRaises(ValueError, self.assertArgSpecEquals, mod2.keyworded, []) @@ -810,6 +811,26 @@ def test_getfullargspec(self): kwonlyargs_e=['arg'], formatted='(*, arg)') + self.assertFullArgSpecEquals(mod2.all_markers, ['c', 'd'], + posonlyargs_e=['a', 'b'], + kwonlyargs_e=['e', 'f'], + formatted='(a, b, /, c, d, *, e, f)') + + self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs, + ['c', 'd'], + posonlyargs_e=['a', 'b'], + varargs_e='args', + varkw_e='kwargs', + kwonlyargs_e=['e', 'f'], + formatted='(a, b, /, c, d, *args, e, f, **kwargs)') + + self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['c', 'd'], + defaults_e=(1,2,3), + posonlyargs_e=['a', 'b'], + kwonlyargs_e=['e', 'f'], + kwonlydefaults_e={'e': 4, 'f': 5}, + formatted='(a, b=1, /, c=2, d=3, *, e=4, f=5)') + def test_argspec_api_ignores_wrapped(self): # Issue 20684: low level introspection API must ignore __wrapped__ @functools.wraps(mod.spam) @@ -856,7 +877,7 @@ def test(): spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY) test.__signature__ = inspect.Signature(parameters=(spam_param,)) - self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)') + self.assertFullArgSpecEquals(test, [], posonlyargs_e=['spam'], formatted='(spam, /)') def test_getfullargspec_signature_annos(self): def test(a:'spam') -> 'ham': pass @@ -870,11 +891,11 @@ def test(): pass @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") def test_getfullargspec_builtin_methods(self): - self.assertFullArgSpecEquals(_pickle.Pickler.dump, - args_e=['self', 'obj'], formatted='(self, obj)') + self.assertFullArgSpecEquals(_pickle.Pickler.dump, [], + posonlyargs_e=['self', 'obj'], formatted='(self, obj, /)') - self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, - args_e=['self', 'obj'], formatted='(self, obj)') + self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, [], + posonlyargs_e=['self', 'obj'], formatted='(self, obj, /)') self.assertFullArgSpecEquals( os.stat, diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index ff587c365f2b90..b830459b190f4e 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -233,6 +233,18 @@ def test_function_defs(self): self.check_suite("def f(*args, a, b = 5): pass") self.check_suite("def f(*args, a, b = 5, **kwds): pass") + # positional-only arguments + self.check_suite("def f(a, /): pass") + self.check_suite("def f(a, /,): pass") + self.check_suite("def f(a, b, /): pass") + self.check_suite("def f(a, b, /, c): pass") + self.check_suite("def f(a, b, /, c = 6): pass") + self.check_suite("def f(a, b, /, c, *, d): pass") + self.check_suite("def f(a, b, /, c = 1, *, d): pass") + self.check_suite("def f(a, b, /, c, *, d = 1): pass") + self.check_suite("def f(a, b=1, /, c=2, *, d = 3): pass") + self.check_suite("def f(a=0, b=1, /, c=2, *, d = 3): pass") + # function annotations self.check_suite("def f(a: int): pass") self.check_suite("def f(a: int = 5): pass") diff --git a/Lib/test/test_positional_only_arg.py b/Lib/test/test_positional_only_arg.py new file mode 100644 index 00000000000000..d4d259ef2693c4 --- /dev/null +++ b/Lib/test/test_positional_only_arg.py @@ -0,0 +1,403 @@ +"""Unit tests for the positional only argument syntax specified in PEP 570.""" + +import pickle +import unittest + +from test.support import check_syntax_error + + +def global_pos_only_f(a, b, /): + return a, b + +def global_pos_only_and_normal(a, /, b): + return a, b + +def global_pos_only_defaults(a=1, /, b=2): + return a, b + + +class PositionalOnlyTestCase(unittest.TestCase): + + def assertRaisesSyntaxError(self, codestr, regex="invalid syntax"): + with self.assertRaisesRegex(SyntaxError, regex): + compile(codestr + "\n", "", "single") + + def test_invalid_syntax_errors(self): + check_syntax_error(self, "def f(a, b = 5, /, c): pass", "non-default argument follows default argument") + check_syntax_error(self, "def f(a = 5, b, /, c): pass", "non-default argument follows default argument") + check_syntax_error(self, "def f(a = 5, b=1, /, c, *, d=2): pass", "non-default argument follows default argument") + check_syntax_error(self, "def f(a = 5, b, /): pass", "non-default argument follows default argument") + check_syntax_error(self, "def f(*args, /): pass") + check_syntax_error(self, "def f(*args, a, /): pass") + check_syntax_error(self, "def f(**kwargs, /): pass") + check_syntax_error(self, "def f(/, a = 1): pass") + check_syntax_error(self, "def f(/, a): pass") + check_syntax_error(self, "def f(/): pass") + check_syntax_error(self, "def f(*, a, /): pass") + check_syntax_error(self, "def f(*, /, a): pass") + check_syntax_error(self, "def f(a, /, a): pass", "duplicate argument 'a' in function definition") + check_syntax_error(self, "def f(a, /, *, a): pass", "duplicate argument 'a' in function definition") + check_syntax_error(self, "def f(a, b/2, c): pass") + check_syntax_error(self, "def f(a, /, c, /): pass") + check_syntax_error(self, "def f(a, /, c, /, d): pass") + check_syntax_error(self, "def f(a, /, c, /, d, *, e): pass") + check_syntax_error(self, "def f(a, *, c, /, d, e): pass") + + def test_invalid_syntax_errors_async(self): + check_syntax_error(self, "async def f(a, b = 5, /, c): pass", "non-default argument follows default argument") + check_syntax_error(self, "async def f(a = 5, b, /, c): pass", "non-default argument follows default argument") + check_syntax_error(self, "async def f(a = 5, b=1, /, c, d=2): pass", "non-default argument follows default argument") + check_syntax_error(self, "async def f(a = 5, b, /): pass", "non-default argument follows default argument") + check_syntax_error(self, "async def f(*args, /): pass") + check_syntax_error(self, "async def f(*args, a, /): pass") + check_syntax_error(self, "async def f(**kwargs, /): pass") + check_syntax_error(self, "async def f(/, a = 1): pass") + check_syntax_error(self, "async def f(/, a): pass") + check_syntax_error(self, "async def f(/): pass") + check_syntax_error(self, "async def f(*, a, /): pass") + check_syntax_error(self, "async def f(*, /, a): pass") + check_syntax_error(self, "async def f(a, /, a): pass", "duplicate argument 'a' in function definition") + check_syntax_error(self, "async def f(a, /, *, a): pass", "duplicate argument 'a' in function definition") + check_syntax_error(self, "async def f(a, b/2, c): pass") + check_syntax_error(self, "async def f(a, /, c, /): pass") + check_syntax_error(self, "async def f(a, /, c, /, d): pass") + check_syntax_error(self, "async def f(a, /, c, /, d, *, e): pass") + check_syntax_error(self, "async def f(a, *, c, /, d, e): pass") + + def test_optional_positional_only_args(self): + def f(a, b=10, /, c=100): + return a + b + c + + self.assertEqual(f(1, 2, 3), 6) + self.assertEqual(f(1, 2, c=3), 6) + with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'b'"): + f(1, b=2, c=3) + + self.assertEqual(f(1, 2), 103) + with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'b'"): + f(1, b=2) + self.assertEqual(f(1, c=2), 13) + + def f(a=1, b=10, /, c=100): + return a + b + c + + self.assertEqual(f(1, 2, 3), 6) + self.assertEqual(f(1, 2, c=3), 6) + with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'b'"): + f(1, b=2, c=3) + + self.assertEqual(f(1, 2), 103) + with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'b'"): + f(1, b=2) + self.assertEqual(f(1, c=2), 13) + + def test_syntax_for_many_positional_only(self): + # more than 255 positional only arguments, should compile ok + fundef = "def f(%s, /):\n pass\n" % ', '.join('i%d' % i for i in range(300)) + compile(fundef, "", "single") + + def test_pos_only_definition(self): + def f(a, b, c, /, d, e=1, *, f, g=2): + pass + + self.assertEqual(2, f.__code__.co_argcount) # 2 "standard args" + self.assertEqual(3, f.__code__.co_posonlyargcount) + self.assertEqual((1,), f.__defaults__) + + def f(a, b, c=1, /, d=2, e=3, *, f, g=4): + pass + + self.assertEqual(2, f.__code__.co_argcount) # 2 "standard args" + self.assertEqual(3, f.__code__.co_posonlyargcount) + self.assertEqual((1, 2, 3), f.__defaults__) + + def test_pos_only_call_via_unpacking(self): + def f(a, b, /): + return a + b + + self.assertEqual(f(*[1, 2]), 3) + + def test_use_positional_as_keyword(self): + def f(a, /): + pass + expected = r"f\(\) got some positional-only arguments passed as keyword arguments: 'a'" + with self.assertRaisesRegex(TypeError, expected): + f(a=1) + + def f(a, /, b): + pass + expected = r"f\(\) got some positional-only arguments passed as keyword arguments: 'a'" + with self.assertRaisesRegex(TypeError, expected): + f(a=1, b=2) + + def f(a, b, /): + pass + expected = r"f\(\) got some positional-only arguments passed as keyword arguments: 'a, b'" + with self.assertRaisesRegex(TypeError, expected): + f(a=1, b=2) + + def test_positional_only_and_arg_invalid_calls(self): + def f(a, b, /, c): + pass + with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'c'"): + f(1, 2) + with self.assertRaisesRegex(TypeError, r"f\(\) missing 2 required positional arguments: 'b' and 'c'"): + f(1) + with self.assertRaisesRegex(TypeError, r"f\(\) missing 3 required positional arguments: 'a', 'b', and 'c'"): + f() + with self.assertRaisesRegex(TypeError, r"f\(\) takes 3 positional arguments but 4 were given"): + f(1, 2, 3, 4) + + def test_positional_only_and_optional_arg_invalid_calls(self): + def f(a, b, /, c=3): + pass + f(1, 2) # does not raise + with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'b'"): + f(1) + with self.assertRaisesRegex(TypeError, r"f\(\) missing 2 required positional arguments: 'a' and 'b'"): + f() + with self.assertRaisesRegex(TypeError, r"f\(\) takes from 2 to 3 positional arguments but 4 were given"): + f(1, 2, 3, 4) + + def test_positional_only_and_kwonlyargs_invalid_calls(self): + def f(a, b, /, c, *, d, e): + pass + f(1, 2, 3, d=1, e=2) # does not raise + with self.assertRaisesRegex(TypeError, r"missing 1 required keyword-only argument: 'd'"): + f(1, 2, 3, e=2) + with self.assertRaisesRegex(TypeError, r"missing 2 required keyword-only arguments: 'd' and 'e'"): + f(1, 2, 3) + with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'c'"): + f(1, 2) + with self.assertRaisesRegex(TypeError, r"f\(\) missing 2 required positional arguments: 'b' and 'c'"): + f(1) + with self.assertRaisesRegex(TypeError, r" missing 3 required positional arguments: 'a', 'b', and 'c'"): + f() + with self.assertRaisesRegex(TypeError, r"f\(\) takes 3 positional arguments but 6 positional arguments " + r"\(and 2 keyword-only arguments\) were given"): + f(1, 2, 3, 4, 5, 6, d=7, e=8) + with self.assertRaisesRegex(TypeError, r"f\(\) got an unexpected keyword argument 'f'"): + f(1, 2, 3, d=1, e=4, f=56) + + def test_positional_only_invalid_calls(self): + def f(a, b, /): + pass + f(1, 2) # does not raise + with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'b'"): + f(1) + with self.assertRaisesRegex(TypeError, r"f\(\) missing 2 required positional arguments: 'a' and 'b'"): + f() + with self.assertRaisesRegex(TypeError, r"f\(\) takes 2 positional arguments but 3 were given"): + f(1, 2, 3) + + def test_positional_only_with_optional_invalid_calls(self): + def f(a, b=2, /): + pass + f(1) # does not raise + with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'a'"): + f() + + with self.assertRaisesRegex(TypeError, r"f\(\) takes from 1 to 2 positional arguments but 3 were given"): + f(1, 2, 3) + + def test_no_standard_args_usage(self): + def f(a, b, /, *, c): + pass + + f(1, 2, c=3) + with self.assertRaises(TypeError): + f(1, b=2, c=3) + + def test_change_default_pos_only(self): + def f(a, b=2, /, c=3): + return a + b + c + + self.assertEqual((2,3), f.__defaults__) + f.__defaults__ = (1, 2, 3) + self.assertEqual(f(1, 2, 3), 6) + + def test_lambdas(self): + x = lambda a, /, b: a + b + self.assertEqual(x(1,2), 3) + self.assertEqual(x(1,b=2), 3) + + x = lambda a, /, b=2: a + b + self.assertEqual(x(1), 3) + + x = lambda a, b, /: a + b + self.assertEqual(x(1, 2), 3) + + x = lambda a, b, /, : a + b + self.assertEqual(x(1, 2), 3) + + def test_invalid_syntax_lambda(self): + check_syntax_error(self, "lambda a, b = 5, /, c: None", "non-default argument follows default argument") + check_syntax_error(self, "lambda a = 5, b, /, c: None", "non-default argument follows default argument") + check_syntax_error(self, "lambda a = 5, b, /: None", "non-default argument follows default argument") + check_syntax_error(self, "lambda *args, /: None") + check_syntax_error(self, "lambda *args, a, /: None") + check_syntax_error(self, "lambda **kwargs, /: None") + check_syntax_error(self, "lambda /, a = 1: None") + check_syntax_error(self, "lambda /, a: None") + check_syntax_error(self, "lambda /: None") + check_syntax_error(self, "lambda *, a, /: None") + check_syntax_error(self, "lambda *, /, a: None") + check_syntax_error(self, "lambda a, /, a: None", "duplicate argument 'a' in function definition") + check_syntax_error(self, "lambda a, /, *, a: None", "duplicate argument 'a' in function definition") + check_syntax_error(self, "lambda a, /, b, /: None") + check_syntax_error(self, "lambda a, /, b, /, c: None") + check_syntax_error(self, "lambda a, /, b, /, c, *, d: None") + check_syntax_error(self, "lambda a, *, b, /, c: None") + + def test_posonly_methods(self): + class Example: + def f(self, a, b, /): + return a, b + + self.assertEqual(Example().f(1, 2), (1, 2)) + self.assertEqual(Example.f(Example(), 1, 2), (1, 2)) + self.assertRaises(TypeError, Example.f, 1, 2) + expected = r"f\(\) got some positional-only arguments passed as keyword arguments: 'b'" + with self.assertRaisesRegex(TypeError, expected): + Example().f(1, b=2) + + def test_mangling(self): + class X: + def f(self, *, __a=42): + return __a + self.assertEqual(X().f(), 42) + + def test_module_function(self): + with self.assertRaisesRegex(TypeError, r"f\(\) missing 2 required positional arguments: 'a' and 'b'"): + global_pos_only_f() + + + def test_closures(self): + def f(x,y): + def g(x2,/,y2): + return x + y + x2 + y2 + return g + + self.assertEqual(f(1,2)(3,4), 10) + with self.assertRaisesRegex(TypeError, r"g\(\) missing 1 required positional argument: 'y2'"): + f(1,2)(3) + with self.assertRaisesRegex(TypeError, r"g\(\) takes 2 positional arguments but 3 were given"): + f(1,2)(3,4,5) + + def f(x,/,y): + def g(x2,y2): + return x + y + x2 + y2 + return g + + self.assertEqual(f(1,2)(3,4), 10) + + def f(x,/,y): + def g(x2,/,y2): + return x + y + x2 + y2 + return g + + self.assertEqual(f(1,2)(3,4), 10) + with self.assertRaisesRegex(TypeError, r"g\(\) missing 1 required positional argument: 'y2'"): + f(1,2)(3) + with self.assertRaisesRegex(TypeError, r"g\(\) takes 2 positional arguments but 3 were given"): + f(1,2)(3,4,5) + + def test_same_keyword_as_positional_with_kwargs(self): + def f(something,/,**kwargs): + return (something, kwargs) + + self.assertEqual(f(42, something=42), (42, {'something': 42})) + + with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'something'"): + f(something=42) + + self.assertEqual(f(42), (42, {})) + + def test_mangling(self): + class X: + def f(self, __a=42, /): + return __a + + def f2(self, __a=42, /, __b=43): + return (__a, __b) + + def f3(self, __a=42, /, __b=43, *, __c=44): + return (__a, __b, __c) + + self.assertEqual(X().f(), 42) + self.assertEqual(X().f2(), (42, 43)) + self.assertEqual(X().f3(), (42, 43, 44)) + + def test_too_many_arguments(self): + # more than 255 positional-only arguments, should compile ok + fundef = "def f(%s, /):\n pass\n" % ', '.join('i%d' % i for i in range(300)) + compile(fundef, "", "single") + + def test_serialization(self): + pickled_posonly = pickle.dumps(global_pos_only_f) + pickled_optional = pickle.dumps(global_pos_only_and_normal) + pickled_defaults = pickle.dumps(global_pos_only_defaults) + + unpickled_posonly = pickle.loads(pickled_posonly) + unpickled_optional = pickle.loads(pickled_optional) + unpickled_defaults = pickle.loads(pickled_defaults) + + self.assertEqual(unpickled_posonly(1,2), (1,2)) + expected = r"global_pos_only_f\(\) got some positional-only arguments "\ + r"passed as keyword arguments: 'a, b'" + with self.assertRaisesRegex(TypeError, expected): + unpickled_posonly(a=1,b=2) + + self.assertEqual(unpickled_optional(1,2), (1,2)) + expected = r"global_pos_only_and_normal\(\) got some positional-only arguments "\ + r"passed as keyword arguments: 'a'" + with self.assertRaisesRegex(TypeError, expected): + unpickled_optional(a=1,b=2) + + self.assertEqual(unpickled_defaults(), (1,2)) + expected = r"global_pos_only_defaults\(\) got some positional-only arguments "\ + r"passed as keyword arguments: 'a'" + with self.assertRaisesRegex(TypeError, expected): + unpickled_defaults(a=1,b=2) + + def test_async(self): + + async def f(a=1, /, b=2): + return a, b + + with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'a'"): + f(a=1, b=2) + + def _check_call(*args, **kwargs): + try: + coro = f(*args, **kwargs) + coro.send(None) + except StopIteration as e: + result = e.value + self.assertEqual(result, (1, 2)) + + _check_call(1, 2) + _check_call(1, b=2) + _check_call(1) + _check_call() + + def test_generator(self): + + def f(a=1, /, b=2): + yield a, b + + with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'a'"): + f(a=1, b=2) + + gen = f(1, 2) + self.assertEqual(next(gen), (1, 2)) + gen = f(1, b=2) + self.assertEqual(next(gen), (1, 2)) + gen = f(1) + self.assertEqual(next(gen), (1, 2)) + gen = f() + self.assertEqual(next(gen), (1, 2)) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_type_comments.py b/Lib/test/test_type_comments.py index cac6e8b25d21af..69a48a104036a0 100644 --- a/Lib/test/test_type_comments.py +++ b/Lib/test/test_type_comments.py @@ -101,7 +101,7 @@ def fab( def fab( a, # type: A - b # type: B + b # type: B ): pass diff --git a/Lib/types.py b/Lib/types.py index cf643088ea9ca3..37ba4bb1f42e5d 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -263,7 +263,7 @@ def coroutine(func): # TODO: Implement this in C. co = func.__code__ func.__code__ = CodeType( - co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, + co.co_argcount, co.co_posonlyargcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, co.co_flags | 0x100, # 0x100 == CO_ITERABLE_COROUTINE co.co_code, diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-06-20-59-19.bpo-36540.SzVUfC.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-06-20-59-19.bpo-36540.SzVUfC.rst new file mode 100644 index 00000000000000..359e8bfe0d16af --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-04-06-20-59-19.bpo-36540.SzVUfC.rst @@ -0,0 +1,2 @@ +Implement :pep:`570` (Python positional-only parameters). Patch by Pablo +Galindo. diff --git a/Objects/call.c b/Objects/call.c index d52e7e26aeba66..68f9e879fa76b4 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -320,11 +320,11 @@ _PyFunction_FastCallDict(PyObject *func, PyObject *const *args, Py_ssize_t nargs (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { /* Fast paths */ - if (argdefs == NULL && co->co_argcount == nargs) { + if (argdefs == NULL && co->co_argcount + co->co_posonlyargcount == nargs) { return function_code_fastcall(co, args, nargs, globals); } else if (nargs == 0 && argdefs != NULL - && co->co_argcount == PyTuple_GET_SIZE(argdefs)) { + && co->co_argcount + co->co_posonlyargcount == PyTuple_GET_SIZE(argdefs)) { /* function called with no arguments, but all parameters have a default value: use default values as arguments .*/ args = _PyTuple_ITEMS(argdefs); @@ -406,11 +406,11 @@ _PyFunction_FastCallKeywords(PyObject *func, PyObject *const *stack, if (co->co_kwonlyargcount == 0 && nkwargs == 0 && (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { - if (argdefs == NULL && co->co_argcount == nargs) { + if (argdefs == NULL && co->co_argcount + co->co_posonlyargcount== nargs) { return function_code_fastcall(co, stack, nargs, globals); } else if (nargs == 0 && argdefs != NULL - && co->co_argcount == PyTuple_GET_SIZE(argdefs)) { + && co->co_argcount + co->co_posonlyargcount == PyTuple_GET_SIZE(argdefs)) { /* function called with no arguments, but all parameters have a default value: use default values as arguments .*/ stack = _PyTuple_ITEMS(argdefs); diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 09182d61c24474..62d7c5d329f07b 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -96,7 +96,7 @@ intern_string_constants(PyObject *tuple) PyCodeObject * -PyCode_New(int argcount, int kwonlyargcount, +PyCode_New(int argcount, int posonlyargcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, @@ -108,8 +108,8 @@ PyCode_New(int argcount, int kwonlyargcount, Py_ssize_t i, n_cellvars, n_varnames, total_args; /* Check argument types */ - if (argcount < 0 || kwonlyargcount < 0 || nlocals < 0 || - code == NULL || !PyBytes_Check(code) || + if (argcount < 0 || posonlyargcount < 0 || kwonlyargcount < 0 || + nlocals < 0 || code == NULL || !PyBytes_Check(code) || consts == NULL || !PyTuple_Check(consts) || names == NULL || !PyTuple_Check(names) || varnames == NULL || !PyTuple_Check(varnames) || @@ -141,10 +141,12 @@ PyCode_New(int argcount, int kwonlyargcount, } n_varnames = PyTuple_GET_SIZE(varnames); - if (argcount <= n_varnames && kwonlyargcount <= n_varnames) { + if (posonlyargcount + argcount <= n_varnames + && kwonlyargcount <= n_varnames) { /* Never overflows. */ - total_args = (Py_ssize_t)argcount + (Py_ssize_t)kwonlyargcount + - ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0); + total_args = (Py_ssize_t)posonlyargcount + (Py_ssize_t)argcount + + (Py_ssize_t)kwonlyargcount + + ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0); } else { total_args = n_varnames + 1; @@ -193,6 +195,7 @@ PyCode_New(int argcount, int kwonlyargcount, return NULL; } co->co_argcount = argcount; + co->co_posonlyargcount = posonlyargcount; co->co_kwonlyargcount = kwonlyargcount; co->co_nlocals = nlocals; co->co_stacksize = stacksize; @@ -249,6 +252,7 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) goto failed; result = PyCode_New(0, /* argcount */ + 0, /* posonlyargcount */ 0, /* kwonlyargcount */ 0, /* nlocals */ 0, /* stacksize */ @@ -274,21 +278,22 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) #define OFF(x) offsetof(PyCodeObject, x) static PyMemberDef code_memberlist[] = { - {"co_argcount", T_INT, OFF(co_argcount), READONLY}, - {"co_kwonlyargcount", T_INT, OFF(co_kwonlyargcount), READONLY}, - {"co_nlocals", T_INT, OFF(co_nlocals), READONLY}, - {"co_stacksize",T_INT, OFF(co_stacksize), READONLY}, - {"co_flags", T_INT, OFF(co_flags), READONLY}, - {"co_code", T_OBJECT, OFF(co_code), READONLY}, - {"co_consts", T_OBJECT, OFF(co_consts), READONLY}, - {"co_names", T_OBJECT, OFF(co_names), READONLY}, - {"co_varnames", T_OBJECT, OFF(co_varnames), READONLY}, - {"co_freevars", T_OBJECT, OFF(co_freevars), READONLY}, - {"co_cellvars", T_OBJECT, OFF(co_cellvars), READONLY}, - {"co_filename", T_OBJECT, OFF(co_filename), READONLY}, - {"co_name", T_OBJECT, OFF(co_name), READONLY}, - {"co_firstlineno", T_INT, OFF(co_firstlineno), READONLY}, - {"co_lnotab", T_OBJECT, OFF(co_lnotab), READONLY}, + {"co_argcount", T_INT, OFF(co_argcount), READONLY}, + {"co_posonlyargcount", T_INT, OFF(co_posonlyargcount), READONLY}, + {"co_kwonlyargcount", T_INT, OFF(co_kwonlyargcount), READONLY}, + {"co_nlocals", T_INT, OFF(co_nlocals), READONLY}, + {"co_stacksize",T_INT, OFF(co_stacksize), READONLY}, + {"co_flags", T_INT, OFF(co_flags), READONLY}, + {"co_code", T_OBJECT, OFF(co_code), READONLY}, + {"co_consts", T_OBJECT, OFF(co_consts), READONLY}, + {"co_names", T_OBJECT, OFF(co_names), READONLY}, + {"co_varnames", T_OBJECT, OFF(co_varnames), READONLY}, + {"co_freevars", T_OBJECT, OFF(co_freevars), READONLY}, + {"co_cellvars", T_OBJECT, OFF(co_cellvars), READONLY}, + {"co_filename", T_OBJECT, OFF(co_filename), READONLY}, + {"co_name", T_OBJECT, OFF(co_name), READONLY}, + {"co_firstlineno", T_INT, OFF(co_firstlineno), READONLY}, + {"co_lnotab", T_OBJECT, OFF(co_lnotab), READONLY}, {NULL} /* Sentinel */ }; @@ -335,9 +340,9 @@ validate_and_copy_tuple(PyObject *tup) } PyDoc_STRVAR(code_doc, -"code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring,\n\ - constants, names, varnames, filename, name, firstlineno,\n\ - lnotab[, freevars[, cellvars]])\n\ +"code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize,\n\ + flags, codestring, constants, names, varnames, filename, name,\n\ + firstlineno, lnotab[, freevars[, cellvars]])\n\ \n\ Create a code object. Not for the faint of heart."); @@ -345,6 +350,7 @@ static PyObject * code_new(PyTypeObject *type, PyObject *args, PyObject *kw) { int argcount; + int posonlyargcount; int kwonlyargcount; int nlocals; int stacksize; @@ -361,8 +367,8 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) int firstlineno; PyObject *lnotab; - if (!PyArg_ParseTuple(args, "iiiiiSO!O!O!UUiS|O!O!:code", - &argcount, &kwonlyargcount, + if (!PyArg_ParseTuple(args, "iiiiiiSO!O!O!UUiS|O!O!:code", + &argcount, &posonlyargcount, &kwonlyargcount, &nlocals, &stacksize, &flags, &code, &PyTuple_Type, &consts, @@ -381,6 +387,13 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) goto cleanup; } + if (posonlyargcount < 0) { + PyErr_SetString( + PyExc_ValueError, + "code: posonlyargcount must not be negative"); + goto cleanup; + } + if (kwonlyargcount < 0) { PyErr_SetString( PyExc_ValueError, @@ -413,7 +426,7 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) if (ourcellvars == NULL) goto cleanup; - co = (PyObject *)PyCode_New(argcount, kwonlyargcount, + co = (PyObject *)PyCode_New(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize, flags, code, consts, ournames, ourvarnames, ourfreevars, ourcellvars, filename, @@ -645,9 +658,11 @@ code_richcompare(PyObject *self, PyObject *other, int op) cp = (PyCodeObject *)other; eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ); - if (eq <= 0) goto unequal; + if (!eq) goto unequal; eq = co->co_argcount == cp->co_argcount; if (!eq) goto unequal; + eq = co->co_posonlyargcount == cp->co_posonlyargcount; + if (!eq) goto unequal; eq = co->co_kwonlyargcount == cp->co_kwonlyargcount; if (!eq) goto unequal; eq = co->co_nlocals == cp->co_nlocals; @@ -720,7 +735,7 @@ code_hash(PyCodeObject *co) h6 = PyObject_Hash(co->co_cellvars); if (h6 == -1) return -1; h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^ - co->co_argcount ^ co->co_kwonlyargcount ^ + co->co_argcount ^ co->co_posonlyargcount ^ co->co_kwonlyargcount ^ co->co_nlocals ^ co->co_flags; if (h == -1) h = -2; return h; diff --git a/PC/launcher.c b/PC/launcher.c index 0f5003a8370e59..ed5ead329e460d 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -1139,7 +1139,7 @@ static PYC_MAGIC magic_values[] = { { 3320, 3351, L"3.5" }, { 3360, 3379, L"3.6" }, { 3390, 3399, L"3.7" }, - { 3400, 3409, L"3.8" }, + { 3400, 3410, L"3.8" }, { 0 } }; diff --git a/Parser/Python.asdl b/Parser/Python.asdl index c32b65a52fe57a..668d3c938090f4 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -111,8 +111,8 @@ module Python excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body) attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset) - arguments = (arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults, - arg? kwarg, expr* defaults) + arguments = (arg* args, arg* posonlyargs, arg? vararg, arg* kwonlyargs, + expr* kw_defaults, arg? kwarg, expr* defaults) arg = (identifier arg, expr? annotation, string? type_comment) attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset) diff --git a/Python/Python-ast.c b/Python/Python-ast.c index d0416eb639c233..6c8488f8fe680a 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -469,6 +469,7 @@ static char *ExceptHandler_fields[]={ }; static PyTypeObject *arguments_type; static PyObject* ast2obj_arguments(void*); +_Py_IDENTIFIER(posonlyargs); _Py_IDENTIFIER(vararg); _Py_IDENTIFIER(kwonlyargs); _Py_IDENTIFIER(kw_defaults); @@ -476,6 +477,7 @@ _Py_IDENTIFIER(kwarg); _Py_IDENTIFIER(defaults); static char *arguments_fields[]={ "args", + "posonlyargs", "vararg", "kwonlyargs", "kw_defaults", @@ -1141,7 +1143,7 @@ static int init_types(void) ExceptHandler_type = make_type("ExceptHandler", excepthandler_type, ExceptHandler_fields, 3); if (!ExceptHandler_type) return 0; - arguments_type = make_type("arguments", &AST_type, arguments_fields, 6); + arguments_type = make_type("arguments", &AST_type, arguments_fields, 7); if (!arguments_type) return 0; if (!add_attributes(arguments_type, NULL, 0)) return 0; arg_type = make_type("arg", &AST_type, arg_fields, 3); @@ -2569,14 +2571,16 @@ ExceptHandler(expr_ty type, identifier name, asdl_seq * body, int lineno, int } arguments_ty -arguments(asdl_seq * args, arg_ty vararg, asdl_seq * kwonlyargs, asdl_seq * - kw_defaults, arg_ty kwarg, asdl_seq * defaults, PyArena *arena) +arguments(asdl_seq * args, asdl_seq * posonlyargs, arg_ty vararg, asdl_seq * + kwonlyargs, asdl_seq * kw_defaults, arg_ty kwarg, asdl_seq * + defaults, PyArena *arena) { arguments_ty p; p = (arguments_ty)PyArena_Malloc(arena, sizeof(*p)); if (!p) return NULL; p->args = args; + p->posonlyargs = posonlyargs; p->vararg = vararg; p->kwonlyargs = kwonlyargs; p->kw_defaults = kw_defaults; @@ -3954,6 +3958,11 @@ ast2obj_arguments(void* _o) if (_PyObject_SetAttrId(result, &PyId_args, value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_list(o->posonlyargs, ast2obj_arg); + if (!value) goto failed; + if (_PyObject_SetAttrId(result, &PyId_posonlyargs, value) == -1) + goto failed; + Py_DECREF(value); value = ast2obj_arg(o->vararg); if (!value) goto failed; if (_PyObject_SetAttrId(result, &PyId_vararg, value) == -1) @@ -8267,6 +8276,7 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) { PyObject* tmp = NULL; asdl_seq* args; + asdl_seq* posonlyargs; arg_ty vararg; asdl_seq* kwonlyargs; asdl_seq* kw_defaults; @@ -8303,6 +8313,36 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) } Py_CLEAR(tmp); } + if (_PyObject_LookupAttrId(obj, &PyId_posonlyargs, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"posonlyargs\" missing from arguments"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "arguments field \"posonlyargs\" must be a list, not a %.200s", tmp->ob_type->tp_name); + goto failed; + } + len = PyList_GET_SIZE(tmp); + posonlyargs = _Py_asdl_seq_new(len, arena); + if (posonlyargs == NULL) goto failed; + for (i = 0; i < len; i++) { + arg_ty val; + res = obj2ast_arg(PyList_GET_ITEM(tmp, i), &val, arena); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "arguments field \"posonlyargs\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(posonlyargs, i, val); + } + Py_CLEAR(tmp); + } if (_PyObject_LookupAttrId(obj, &PyId_vararg, &tmp) < 0) { return 1; } @@ -8419,8 +8459,8 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) } Py_CLEAR(tmp); } - *out = arguments(args, vararg, kwonlyargs, kw_defaults, kwarg, defaults, - arena); + *out = arguments(args, posonlyargs, vararg, kwonlyargs, kw_defaults, kwarg, + defaults, arena); return 0; failed: Py_XDECREF(tmp); diff --git a/Python/ast.c b/Python/ast.c index 913e53ad7937d8..4687f8178b0244 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -110,8 +110,9 @@ expr_context_name(expr_context_ty ctx) static int validate_arguments(arguments_ty args) { - if (!validate_args(args->args)) + if (!validate_args(args->posonlyargs) || !validate_args(args->args)) { return 0; + } if (args->vararg && args->vararg->annotation && !validate_expr(args->vararg->annotation, Load)) { return 0; @@ -1431,31 +1432,73 @@ ast_for_arguments(struct compiling *c, const node *n) and varargslist (lambda definition). parameters: '(' [typedargslist] ')' - typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [',' [ - '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] - | '**' tfpdef [',']]] - | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] - | '**' tfpdef [',']) + + The following definition for typedarglist is equivalent to this set of rules: + + arguments = argument (',' [TYPE_COMMENT] argument)* + argument = tfpdef ['=' test] + kwargs = '**' tfpdef [','] [TYPE_COMMENT] + args = '*' [tfpdef] + kwonly_kwargs = (',' [TYPE_COMMENT] argument)* (TYPE_COMMENT | [',' + [TYPE_COMMENT] [kwargs]]) + args_kwonly_kwargs = args kwonly_kwargs | kwargs + poskeyword_args_kwonly_kwargs = arguments ( TYPE_COMMENT | [',' + [TYPE_COMMENT] [args_kwonly_kwargs]]) + typedargslist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs + typedarglist = (arguments ',' [TYPE_COMMENT] '/' [',' [[TYPE_COMMENT] + typedargslist_no_posonly]])|(typedargslist_no_posonly)" + + typedargslist: ( (tfpdef ['=' test] (',' [TYPE_COMMENT] tfpdef ['=' test])* + ',' [TYPE_COMMENT] '/' [',' [ [TYPE_COMMENT] tfpdef ['=' test] ( ',' + [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] [ '*' + [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' + [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | '**' tfpdef [','] + [TYPE_COMMENT]]]) | '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* + (TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | + '**' tfpdef [','] [TYPE_COMMENT]]] ) | (tfpdef ['=' test] (',' + [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' [TYPE_COMMENT] [ '*' + [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* (TYPE_COMMENT | [',' + [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | '**' tfpdef [','] + [TYPE_COMMENT]]]) | '*' [tfpdef] (',' [TYPE_COMMENT] tfpdef ['=' test])* + (TYPE_COMMENT | [',' [TYPE_COMMENT] ['**' tfpdef [','] [TYPE_COMMENT]]]) | + '**' tfpdef [','] [TYPE_COMMENT])) + tfpdef: NAME [':' test] - varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [',' [ - '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] - | '**' vfpdef [',']]] - | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] - | '**' vfpdef [','] - ) + + The following definition for varargslist is equivalent to this set of rules: + + arguments = argument (',' argument )* + argument = vfpdef ['=' test] + kwargs = '**' vfpdef [','] + args = '*' [vfpdef] + kwonly_kwargs = (',' argument )* [',' [kwargs]] + args_kwonly_kwargs = args kwonly_kwargs | kwargs + poskeyword_args_kwonly_kwargs = arguments [',' [args_kwonly_kwargs]] + vararglist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs + varargslist = arguments ',' '/' [','[(vararglist_no_posonly)]] | + (vararglist_no_posonly) + + varargslist: vfpdef ['=' test ](',' vfpdef ['=' test])* ',' '/' [',' [ (vfpdef ['=' + test] (',' vfpdef ['=' test])* [',' [ '*' [vfpdef] (',' vfpdef ['=' test])* [',' + ['**' vfpdef [',']]] | '**' vfpdef [',']]] | '*' [vfpdef] (',' vfpdef ['=' test])* + [',' ['**' vfpdef [',']]] | '**' vfpdef [',']) ]] | (vfpdef ['=' test] (',' vfpdef + ['=' test])* [',' [ '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef [',']]] + | '**' vfpdef [',']]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' ['**' vfpdef + [',']]] | '**' vfpdef [',']) + vfpdef: NAME */ - int i, j, k, nposargs = 0, nkwonlyargs = 0; + int i, j, k, l, nposonlyargs=0, nposargs = 0, nkwonlyargs = 0; int nposdefaults = 0, found_default = 0; - asdl_seq *posargs, *posdefaults, *kwonlyargs, *kwdefaults; + asdl_seq *posonlyargs, *posargs, *posdefaults, *kwonlyargs, *kwdefaults; arg_ty vararg = NULL, kwarg = NULL; arg_ty arg = NULL; node *ch; if (TYPE(n) == parameters) { if (NCH(n) == 2) /* () as argument list */ - return arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena); + return arguments(NULL, NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena); n = CHILD(n, 1); } assert(TYPE(n) == typedargslist || TYPE(n) == varargslist); @@ -1479,6 +1522,10 @@ ast_for_arguments(struct compiling *c, const node *n) if (TYPE(ch) == DOUBLESTAR) break; if (TYPE(ch) == vfpdef || TYPE(ch) == tfpdef) nposargs++; if (TYPE(ch) == EQUAL) nposdefaults++; + if (TYPE(ch) == SLASH ) { + nposonlyargs = nposargs; + nposargs = 0; + } } /* count the number of keyword only args & defaults for keyword only args */ @@ -1487,6 +1534,10 @@ ast_for_arguments(struct compiling *c, const node *n) if (TYPE(ch) == DOUBLESTAR) break; if (TYPE(ch) == tfpdef || TYPE(ch) == vfpdef) nkwonlyargs++; } + posonlyargs = (nposonlyargs ? _Py_asdl_seq_new(nposonlyargs, c->c_arena) : NULL); + if (!posonlyargs && nposonlyargs) { + return NULL; + } posargs = (nposargs ? _Py_asdl_seq_new(nposargs, c->c_arena) : NULL); if (!posargs && nposargs) return NULL; @@ -1512,6 +1563,7 @@ ast_for_arguments(struct compiling *c, const node *n) i = 0; j = 0; /* index for defaults */ k = 0; /* index for args */ + l = 0; /* index for posonlyargs */ while (i < NCH(n)) { ch = CHILD(n, i); switch (TYPE(ch)) { @@ -1537,11 +1589,23 @@ ast_for_arguments(struct compiling *c, const node *n) arg = ast_for_arg(c, ch); if (!arg) return NULL; - asdl_seq_SET(posargs, k++, arg); + if (l < nposonlyargs) { + asdl_seq_SET(posonlyargs, l++, arg); + } else { + asdl_seq_SET(posargs, k++, arg); + } i += 1; /* the name */ if (i < NCH(n) && TYPE(CHILD(n, i)) == COMMA) i += 1; /* the comma, if present */ break; + case SLASH: + /* Advance the slash and the comma. If there are more names + * after the slash there will be a comma so we are advancing + * the correct number of nodes. If the slash is the last item, + * we will be advancing an extra token but then * i > NCH(n) + * and the enclosing while will finish correctly. */ + i += 2; + break; case STAR: if (i+1 >= NCH(n) || (i+2 == NCH(n) && (TYPE(CHILD(n, i+1)) == COMMA @@ -1621,7 +1685,7 @@ ast_for_arguments(struct compiling *c, const node *n) return NULL; } } - return arguments(posargs, vararg, kwonlyargs, kwdefaults, kwarg, posdefaults, c->c_arena); + return arguments(posargs, posonlyargs, vararg, kwonlyargs, kwdefaults, kwarg, posdefaults, c->c_arena); } static expr_ty @@ -1909,7 +1973,7 @@ ast_for_lambdef(struct compiling *c, const node *n) expr_ty expression; if (NCH(n) == 3) { - args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena); + args = arguments(NULL, NULL, NULL, NULL, NULL, NULL, NULL, c->c_arena); if (!args) return NULL; expression = ast_for_expr(c, CHILD(n, 2)); diff --git a/Python/ceval.c b/Python/ceval.c index ccd0427a142936..8ae273e0820d2a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3694,10 +3694,10 @@ missing_arguments(PyCodeObject *co, Py_ssize_t missing, Py_ssize_t defcount, return; if (positional) { start = 0; - end = co->co_argcount - defcount; + end = co->co_posonlyargcount + co->co_argcount - defcount; } else { - start = co->co_argcount; + start = co->co_posonlyargcount + co->co_argcount; end = start + co->co_kwonlyargcount; } for (i = start; i < end; i++) { @@ -3724,23 +3724,25 @@ too_many_positional(PyCodeObject *co, Py_ssize_t given, Py_ssize_t defcount, Py_ssize_t kwonly_given = 0; Py_ssize_t i; PyObject *sig, *kwonly_sig; + Py_ssize_t co_posonlyargcount = co->co_posonlyargcount; Py_ssize_t co_argcount = co->co_argcount; + Py_ssize_t total_positional = co_argcount + co_posonlyargcount; assert((co->co_flags & CO_VARARGS) == 0); /* Count missing keyword-only args. */ - for (i = co_argcount; i < co_argcount + co->co_kwonlyargcount; i++) { + for (i = total_positional; i < total_positional + co->co_kwonlyargcount; i++) { if (GETLOCAL(i) != NULL) { kwonly_given++; } } if (defcount) { - Py_ssize_t atleast = co_argcount - defcount; + Py_ssize_t atleast = total_positional - defcount; plural = 1; - sig = PyUnicode_FromFormat("from %zd to %zd", atleast, co_argcount); + sig = PyUnicode_FromFormat("from %zd to %zd", atleast, total_positional); } else { - plural = (co_argcount != 1); - sig = PyUnicode_FromFormat("%zd", co_argcount); + plural = (total_positional != 1); + sig = PyUnicode_FromFormat("%zd", total_positional); } if (sig == NULL) return; @@ -3772,6 +3774,67 @@ too_many_positional(PyCodeObject *co, Py_ssize_t given, Py_ssize_t defcount, Py_DECREF(kwonly_sig); } +static int +positional_only_passed_as_keyword(PyCodeObject *co, Py_ssize_t kwcount, + PyObject* const* kwnames) +{ + int posonly_conflicts = 0; + PyObject* posonly_names = PyList_New(0); + + for(int k=0; k < co->co_posonlyargcount; k++){ + PyObject* posonly_name = PyTuple_GET_ITEM(co->co_varnames, k); + + for (int k2=0; k2 0) { + if(PyList_Append(posonly_names, kwname) != 0) { + goto fail; + } + posonly_conflicts++; + } else if (cmp < 0) { + goto fail; + } + + } + } + if (posonly_conflicts) { + PyObject* comma = PyUnicode_FromString(", "); + if (comma == NULL) { + goto fail; + } + PyObject* error_names = PyUnicode_Join(comma, posonly_names); + Py_DECREF(comma); + if (error_names == NULL) { + goto fail; + } + PyErr_Format(PyExc_TypeError, + "%U() got some positional-only arguments passed" + " as keyword arguments: '%U'", + co->co_name, error_names); + Py_DECREF(error_names); + goto fail; + } + + Py_DECREF(posonly_names); + return 0; + +fail: + Py_XDECREF(posonly_names); + return 1; + +} + /* This is gonna seem *real weird*, but if you put some other code between PyEval_EvalFrame() and _PyEval_EvalFrameDefault() you will need to adjust the test in the if statements in Misc/gdbinit (pystack and pystackv). */ @@ -3791,8 +3854,8 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, PyObject **fastlocals, **freevars; PyThreadState *tstate; PyObject *x, *u; - const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount; - Py_ssize_t i, n; + const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount + co->co_posonlyargcount; + Py_ssize_t i, j, n; PyObject *kwdict; if (globals == NULL) { @@ -3826,14 +3889,28 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, kwdict = NULL; } + /* Copy positional only arguments into local variables */ + if (argcount > co->co_argcount + co->co_posonlyargcount) { + n = co->co_posonlyargcount; + } + else { + n = argcount; + } + for (j = 0; j < n; j++) { + x = args[j]; + Py_INCREF(x); + SETLOCAL(j, x); + } + + /* Copy positional arguments into local variables */ - if (argcount > co->co_argcount) { - n = co->co_argcount; + if (argcount > co->co_argcount + co->co_posonlyargcount) { + n += co->co_argcount; } else { n = argcount; } - for (i = 0; i < n; i++) { + for (i = j; i < n; i++) { x = args[i]; Py_INCREF(x); SETLOCAL(i, x); @@ -3866,7 +3943,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, /* Speed hack: do raw pointer compares. As names are normally interned this should almost always hit. */ co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; - for (j = 0; j < total_args; j++) { + for (j = co->co_posonlyargcount; j < total_args; j++) { PyObject *name = co_varnames[j]; if (name == keyword) { goto kw_found; @@ -3874,7 +3951,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, } /* Slow fallback, just in case */ - for (j = 0; j < total_args; j++) { + for (j = co->co_posonlyargcount; j < total_args; j++) { PyObject *name = co_varnames[j]; int cmp = PyObject_RichCompareBool( keyword, name, Py_EQ); if (cmp > 0) { @@ -3887,6 +3964,11 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, assert(j >= total_args); if (kwdict == NULL) { + + if (co->co_posonlyargcount && positional_only_passed_as_keyword(co, kwcount, kwnames)) { + goto fail; + } + PyErr_Format(PyExc_TypeError, "%U() got an unexpected keyword argument '%S'", co->co_name, keyword); @@ -3910,14 +3992,14 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, } /* Check the number of positional arguments */ - if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) { + if ((argcount > co->co_argcount + co->co_posonlyargcount) && !(co->co_flags & CO_VARARGS)) { too_many_positional(co, argcount, defcount, fastlocals); goto fail; } /* Add missing positional arguments (copy default values from defs) */ - if (argcount < co->co_argcount) { - Py_ssize_t m = co->co_argcount - defcount; + if (argcount < co->co_posonlyargcount + co->co_argcount) { + Py_ssize_t m = co->co_posonlyargcount + co->co_argcount - defcount; Py_ssize_t missing = 0; for (i = argcount; i < m; i++) { if (GETLOCAL(i) == NULL) { @@ -3944,7 +4026,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, /* Add missing keyword arguments (copy default values from kwdefs) */ if (co->co_kwonlyargcount > 0) { Py_ssize_t missing = 0; - for (i = co->co_argcount; i < total_args; i++) { + for (i = co->co_posonlyargcount + co->co_argcount; i < total_args; i++) { PyObject *name; if (GETLOCAL(i) != NULL) continue; diff --git a/Python/compile.c b/Python/compile.c index ecf7d357c85645..86f2a09ffb3a68 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -122,6 +122,7 @@ struct compiler_unit { PyObject *u_private; /* for private name mangling */ Py_ssize_t u_argcount; /* number of arguments for block */ + Py_ssize_t u_posonlyargcount; /* number of positional only arguments for block */ Py_ssize_t u_kwonlyargcount; /* number of keyword only arguments for block */ /* Pointer to the most recently allocated block. By following b_list members, you can reach all early allocated blocks. */ @@ -552,6 +553,7 @@ compiler_enter_scope(struct compiler *c, identifier name, memset(u, 0, sizeof(struct compiler_unit)); u->u_scope_type = scope_type; u->u_argcount = 0; + u->u_posonlyargcount = 0; u->u_kwonlyargcount = 0; u->u_ste = PySymtable_Lookup(c->c_st, key); if (!u->u_ste) { @@ -2127,6 +2129,7 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) } c->u->u_argcount = asdl_seq_LEN(args->args); + c->u->u_posonlyargcount = asdl_seq_LEN(args->posonlyargs); c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); VISIT_SEQ_IN_SCOPE(c, stmt, body); co = assemble(c, 1); @@ -2507,6 +2510,7 @@ compiler_lambda(struct compiler *c, expr_ty e) return 0; c->u->u_argcount = asdl_seq_LEN(args->args); + c->u->u_posonlyargcount = asdl_seq_LEN(args->posonlyargs); c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); if (c->u->u_ste->ste_generator) { @@ -5742,7 +5746,7 @@ makecode(struct compiler *c, struct assembler *a) Py_ssize_t nlocals; int nlocals_int; int flags; - int argcount, kwonlyargcount, maxdepth; + int argcount, posonlyargcount, kwonlyargcount, maxdepth; consts = consts_dict_keys_inorder(c->u->u_consts); names = dict_keys_inorder(c->u->u_names, 0); @@ -5787,12 +5791,13 @@ makecode(struct compiler *c, struct assembler *a) } argcount = Py_SAFE_DOWNCAST(c->u->u_argcount, Py_ssize_t, int); + posonlyargcount = Py_SAFE_DOWNCAST(c->u->u_posonlyargcount, Py_ssize_t, int); kwonlyargcount = Py_SAFE_DOWNCAST(c->u->u_kwonlyargcount, Py_ssize_t, int); maxdepth = stackdepth(c); if (maxdepth < 0) { goto error; } - co = PyCode_New(argcount, kwonlyargcount, + co = PyCode_New(argcount, posonlyargcount, kwonlyargcount, nlocals_int, maxdepth, flags, bytecode, consts, names, varnames, freevars, cellvars, diff --git a/Python/frozen.c b/Python/frozen.c index f1901d24deeb66..228a11019cfa6a 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -15,15 +15,15 @@ the appropriate bytes from M___main__.c. */ static unsigned char M___hello__[] = { - 227,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,64,0,0,0,115,16,0,0,0,100,0,90,0,101,1, - 100,1,131,1,1,0,100,2,83,0,41,3,84,122,12,72, - 101,108,108,111,32,119,111,114,108,100,33,78,41,2,218,11, - 105,110,105,116,105,97,108,105,122,101,100,218,5,112,114,105, - 110,116,169,0,114,3,0,0,0,114,3,0,0,0,250,22, - 46,47,84,111,111,108,115,47,102,114,101,101,122,101,47,102, - 108,97,103,46,112,121,218,8,60,109,111,100,117,108,101,62, - 1,0,0,0,115,2,0,0,0,4,1, + 227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,64,0,0,0,115,16,0,0,0,100,0, + 90,0,101,1,100,1,131,1,1,0,100,2,83,0,41,3, + 84,122,12,72,101,108,108,111,32,119,111,114,108,100,33,78, + 41,2,218,11,105,110,105,116,105,97,108,105,122,101,100,218, + 5,112,114,105,110,116,169,0,114,3,0,0,0,114,3,0, + 0,0,250,20,84,111,111,108,115,47,102,114,101,101,122,101, + 47,102,108,97,103,46,112,121,218,8,60,109,111,100,117,108, + 101,62,1,0,0,0,115,2,0,0,0,4,1, }; #define SIZE (int)sizeof(M___hello__) diff --git a/Python/graminit.c b/Python/graminit.c index 96e32aa8fd338e..0587b1c0fc105d 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -216,15 +216,16 @@ static const arc arcs_9_7[3] = { {61, 5}, {0, 7}, }; -static const arc arcs_9_8[5] = { +static const arc arcs_9_8[6] = { {6, 13}, {64, 2}, - {61, 14}, + {68, 14}, + {61, 15}, {65, 3}, {0, 8}, }; static const arc arcs_9_9[1] = { - {60, 15}, + {60, 16}, }; static const arc arcs_9_10[3] = { {64, 2}, @@ -233,7 +234,7 @@ static const arc arcs_9_10[3] = { }; static const arc arcs_9_11[4] = { {66, 4}, - {67, 16}, + {67, 17}, {61, 5}, {0, 11}, }; @@ -242,51 +243,155 @@ static const arc arcs_9_12[2] = { {0, 12}, }; static const arc arcs_9_13[4] = { - {66, 17}, + {66, 18}, {61, 5}, - {65, 18}, + {65, 19}, {0, 13}, }; -static const arc arcs_9_14[4] = { +static const arc arcs_9_14[2] = { + {66, 20}, + {0, 14}, +}; +static const arc arcs_9_15[5] = { {6, 13}, {64, 2}, + {68, 14}, {65, 3}, - {0, 14}, + {0, 15}, }; -static const arc arcs_9_15[3] = { +static const arc arcs_9_16[3] = { {66, 8}, {61, 5}, - {0, 15}, + {0, 16}, }; -static const arc arcs_9_16[1] = { +static const arc arcs_9_17[1] = { {60, 6}, }; -static const arc arcs_9_17[4] = { +static const arc arcs_9_18[4] = { {64, 2}, - {61, 19}, - {65, 20}, - {0, 17}, -}; -static const arc arcs_9_18[3] = { - {66, 17}, - {61, 5}, + {61, 21}, + {65, 22}, {0, 18}, }; static const arc arcs_9_19[3] = { - {64, 2}, - {65, 20}, + {66, 18}, + {61, 5}, {0, 19}, }; -static const arc arcs_9_20[4] = { - {66, 17}, - {67, 21}, - {61, 5}, +static const arc arcs_9_20[5] = { + {6, 23}, + {64, 2}, + {61, 24}, + {65, 25}, {0, 20}, }; -static const arc arcs_9_21[1] = { - {60, 18}, +static const arc arcs_9_21[3] = { + {64, 2}, + {65, 22}, + {0, 21}, +}; +static const arc arcs_9_22[4] = { + {66, 18}, + {67, 26}, + {61, 5}, + {0, 22}, +}; +static const arc arcs_9_23[4] = { + {66, 27}, + {61, 5}, + {65, 28}, + {0, 23}, +}; +static const arc arcs_9_24[1] = { + {65, 25}, +}; +static const arc arcs_9_25[4] = { + {66, 29}, + {67, 30}, + {61, 5}, + {0, 25}, +}; +static const arc arcs_9_26[1] = { + {60, 19}, +}; +static const arc arcs_9_27[4] = { + {64, 2}, + {61, 31}, + {65, 32}, + {0, 27}, +}; +static const arc arcs_9_28[3] = { + {66, 27}, + {61, 5}, + {0, 28}, +}; +static const arc arcs_9_29[5] = { + {6, 33}, + {64, 2}, + {61, 34}, + {65, 25}, + {0, 29}, +}; +static const arc arcs_9_30[1] = { + {60, 35}, +}; +static const arc arcs_9_31[3] = { + {64, 2}, + {65, 32}, + {0, 31}, +}; +static const arc arcs_9_32[4] = { + {66, 27}, + {67, 36}, + {61, 5}, + {0, 32}, +}; +static const arc arcs_9_33[4] = { + {66, 37}, + {61, 5}, + {65, 38}, + {0, 33}, }; -static state states_9[22] = { +static const arc arcs_9_34[4] = { + {6, 33}, + {64, 2}, + {65, 25}, + {0, 34}, +}; +static const arc arcs_9_35[3] = { + {66, 29}, + {61, 5}, + {0, 35}, +}; +static const arc arcs_9_36[1] = { + {60, 28}, +}; +static const arc arcs_9_37[4] = { + {64, 2}, + {61, 39}, + {65, 40}, + {0, 37}, +}; +static const arc arcs_9_38[3] = { + {66, 37}, + {61, 5}, + {0, 38}, +}; +static const arc arcs_9_39[3] = { + {64, 2}, + {65, 40}, + {0, 39}, +}; +static const arc arcs_9_40[4] = { + {66, 37}, + {67, 41}, + {61, 5}, + {0, 40}, +}; +static const arc arcs_9_41[1] = { + {60, 38}, +}; +static state states_9[42] = { {3, arcs_9_0}, {4, arcs_9_1}, {1, arcs_9_2}, @@ -295,20 +400,40 @@ static state states_9[22] = { {1, arcs_9_5}, {3, arcs_9_6}, {3, arcs_9_7}, - {5, arcs_9_8}, + {6, arcs_9_8}, {1, arcs_9_9}, {3, arcs_9_10}, {4, arcs_9_11}, {2, arcs_9_12}, {4, arcs_9_13}, - {4, arcs_9_14}, - {3, arcs_9_15}, - {1, arcs_9_16}, - {4, arcs_9_17}, - {3, arcs_9_18}, + {2, arcs_9_14}, + {5, arcs_9_15}, + {3, arcs_9_16}, + {1, arcs_9_17}, + {4, arcs_9_18}, {3, arcs_9_19}, - {4, arcs_9_20}, - {1, arcs_9_21}, + {5, arcs_9_20}, + {3, arcs_9_21}, + {4, arcs_9_22}, + {4, arcs_9_23}, + {1, arcs_9_24}, + {4, arcs_9_25}, + {1, arcs_9_26}, + {4, arcs_9_27}, + {3, arcs_9_28}, + {5, arcs_9_29}, + {1, arcs_9_30}, + {3, arcs_9_31}, + {4, arcs_9_32}, + {4, arcs_9_33}, + {4, arcs_9_34}, + {3, arcs_9_35}, + {1, arcs_9_36}, + {4, arcs_9_37}, + {3, arcs_9_38}, + {3, arcs_9_39}, + {4, arcs_9_40}, + {1, arcs_9_41}, }; static const arc arcs_10_0[1] = { {40, 1}, @@ -332,15 +457,15 @@ static state states_10[4] = { static const arc arcs_11_0[3] = { {6, 1}, {64, 2}, - {69, 3}, + {70, 3}, }; static const arc arcs_11_1[3] = { {66, 4}, - {69, 5}, + {70, 5}, {0, 1}, }; static const arc arcs_11_2[1] = { - {69, 6}, + {70, 6}, }; static const arc arcs_11_3[3] = { {66, 7}, @@ -349,7 +474,7 @@ static const arc arcs_11_3[3] = { }; static const arc arcs_11_4[3] = { {64, 2}, - {69, 9}, + {70, 9}, {0, 4}, }; static const arc arcs_11_5[2] = { @@ -360,53 +485,126 @@ static const arc arcs_11_6[2] = { {66, 10}, {0, 6}, }; -static const arc arcs_11_7[4] = { +static const arc arcs_11_7[5] = { {6, 11}, {64, 2}, - {69, 3}, + {68, 12}, + {70, 3}, {0, 7}, }; static const arc arcs_11_8[1] = { - {60, 12}, + {60, 13}, }; static const arc arcs_11_9[3] = { {66, 4}, - {67, 13}, + {67, 14}, {0, 9}, }; static const arc arcs_11_10[1] = { {0, 10}, }; static const arc arcs_11_11[3] = { - {66, 14}, - {69, 15}, + {66, 15}, + {70, 16}, {0, 11}, }; static const arc arcs_11_12[2] = { - {66, 7}, + {66, 17}, {0, 12}, }; -static const arc arcs_11_13[1] = { +static const arc arcs_11_13[2] = { + {66, 7}, + {0, 13}, +}; +static const arc arcs_11_14[1] = { {60, 5}, }; -static const arc arcs_11_14[3] = { +static const arc arcs_11_15[3] = { {64, 2}, - {69, 16}, - {0, 14}, -}; -static const arc arcs_11_15[2] = { - {66, 14}, + {70, 18}, {0, 15}, }; -static const arc arcs_11_16[3] = { - {66, 14}, - {67, 17}, +static const arc arcs_11_16[2] = { + {66, 15}, {0, 16}, }; -static const arc arcs_11_17[1] = { - {60, 15}, +static const arc arcs_11_17[4] = { + {6, 19}, + {64, 2}, + {70, 20}, + {0, 17}, +}; +static const arc arcs_11_18[3] = { + {66, 15}, + {67, 21}, + {0, 18}, }; -static state states_11[18] = { +static const arc arcs_11_19[3] = { + {66, 22}, + {70, 23}, + {0, 19}, +}; +static const arc arcs_11_20[3] = { + {66, 24}, + {67, 25}, + {0, 20}, +}; +static const arc arcs_11_21[1] = { + {60, 16}, +}; +static const arc arcs_11_22[3] = { + {64, 2}, + {70, 26}, + {0, 22}, +}; +static const arc arcs_11_23[2] = { + {66, 22}, + {0, 23}, +}; +static const arc arcs_11_24[4] = { + {6, 27}, + {64, 2}, + {70, 20}, + {0, 24}, +}; +static const arc arcs_11_25[1] = { + {60, 28}, +}; +static const arc arcs_11_26[3] = { + {66, 22}, + {67, 29}, + {0, 26}, +}; +static const arc arcs_11_27[3] = { + {66, 30}, + {70, 31}, + {0, 27}, +}; +static const arc arcs_11_28[2] = { + {66, 24}, + {0, 28}, +}; +static const arc arcs_11_29[1] = { + {60, 23}, +}; +static const arc arcs_11_30[3] = { + {64, 2}, + {70, 32}, + {0, 30}, +}; +static const arc arcs_11_31[2] = { + {66, 30}, + {0, 31}, +}; +static const arc arcs_11_32[3] = { + {66, 30}, + {67, 33}, + {0, 32}, +}; +static const arc arcs_11_33[1] = { + {60, 31}, +}; +static state states_11[34] = { {3, arcs_11_0}, {3, arcs_11_1}, {1, arcs_11_2}, @@ -414,17 +612,33 @@ static state states_11[18] = { {3, arcs_11_4}, {2, arcs_11_5}, {2, arcs_11_6}, - {4, arcs_11_7}, + {5, arcs_11_7}, {1, arcs_11_8}, {3, arcs_11_9}, {1, arcs_11_10}, {3, arcs_11_11}, {2, arcs_11_12}, - {1, arcs_11_13}, - {3, arcs_11_14}, - {2, arcs_11_15}, - {3, arcs_11_16}, - {1, arcs_11_17}, + {2, arcs_11_13}, + {1, arcs_11_14}, + {3, arcs_11_15}, + {2, arcs_11_16}, + {4, arcs_11_17}, + {3, arcs_11_18}, + {3, arcs_11_19}, + {3, arcs_11_20}, + {1, arcs_11_21}, + {3, arcs_11_22}, + {2, arcs_11_23}, + {4, arcs_11_24}, + {1, arcs_11_25}, + {3, arcs_11_26}, + {3, arcs_11_27}, + {2, arcs_11_28}, + {1, arcs_11_29}, + {3, arcs_11_30}, + {2, arcs_11_31}, + {3, arcs_11_32}, + {1, arcs_11_33}, }; static const arc arcs_12_0[1] = { {40, 1}, @@ -448,15 +662,15 @@ static state states_13[2] = { {1, arcs_13_1}, }; static const arc arcs_14_0[1] = { - {70, 1}, + {71, 1}, }; static const arc arcs_14_1[2] = { - {71, 2}, + {72, 2}, {2, 3}, }; static const arc arcs_14_2[2] = { {2, 3}, - {70, 1}, + {71, 1}, }; static const arc arcs_14_3[1] = { {0, 3}, @@ -468,7 +682,6 @@ static state states_14[4] = { {1, arcs_14_3}, }; static const arc arcs_15_0[8] = { - {72, 1}, {73, 1}, {74, 1}, {75, 1}, @@ -476,6 +689,7 @@ static const arc arcs_15_0[8] = { {77, 1}, {78, 1}, {79, 1}, + {80, 1}, }; static const arc arcs_15_1[1] = { {0, 1}, @@ -485,24 +699,24 @@ static state states_15[2] = { {1, arcs_15_1}, }; static const arc arcs_16_0[1] = { - {80, 1}, + {81, 1}, }; static const arc arcs_16_1[4] = { {67, 2}, - {81, 3}, - {82, 4}, + {82, 3}, + {83, 4}, {0, 1}, }; static const arc arcs_16_2[2] = { - {80, 5}, - {83, 5}, + {81, 5}, + {84, 5}, }; static const arc arcs_16_3[1] = { {0, 3}, }; static const arc arcs_16_4[2] = { {47, 3}, - {83, 3}, + {84, 3}, }; static const arc arcs_16_5[3] = { {67, 2}, @@ -529,7 +743,7 @@ static const arc arcs_17_2[2] = { }; static const arc arcs_17_3[2] = { {47, 4}, - {83, 4}, + {84, 4}, }; static const arc arcs_17_4[1] = { {0, 4}, @@ -542,7 +756,7 @@ static state states_17[5] = { {1, arcs_17_4}, }; static const arc arcs_18_0[2] = { - {84, 1}, + {85, 1}, {60, 1}, }; static const arc arcs_18_1[2] = { @@ -550,7 +764,7 @@ static const arc arcs_18_1[2] = { {0, 1}, }; static const arc arcs_18_2[3] = { - {84, 1}, + {85, 1}, {60, 1}, {0, 2}, }; @@ -560,7 +774,6 @@ static state states_18[3] = { {3, arcs_18_2}, }; static const arc arcs_19_0[13] = { - {85, 1}, {86, 1}, {87, 1}, {88, 1}, @@ -573,6 +786,7 @@ static const arc arcs_19_0[13] = { {95, 1}, {96, 1}, {97, 1}, + {98, 1}, }; static const arc arcs_19_1[1] = { {0, 1}, @@ -585,7 +799,7 @@ static const arc arcs_20_0[1] = { {20, 1}, }; static const arc arcs_20_1[1] = { - {98, 2}, + {99, 2}, }; static const arc arcs_20_2[1] = { {0, 2}, @@ -606,11 +820,11 @@ static state states_21[2] = { {1, arcs_21_1}, }; static const arc arcs_22_0[5] = { - {99, 1}, {100, 1}, {101, 1}, {102, 1}, {103, 1}, + {104, 1}, }; static const arc arcs_22_1[1] = { {0, 1}, @@ -643,7 +857,7 @@ static const arc arcs_25_0[1] = { {31, 1}, }; static const arc arcs_25_1[2] = { - {80, 2}, + {81, 2}, {0, 1}, }; static const arc arcs_25_2[1] = { @@ -655,7 +869,7 @@ static state states_25[3] = { {1, arcs_25_2}, }; static const arc arcs_26_0[1] = { - {83, 1}, + {84, 1}, }; static const arc arcs_26_1[1] = { {0, 1}, @@ -689,8 +903,8 @@ static state states_27[5] = { {1, arcs_27_4}, }; static const arc arcs_28_0[2] = { - {104, 1}, {105, 1}, + {106, 1}, }; static const arc arcs_28_1[1] = { {0, 1}, @@ -703,7 +917,7 @@ static const arc arcs_29_0[1] = { {25, 1}, }; static const arc arcs_29_1[1] = { - {106, 2}, + {107, 2}, }; static const arc arcs_29_2[1] = { {0, 2}, @@ -717,12 +931,12 @@ static const arc arcs_30_0[1] = { {22, 1}, }; static const arc arcs_30_1[3] = { - {107, 2}, + {108, 2}, {9, 2}, {49, 3}, }; static const arc arcs_30_2[4] = { - {107, 2}, + {108, 2}, {9, 2}, {25, 4}, {49, 3}, @@ -733,10 +947,10 @@ static const arc arcs_30_3[1] = { static const arc arcs_30_4[3] = { {5, 5}, {6, 6}, - {108, 6}, + {109, 6}, }; static const arc arcs_30_5[1] = { - {108, 7}, + {109, 7}, }; static const arc arcs_30_6[1] = { {0, 6}, @@ -758,7 +972,7 @@ static const arc arcs_31_0[1] = { {40, 1}, }; static const arc arcs_31_1[2] = { - {110, 2}, + {111, 2}, {0, 1}, }; static const arc arcs_31_2[1] = { @@ -777,7 +991,7 @@ static const arc arcs_32_0[1] = { {49, 1}, }; static const arc arcs_32_1[2] = { - {110, 2}, + {111, 2}, {0, 1}, }; static const arc arcs_32_2[1] = { @@ -793,14 +1007,14 @@ static state states_32[4] = { {1, arcs_32_3}, }; static const arc arcs_33_0[1] = { - {109, 1}, + {110, 1}, }; static const arc arcs_33_1[2] = { {66, 2}, {0, 1}, }; static const arc arcs_33_2[2] = { - {109, 1}, + {110, 1}, {0, 2}, }; static state states_33[3] = { @@ -809,7 +1023,7 @@ static state states_33[3] = { {2, arcs_33_2}, }; static const arc arcs_34_0[1] = { - {111, 1}, + {112, 1}, }; static const arc arcs_34_1[2] = { {66, 0}, @@ -823,7 +1037,7 @@ static const arc arcs_35_0[1] = { {40, 1}, }; static const arc arcs_35_1[2] = { - {107, 0}, + {108, 0}, {0, 1}, }; static state states_35[2] = { @@ -884,15 +1098,15 @@ static state states_38[5] = { {1, arcs_38_4}, }; static const arc arcs_39_0[9] = { - {112, 1}, + {113, 1}, {55, 1}, {53, 1}, - {113, 1}, - {56, 1}, {114, 1}, + {56, 1}, {115, 1}, {116, 1}, {117, 1}, + {118, 1}, }; static const arc arcs_39_1[1] = { {0, 1}, @@ -905,9 +1119,9 @@ static const arc arcs_40_0[1] = { {38, 1}, }; static const arc arcs_40_1[3] = { - {113, 2}, + {114, 2}, {56, 2}, - {117, 2}, + {118, 2}, }; static const arc arcs_40_2[1] = { {0, 2}, @@ -921,24 +1135,24 @@ static const arc arcs_41_0[1] = { {24, 1}, }; static const arc arcs_41_1[1] = { - {118, 2}, + {119, 2}, }; static const arc arcs_41_2[1] = { {59, 3}, }; static const arc arcs_41_3[1] = { - {119, 4}, + {120, 4}, }; static const arc arcs_41_4[3] = { - {120, 1}, - {121, 5}, + {121, 1}, + {122, 5}, {0, 4}, }; static const arc arcs_41_5[1] = { {59, 6}, }; static const arc arcs_41_6[1] = { - {119, 7}, + {120, 7}, }; static const arc arcs_41_7[1] = { {0, 7}, @@ -957,23 +1171,23 @@ static const arc arcs_42_0[1] = { {33, 1}, }; static const arc arcs_42_1[1] = { - {118, 2}, + {119, 2}, }; static const arc arcs_42_2[1] = { {59, 3}, }; static const arc arcs_42_3[1] = { - {119, 4}, + {120, 4}, }; static const arc arcs_42_4[2] = { - {121, 5}, + {122, 5}, {0, 4}, }; static const arc arcs_42_5[1] = { {59, 6}, }; static const arc arcs_42_6[1] = { - {119, 7}, + {120, 7}, }; static const arc arcs_42_7[1] = { {0, 7}, @@ -992,10 +1206,10 @@ static const arc arcs_43_0[1] = { {21, 1}, }; static const arc arcs_43_1[1] = { - {98, 2}, + {99, 2}, }; static const arc arcs_43_2[1] = { - {122, 3}, + {123, 3}, }; static const arc arcs_43_3[1] = { {47, 4}, @@ -1005,20 +1219,20 @@ static const arc arcs_43_4[1] = { }; static const arc arcs_43_5[2] = { {61, 6}, - {119, 7}, + {120, 7}, }; static const arc arcs_43_6[1] = { - {119, 7}, + {120, 7}, }; static const arc arcs_43_7[2] = { - {121, 8}, + {122, 8}, {0, 7}, }; static const arc arcs_43_8[1] = { {59, 9}, }; static const arc arcs_43_9[1] = { - {119, 10}, + {120, 10}, }; static const arc arcs_43_10[1] = { {0, 10}, @@ -1043,11 +1257,11 @@ static const arc arcs_44_1[1] = { {59, 2}, }; static const arc arcs_44_2[1] = { - {119, 3}, + {120, 3}, }; static const arc arcs_44_3[2] = { - {123, 4}, - {124, 5}, + {124, 4}, + {125, 5}, }; static const arc arcs_44_4[1] = { {59, 6}, @@ -1056,28 +1270,28 @@ static const arc arcs_44_5[1] = { {59, 7}, }; static const arc arcs_44_6[1] = { - {119, 8}, + {120, 8}, }; static const arc arcs_44_7[1] = { - {119, 9}, + {120, 9}, }; static const arc arcs_44_8[1] = { {0, 8}, }; static const arc arcs_44_9[4] = { - {121, 10}, - {123, 4}, - {124, 5}, + {122, 10}, + {124, 4}, + {125, 5}, {0, 9}, }; static const arc arcs_44_10[1] = { {59, 11}, }; static const arc arcs_44_11[1] = { - {119, 12}, + {120, 12}, }; static const arc arcs_44_12[2] = { - {123, 4}, + {124, 4}, {0, 12}, }; static state states_44[13] = { @@ -1099,7 +1313,7 @@ static const arc arcs_45_0[1] = { {34, 1}, }; static const arc arcs_45_1[1] = { - {125, 2}, + {126, 2}, }; static const arc arcs_45_2[2] = { {66, 1}, @@ -1107,10 +1321,10 @@ static const arc arcs_45_2[2] = { }; static const arc arcs_45_3[2] = { {61, 4}, - {119, 5}, + {120, 5}, }; static const arc arcs_45_4[1] = { - {119, 5}, + {120, 5}, }; static const arc arcs_45_5[1] = { {0, 5}, @@ -1127,11 +1341,11 @@ static const arc arcs_46_0[1] = { {60, 1}, }; static const arc arcs_46_1[2] = { - {110, 2}, + {111, 2}, {0, 1}, }; static const arc arcs_46_2[1] = { - {126, 3}, + {127, 3}, }; static const arc arcs_46_3[1] = { {0, 3}, @@ -1143,14 +1357,14 @@ static state states_46[4] = { {1, arcs_46_3}, }; static const arc arcs_47_0[1] = { - {127, 1}, + {128, 1}, }; static const arc arcs_47_1[2] = { {60, 2}, {0, 1}, }; static const arc arcs_47_2[2] = { - {110, 3}, + {111, 3}, {0, 2}, }; static const arc arcs_47_3[1] = { @@ -1171,7 +1385,7 @@ static const arc arcs_48_0[2] = { {4, 2}, }; static const arc arcs_48_1[1] = { - {128, 3}, + {129, 3}, }; static const arc arcs_48_2[1] = { {0, 2}, @@ -1180,7 +1394,7 @@ static const arc arcs_48_3[1] = { {45, 4}, }; static const arc arcs_48_4[2] = { - {129, 2}, + {130, 2}, {45, 4}, }; static state states_48[5] = { @@ -1194,7 +1408,7 @@ static const arc arcs_49_0[1] = { {60, 1}, }; static const arc arcs_49_1[2] = { - {130, 2}, + {131, 2}, {0, 1}, }; static const arc arcs_49_2[1] = { @@ -1210,8 +1424,8 @@ static state states_49[4] = { {1, arcs_49_3}, }; static const arc arcs_50_0[2] = { - {131, 1}, - {132, 2}, + {132, 1}, + {133, 2}, }; static const arc arcs_50_1[1] = { {0, 1}, @@ -1221,10 +1435,10 @@ static const arc arcs_50_2[2] = { {0, 2}, }; static const arc arcs_50_3[1] = { - {132, 4}, + {133, 4}, }; static const arc arcs_50_4[1] = { - {121, 5}, + {122, 5}, }; static const arc arcs_50_5[1] = { {60, 1}, @@ -1238,8 +1452,8 @@ static state states_50[6] = { {1, arcs_50_5}, }; static const arc arcs_51_0[2] = { - {134, 1}, - {132, 1}, + {135, 1}, + {133, 1}, }; static const arc arcs_51_1[1] = { {0, 1}, @@ -1253,7 +1467,7 @@ static const arc arcs_52_0[1] = { }; static const arc arcs_52_1[2] = { {59, 2}, - {68, 3}, + {69, 3}, }; static const arc arcs_52_2[1] = { {60, 4}, @@ -1276,10 +1490,10 @@ static const arc arcs_53_0[1] = { }; static const arc arcs_53_1[2] = { {59, 2}, - {68, 3}, + {69, 3}, }; static const arc arcs_53_2[1] = { - {133, 4}, + {134, 4}, }; static const arc arcs_53_3[1] = { {59, 2}, @@ -1295,10 +1509,10 @@ static state states_53[5] = { {1, arcs_53_4}, }; static const arc arcs_54_0[1] = { - {135, 1}, + {136, 1}, }; static const arc arcs_54_1[2] = { - {136, 0}, + {137, 0}, {0, 1}, }; static state states_54[2] = { @@ -1306,10 +1520,10 @@ static state states_54[2] = { {2, arcs_54_1}, }; static const arc arcs_55_0[1] = { - {137, 1}, + {138, 1}, }; static const arc arcs_55_1[2] = { - {138, 0}, + {139, 0}, {0, 1}, }; static state states_55[2] = { @@ -1318,10 +1532,10 @@ static state states_55[2] = { }; static const arc arcs_56_0[2] = { {28, 1}, - {139, 2}, + {140, 2}, }; static const arc arcs_56_1[1] = { - {137, 2}, + {138, 2}, }; static const arc arcs_56_2[1] = { {0, 2}, @@ -1332,10 +1546,10 @@ static state states_56[3] = { {1, arcs_56_2}, }; static const arc arcs_57_0[1] = { - {126, 1}, + {127, 1}, }; static const arc arcs_57_1[2] = { - {140, 0}, + {141, 0}, {0, 1}, }; static state states_57[2] = { @@ -1343,15 +1557,15 @@ static state states_57[2] = { {2, arcs_57_1}, }; static const arc arcs_58_0[10] = { - {141, 1}, {142, 1}, {143, 1}, - {141, 1}, {144, 1}, + {142, 1}, {145, 1}, {146, 1}, - {122, 1}, - {147, 2}, + {147, 1}, + {123, 1}, + {148, 2}, {28, 3}, }; static const arc arcs_58_1[1] = { @@ -1362,7 +1576,7 @@ static const arc arcs_58_2[2] = { {0, 2}, }; static const arc arcs_58_3[1] = { - {122, 1}, + {123, 1}, }; static state states_58[4] = { {10, arcs_58_0}, @@ -1374,7 +1588,7 @@ static const arc arcs_59_0[1] = { {6, 1}, }; static const arc arcs_59_1[1] = { - {126, 2}, + {127, 2}, }; static const arc arcs_59_2[1] = { {0, 2}, @@ -1385,10 +1599,10 @@ static state states_59[3] = { {1, arcs_59_2}, }; static const arc arcs_60_0[1] = { - {148, 1}, + {149, 1}, }; static const arc arcs_60_1[2] = { - {149, 0}, + {150, 0}, {0, 1}, }; static state states_60[2] = { @@ -1396,10 +1610,10 @@ static state states_60[2] = { {2, arcs_60_1}, }; static const arc arcs_61_0[1] = { - {150, 1}, + {151, 1}, }; static const arc arcs_61_1[2] = { - {151, 0}, + {152, 0}, {0, 1}, }; static state states_61[2] = { @@ -1407,10 +1621,10 @@ static state states_61[2] = { {2, arcs_61_1}, }; static const arc arcs_62_0[1] = { - {152, 1}, + {153, 1}, }; static const arc arcs_62_1[2] = { - {153, 0}, + {154, 0}, {0, 1}, }; static state states_62[2] = { @@ -1418,11 +1632,11 @@ static state states_62[2] = { {2, arcs_62_1}, }; static const arc arcs_63_0[1] = { - {154, 1}, + {155, 1}, }; static const arc arcs_63_1[3] = { - {155, 0}, {156, 0}, + {157, 0}, {0, 1}, }; static state states_63[2] = { @@ -1430,7 +1644,7 @@ static state states_63[2] = { {3, arcs_63_1}, }; static const arc arcs_64_0[1] = { - {157, 1}, + {158, 1}, }; static const arc arcs_64_1[3] = { {7, 0}, @@ -1442,12 +1656,12 @@ static state states_64[2] = { {3, arcs_64_1}, }; static const arc arcs_65_0[1] = { - {158, 1}, + {159, 1}, }; static const arc arcs_65_1[6] = { - {159, 0}, - {6, 0}, {160, 0}, + {6, 0}, + {68, 0}, {161, 0}, {10, 0}, {0, 1}, @@ -1463,7 +1677,7 @@ static const arc arcs_66_0[4] = { {162, 2}, }; static const arc arcs_66_1[1] = { - {158, 2}, + {159, 2}, }; static const arc arcs_66_2[1] = { {0, 2}, @@ -1481,7 +1695,7 @@ static const arc arcs_67_1[2] = { {0, 1}, }; static const arc arcs_67_2[1] = { - {158, 3}, + {159, 3}, }; static const arc arcs_67_3[1] = { {0, 3}, @@ -1523,7 +1737,7 @@ static const arc arcs_69_0[10] = { static const arc arcs_69_1[3] = { {50, 2}, {166, 6}, - {83, 6}, + {84, 6}, }; static const arc arcs_69_2[1] = { {0, 2}, @@ -1561,8 +1775,8 @@ static state states_69[9] = { {1, arcs_69_8}, }; static const arc arcs_70_0[2] = { - {118, 1}, - {84, 1}, + {119, 1}, + {85, 1}, }; static const arc arcs_70_1[3] = { {66, 2}, @@ -1570,8 +1784,8 @@ static const arc arcs_70_1[3] = { {0, 1}, }; static const arc arcs_70_2[3] = { - {118, 4}, - {84, 4}, + {119, 4}, + {85, 4}, {0, 2}, }; static const arc arcs_70_3[1] = { @@ -1590,7 +1804,7 @@ static state states_70[5] = { }; static const arc arcs_71_0[3] = { {5, 1}, - {107, 2}, + {108, 2}, {14, 3}, }; static const arc arcs_71_1[2] = { @@ -1680,16 +1894,16 @@ static state states_74[3] = { {1, arcs_74_2}, }; static const arc arcs_75_0[2] = { - {126, 1}, - {84, 1}, + {127, 1}, + {85, 1}, }; static const arc arcs_75_1[2] = { {66, 2}, {0, 1}, }; static const arc arcs_75_2[3] = { - {126, 1}, - {84, 1}, + {127, 1}, + {85, 1}, {0, 2}, }; static state states_75[3] = { @@ -1715,11 +1929,11 @@ static state states_76[3] = { }; static const arc arcs_77_0[3] = { {64, 1}, - {84, 2}, + {85, 2}, {60, 3}, }; static const arc arcs_77_1[1] = { - {126, 4}, + {127, 4}, }; static const arc arcs_77_2[3] = { {66, 5}, @@ -1738,7 +1952,7 @@ static const arc arcs_77_4[3] = { {0, 4}, }; static const arc arcs_77_5[3] = { - {84, 9}, + {85, 9}, {60, 9}, {0, 5}, }; @@ -1758,7 +1972,7 @@ static const arc arcs_77_9[2] = { {0, 9}, }; static const arc arcs_77_10[1] = { - {126, 12}, + {127, 12}, }; static const arc arcs_77_11[1] = { {59, 13}, @@ -1801,7 +2015,7 @@ static const arc arcs_78_3[2] = { {51, 6}, }; static const arc arcs_78_4[1] = { - {119, 7}, + {120, 7}, }; static const arc arcs_78_5[1] = { {59, 4}, @@ -1847,7 +2061,7 @@ static const arc arcs_80_1[1] = { {60, 3}, }; static const arc arcs_80_2[4] = { - {130, 1}, + {131, 1}, {67, 1}, {170, 3}, {0, 2}, @@ -1876,13 +2090,13 @@ static const arc arcs_82_0[1] = { {21, 1}, }; static const arc arcs_82_1[1] = { - {98, 2}, + {99, 2}, }; static const arc arcs_82_2[1] = { - {122, 3}, + {123, 3}, }; static const arc arcs_82_3[1] = { - {132, 4}, + {133, 4}, }; static const arc arcs_82_4[2] = { {175, 5}, @@ -1918,7 +2132,7 @@ static const arc arcs_84_0[1] = { {24, 1}, }; static const arc arcs_84_1[1] = { - {133, 2}, + {134, 2}, }; static const arc arcs_84_2[2] = { {175, 3}, @@ -1960,7 +2174,7 @@ static state states_86[3] = { }; static const arc arcs_87_0[2] = { {22, 1}, - {80, 2}, + {81, 2}, }; static const arc arcs_87_1[1] = { {60, 2}, @@ -1978,7 +2192,7 @@ static const arc arcs_88_0[2] = { {4, 2}, }; static const arc arcs_88_1[2] = { - {128, 3}, + {129, 3}, {61, 4}, }; static const arc arcs_88_2[1] = { @@ -1991,11 +2205,11 @@ static const arc arcs_88_4[1] = { {2, 6}, }; static const arc arcs_88_5[2] = { - {129, 2}, + {130, 2}, {45, 5}, }; static const arc arcs_88_6[1] = { - {128, 3}, + {129, 3}, }; static state states_88[7] = { {2, arcs_88_0}, @@ -2127,11 +2341,11 @@ static const dfa dfas[92] = { "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {264, "parameters", 4, states_8, "\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {265, "typedargslist", 22, states_9, + {265, "typedargslist", 42, states_9, "\100\000\000\000\000\001\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {266, "tfpdef", 4, states_10, "\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {267, "varargslist", 18, states_11, + {267, "varargslist", 34, states_11, "\100\000\000\000\000\001\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {268, "vfpdef", 2, states_12, "\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, @@ -2148,7 +2362,7 @@ static const dfa dfas[92] = { {274, "testlist_star_expr", 3, states_18, "\340\173\000\024\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {275, "augassign", 2, states_19, - "\000\000\000\000\000\000\000\000\000\000\340\377\003\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\300\377\007\000\000\000\000\000\000\000\000\000\000"}, {276, "del_stmt", 3, states_20, "\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {277, "pass_stmt", 2, states_21, @@ -2204,7 +2418,7 @@ static const dfa dfas[92] = { {302, "with_item", 4, states_46, "\240\173\000\024\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {303, "except_clause", 5, states_47, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000"}, {304, "suite", 5, states_48, "\344\373\325\376\270\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {305, "namedexpr_test", 4, states_49, @@ -2226,7 +2440,7 @@ static const dfa dfas[92] = { {313, "comparison", 2, states_57, "\240\173\000\000\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {314, "comp_op", 4, states_58, - "\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\004\000\340\017\000\000\000\000"}, + "\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\010\000\300\037\000\000\000\000"}, {315, "star_expr", 3, states_59, "\100\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {316, "expr", 2, states_60, @@ -2252,7 +2466,7 @@ static const dfa dfas[92] = { {326, "testlist_comp", 5, states_70, "\340\173\000\024\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {327, "trailer", 7, states_71, - "\040\100\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000"}, + "\040\100\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, {328, "subscriptlist", 3, states_72, "\240\173\000\024\260\007\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {329, "subscript", 5, states_73, @@ -2363,6 +2577,7 @@ static const label labels[183] = { {266, 0}, {12, 0}, {22, 0}, + {17, 0}, {267, 0}, {268, 0}, {271, 0}, @@ -2455,7 +2670,6 @@ static const label labels[183] = { {321, 0}, {322, 0}, {24, 0}, - {17, 0}, {47, 0}, {323, 0}, {324, 0}, diff --git a/Python/importlib.h b/Python/importlib.h index b5774f83de607b..694984af8060f8 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -1,83 +1,84 @@ /* Auto-generated by Programs/_freeze_importlib.c */ const unsigned char _Py_M__importlib_bootstrap[] = { - 99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, - 0,64,0,0,0,115,194,1,0,0,100,0,90,0,100,1, - 97,1,100,2,100,3,132,0,90,2,100,4,100,5,132,0, - 90,3,105,0,90,4,105,0,90,5,71,0,100,6,100,7, - 132,0,100,7,101,6,131,3,90,7,71,0,100,8,100,9, - 132,0,100,9,131,2,90,8,71,0,100,10,100,11,132,0, - 100,11,131,2,90,9,71,0,100,12,100,13,132,0,100,13, - 131,2,90,10,100,14,100,15,132,0,90,11,100,16,100,17, - 132,0,90,12,100,18,100,19,132,0,90,13,100,20,100,21, - 156,1,100,22,100,23,132,2,90,14,100,24,100,25,132,0, - 90,15,100,26,100,27,132,0,90,16,100,28,100,29,132,0, - 90,17,100,30,100,31,132,0,90,18,71,0,100,32,100,33, - 132,0,100,33,131,2,90,19,100,1,100,1,100,34,156,2, - 100,35,100,36,132,2,90,20,100,94,100,37,100,38,132,1, - 90,21,100,39,100,40,156,1,100,41,100,42,132,2,90,22, - 100,43,100,44,132,0,90,23,100,45,100,46,132,0,90,24, - 100,47,100,48,132,0,90,25,100,49,100,50,132,0,90,26, - 100,51,100,52,132,0,90,27,100,53,100,54,132,0,90,28, - 71,0,100,55,100,56,132,0,100,56,131,2,90,29,71,0, - 100,57,100,58,132,0,100,58,131,2,90,30,71,0,100,59, - 100,60,132,0,100,60,131,2,90,31,100,61,100,62,132,0, - 90,32,100,63,100,64,132,0,90,33,100,95,100,65,100,66, - 132,1,90,34,100,67,100,68,132,0,90,35,100,69,90,36, - 101,36,100,70,23,0,90,37,100,71,100,72,132,0,90,38, - 101,39,131,0,90,40,100,73,100,74,132,0,90,41,100,96, - 100,76,100,77,132,1,90,42,100,39,100,78,156,1,100,79, - 100,80,132,2,90,43,100,81,100,82,132,0,90,44,100,97, - 100,84,100,85,132,1,90,45,100,86,100,87,132,0,90,46, - 100,88,100,89,132,0,90,47,100,90,100,91,132,0,90,48, - 100,92,100,93,132,0,90,49,100,1,83,0,41,98,97,83, - 1,0,0,67,111,114,101,32,105,109,112,108,101,109,101,110, - 116,97,116,105,111,110,32,111,102,32,105,109,112,111,114,116, - 46,10,10,84,104,105,115,32,109,111,100,117,108,101,32,105, - 115,32,78,79,84,32,109,101,97,110,116,32,116,111,32,98, - 101,32,100,105,114,101,99,116,108,121,32,105,109,112,111,114, - 116,101,100,33,32,73,116,32,104,97,115,32,98,101,101,110, - 32,100,101,115,105,103,110,101,100,32,115,117,99,104,10,116, - 104,97,116,32,105,116,32,99,97,110,32,98,101,32,98,111, - 111,116,115,116,114,97,112,112,101,100,32,105,110,116,111,32, - 80,121,116,104,111,110,32,97,115,32,116,104,101,32,105,109, - 112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32, - 105,109,112,111,114,116,46,32,65,115,10,115,117,99,104,32, - 105,116,32,114,101,113,117,105,114,101,115,32,116,104,101,32, - 105,110,106,101,99,116,105,111,110,32,111,102,32,115,112,101, - 99,105,102,105,99,32,109,111,100,117,108,101,115,32,97,110, - 100,32,97,116,116,114,105,98,117,116,101,115,32,105,110,32, - 111,114,100,101,114,32,116,111,10,119,111,114,107,46,32,79, - 110,101,32,115,104,111,117,108,100,32,117,115,101,32,105,109, - 112,111,114,116,108,105,98,32,97,115,32,116,104,101,32,112, - 117,98,108,105,99,45,102,97,99,105,110,103,32,118,101,114, - 115,105,111,110,32,111,102,32,116,104,105,115,32,109,111,100, - 117,108,101,46,10,10,78,99,2,0,0,0,0,0,0,0, - 3,0,0,0,7,0,0,0,67,0,0,0,115,56,0,0, - 0,100,1,68,0,93,32,125,2,116,0,124,1,124,2,131, - 2,114,4,116,1,124,0,124,2,116,2,124,1,124,2,131, - 2,131,3,1,0,113,4,124,0,106,3,160,4,124,1,106, - 3,161,1,1,0,100,2,83,0,41,3,122,47,83,105,109, - 112,108,101,32,115,117,98,115,116,105,116,117,116,101,32,102, - 111,114,32,102,117,110,99,116,111,111,108,115,46,117,112,100, - 97,116,101,95,119,114,97,112,112,101,114,46,41,4,218,10, - 95,95,109,111,100,117,108,101,95,95,218,8,95,95,110,97, - 109,101,95,95,218,12,95,95,113,117,97,108,110,97,109,101, - 95,95,218,7,95,95,100,111,99,95,95,78,41,5,218,7, - 104,97,115,97,116,116,114,218,7,115,101,116,97,116,116,114, - 218,7,103,101,116,97,116,116,114,218,8,95,95,100,105,99, - 116,95,95,218,6,117,112,100,97,116,101,41,3,90,3,110, - 101,119,90,3,111,108,100,218,7,114,101,112,108,97,99,101, - 169,0,114,10,0,0,0,250,29,60,102,114,111,122,101,110, - 32,105,109,112,111,114,116,108,105,98,46,95,98,111,111,116, - 115,116,114,97,112,62,218,5,95,119,114,97,112,27,0,0, - 0,115,8,0,0,0,0,2,8,1,10,1,20,1,114,12, - 0,0,0,99,1,0,0,0,0,0,0,0,1,0,0,0, - 2,0,0,0,67,0,0,0,115,12,0,0,0,116,0,116, - 1,131,1,124,0,131,1,83,0,169,1,78,41,2,218,4, - 116,121,112,101,218,3,115,121,115,169,1,218,4,110,97,109, - 101,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 218,11,95,110,101,119,95,109,111,100,117,108,101,35,0,0, - 0,115,2,0,0,0,0,1,114,18,0,0,0,99,0,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,4,0,0,0,64,0,0,0,115,194,1,0,0,100,0, + 90,0,100,1,97,1,100,2,100,3,132,0,90,2,100,4, + 100,5,132,0,90,3,105,0,90,4,105,0,90,5,71,0, + 100,6,100,7,132,0,100,7,101,6,131,3,90,7,71,0, + 100,8,100,9,132,0,100,9,131,2,90,8,71,0,100,10, + 100,11,132,0,100,11,131,2,90,9,71,0,100,12,100,13, + 132,0,100,13,131,2,90,10,100,14,100,15,132,0,90,11, + 100,16,100,17,132,0,90,12,100,18,100,19,132,0,90,13, + 100,20,100,21,156,1,100,22,100,23,132,2,90,14,100,24, + 100,25,132,0,90,15,100,26,100,27,132,0,90,16,100,28, + 100,29,132,0,90,17,100,30,100,31,132,0,90,18,71,0, + 100,32,100,33,132,0,100,33,131,2,90,19,100,1,100,1, + 100,34,156,2,100,35,100,36,132,2,90,20,100,94,100,37, + 100,38,132,1,90,21,100,39,100,40,156,1,100,41,100,42, + 132,2,90,22,100,43,100,44,132,0,90,23,100,45,100,46, + 132,0,90,24,100,47,100,48,132,0,90,25,100,49,100,50, + 132,0,90,26,100,51,100,52,132,0,90,27,100,53,100,54, + 132,0,90,28,71,0,100,55,100,56,132,0,100,56,131,2, + 90,29,71,0,100,57,100,58,132,0,100,58,131,2,90,30, + 71,0,100,59,100,60,132,0,100,60,131,2,90,31,100,61, + 100,62,132,0,90,32,100,63,100,64,132,0,90,33,100,95, + 100,65,100,66,132,1,90,34,100,67,100,68,132,0,90,35, + 100,69,90,36,101,36,100,70,23,0,90,37,100,71,100,72, + 132,0,90,38,101,39,131,0,90,40,100,73,100,74,132,0, + 90,41,100,96,100,76,100,77,132,1,90,42,100,39,100,78, + 156,1,100,79,100,80,132,2,90,43,100,81,100,82,132,0, + 90,44,100,97,100,84,100,85,132,1,90,45,100,86,100,87, + 132,0,90,46,100,88,100,89,132,0,90,47,100,90,100,91, + 132,0,90,48,100,92,100,93,132,0,90,49,100,1,83,0, + 41,98,97,83,1,0,0,67,111,114,101,32,105,109,112,108, + 101,109,101,110,116,97,116,105,111,110,32,111,102,32,105,109, + 112,111,114,116,46,10,10,84,104,105,115,32,109,111,100,117, + 108,101,32,105,115,32,78,79,84,32,109,101,97,110,116,32, + 116,111,32,98,101,32,100,105,114,101,99,116,108,121,32,105, + 109,112,111,114,116,101,100,33,32,73,116,32,104,97,115,32, + 98,101,101,110,32,100,101,115,105,103,110,101,100,32,115,117, + 99,104,10,116,104,97,116,32,105,116,32,99,97,110,32,98, + 101,32,98,111,111,116,115,116,114,97,112,112,101,100,32,105, + 110,116,111,32,80,121,116,104,111,110,32,97,115,32,116,104, + 101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110, + 32,111,102,32,105,109,112,111,114,116,46,32,65,115,10,115, + 117,99,104,32,105,116,32,114,101,113,117,105,114,101,115,32, + 116,104,101,32,105,110,106,101,99,116,105,111,110,32,111,102, + 32,115,112,101,99,105,102,105,99,32,109,111,100,117,108,101, + 115,32,97,110,100,32,97,116,116,114,105,98,117,116,101,115, + 32,105,110,32,111,114,100,101,114,32,116,111,10,119,111,114, + 107,46,32,79,110,101,32,115,104,111,117,108,100,32,117,115, + 101,32,105,109,112,111,114,116,108,105,98,32,97,115,32,116, + 104,101,32,112,117,98,108,105,99,45,102,97,99,105,110,103, + 32,118,101,114,115,105,111,110,32,111,102,32,116,104,105,115, + 32,109,111,100,117,108,101,46,10,10,78,99,2,0,0,0, + 0,0,0,0,0,0,0,0,3,0,0,0,7,0,0,0, + 67,0,0,0,115,56,0,0,0,100,1,68,0,93,32,125, + 2,116,0,124,1,124,2,131,2,114,4,116,1,124,0,124, + 2,116,2,124,1,124,2,131,2,131,3,1,0,113,4,124, + 0,106,3,160,4,124,1,106,3,161,1,1,0,100,2,83, + 0,41,3,122,47,83,105,109,112,108,101,32,115,117,98,115, + 116,105,116,117,116,101,32,102,111,114,32,102,117,110,99,116, + 111,111,108,115,46,117,112,100,97,116,101,95,119,114,97,112, + 112,101,114,46,41,4,218,10,95,95,109,111,100,117,108,101, + 95,95,218,8,95,95,110,97,109,101,95,95,218,12,95,95, + 113,117,97,108,110,97,109,101,95,95,218,7,95,95,100,111, + 99,95,95,78,41,5,218,7,104,97,115,97,116,116,114,218, + 7,115,101,116,97,116,116,114,218,7,103,101,116,97,116,116, + 114,218,8,95,95,100,105,99,116,95,95,218,6,117,112,100, + 97,116,101,41,3,90,3,110,101,119,90,3,111,108,100,218, + 7,114,101,112,108,97,99,101,169,0,114,10,0,0,0,250, + 29,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, + 105,98,46,95,98,111,111,116,115,116,114,97,112,62,218,5, + 95,119,114,97,112,27,0,0,0,115,8,0,0,0,0,2, + 8,1,10,1,20,1,114,12,0,0,0,99,1,0,0,0, + 0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0, + 67,0,0,0,115,12,0,0,0,116,0,116,1,131,1,124, + 0,131,1,83,0,169,1,78,41,2,218,4,116,121,112,101, + 218,3,115,121,115,169,1,218,4,110,97,109,101,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,11,95,110, + 101,119,95,109,111,100,117,108,101,35,0,0,0,115,2,0, + 0,0,0,1,114,18,0,0,0,99,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,1,0,0,0,64,0, 0,0,115,12,0,0,0,101,0,90,1,100,0,90,2,100, 1,83,0,41,2,218,14,95,68,101,97,100,108,111,99,107, @@ -85,52 +86,53 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,114,2,0,0,0,114,10,0,0,0,114,10,0,0, 0,114,10,0,0,0,114,11,0,0,0,114,19,0,0,0, 48,0,0,0,115,2,0,0,0,8,1,114,19,0,0,0, - 99,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,64,0,0,0,115,56,0,0,0,101,0,90,1,100,0, - 90,2,100,1,90,3,100,2,100,3,132,0,90,4,100,4, - 100,5,132,0,90,5,100,6,100,7,132,0,90,6,100,8, - 100,9,132,0,90,7,100,10,100,11,132,0,90,8,100,12, - 83,0,41,13,218,11,95,77,111,100,117,108,101,76,111,99, - 107,122,169,65,32,114,101,99,117,114,115,105,118,101,32,108, - 111,99,107,32,105,109,112,108,101,109,101,110,116,97,116,105, - 111,110,32,119,104,105,99,104,32,105,115,32,97,98,108,101, - 32,116,111,32,100,101,116,101,99,116,32,100,101,97,100,108, - 111,99,107,115,10,32,32,32,32,40,101,46,103,46,32,116, - 104,114,101,97,100,32,49,32,116,114,121,105,110,103,32,116, - 111,32,116,97,107,101,32,108,111,99,107,115,32,65,32,116, - 104,101,110,32,66,44,32,97,110,100,32,116,104,114,101,97, - 100,32,50,32,116,114,121,105,110,103,32,116,111,10,32,32, - 32,32,116,97,107,101,32,108,111,99,107,115,32,66,32,116, - 104,101,110,32,65,41,46,10,32,32,32,32,99,2,0,0, - 0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,0, - 0,115,48,0,0,0,116,0,160,1,161,0,124,0,95,2, - 116,0,160,1,161,0,124,0,95,3,124,1,124,0,95,4, - 100,0,124,0,95,5,100,1,124,0,95,6,100,1,124,0, - 95,7,100,0,83,0,169,2,78,233,0,0,0,0,41,8, - 218,7,95,116,104,114,101,97,100,90,13,97,108,108,111,99, - 97,116,101,95,108,111,99,107,218,4,108,111,99,107,218,6, - 119,97,107,101,117,112,114,17,0,0,0,218,5,111,119,110, - 101,114,218,5,99,111,117,110,116,218,7,119,97,105,116,101, - 114,115,169,2,218,4,115,101,108,102,114,17,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,8, - 95,95,105,110,105,116,95,95,58,0,0,0,115,12,0,0, - 0,0,1,10,1,10,1,6,1,6,1,6,1,122,20,95, - 77,111,100,117,108,101,76,111,99,107,46,95,95,105,110,105, - 116,95,95,99,1,0,0,0,0,0,0,0,4,0,0,0, - 3,0,0,0,67,0,0,0,115,60,0,0,0,116,0,160, - 1,161,0,125,1,124,0,106,2,125,2,116,3,160,4,124, - 2,161,1,125,3,124,3,100,0,107,8,114,36,100,1,83, - 0,124,3,106,2,125,2,124,2,124,1,107,2,114,14,100, - 2,83,0,113,14,100,0,83,0,41,3,78,70,84,41,5, - 114,23,0,0,0,218,9,103,101,116,95,105,100,101,110,116, - 114,26,0,0,0,218,12,95,98,108,111,99,107,105,110,103, - 95,111,110,218,3,103,101,116,41,4,114,30,0,0,0,90, - 2,109,101,218,3,116,105,100,114,24,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,218,12,104,97, - 115,95,100,101,97,100,108,111,99,107,66,0,0,0,115,16, - 0,0,0,0,2,8,1,6,2,10,1,8,1,4,1,6, - 1,8,1,122,24,95,77,111,100,117,108,101,76,111,99,107, - 46,104,97,115,95,100,101,97,100,108,111,99,107,99,1,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,64,0,0,0,115,56,0,0,0,101,0, + 90,1,100,0,90,2,100,1,90,3,100,2,100,3,132,0, + 90,4,100,4,100,5,132,0,90,5,100,6,100,7,132,0, + 90,6,100,8,100,9,132,0,90,7,100,10,100,11,132,0, + 90,8,100,12,83,0,41,13,218,11,95,77,111,100,117,108, + 101,76,111,99,107,122,169,65,32,114,101,99,117,114,115,105, + 118,101,32,108,111,99,107,32,105,109,112,108,101,109,101,110, + 116,97,116,105,111,110,32,119,104,105,99,104,32,105,115,32, + 97,98,108,101,32,116,111,32,100,101,116,101,99,116,32,100, + 101,97,100,108,111,99,107,115,10,32,32,32,32,40,101,46, + 103,46,32,116,104,114,101,97,100,32,49,32,116,114,121,105, + 110,103,32,116,111,32,116,97,107,101,32,108,111,99,107,115, + 32,65,32,116,104,101,110,32,66,44,32,97,110,100,32,116, + 104,114,101,97,100,32,50,32,116,114,121,105,110,103,32,116, + 111,10,32,32,32,32,116,97,107,101,32,108,111,99,107,115, + 32,66,32,116,104,101,110,32,65,41,46,10,32,32,32,32, + 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,2,0,0,0,67,0,0,0,115,48,0,0,0,116,0, + 160,1,161,0,124,0,95,2,116,0,160,1,161,0,124,0, + 95,3,124,1,124,0,95,4,100,0,124,0,95,5,100,1, + 124,0,95,6,100,1,124,0,95,7,100,0,83,0,169,2, + 78,233,0,0,0,0,41,8,218,7,95,116,104,114,101,97, + 100,90,13,97,108,108,111,99,97,116,101,95,108,111,99,107, + 218,4,108,111,99,107,218,6,119,97,107,101,117,112,114,17, + 0,0,0,218,5,111,119,110,101,114,218,5,99,111,117,110, + 116,218,7,119,97,105,116,101,114,115,169,2,218,4,115,101, + 108,102,114,17,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,218,8,95,95,105,110,105,116,95,95, + 58,0,0,0,115,12,0,0,0,0,1,10,1,10,1,6, + 1,6,1,6,1,122,20,95,77,111,100,117,108,101,76,111, + 99,107,46,95,95,105,110,105,116,95,95,99,1,0,0,0, + 0,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0, + 67,0,0,0,115,60,0,0,0,116,0,160,1,161,0,125, + 1,124,0,106,2,125,2,116,3,160,4,124,2,161,1,125, + 3,124,3,100,0,107,8,114,36,100,1,83,0,124,3,106, + 2,125,2,124,2,124,1,107,2,114,14,100,2,83,0,113, + 14,100,0,83,0,41,3,78,70,84,41,5,114,23,0,0, + 0,218,9,103,101,116,95,105,100,101,110,116,114,26,0,0, + 0,218,12,95,98,108,111,99,107,105,110,103,95,111,110,218, + 3,103,101,116,41,4,114,30,0,0,0,90,2,109,101,218, + 3,116,105,100,114,24,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,218,12,104,97,115,95,100,101, + 97,100,108,111,99,107,66,0,0,0,115,16,0,0,0,0, + 2,8,1,6,2,10,1,8,1,4,1,6,1,8,1,122, + 24,95,77,111,100,117,108,101,76,111,99,107,46,104,97,115, + 95,100,101,97,100,108,111,99,107,99,1,0,0,0,0,0, 0,0,0,0,0,0,2,0,0,0,9,0,0,0,67,0, 0,0,115,178,0,0,0,116,0,160,1,161,0,125,1,124, 0,116,2,124,1,60,0,122,148,124,0,106,3,143,110,1, @@ -168,55 +170,56 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 1,2,2,8,1,20,1,6,1,14,1,18,1,8,1,12, 1,12,1,24,2,10,1,16,2,122,19,95,77,111,100,117, 108,101,76,111,99,107,46,97,99,113,117,105,114,101,99,1, - 0,0,0,0,0,0,0,2,0,0,0,9,0,0,0,67, - 0,0,0,115,122,0,0,0,116,0,160,1,161,0,125,1, - 124,0,106,2,143,98,1,0,124,0,106,3,124,1,107,3, - 114,34,116,4,100,1,131,1,130,1,124,0,106,5,100,2, - 107,4,115,48,116,6,130,1,124,0,4,0,106,5,100,3, - 56,0,2,0,95,5,124,0,106,5,100,2,107,2,114,108, - 100,0,124,0,95,3,124,0,106,7,114,108,124,0,4,0, - 106,7,100,3,56,0,2,0,95,7,124,0,106,8,160,9, - 161,0,1,0,87,0,53,0,81,0,82,0,88,0,100,0, - 83,0,41,4,78,250,31,99,97,110,110,111,116,32,114,101, - 108,101,97,115,101,32,117,110,45,97,99,113,117,105,114,101, - 100,32,108,111,99,107,114,22,0,0,0,114,37,0,0,0, - 41,10,114,23,0,0,0,114,32,0,0,0,114,24,0,0, - 0,114,26,0,0,0,218,12,82,117,110,116,105,109,101,69, - 114,114,111,114,114,27,0,0,0,218,14,65,115,115,101,114, - 116,105,111,110,69,114,114,111,114,114,28,0,0,0,114,25, - 0,0,0,114,39,0,0,0,114,40,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,39,0,0, - 0,103,0,0,0,115,22,0,0,0,0,1,8,1,8,1, - 10,1,8,1,14,1,14,1,10,1,6,1,6,1,14,1, - 122,19,95,77,111,100,117,108,101,76,111,99,107,46,114,101, - 108,101,97,115,101,99,1,0,0,0,0,0,0,0,1,0, - 0,0,5,0,0,0,67,0,0,0,115,18,0,0,0,100, - 1,160,0,124,0,106,1,116,2,124,0,131,1,161,2,83, - 0,41,2,78,122,23,95,77,111,100,117,108,101,76,111,99, - 107,40,123,33,114,125,41,32,97,116,32,123,125,169,3,218, - 6,102,111,114,109,97,116,114,17,0,0,0,218,2,105,100, - 169,1,114,30,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,8,95,95,114,101,112,114,95,95, - 116,0,0,0,115,2,0,0,0,0,1,122,20,95,77,111, - 100,117,108,101,76,111,99,107,46,95,95,114,101,112,114,95, - 95,78,41,9,114,1,0,0,0,114,0,0,0,0,114,2, - 0,0,0,114,3,0,0,0,114,31,0,0,0,114,36,0, - 0,0,114,38,0,0,0,114,39,0,0,0,114,48,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,20,0,0,0,52,0,0,0,115,12, - 0,0,0,8,1,4,5,8,8,8,12,8,25,8,13,114, - 20,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,64,0,0,0,115,48,0,0,0,101,0, - 90,1,100,0,90,2,100,1,90,3,100,2,100,3,132,0, - 90,4,100,4,100,5,132,0,90,5,100,6,100,7,132,0, - 90,6,100,8,100,9,132,0,90,7,100,10,83,0,41,11, - 218,16,95,68,117,109,109,121,77,111,100,117,108,101,76,111, - 99,107,122,86,65,32,115,105,109,112,108,101,32,95,77,111, - 100,117,108,101,76,111,99,107,32,101,113,117,105,118,97,108, - 101,110,116,32,102,111,114,32,80,121,116,104,111,110,32,98, - 117,105,108,100,115,32,119,105,116,104,111,117,116,10,32,32, - 32,32,109,117,108,116,105,45,116,104,114,101,97,100,105,110, - 103,32,115,117,112,112,111,114,116,46,99,2,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,9, + 0,0,0,67,0,0,0,115,122,0,0,0,116,0,160,1, + 161,0,125,1,124,0,106,2,143,98,1,0,124,0,106,3, + 124,1,107,3,114,34,116,4,100,1,131,1,130,1,124,0, + 106,5,100,2,107,4,115,48,116,6,130,1,124,0,4,0, + 106,5,100,3,56,0,2,0,95,5,124,0,106,5,100,2, + 107,2,114,108,100,0,124,0,95,3,124,0,106,7,114,108, + 124,0,4,0,106,7,100,3,56,0,2,0,95,7,124,0, + 106,8,160,9,161,0,1,0,87,0,53,0,81,0,82,0, + 88,0,100,0,83,0,41,4,78,250,31,99,97,110,110,111, + 116,32,114,101,108,101,97,115,101,32,117,110,45,97,99,113, + 117,105,114,101,100,32,108,111,99,107,114,22,0,0,0,114, + 37,0,0,0,41,10,114,23,0,0,0,114,32,0,0,0, + 114,24,0,0,0,114,26,0,0,0,218,12,82,117,110,116, + 105,109,101,69,114,114,111,114,114,27,0,0,0,218,14,65, + 115,115,101,114,116,105,111,110,69,114,114,111,114,114,28,0, + 0,0,114,25,0,0,0,114,39,0,0,0,114,40,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 114,39,0,0,0,103,0,0,0,115,22,0,0,0,0,1, + 8,1,8,1,10,1,8,1,14,1,14,1,10,1,6,1, + 6,1,14,1,122,19,95,77,111,100,117,108,101,76,111,99, + 107,46,114,101,108,101,97,115,101,99,1,0,0,0,0,0, + 0,0,0,0,0,0,1,0,0,0,5,0,0,0,67,0, + 0,0,115,18,0,0,0,100,1,160,0,124,0,106,1,116, + 2,124,0,131,1,161,2,83,0,41,2,78,122,23,95,77, + 111,100,117,108,101,76,111,99,107,40,123,33,114,125,41,32, + 97,116,32,123,125,169,3,218,6,102,111,114,109,97,116,114, + 17,0,0,0,218,2,105,100,169,1,114,30,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,8, + 95,95,114,101,112,114,95,95,116,0,0,0,115,2,0,0, + 0,0,1,122,20,95,77,111,100,117,108,101,76,111,99,107, + 46,95,95,114,101,112,114,95,95,78,41,9,114,1,0,0, + 0,114,0,0,0,0,114,2,0,0,0,114,3,0,0,0, + 114,31,0,0,0,114,36,0,0,0,114,38,0,0,0,114, + 39,0,0,0,114,48,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,20,0, + 0,0,52,0,0,0,115,12,0,0,0,8,1,4,5,8, + 8,8,12,8,25,8,13,114,20,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,64,0,0,0,115,48,0,0,0,101,0,90,1,100,0, + 90,2,100,1,90,3,100,2,100,3,132,0,90,4,100,4, + 100,5,132,0,90,5,100,6,100,7,132,0,90,6,100,8, + 100,9,132,0,90,7,100,10,83,0,41,11,218,16,95,68, + 117,109,109,121,77,111,100,117,108,101,76,111,99,107,122,86, + 65,32,115,105,109,112,108,101,32,95,77,111,100,117,108,101, + 76,111,99,107,32,101,113,117,105,118,97,108,101,110,116,32, + 102,111,114,32,80,121,116,104,111,110,32,98,117,105,108,100, + 115,32,119,105,116,104,111,117,116,10,32,32,32,32,109,117, + 108,116,105,45,116,104,114,101,97,100,105,110,103,32,115,117, + 112,112,111,114,116,46,99,2,0,0,0,0,0,0,0,0, 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,115, 16,0,0,0,124,1,124,0,95,0,100,1,124,0,95,1, 100,0,83,0,114,21,0,0,0,41,2,114,17,0,0,0, @@ -224,77 +227,79 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 10,0,0,0,114,11,0,0,0,114,31,0,0,0,124,0, 0,0,115,4,0,0,0,0,1,6,1,122,25,95,68,117, 109,109,121,77,111,100,117,108,101,76,111,99,107,46,95,95, - 105,110,105,116,95,95,99,1,0,0,0,0,0,0,0,1, - 0,0,0,3,0,0,0,67,0,0,0,115,18,0,0,0, - 124,0,4,0,106,0,100,1,55,0,2,0,95,0,100,2, - 83,0,41,3,78,114,37,0,0,0,84,41,1,114,27,0, - 0,0,114,47,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,114,38,0,0,0,128,0,0,0,115, - 4,0,0,0,0,1,14,1,122,24,95,68,117,109,109,121, - 77,111,100,117,108,101,76,111,99,107,46,97,99,113,117,105, - 114,101,99,1,0,0,0,0,0,0,0,1,0,0,0,3, - 0,0,0,67,0,0,0,115,36,0,0,0,124,0,106,0, - 100,1,107,2,114,18,116,1,100,2,131,1,130,1,124,0, - 4,0,106,0,100,3,56,0,2,0,95,0,100,0,83,0, - 41,4,78,114,22,0,0,0,114,41,0,0,0,114,37,0, - 0,0,41,2,114,27,0,0,0,114,42,0,0,0,114,47, + 105,110,105,116,95,95,99,1,0,0,0,0,0,0,0,0, + 0,0,0,1,0,0,0,3,0,0,0,67,0,0,0,115, + 18,0,0,0,124,0,4,0,106,0,100,1,55,0,2,0, + 95,0,100,2,83,0,41,3,78,114,37,0,0,0,84,41, + 1,114,27,0,0,0,114,47,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,38,0,0,0,128, + 0,0,0,115,4,0,0,0,0,1,14,1,122,24,95,68, + 117,109,109,121,77,111,100,117,108,101,76,111,99,107,46,97, + 99,113,117,105,114,101,99,1,0,0,0,0,0,0,0,0, + 0,0,0,1,0,0,0,3,0,0,0,67,0,0,0,115, + 36,0,0,0,124,0,106,0,100,1,107,2,114,18,116,1, + 100,2,131,1,130,1,124,0,4,0,106,0,100,3,56,0, + 2,0,95,0,100,0,83,0,41,4,78,114,22,0,0,0, + 114,41,0,0,0,114,37,0,0,0,41,2,114,27,0,0, + 0,114,42,0,0,0,114,47,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,39,0,0,0,132, + 0,0,0,115,6,0,0,0,0,1,10,1,8,1,122,24, + 95,68,117,109,109,121,77,111,100,117,108,101,76,111,99,107, + 46,114,101,108,101,97,115,101,99,1,0,0,0,0,0,0, + 0,0,0,0,0,1,0,0,0,5,0,0,0,67,0,0, + 0,115,18,0,0,0,100,1,160,0,124,0,106,1,116,2, + 124,0,131,1,161,2,83,0,41,2,78,122,28,95,68,117, + 109,109,121,77,111,100,117,108,101,76,111,99,107,40,123,33, + 114,125,41,32,97,116,32,123,125,114,44,0,0,0,114,47, 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,39,0,0,0,132,0,0,0,115,6,0,0,0, - 0,1,10,1,8,1,122,24,95,68,117,109,109,121,77,111, - 100,117,108,101,76,111,99,107,46,114,101,108,101,97,115,101, - 99,1,0,0,0,0,0,0,0,1,0,0,0,5,0,0, - 0,67,0,0,0,115,18,0,0,0,100,1,160,0,124,0, - 106,1,116,2,124,0,131,1,161,2,83,0,41,2,78,122, - 28,95,68,117,109,109,121,77,111,100,117,108,101,76,111,99, - 107,40,123,33,114,125,41,32,97,116,32,123,125,114,44,0, - 0,0,114,47,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,114,48,0,0,0,137,0,0,0,115, - 2,0,0,0,0,1,122,25,95,68,117,109,109,121,77,111, - 100,117,108,101,76,111,99,107,46,95,95,114,101,112,114,95, - 95,78,41,8,114,1,0,0,0,114,0,0,0,0,114,2, - 0,0,0,114,3,0,0,0,114,31,0,0,0,114,38,0, - 0,0,114,39,0,0,0,114,48,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,49,0,0,0,120,0,0,0,115,10,0,0,0,8,1, - 4,3,8,4,8,4,8,5,114,49,0,0,0,99,0,0, + 0,0,114,48,0,0,0,137,0,0,0,115,2,0,0,0, + 0,1,122,25,95,68,117,109,109,121,77,111,100,117,108,101, + 76,111,99,107,46,95,95,114,101,112,114,95,95,78,41,8, + 114,1,0,0,0,114,0,0,0,0,114,2,0,0,0,114, + 3,0,0,0,114,31,0,0,0,114,38,0,0,0,114,39, + 0,0,0,114,48,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,114,49,0,0, + 0,120,0,0,0,115,10,0,0,0,8,1,4,3,8,4, + 8,4,8,5,114,49,0,0,0,99,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,2,0,0,0,64,0, 0,0,115,36,0,0,0,101,0,90,1,100,0,90,2,100, 1,100,2,132,0,90,3,100,3,100,4,132,0,90,4,100, 5,100,6,132,0,90,5,100,7,83,0,41,8,218,18,95, 77,111,100,117,108,101,76,111,99,107,77,97,110,97,103,101, - 114,99,2,0,0,0,0,0,0,0,2,0,0,0,2,0, - 0,0,67,0,0,0,115,16,0,0,0,124,1,124,0,95, - 0,100,0,124,0,95,1,100,0,83,0,114,13,0,0,0, - 41,2,218,5,95,110,97,109,101,218,5,95,108,111,99,107, - 114,29,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,31,0,0,0,143,0,0,0,115,4,0, - 0,0,0,1,6,1,122,27,95,77,111,100,117,108,101,76, - 111,99,107,77,97,110,97,103,101,114,46,95,95,105,110,105, - 116,95,95,99,1,0,0,0,0,0,0,0,1,0,0,0, - 2,0,0,0,67,0,0,0,115,26,0,0,0,116,0,124, - 0,106,1,131,1,124,0,95,2,124,0,106,2,160,3,161, - 0,1,0,100,0,83,0,114,13,0,0,0,41,4,218,16, - 95,103,101,116,95,109,111,100,117,108,101,95,108,111,99,107, - 114,51,0,0,0,114,52,0,0,0,114,38,0,0,0,114, - 47,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,218,9,95,95,101,110,116,101,114,95,95,147,0, - 0,0,115,4,0,0,0,0,1,12,1,122,28,95,77,111, - 100,117,108,101,76,111,99,107,77,97,110,97,103,101,114,46, - 95,95,101,110,116,101,114,95,95,99,1,0,0,0,0,0, - 0,0,3,0,0,0,2,0,0,0,79,0,0,0,115,14, - 0,0,0,124,0,106,0,160,1,161,0,1,0,100,0,83, - 0,114,13,0,0,0,41,2,114,52,0,0,0,114,39,0, - 0,0,41,3,114,30,0,0,0,218,4,97,114,103,115,90, - 6,107,119,97,114,103,115,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,8,95,95,101,120,105,116,95,95, - 151,0,0,0,115,2,0,0,0,0,1,122,27,95,77,111, - 100,117,108,101,76,111,99,107,77,97,110,97,103,101,114,46, - 95,95,101,120,105,116,95,95,78,41,6,114,1,0,0,0, - 114,0,0,0,0,114,2,0,0,0,114,31,0,0,0,114, - 54,0,0,0,114,56,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,50,0, - 0,0,141,0,0,0,115,6,0,0,0,8,2,8,4,8, - 4,114,50,0,0,0,99,1,0,0,0,0,0,0,0,3, + 114,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, + 0,0,2,0,0,0,67,0,0,0,115,16,0,0,0,124, + 1,124,0,95,0,100,0,124,0,95,1,100,0,83,0,114, + 13,0,0,0,41,2,218,5,95,110,97,109,101,218,5,95, + 108,111,99,107,114,29,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,31,0,0,0,143,0,0, + 0,115,4,0,0,0,0,1,6,1,122,27,95,77,111,100, + 117,108,101,76,111,99,107,77,97,110,97,103,101,114,46,95, + 95,105,110,105,116,95,95,99,1,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,0,2,0,0,0,67,0,0,0, + 115,26,0,0,0,116,0,124,0,106,1,131,1,124,0,95, + 2,124,0,106,2,160,3,161,0,1,0,100,0,83,0,114, + 13,0,0,0,41,4,218,16,95,103,101,116,95,109,111,100, + 117,108,101,95,108,111,99,107,114,51,0,0,0,114,52,0, + 0,0,114,38,0,0,0,114,47,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,218,9,95,95,101, + 110,116,101,114,95,95,147,0,0,0,115,4,0,0,0,0, + 1,12,1,122,28,95,77,111,100,117,108,101,76,111,99,107, + 77,97,110,97,103,101,114,46,95,95,101,110,116,101,114,95, + 95,99,1,0,0,0,0,0,0,0,0,0,0,0,3,0, + 0,0,2,0,0,0,79,0,0,0,115,14,0,0,0,124, + 0,106,0,160,1,161,0,1,0,100,0,83,0,114,13,0, + 0,0,41,2,114,52,0,0,0,114,39,0,0,0,41,3, + 114,30,0,0,0,218,4,97,114,103,115,90,6,107,119,97, + 114,103,115,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,218,8,95,95,101,120,105,116,95,95,151,0,0,0, + 115,2,0,0,0,0,1,122,27,95,77,111,100,117,108,101, + 76,111,99,107,77,97,110,97,103,101,114,46,95,95,101,120, + 105,116,95,95,78,41,6,114,1,0,0,0,114,0,0,0, + 0,114,2,0,0,0,114,31,0,0,0,114,54,0,0,0, + 114,56,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,50,0,0,0,141,0, + 0,0,115,6,0,0,0,8,2,8,4,8,4,114,50,0, + 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,3, 0,0,0,8,0,0,0,67,0,0,0,115,130,0,0,0, 116,0,160,1,161,0,1,0,122,106,122,14,116,2,124,0, 25,0,131,0,125,1,87,0,110,24,4,0,116,3,107,10, @@ -313,80 +318,81 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 32,103,108,111,98,97,108,32,105,109,112,111,114,116,32,108, 111,99,107,32,116,111,32,112,114,111,116,101,99,116,10,32, 32,32,32,95,109,111,100,117,108,101,95,108,111,99,107,115, - 46,78,99,2,0,0,0,0,0,0,0,2,0,0,0,8, - 0,0,0,83,0,0,0,115,48,0,0,0,116,0,160,1, - 161,0,1,0,122,24,116,2,160,3,124,1,161,1,124,0, - 107,8,114,30,116,2,124,1,61,0,87,0,53,0,116,0, - 160,4,161,0,1,0,88,0,100,0,83,0,114,13,0,0, - 0,41,5,218,4,95,105,109,112,218,12,97,99,113,117,105, - 114,101,95,108,111,99,107,218,13,95,109,111,100,117,108,101, - 95,108,111,99,107,115,114,34,0,0,0,218,12,114,101,108, - 101,97,115,101,95,108,111,99,107,41,2,218,3,114,101,102, - 114,17,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,218,2,99,98,176,0,0,0,115,10,0,0, - 0,0,1,8,1,2,4,14,1,10,2,122,28,95,103,101, - 116,95,109,111,100,117,108,101,95,108,111,99,107,46,60,108, - 111,99,97,108,115,62,46,99,98,41,10,114,57,0,0,0, - 114,58,0,0,0,114,59,0,0,0,218,8,75,101,121,69, - 114,114,111,114,114,23,0,0,0,114,49,0,0,0,114,20, - 0,0,0,218,8,95,119,101,97,107,114,101,102,114,61,0, - 0,0,114,60,0,0,0,41,3,114,17,0,0,0,114,24, - 0,0,0,114,62,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,53,0,0,0,157,0,0,0, - 115,28,0,0,0,0,6,8,1,2,1,2,1,14,1,14, - 1,10,2,8,1,8,1,10,2,8,2,12,11,20,2,10, - 2,114,53,0,0,0,99,1,0,0,0,0,0,0,0,2, - 0,0,0,8,0,0,0,67,0,0,0,115,54,0,0,0, - 116,0,124,0,131,1,125,1,122,12,124,1,160,1,161,0, - 1,0,87,0,110,20,4,0,116,2,107,10,114,40,1,0, - 1,0,1,0,89,0,110,10,88,0,124,1,160,3,161,0, - 1,0,100,1,83,0,41,2,122,189,65,99,113,117,105,114, - 101,115,32,116,104,101,110,32,114,101,108,101,97,115,101,115, - 32,116,104,101,32,109,111,100,117,108,101,32,108,111,99,107, - 32,102,111,114,32,97,32,103,105,118,101,110,32,109,111,100, - 117,108,101,32,110,97,109,101,46,10,10,32,32,32,32,84, - 104,105,115,32,105,115,32,117,115,101,100,32,116,111,32,101, - 110,115,117,114,101,32,97,32,109,111,100,117,108,101,32,105, - 115,32,99,111,109,112,108,101,116,101,108,121,32,105,110,105, - 116,105,97,108,105,122,101,100,44,32,105,110,32,116,104,101, - 10,32,32,32,32,101,118,101,110,116,32,105,116,32,105,115, - 32,98,101,105,110,103,32,105,109,112,111,114,116,101,100,32, - 98,121,32,97,110,111,116,104,101,114,32,116,104,114,101,97, - 100,46,10,32,32,32,32,78,41,4,114,53,0,0,0,114, - 38,0,0,0,114,19,0,0,0,114,39,0,0,0,41,2, - 114,17,0,0,0,114,24,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,19,95,108,111,99,107, - 95,117,110,108,111,99,107,95,109,111,100,117,108,101,194,0, - 0,0,115,12,0,0,0,0,6,8,1,2,1,12,1,14, - 3,6,2,114,65,0,0,0,99,1,0,0,0,0,0,0, - 0,3,0,0,0,3,0,0,0,79,0,0,0,115,10,0, - 0,0,124,0,124,1,124,2,142,1,83,0,41,1,97,46, - 1,0,0,114,101,109,111,118,101,95,105,109,112,111,114,116, - 108,105,98,95,102,114,97,109,101,115,32,105,110,32,105,109, - 112,111,114,116,46,99,32,119,105,108,108,32,97,108,119,97, - 121,115,32,114,101,109,111,118,101,32,115,101,113,117,101,110, - 99,101,115,10,32,32,32,32,111,102,32,105,109,112,111,114, - 116,108,105,98,32,102,114,97,109,101,115,32,116,104,97,116, - 32,101,110,100,32,119,105,116,104,32,97,32,99,97,108,108, - 32,116,111,32,116,104,105,115,32,102,117,110,99,116,105,111, - 110,10,10,32,32,32,32,85,115,101,32,105,116,32,105,110, - 115,116,101,97,100,32,111,102,32,97,32,110,111,114,109,97, - 108,32,99,97,108,108,32,105,110,32,112,108,97,99,101,115, - 32,119,104,101,114,101,32,105,110,99,108,117,100,105,110,103, - 32,116,104,101,32,105,109,112,111,114,116,108,105,98,10,32, - 32,32,32,102,114,97,109,101,115,32,105,110,116,114,111,100, - 117,99,101,115,32,117,110,119,97,110,116,101,100,32,110,111, - 105,115,101,32,105,110,116,111,32,116,104,101,32,116,114,97, - 99,101,98,97,99,107,32,40,101,46,103,46,32,119,104,101, - 110,32,101,120,101,99,117,116,105,110,103,10,32,32,32,32, - 109,111,100,117,108,101,32,99,111,100,101,41,10,32,32,32, - 32,114,10,0,0,0,41,3,218,1,102,114,55,0,0,0, - 90,4,107,119,100,115,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,218,25,95,99,97,108,108,95,119,105,116, - 104,95,102,114,97,109,101,115,95,114,101,109,111,118,101,100, - 211,0,0,0,115,2,0,0,0,0,8,114,67,0,0,0, - 114,37,0,0,0,41,1,218,9,118,101,114,98,111,115,105, - 116,121,99,1,0,0,0,1,0,0,0,3,0,0,0,4, + 46,78,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,8,0,0,0,83,0,0,0,115,48,0,0,0, + 116,0,160,1,161,0,1,0,122,24,116,2,160,3,124,1, + 161,1,124,0,107,8,114,30,116,2,124,1,61,0,87,0, + 53,0,116,0,160,4,161,0,1,0,88,0,100,0,83,0, + 114,13,0,0,0,41,5,218,4,95,105,109,112,218,12,97, + 99,113,117,105,114,101,95,108,111,99,107,218,13,95,109,111, + 100,117,108,101,95,108,111,99,107,115,114,34,0,0,0,218, + 12,114,101,108,101,97,115,101,95,108,111,99,107,41,2,218, + 3,114,101,102,114,17,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,218,2,99,98,176,0,0,0, + 115,10,0,0,0,0,1,8,1,2,4,14,1,10,2,122, + 28,95,103,101,116,95,109,111,100,117,108,101,95,108,111,99, + 107,46,60,108,111,99,97,108,115,62,46,99,98,41,10,114, + 57,0,0,0,114,58,0,0,0,114,59,0,0,0,218,8, + 75,101,121,69,114,114,111,114,114,23,0,0,0,114,49,0, + 0,0,114,20,0,0,0,218,8,95,119,101,97,107,114,101, + 102,114,61,0,0,0,114,60,0,0,0,41,3,114,17,0, + 0,0,114,24,0,0,0,114,62,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,53,0,0,0, + 157,0,0,0,115,28,0,0,0,0,6,8,1,2,1,2, + 1,14,1,14,1,10,2,8,1,8,1,10,2,8,2,12, + 11,20,2,10,2,114,53,0,0,0,99,1,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,8,0,0,0,67, + 0,0,0,115,54,0,0,0,116,0,124,0,131,1,125,1, + 122,12,124,1,160,1,161,0,1,0,87,0,110,20,4,0, + 116,2,107,10,114,40,1,0,1,0,1,0,89,0,110,10, + 88,0,124,1,160,3,161,0,1,0,100,1,83,0,41,2, + 122,189,65,99,113,117,105,114,101,115,32,116,104,101,110,32, + 114,101,108,101,97,115,101,115,32,116,104,101,32,109,111,100, + 117,108,101,32,108,111,99,107,32,102,111,114,32,97,32,103, + 105,118,101,110,32,109,111,100,117,108,101,32,110,97,109,101, + 46,10,10,32,32,32,32,84,104,105,115,32,105,115,32,117, + 115,101,100,32,116,111,32,101,110,115,117,114,101,32,97,32, + 109,111,100,117,108,101,32,105,115,32,99,111,109,112,108,101, + 116,101,108,121,32,105,110,105,116,105,97,108,105,122,101,100, + 44,32,105,110,32,116,104,101,10,32,32,32,32,101,118,101, + 110,116,32,105,116,32,105,115,32,98,101,105,110,103,32,105, + 109,112,111,114,116,101,100,32,98,121,32,97,110,111,116,104, + 101,114,32,116,104,114,101,97,100,46,10,32,32,32,32,78, + 41,4,114,53,0,0,0,114,38,0,0,0,114,19,0,0, + 0,114,39,0,0,0,41,2,114,17,0,0,0,114,24,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,218,19,95,108,111,99,107,95,117,110,108,111,99,107,95, + 109,111,100,117,108,101,194,0,0,0,115,12,0,0,0,0, + 6,8,1,2,1,12,1,14,3,6,2,114,65,0,0,0, + 99,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,79,0,0,0,115,10,0,0,0,124,0, + 124,1,124,2,142,1,83,0,41,1,97,46,1,0,0,114, + 101,109,111,118,101,95,105,109,112,111,114,116,108,105,98,95, + 102,114,97,109,101,115,32,105,110,32,105,109,112,111,114,116, + 46,99,32,119,105,108,108,32,97,108,119,97,121,115,32,114, + 101,109,111,118,101,32,115,101,113,117,101,110,99,101,115,10, + 32,32,32,32,111,102,32,105,109,112,111,114,116,108,105,98, + 32,102,114,97,109,101,115,32,116,104,97,116,32,101,110,100, + 32,119,105,116,104,32,97,32,99,97,108,108,32,116,111,32, + 116,104,105,115,32,102,117,110,99,116,105,111,110,10,10,32, + 32,32,32,85,115,101,32,105,116,32,105,110,115,116,101,97, + 100,32,111,102,32,97,32,110,111,114,109,97,108,32,99,97, + 108,108,32,105,110,32,112,108,97,99,101,115,32,119,104,101, + 114,101,32,105,110,99,108,117,100,105,110,103,32,116,104,101, + 32,105,109,112,111,114,116,108,105,98,10,32,32,32,32,102, + 114,97,109,101,115,32,105,110,116,114,111,100,117,99,101,115, + 32,117,110,119,97,110,116,101,100,32,110,111,105,115,101,32, + 105,110,116,111,32,116,104,101,32,116,114,97,99,101,98,97, + 99,107,32,40,101,46,103,46,32,119,104,101,110,32,101,120, + 101,99,117,116,105,110,103,10,32,32,32,32,109,111,100,117, + 108,101,32,99,111,100,101,41,10,32,32,32,32,114,10,0, + 0,0,41,3,218,1,102,114,55,0,0,0,90,4,107,119, + 100,115,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,218,25,95,99,97,108,108,95,119,105,116,104,95,102,114, + 97,109,101,115,95,114,101,109,111,118,101,100,211,0,0,0, + 115,2,0,0,0,0,8,114,67,0,0,0,114,37,0,0, + 0,41,1,218,9,118,101,114,98,111,115,105,116,121,99,1, + 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,4, 0,0,0,71,0,0,0,115,54,0,0,0,116,0,106,1, 106,2,124,1,107,5,114,50,124,0,160,3,100,1,161,1, 115,30,100,2,124,0,23,0,125,0,116,4,124,0,106,5, @@ -405,42 +411,43 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 10,0,0,0,114,11,0,0,0,218,16,95,118,101,114,98, 111,115,101,95,109,101,115,115,97,103,101,222,0,0,0,115, 8,0,0,0,0,2,12,1,10,1,8,1,114,76,0,0, - 0,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, - 0,0,3,0,0,0,115,26,0,0,0,135,0,102,1,100, - 1,100,2,132,8,125,1,116,0,124,1,136,0,131,2,1, - 0,124,1,83,0,41,3,122,49,68,101,99,111,114,97,116, - 111,114,32,116,111,32,118,101,114,105,102,121,32,116,104,101, - 32,110,97,109,101,100,32,109,111,100,117,108,101,32,105,115, - 32,98,117,105,108,116,45,105,110,46,99,2,0,0,0,0, - 0,0,0,2,0,0,0,4,0,0,0,19,0,0,0,115, - 38,0,0,0,124,1,116,0,106,1,107,7,114,28,116,2, - 100,1,160,3,124,1,161,1,124,1,100,2,141,2,130,1, - 136,0,124,0,124,1,131,2,83,0,41,3,78,250,29,123, - 33,114,125,32,105,115,32,110,111,116,32,97,32,98,117,105, - 108,116,45,105,110,32,109,111,100,117,108,101,114,16,0,0, - 0,41,4,114,15,0,0,0,218,20,98,117,105,108,116,105, - 110,95,109,111,100,117,108,101,95,110,97,109,101,115,218,11, - 73,109,112,111,114,116,69,114,114,111,114,114,45,0,0,0, - 169,2,114,30,0,0,0,218,8,102,117,108,108,110,97,109, - 101,169,1,218,3,102,120,110,114,10,0,0,0,114,11,0, - 0,0,218,25,95,114,101,113,117,105,114,101,115,95,98,117, - 105,108,116,105,110,95,119,114,97,112,112,101,114,232,0,0, - 0,115,10,0,0,0,0,1,10,1,10,1,2,255,6,2, - 122,52,95,114,101,113,117,105,114,101,115,95,98,117,105,108, - 116,105,110,46,60,108,111,99,97,108,115,62,46,95,114,101, - 113,117,105,114,101,115,95,98,117,105,108,116,105,110,95,119, - 114,97,112,112,101,114,169,1,114,12,0,0,0,41,2,114, - 83,0,0,0,114,84,0,0,0,114,10,0,0,0,114,82, - 0,0,0,114,11,0,0,0,218,17,95,114,101,113,117,105, - 114,101,115,95,98,117,105,108,116,105,110,230,0,0,0,115, - 6,0,0,0,0,2,12,5,10,1,114,86,0,0,0,99, - 1,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, - 3,0,0,0,115,26,0,0,0,135,0,102,1,100,1,100, - 2,132,8,125,1,116,0,124,1,136,0,131,2,1,0,124, - 1,83,0,41,3,122,47,68,101,99,111,114,97,116,111,114, - 32,116,111,32,118,101,114,105,102,121,32,116,104,101,32,110, - 97,109,101,100,32,109,111,100,117,108,101,32,105,115,32,102, - 114,111,122,101,110,46,99,2,0,0,0,0,0,0,0,2, + 0,99,1,0,0,0,0,0,0,0,0,0,0,0,2,0, + 0,0,3,0,0,0,3,0,0,0,115,26,0,0,0,135, + 0,102,1,100,1,100,2,132,8,125,1,116,0,124,1,136, + 0,131,2,1,0,124,1,83,0,41,3,122,49,68,101,99, + 111,114,97,116,111,114,32,116,111,32,118,101,114,105,102,121, + 32,116,104,101,32,110,97,109,101,100,32,109,111,100,117,108, + 101,32,105,115,32,98,117,105,108,116,45,105,110,46,99,2, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,4, + 0,0,0,19,0,0,0,115,38,0,0,0,124,1,116,0, + 106,1,107,7,114,28,116,2,100,1,160,3,124,1,161,1, + 124,1,100,2,141,2,130,1,136,0,124,0,124,1,131,2, + 83,0,41,3,78,250,29,123,33,114,125,32,105,115,32,110, + 111,116,32,97,32,98,117,105,108,116,45,105,110,32,109,111, + 100,117,108,101,114,16,0,0,0,41,4,114,15,0,0,0, + 218,20,98,117,105,108,116,105,110,95,109,111,100,117,108,101, + 95,110,97,109,101,115,218,11,73,109,112,111,114,116,69,114, + 114,111,114,114,45,0,0,0,169,2,114,30,0,0,0,218, + 8,102,117,108,108,110,97,109,101,169,1,218,3,102,120,110, + 114,10,0,0,0,114,11,0,0,0,218,25,95,114,101,113, + 117,105,114,101,115,95,98,117,105,108,116,105,110,95,119,114, + 97,112,112,101,114,232,0,0,0,115,10,0,0,0,0,1, + 10,1,10,1,2,255,6,2,122,52,95,114,101,113,117,105, + 114,101,115,95,98,117,105,108,116,105,110,46,60,108,111,99, + 97,108,115,62,46,95,114,101,113,117,105,114,101,115,95,98, + 117,105,108,116,105,110,95,119,114,97,112,112,101,114,169,1, + 114,12,0,0,0,41,2,114,83,0,0,0,114,84,0,0, + 0,114,10,0,0,0,114,82,0,0,0,114,11,0,0,0, + 218,17,95,114,101,113,117,105,114,101,115,95,98,117,105,108, + 116,105,110,230,0,0,0,115,6,0,0,0,0,2,12,5, + 10,1,114,86,0,0,0,99,1,0,0,0,0,0,0,0, + 0,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0, + 115,26,0,0,0,135,0,102,1,100,1,100,2,132,8,125, + 1,116,0,124,1,136,0,131,2,1,0,124,1,83,0,41, + 3,122,47,68,101,99,111,114,97,116,111,114,32,116,111,32, + 118,101,114,105,102,121,32,116,104,101,32,110,97,109,101,100, + 32,109,111,100,117,108,101,32,105,115,32,102,114,111,122,101, + 110,46,99,2,0,0,0,0,0,0,0,0,0,0,0,2, 0,0,0,4,0,0,0,19,0,0,0,115,38,0,0,0, 116,0,160,1,124,1,161,1,115,28,116,2,100,1,160,3, 124,1,161,1,124,1,100,2,141,2,130,1,136,0,124,0, @@ -460,170 +467,171 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,114,82,0,0,0,114,11,0,0,0,218,16,95,114, 101,113,117,105,114,101,115,95,102,114,111,122,101,110,241,0, 0,0,115,6,0,0,0,0,2,12,5,10,1,114,90,0, - 0,0,99,2,0,0,0,0,0,0,0,4,0,0,0,3, - 0,0,0,67,0,0,0,115,62,0,0,0,116,0,124,1, - 124,0,131,2,125,2,124,1,116,1,106,2,107,6,114,50, - 116,1,106,2,124,1,25,0,125,3,116,3,124,2,124,3, - 131,2,1,0,116,1,106,2,124,1,25,0,83,0,116,4, - 124,2,131,1,83,0,100,1,83,0,41,2,122,128,76,111, - 97,100,32,116,104,101,32,115,112,101,99,105,102,105,101,100, - 32,109,111,100,117,108,101,32,105,110,116,111,32,115,121,115, - 46,109,111,100,117,108,101,115,32,97,110,100,32,114,101,116, - 117,114,110,32,105,116,46,10,10,32,32,32,32,84,104,105, - 115,32,109,101,116,104,111,100,32,105,115,32,100,101,112,114, - 101,99,97,116,101,100,46,32,32,85,115,101,32,108,111,97, - 100,101,114,46,101,120,101,99,95,109,111,100,117,108,101,32, - 105,110,115,116,101,97,100,46,10,10,32,32,32,32,78,41, - 5,218,16,115,112,101,99,95,102,114,111,109,95,108,111,97, - 100,101,114,114,15,0,0,0,218,7,109,111,100,117,108,101, - 115,218,5,95,101,120,101,99,218,5,95,108,111,97,100,41, - 4,114,30,0,0,0,114,81,0,0,0,218,4,115,112,101, - 99,218,6,109,111,100,117,108,101,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,218,17,95,108,111,97,100,95, - 109,111,100,117,108,101,95,115,104,105,109,253,0,0,0,115, - 12,0,0,0,0,6,10,1,10,1,10,1,10,1,10,2, - 114,97,0,0,0,99,1,0,0,0,0,0,0,0,5,0, - 0,0,8,0,0,0,67,0,0,0,115,226,0,0,0,116, - 0,124,0,100,1,100,0,131,3,125,1,116,1,124,1,100, - 2,131,2,114,56,122,12,124,1,160,2,124,0,161,1,87, - 0,83,0,4,0,116,3,107,10,114,54,1,0,1,0,1, - 0,89,0,110,2,88,0,122,10,124,0,106,4,125,2,87, - 0,110,20,4,0,116,5,107,10,114,86,1,0,1,0,1, - 0,89,0,110,18,88,0,124,2,100,0,107,9,114,104,116, - 6,124,2,131,1,83,0,122,10,124,0,106,7,125,3,87, - 0,110,24,4,0,116,5,107,10,114,138,1,0,1,0,1, - 0,100,3,125,3,89,0,110,2,88,0,122,10,124,0,106, - 8,125,4,87,0,110,58,4,0,116,5,107,10,114,208,1, - 0,1,0,1,0,124,1,100,0,107,8,114,188,100,4,160, - 9,124,3,161,1,6,0,89,0,83,0,100,5,160,9,124, - 3,124,1,161,2,6,0,89,0,83,0,89,0,110,14,88, - 0,100,6,160,9,124,3,124,4,161,2,83,0,100,0,83, - 0,41,7,78,218,10,95,95,108,111,97,100,101,114,95,95, - 218,11,109,111,100,117,108,101,95,114,101,112,114,250,1,63, - 250,13,60,109,111,100,117,108,101,32,123,33,114,125,62,250, - 20,60,109,111,100,117,108,101,32,123,33,114,125,32,40,123, - 33,114,125,41,62,250,23,60,109,111,100,117,108,101,32,123, - 33,114,125,32,102,114,111,109,32,123,33,114,125,62,41,10, - 114,6,0,0,0,114,4,0,0,0,114,99,0,0,0,218, - 9,69,120,99,101,112,116,105,111,110,218,8,95,95,115,112, - 101,99,95,95,218,14,65,116,116,114,105,98,117,116,101,69, - 114,114,111,114,218,22,95,109,111,100,117,108,101,95,114,101, - 112,114,95,102,114,111,109,95,115,112,101,99,114,1,0,0, - 0,218,8,95,95,102,105,108,101,95,95,114,45,0,0,0, - 41,5,114,96,0,0,0,218,6,108,111,97,100,101,114,114, - 95,0,0,0,114,17,0,0,0,218,8,102,105,108,101,110, - 97,109,101,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,12,95,109,111,100,117,108,101,95,114,101,112,114, - 13,1,0,0,115,46,0,0,0,0,2,12,1,10,4,2, - 1,12,1,14,1,6,1,2,1,10,1,14,1,6,2,8, - 1,8,4,2,1,10,1,14,1,10,1,2,1,10,1,14, - 1,8,1,14,2,22,2,114,111,0,0,0,99,0,0,0, - 0,0,0,0,0,0,0,0,0,4,0,0,0,64,0,0, - 0,115,114,0,0,0,101,0,90,1,100,0,90,2,100,1, - 90,3,100,2,100,2,100,2,100,3,156,3,100,4,100,5, - 132,2,90,4,100,6,100,7,132,0,90,5,100,8,100,9, - 132,0,90,6,101,7,100,10,100,11,132,0,131,1,90,8, - 101,8,106,9,100,12,100,11,132,0,131,1,90,8,101,7, - 100,13,100,14,132,0,131,1,90,10,101,7,100,15,100,16, - 132,0,131,1,90,11,101,11,106,9,100,17,100,16,132,0, - 131,1,90,11,100,2,83,0,41,18,218,10,77,111,100,117, - 108,101,83,112,101,99,97,208,5,0,0,84,104,101,32,115, - 112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114, - 32,97,32,109,111,100,117,108,101,44,32,117,115,101,100,32, - 102,111,114,32,108,111,97,100,105,110,103,46,10,10,32,32, - 32,32,65,32,109,111,100,117,108,101,39,115,32,115,112,101, - 99,32,105,115,32,116,104,101,32,115,111,117,114,99,101,32, - 102,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32, - 97,98,111,117,116,32,116,104,101,32,109,111,100,117,108,101, - 46,32,32,70,111,114,10,32,32,32,32,100,97,116,97,32, - 97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32, - 116,104,101,32,109,111,100,117,108,101,44,32,105,110,99,108, - 117,100,105,110,103,32,115,111,117,114,99,101,44,32,117,115, - 101,32,116,104,101,32,115,112,101,99,39,115,10,32,32,32, - 32,108,111,97,100,101,114,46,10,10,32,32,32,32,96,110, - 97,109,101,96,32,105,115,32,116,104,101,32,97,98,115,111, - 108,117,116,101,32,110,97,109,101,32,111,102,32,116,104,101, - 32,109,111,100,117,108,101,46,32,32,96,108,111,97,100,101, - 114,96,32,105,115,32,116,104,101,32,108,111,97,100,101,114, - 10,32,32,32,32,116,111,32,117,115,101,32,119,104,101,110, - 32,108,111,97,100,105,110,103,32,116,104,101,32,109,111,100, - 117,108,101,46,32,32,96,112,97,114,101,110,116,96,32,105, - 115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104, - 101,10,32,32,32,32,112,97,99,107,97,103,101,32,116,104, - 101,32,109,111,100,117,108,101,32,105,115,32,105,110,46,32, - 32,84,104,101,32,112,97,114,101,110,116,32,105,115,32,100, - 101,114,105,118,101,100,32,102,114,111,109,32,116,104,101,32, - 110,97,109,101,46,10,10,32,32,32,32,96,105,115,95,112, - 97,99,107,97,103,101,96,32,100,101,116,101,114,109,105,110, - 101,115,32,105,102,32,116,104,101,32,109,111,100,117,108,101, - 32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97, - 32,112,97,99,107,97,103,101,32,111,114,10,32,32,32,32, - 110,111,116,46,32,32,79,110,32,109,111,100,117,108,101,115, - 32,116,104,105,115,32,105,115,32,114,101,102,108,101,99,116, - 101,100,32,98,121,32,116,104,101,32,96,95,95,112,97,116, - 104,95,95,96,32,97,116,116,114,105,98,117,116,101,46,10, - 10,32,32,32,32,96,111,114,105,103,105,110,96,32,105,115, - 32,116,104,101,32,115,112,101,99,105,102,105,99,32,108,111, - 99,97,116,105,111,110,32,117,115,101,100,32,98,121,32,116, - 104,101,32,108,111,97,100,101,114,32,102,114,111,109,32,119, - 104,105,99,104,32,116,111,10,32,32,32,32,108,111,97,100, - 32,116,104,101,32,109,111,100,117,108,101,44,32,105,102,32, - 116,104,97,116,32,105,110,102,111,114,109,97,116,105,111,110, - 32,105,115,32,97,118,97,105,108,97,98,108,101,46,32,32, - 87,104,101,110,32,102,105,108,101,110,97,109,101,32,105,115, - 10,32,32,32,32,115,101,116,44,32,111,114,105,103,105,110, - 32,119,105,108,108,32,109,97,116,99,104,46,10,10,32,32, - 32,32,96,104,97,115,95,108,111,99,97,116,105,111,110,96, - 32,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32, - 97,32,115,112,101,99,39,115,32,34,111,114,105,103,105,110, - 34,32,114,101,102,108,101,99,116,115,32,97,32,108,111,99, - 97,116,105,111,110,46,10,32,32,32,32,87,104,101,110,32, - 116,104,105,115,32,105,115,32,84,114,117,101,44,32,96,95, - 95,102,105,108,101,95,95,96,32,97,116,116,114,105,98,117, - 116,101,32,111,102,32,116,104,101,32,109,111,100,117,108,101, - 32,105,115,32,115,101,116,46,10,10,32,32,32,32,96,99, - 97,99,104,101,100,96,32,105,115,32,116,104,101,32,108,111, - 99,97,116,105,111,110,32,111,102,32,116,104,101,32,99,97, - 99,104,101,100,32,98,121,116,101,99,111,100,101,32,102,105, - 108,101,44,32,105,102,32,97,110,121,46,32,32,73,116,10, - 32,32,32,32,99,111,114,114,101,115,112,111,110,100,115,32, - 116,111,32,116,104,101,32,96,95,95,99,97,99,104,101,100, - 95,95,96,32,97,116,116,114,105,98,117,116,101,46,10,10, - 32,32,32,32,96,115,117,98,109,111,100,117,108,101,95,115, - 101,97,114,99,104,95,108,111,99,97,116,105,111,110,115,96, - 32,105,115,32,116,104,101,32,115,101,113,117,101,110,99,101, - 32,111,102,32,112,97,116,104,32,101,110,116,114,105,101,115, - 32,116,111,10,32,32,32,32,115,101,97,114,99,104,32,119, - 104,101,110,32,105,109,112,111,114,116,105,110,103,32,115,117, - 98,109,111,100,117,108,101,115,46,32,32,73,102,32,115,101, - 116,44,32,105,115,95,112,97,99,107,97,103,101,32,115,104, - 111,117,108,100,32,98,101,10,32,32,32,32,84,114,117,101, - 45,45,97,110,100,32,70,97,108,115,101,32,111,116,104,101, - 114,119,105,115,101,46,10,10,32,32,32,32,80,97,99,107, - 97,103,101,115,32,97,114,101,32,115,105,109,112,108,121,32, - 109,111,100,117,108,101,115,32,116,104,97,116,32,40,109,97, - 121,41,32,104,97,118,101,32,115,117,98,109,111,100,117,108, - 101,115,46,32,32,73,102,32,97,32,115,112,101,99,10,32, - 32,32,32,104,97,115,32,97,32,110,111,110,45,78,111,110, - 101,32,118,97,108,117,101,32,105,110,32,96,115,117,98,109, - 111,100,117,108,101,95,115,101,97,114,99,104,95,108,111,99, - 97,116,105,111,110,115,96,44,32,116,104,101,32,105,109,112, - 111,114,116,10,32,32,32,32,115,121,115,116,101,109,32,119, - 105,108,108,32,99,111,110,115,105,100,101,114,32,109,111,100, - 117,108,101,115,32,108,111,97,100,101,100,32,102,114,111,109, - 32,116,104,101,32,115,112,101,99,32,97,115,32,112,97,99, - 107,97,103,101,115,46,10,10,32,32,32,32,79,110,108,121, - 32,102,105,110,100,101,114,115,32,40,115,101,101,32,105,109, - 112,111,114,116,108,105,98,46,97,98,99,46,77,101,116,97, - 80,97,116,104,70,105,110,100,101,114,32,97,110,100,10,32, - 32,32,32,105,109,112,111,114,116,108,105,98,46,97,98,99, - 46,80,97,116,104,69,110,116,114,121,70,105,110,100,101,114, - 41,32,115,104,111,117,108,100,32,109,111,100,105,102,121,32, - 77,111,100,117,108,101,83,112,101,99,32,105,110,115,116,97, - 110,99,101,115,46,10,10,32,32,32,32,78,41,3,218,6, - 111,114,105,103,105,110,218,12,108,111,97,100,101,114,95,115, - 116,97,116,101,218,10,105,115,95,112,97,99,107,97,103,101, - 99,3,0,0,0,3,0,0,0,6,0,0,0,2,0,0, + 0,0,99,2,0,0,0,0,0,0,0,0,0,0,0,4, + 0,0,0,3,0,0,0,67,0,0,0,115,62,0,0,0, + 116,0,124,1,124,0,131,2,125,2,124,1,116,1,106,2, + 107,6,114,50,116,1,106,2,124,1,25,0,125,3,116,3, + 124,2,124,3,131,2,1,0,116,1,106,2,124,1,25,0, + 83,0,116,4,124,2,131,1,83,0,100,1,83,0,41,2, + 122,128,76,111,97,100,32,116,104,101,32,115,112,101,99,105, + 102,105,101,100,32,109,111,100,117,108,101,32,105,110,116,111, + 32,115,121,115,46,109,111,100,117,108,101,115,32,97,110,100, + 32,114,101,116,117,114,110,32,105,116,46,10,10,32,32,32, + 32,84,104,105,115,32,109,101,116,104,111,100,32,105,115,32, + 100,101,112,114,101,99,97,116,101,100,46,32,32,85,115,101, + 32,108,111,97,100,101,114,46,101,120,101,99,95,109,111,100, + 117,108,101,32,105,110,115,116,101,97,100,46,10,10,32,32, + 32,32,78,41,5,218,16,115,112,101,99,95,102,114,111,109, + 95,108,111,97,100,101,114,114,15,0,0,0,218,7,109,111, + 100,117,108,101,115,218,5,95,101,120,101,99,218,5,95,108, + 111,97,100,41,4,114,30,0,0,0,114,81,0,0,0,218, + 4,115,112,101,99,218,6,109,111,100,117,108,101,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,17,95,108, + 111,97,100,95,109,111,100,117,108,101,95,115,104,105,109,253, + 0,0,0,115,12,0,0,0,0,6,10,1,10,1,10,1, + 10,1,10,2,114,97,0,0,0,99,1,0,0,0,0,0, + 0,0,0,0,0,0,5,0,0,0,8,0,0,0,67,0, + 0,0,115,226,0,0,0,116,0,124,0,100,1,100,0,131, + 3,125,1,116,1,124,1,100,2,131,2,114,56,122,12,124, + 1,160,2,124,0,161,1,87,0,83,0,4,0,116,3,107, + 10,114,54,1,0,1,0,1,0,89,0,110,2,88,0,122, + 10,124,0,106,4,125,2,87,0,110,20,4,0,116,5,107, + 10,114,86,1,0,1,0,1,0,89,0,110,18,88,0,124, + 2,100,0,107,9,114,104,116,6,124,2,131,1,83,0,122, + 10,124,0,106,7,125,3,87,0,110,24,4,0,116,5,107, + 10,114,138,1,0,1,0,1,0,100,3,125,3,89,0,110, + 2,88,0,122,10,124,0,106,8,125,4,87,0,110,58,4, + 0,116,5,107,10,114,208,1,0,1,0,1,0,124,1,100, + 0,107,8,114,188,100,4,160,9,124,3,161,1,6,0,89, + 0,83,0,100,5,160,9,124,3,124,1,161,2,6,0,89, + 0,83,0,89,0,110,14,88,0,100,6,160,9,124,3,124, + 4,161,2,83,0,100,0,83,0,41,7,78,218,10,95,95, + 108,111,97,100,101,114,95,95,218,11,109,111,100,117,108,101, + 95,114,101,112,114,250,1,63,250,13,60,109,111,100,117,108, + 101,32,123,33,114,125,62,250,20,60,109,111,100,117,108,101, + 32,123,33,114,125,32,40,123,33,114,125,41,62,250,23,60, + 109,111,100,117,108,101,32,123,33,114,125,32,102,114,111,109, + 32,123,33,114,125,62,41,10,114,6,0,0,0,114,4,0, + 0,0,114,99,0,0,0,218,9,69,120,99,101,112,116,105, + 111,110,218,8,95,95,115,112,101,99,95,95,218,14,65,116, + 116,114,105,98,117,116,101,69,114,114,111,114,218,22,95,109, + 111,100,117,108,101,95,114,101,112,114,95,102,114,111,109,95, + 115,112,101,99,114,1,0,0,0,218,8,95,95,102,105,108, + 101,95,95,114,45,0,0,0,41,5,114,96,0,0,0,218, + 6,108,111,97,100,101,114,114,95,0,0,0,114,17,0,0, + 0,218,8,102,105,108,101,110,97,109,101,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,218,12,95,109,111,100, + 117,108,101,95,114,101,112,114,13,1,0,0,115,46,0,0, + 0,0,2,12,1,10,4,2,1,12,1,14,1,6,1,2, + 1,10,1,14,1,6,2,8,1,8,4,2,1,10,1,14, + 1,10,1,2,1,10,1,14,1,8,1,14,2,22,2,114, + 111,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,4,0,0,0,64,0,0,0,115,114,0, + 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, + 100,2,100,2,100,3,156,3,100,4,100,5,132,2,90,4, + 100,6,100,7,132,0,90,5,100,8,100,9,132,0,90,6, + 101,7,100,10,100,11,132,0,131,1,90,8,101,8,106,9, + 100,12,100,11,132,0,131,1,90,8,101,7,100,13,100,14, + 132,0,131,1,90,10,101,7,100,15,100,16,132,0,131,1, + 90,11,101,11,106,9,100,17,100,16,132,0,131,1,90,11, + 100,2,83,0,41,18,218,10,77,111,100,117,108,101,83,112, + 101,99,97,208,5,0,0,84,104,101,32,115,112,101,99,105, + 102,105,99,97,116,105,111,110,32,102,111,114,32,97,32,109, + 111,100,117,108,101,44,32,117,115,101,100,32,102,111,114,32, + 108,111,97,100,105,110,103,46,10,10,32,32,32,32,65,32, + 109,111,100,117,108,101,39,115,32,115,112,101,99,32,105,115, + 32,116,104,101,32,115,111,117,114,99,101,32,102,111,114,32, + 105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117, + 116,32,116,104,101,32,109,111,100,117,108,101,46,32,32,70, + 111,114,10,32,32,32,32,100,97,116,97,32,97,115,115,111, + 99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32, + 109,111,100,117,108,101,44,32,105,110,99,108,117,100,105,110, + 103,32,115,111,117,114,99,101,44,32,117,115,101,32,116,104, + 101,32,115,112,101,99,39,115,10,32,32,32,32,108,111,97, + 100,101,114,46,10,10,32,32,32,32,96,110,97,109,101,96, + 32,105,115,32,116,104,101,32,97,98,115,111,108,117,116,101, + 32,110,97,109,101,32,111,102,32,116,104,101,32,109,111,100, + 117,108,101,46,32,32,96,108,111,97,100,101,114,96,32,105, + 115,32,116,104,101,32,108,111,97,100,101,114,10,32,32,32, + 32,116,111,32,117,115,101,32,119,104,101,110,32,108,111,97, + 100,105,110,103,32,116,104,101,32,109,111,100,117,108,101,46, + 32,32,96,112,97,114,101,110,116,96,32,105,115,32,116,104, + 101,32,110,97,109,101,32,111,102,32,116,104,101,10,32,32, + 32,32,112,97,99,107,97,103,101,32,116,104,101,32,109,111, + 100,117,108,101,32,105,115,32,105,110,46,32,32,84,104,101, + 32,112,97,114,101,110,116,32,105,115,32,100,101,114,105,118, + 101,100,32,102,114,111,109,32,116,104,101,32,110,97,109,101, + 46,10,10,32,32,32,32,96,105,115,95,112,97,99,107,97, + 103,101,96,32,100,101,116,101,114,109,105,110,101,115,32,105, + 102,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32, + 99,111,110,115,105,100,101,114,101,100,32,97,32,112,97,99, + 107,97,103,101,32,111,114,10,32,32,32,32,110,111,116,46, + 32,32,79,110,32,109,111,100,117,108,101,115,32,116,104,105, + 115,32,105,115,32,114,101,102,108,101,99,116,101,100,32,98, + 121,32,116,104,101,32,96,95,95,112,97,116,104,95,95,96, + 32,97,116,116,114,105,98,117,116,101,46,10,10,32,32,32, + 32,96,111,114,105,103,105,110,96,32,105,115,32,116,104,101, + 32,115,112,101,99,105,102,105,99,32,108,111,99,97,116,105, + 111,110,32,117,115,101,100,32,98,121,32,116,104,101,32,108, + 111,97,100,101,114,32,102,114,111,109,32,119,104,105,99,104, + 32,116,111,10,32,32,32,32,108,111,97,100,32,116,104,101, + 32,109,111,100,117,108,101,44,32,105,102,32,116,104,97,116, + 32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32, + 97,118,97,105,108,97,98,108,101,46,32,32,87,104,101,110, + 32,102,105,108,101,110,97,109,101,32,105,115,10,32,32,32, + 32,115,101,116,44,32,111,114,105,103,105,110,32,119,105,108, + 108,32,109,97,116,99,104,46,10,10,32,32,32,32,96,104, + 97,115,95,108,111,99,97,116,105,111,110,96,32,105,110,100, + 105,99,97,116,101,115,32,116,104,97,116,32,97,32,115,112, + 101,99,39,115,32,34,111,114,105,103,105,110,34,32,114,101, + 102,108,101,99,116,115,32,97,32,108,111,99,97,116,105,111, + 110,46,10,32,32,32,32,87,104,101,110,32,116,104,105,115, + 32,105,115,32,84,114,117,101,44,32,96,95,95,102,105,108, + 101,95,95,96,32,97,116,116,114,105,98,117,116,101,32,111, + 102,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32, + 115,101,116,46,10,10,32,32,32,32,96,99,97,99,104,101, + 100,96,32,105,115,32,116,104,101,32,108,111,99,97,116,105, + 111,110,32,111,102,32,116,104,101,32,99,97,99,104,101,100, + 32,98,121,116,101,99,111,100,101,32,102,105,108,101,44,32, + 105,102,32,97,110,121,46,32,32,73,116,10,32,32,32,32, + 99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116, + 104,101,32,96,95,95,99,97,99,104,101,100,95,95,96,32, + 97,116,116,114,105,98,117,116,101,46,10,10,32,32,32,32, + 96,115,117,98,109,111,100,117,108,101,95,115,101,97,114,99, + 104,95,108,111,99,97,116,105,111,110,115,96,32,105,115,32, + 116,104,101,32,115,101,113,117,101,110,99,101,32,111,102,32, + 112,97,116,104,32,101,110,116,114,105,101,115,32,116,111,10, + 32,32,32,32,115,101,97,114,99,104,32,119,104,101,110,32, + 105,109,112,111,114,116,105,110,103,32,115,117,98,109,111,100, + 117,108,101,115,46,32,32,73,102,32,115,101,116,44,32,105, + 115,95,112,97,99,107,97,103,101,32,115,104,111,117,108,100, + 32,98,101,10,32,32,32,32,84,114,117,101,45,45,97,110, + 100,32,70,97,108,115,101,32,111,116,104,101,114,119,105,115, + 101,46,10,10,32,32,32,32,80,97,99,107,97,103,101,115, + 32,97,114,101,32,115,105,109,112,108,121,32,109,111,100,117, + 108,101,115,32,116,104,97,116,32,40,109,97,121,41,32,104, + 97,118,101,32,115,117,98,109,111,100,117,108,101,115,46,32, + 32,73,102,32,97,32,115,112,101,99,10,32,32,32,32,104, + 97,115,32,97,32,110,111,110,45,78,111,110,101,32,118,97, + 108,117,101,32,105,110,32,96,115,117,98,109,111,100,117,108, + 101,95,115,101,97,114,99,104,95,108,111,99,97,116,105,111, + 110,115,96,44,32,116,104,101,32,105,109,112,111,114,116,10, + 32,32,32,32,115,121,115,116,101,109,32,119,105,108,108,32, + 99,111,110,115,105,100,101,114,32,109,111,100,117,108,101,115, + 32,108,111,97,100,101,100,32,102,114,111,109,32,116,104,101, + 32,115,112,101,99,32,97,115,32,112,97,99,107,97,103,101, + 115,46,10,10,32,32,32,32,79,110,108,121,32,102,105,110, + 100,101,114,115,32,40,115,101,101,32,105,109,112,111,114,116, + 108,105,98,46,97,98,99,46,77,101,116,97,80,97,116,104, + 70,105,110,100,101,114,32,97,110,100,10,32,32,32,32,105, + 109,112,111,114,116,108,105,98,46,97,98,99,46,80,97,116, + 104,69,110,116,114,121,70,105,110,100,101,114,41,32,115,104, + 111,117,108,100,32,109,111,100,105,102,121,32,77,111,100,117, + 108,101,83,112,101,99,32,105,110,115,116,97,110,99,101,115, + 46,10,10,32,32,32,32,78,41,3,218,6,111,114,105,103, + 105,110,218,12,108,111,97,100,101,114,95,115,116,97,116,101, + 218,10,105,115,95,112,97,99,107,97,103,101,99,3,0,0, + 0,0,0,0,0,3,0,0,0,6,0,0,0,2,0,0, 0,67,0,0,0,115,54,0,0,0,124,1,124,0,95,0, 124,2,124,0,95,1,124,3,124,0,95,2,124,4,124,0, 95,3,124,5,114,32,103,0,110,2,100,0,124,0,95,4, @@ -639,101 +647,103 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,86,1,0,0,115,14,0,0,0,0,2,6,1,6, 1,6,1,6,1,14,3,6,1,122,19,77,111,100,117,108, 101,83,112,101,99,46,95,95,105,110,105,116,95,95,99,1, - 0,0,0,0,0,0,0,2,0,0,0,6,0,0,0,67, - 0,0,0,115,102,0,0,0,100,1,160,0,124,0,106,1, - 161,1,100,2,160,0,124,0,106,2,161,1,103,2,125,1, - 124,0,106,3,100,0,107,9,114,52,124,1,160,4,100,3, - 160,0,124,0,106,3,161,1,161,1,1,0,124,0,106,5, - 100,0,107,9,114,80,124,1,160,4,100,4,160,0,124,0, - 106,5,161,1,161,1,1,0,100,5,160,0,124,0,106,6, - 106,7,100,6,160,8,124,1,161,1,161,2,83,0,41,7, - 78,122,9,110,97,109,101,61,123,33,114,125,122,11,108,111, - 97,100,101,114,61,123,33,114,125,122,11,111,114,105,103,105, - 110,61,123,33,114,125,122,29,115,117,98,109,111,100,117,108, - 101,95,115,101,97,114,99,104,95,108,111,99,97,116,105,111, - 110,115,61,123,125,122,6,123,125,40,123,125,41,122,2,44, - 32,41,9,114,45,0,0,0,114,17,0,0,0,114,109,0, - 0,0,114,113,0,0,0,218,6,97,112,112,101,110,100,114, - 117,0,0,0,218,9,95,95,99,108,97,115,115,95,95,114, - 1,0,0,0,218,4,106,111,105,110,41,2,114,30,0,0, - 0,114,55,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,48,0,0,0,98,1,0,0,115,20, - 0,0,0,0,1,10,1,10,255,4,2,10,1,18,1,10, - 1,8,1,4,255,6,2,122,19,77,111,100,117,108,101,83, - 112,101,99,46,95,95,114,101,112,114,95,95,99,2,0,0, - 0,0,0,0,0,3,0,0,0,8,0,0,0,67,0,0, - 0,115,114,0,0,0,124,0,106,0,125,2,122,76,124,0, - 106,1,124,1,106,1,107,2,111,76,124,0,106,2,124,1, - 106,2,107,2,111,76,124,0,106,3,124,1,106,3,107,2, - 111,76,124,2,124,1,106,0,107,2,111,76,124,0,106,4, - 124,1,106,4,107,2,111,76,124,0,106,5,124,1,106,5, - 107,2,87,0,83,0,87,0,110,26,4,0,116,6,107,10, - 114,108,1,0,1,0,1,0,89,0,100,1,83,0,89,0, - 110,2,88,0,100,0,83,0,114,116,0,0,0,41,7,114, - 117,0,0,0,114,17,0,0,0,114,109,0,0,0,114,113, - 0,0,0,218,6,99,97,99,104,101,100,218,12,104,97,115, - 95,108,111,99,97,116,105,111,110,114,106,0,0,0,41,3, - 114,30,0,0,0,90,5,111,116,104,101,114,90,4,115,109, - 115,108,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,218,6,95,95,101,113,95,95,108,1,0,0,115,30,0, - 0,0,0,1,6,1,2,1,12,1,10,255,2,2,10,254, - 2,3,8,253,2,4,10,252,2,5,10,251,8,6,14,1, - 122,17,77,111,100,117,108,101,83,112,101,99,46,95,95,101, - 113,95,95,99,1,0,0,0,0,0,0,0,1,0,0,0, - 3,0,0,0,67,0,0,0,115,58,0,0,0,124,0,106, - 0,100,0,107,8,114,52,124,0,106,1,100,0,107,9,114, - 52,124,0,106,2,114,52,116,3,100,0,107,8,114,38,116, - 4,130,1,116,3,160,5,124,0,106,1,161,1,124,0,95, - 0,124,0,106,0,83,0,114,13,0,0,0,41,6,114,119, - 0,0,0,114,113,0,0,0,114,118,0,0,0,218,19,95, - 98,111,111,116,115,116,114,97,112,95,101,120,116,101,114,110, - 97,108,218,19,78,111,116,73,109,112,108,101,109,101,110,116, - 101,100,69,114,114,111,114,90,11,95,103,101,116,95,99,97, - 99,104,101,100,114,47,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,123,0,0,0,120,1,0, - 0,115,12,0,0,0,0,2,10,1,16,1,8,1,4,1, - 14,1,122,17,77,111,100,117,108,101,83,112,101,99,46,99, - 97,99,104,101,100,99,2,0,0,0,0,0,0,0,2,0, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,6, + 0,0,0,67,0,0,0,115,102,0,0,0,100,1,160,0, + 124,0,106,1,161,1,100,2,160,0,124,0,106,2,161,1, + 103,2,125,1,124,0,106,3,100,0,107,9,114,52,124,1, + 160,4,100,3,160,0,124,0,106,3,161,1,161,1,1,0, + 124,0,106,5,100,0,107,9,114,80,124,1,160,4,100,4, + 160,0,124,0,106,5,161,1,161,1,1,0,100,5,160,0, + 124,0,106,6,106,7,100,6,160,8,124,1,161,1,161,2, + 83,0,41,7,78,122,9,110,97,109,101,61,123,33,114,125, + 122,11,108,111,97,100,101,114,61,123,33,114,125,122,11,111, + 114,105,103,105,110,61,123,33,114,125,122,29,115,117,98,109, + 111,100,117,108,101,95,115,101,97,114,99,104,95,108,111,99, + 97,116,105,111,110,115,61,123,125,122,6,123,125,40,123,125, + 41,122,2,44,32,41,9,114,45,0,0,0,114,17,0,0, + 0,114,109,0,0,0,114,113,0,0,0,218,6,97,112,112, + 101,110,100,114,117,0,0,0,218,9,95,95,99,108,97,115, + 115,95,95,114,1,0,0,0,218,4,106,111,105,110,41,2, + 114,30,0,0,0,114,55,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,48,0,0,0,98,1, + 0,0,115,20,0,0,0,0,1,10,1,10,255,4,2,10, + 1,18,1,10,1,8,1,4,255,6,2,122,19,77,111,100, + 117,108,101,83,112,101,99,46,95,95,114,101,112,114,95,95, + 99,2,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,8,0,0,0,67,0,0,0,115,114,0,0,0,124,0, + 106,0,125,2,122,76,124,0,106,1,124,1,106,1,107,2, + 111,76,124,0,106,2,124,1,106,2,107,2,111,76,124,0, + 106,3,124,1,106,3,107,2,111,76,124,2,124,1,106,0, + 107,2,111,76,124,0,106,4,124,1,106,4,107,2,111,76, + 124,0,106,5,124,1,106,5,107,2,87,0,83,0,87,0, + 110,26,4,0,116,6,107,10,114,108,1,0,1,0,1,0, + 89,0,100,1,83,0,89,0,110,2,88,0,100,0,83,0, + 114,116,0,0,0,41,7,114,117,0,0,0,114,17,0,0, + 0,114,109,0,0,0,114,113,0,0,0,218,6,99,97,99, + 104,101,100,218,12,104,97,115,95,108,111,99,97,116,105,111, + 110,114,106,0,0,0,41,3,114,30,0,0,0,90,5,111, + 116,104,101,114,90,4,115,109,115,108,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,218,6,95,95,101,113,95, + 95,108,1,0,0,115,30,0,0,0,0,1,6,1,2,1, + 12,1,10,255,2,2,10,254,2,3,8,253,2,4,10,252, + 2,5,10,251,8,6,14,1,122,17,77,111,100,117,108,101, + 83,112,101,99,46,95,95,101,113,95,95,99,1,0,0,0, + 0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 67,0,0,0,115,58,0,0,0,124,0,106,0,100,0,107, + 8,114,52,124,0,106,1,100,0,107,9,114,52,124,0,106, + 2,114,52,116,3,100,0,107,8,114,38,116,4,130,1,116, + 3,160,5,124,0,106,1,161,1,124,0,95,0,124,0,106, + 0,83,0,114,13,0,0,0,41,6,114,119,0,0,0,114, + 113,0,0,0,114,118,0,0,0,218,19,95,98,111,111,116, + 115,116,114,97,112,95,101,120,116,101,114,110,97,108,218,19, + 78,111,116,73,109,112,108,101,109,101,110,116,101,100,69,114, + 114,111,114,90,11,95,103,101,116,95,99,97,99,104,101,100, + 114,47,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,114,123,0,0,0,120,1,0,0,115,12,0, + 0,0,0,2,10,1,16,1,8,1,4,1,14,1,122,17, + 77,111,100,117,108,101,83,112,101,99,46,99,97,99,104,101, + 100,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, 0,0,2,0,0,0,67,0,0,0,115,10,0,0,0,124, 1,124,0,95,0,100,0,83,0,114,13,0,0,0,41,1, 114,119,0,0,0,41,2,114,30,0,0,0,114,123,0,0, 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, 114,123,0,0,0,129,1,0,0,115,2,0,0,0,0,2, - 99,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0, - 0,67,0,0,0,115,36,0,0,0,124,0,106,0,100,1, - 107,8,114,26,124,0,106,1,160,2,100,2,161,1,100,3, - 25,0,83,0,124,0,106,1,83,0,100,1,83,0,41,4, - 122,32,84,104,101,32,110,97,109,101,32,111,102,32,116,104, - 101,32,109,111,100,117,108,101,39,115,32,112,97,114,101,110, - 116,46,78,218,1,46,114,22,0,0,0,41,3,114,117,0, - 0,0,114,17,0,0,0,218,10,114,112,97,114,116,105,116, - 105,111,110,114,47,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,218,6,112,97,114,101,110,116,133, - 1,0,0,115,6,0,0,0,0,3,10,1,16,2,122,17, - 77,111,100,117,108,101,83,112,101,99,46,112,97,114,101,110, - 116,99,1,0,0,0,0,0,0,0,1,0,0,0,1,0, - 0,0,67,0,0,0,115,6,0,0,0,124,0,106,0,83, - 0,114,13,0,0,0,41,1,114,118,0,0,0,114,47,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,124,0,0,0,141,1,0,0,115,2,0,0,0,0, - 2,122,23,77,111,100,117,108,101,83,112,101,99,46,104,97, - 115,95,108,111,99,97,116,105,111,110,99,2,0,0,0,0, - 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,115, - 14,0,0,0,116,0,124,1,131,1,124,0,95,1,100,0, - 83,0,114,13,0,0,0,41,2,218,4,98,111,111,108,114, - 118,0,0,0,41,2,114,30,0,0,0,218,5,118,97,108, - 117,101,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,124,0,0,0,145,1,0,0,115,2,0,0,0,0, - 2,41,12,114,1,0,0,0,114,0,0,0,0,114,2,0, - 0,0,114,3,0,0,0,114,31,0,0,0,114,48,0,0, - 0,114,125,0,0,0,218,8,112,114,111,112,101,114,116,121, - 114,123,0,0,0,218,6,115,101,116,116,101,114,114,130,0, - 0,0,114,124,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,112,0,0,0, - 49,1,0,0,115,32,0,0,0,8,1,4,36,4,1,2, - 255,12,12,8,10,8,12,2,1,10,8,4,1,10,3,2, - 1,10,7,2,1,10,3,4,1,114,112,0,0,0,169,2, - 114,113,0,0,0,114,115,0,0,0,99,2,0,0,0,2, + 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, + 0,3,0,0,0,67,0,0,0,115,36,0,0,0,124,0, + 106,0,100,1,107,8,114,26,124,0,106,1,160,2,100,2, + 161,1,100,3,25,0,83,0,124,0,106,1,83,0,100,1, + 83,0,41,4,122,32,84,104,101,32,110,97,109,101,32,111, + 102,32,116,104,101,32,109,111,100,117,108,101,39,115,32,112, + 97,114,101,110,116,46,78,218,1,46,114,22,0,0,0,41, + 3,114,117,0,0,0,114,17,0,0,0,218,10,114,112,97, + 114,116,105,116,105,111,110,114,47,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,218,6,112,97,114, + 101,110,116,133,1,0,0,115,6,0,0,0,0,3,10,1, + 16,2,122,17,77,111,100,117,108,101,83,112,101,99,46,112, + 97,114,101,110,116,99,1,0,0,0,0,0,0,0,0,0, + 0,0,1,0,0,0,1,0,0,0,67,0,0,0,115,6, + 0,0,0,124,0,106,0,83,0,114,13,0,0,0,41,1, + 114,118,0,0,0,114,47,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,124,0,0,0,141,1, + 0,0,115,2,0,0,0,0,2,122,23,77,111,100,117,108, + 101,83,112,101,99,46,104,97,115,95,108,111,99,97,116,105, + 111,110,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,2,0,0,0,67,0,0,0,115,14,0,0,0, + 116,0,124,1,131,1,124,0,95,1,100,0,83,0,114,13, + 0,0,0,41,2,218,4,98,111,111,108,114,118,0,0,0, + 41,2,114,30,0,0,0,218,5,118,97,108,117,101,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,124,0, + 0,0,145,1,0,0,115,2,0,0,0,0,2,41,12,114, + 1,0,0,0,114,0,0,0,0,114,2,0,0,0,114,3, + 0,0,0,114,31,0,0,0,114,48,0,0,0,114,125,0, + 0,0,218,8,112,114,111,112,101,114,116,121,114,123,0,0, + 0,218,6,115,101,116,116,101,114,114,130,0,0,0,114,124, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,112,0,0,0,49,1,0,0, + 115,32,0,0,0,8,1,4,36,4,1,2,255,12,12,8, + 10,8,12,2,1,10,8,4,1,10,3,2,1,10,7,2, + 1,10,3,4,1,114,112,0,0,0,169,2,114,113,0,0, + 0,114,115,0,0,0,99,2,0,0,0,0,0,0,0,2, 0,0,0,6,0,0,0,8,0,0,0,67,0,0,0,115, 154,0,0,0,116,0,124,1,100,1,131,2,114,74,116,1, 100,2,107,8,114,22,116,2,130,1,116,1,106,3,125,4, @@ -761,121 +771,122 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 91,0,0,0,150,1,0,0,115,36,0,0,0,0,2,10, 1,8,1,4,1,6,2,8,1,12,1,12,1,6,1,2, 255,6,3,8,1,10,1,2,1,14,1,14,1,12,3,4, - 2,114,91,0,0,0,99,3,0,0,0,0,0,0,0,8, - 0,0,0,8,0,0,0,67,0,0,0,115,56,1,0,0, - 122,10,124,0,106,0,125,3,87,0,110,20,4,0,116,1, - 107,10,114,30,1,0,1,0,1,0,89,0,110,14,88,0, - 124,3,100,0,107,9,114,44,124,3,83,0,124,0,106,2, - 125,4,124,1,100,0,107,8,114,90,122,10,124,0,106,3, - 125,1,87,0,110,20,4,0,116,1,107,10,114,88,1,0, - 1,0,1,0,89,0,110,2,88,0,122,10,124,0,106,4, - 125,5,87,0,110,24,4,0,116,1,107,10,114,124,1,0, - 1,0,1,0,100,0,125,5,89,0,110,2,88,0,124,2, - 100,0,107,8,114,184,124,5,100,0,107,8,114,180,122,10, - 124,1,106,5,125,2,87,0,113,184,4,0,116,1,107,10, - 114,176,1,0,1,0,1,0,100,0,125,2,89,0,113,184, - 88,0,110,4,124,5,125,2,122,10,124,0,106,6,125,6, - 87,0,110,24,4,0,116,1,107,10,114,218,1,0,1,0, - 1,0,100,0,125,6,89,0,110,2,88,0,122,14,116,7, - 124,0,106,8,131,1,125,7,87,0,110,26,4,0,116,1, - 107,10,144,1,114,4,1,0,1,0,1,0,100,0,125,7, - 89,0,110,2,88,0,116,9,124,4,124,1,124,2,100,1, - 141,3,125,3,124,5,100,0,107,8,144,1,114,34,100,2, - 110,2,100,3,124,3,95,10,124,6,124,3,95,11,124,7, - 124,3,95,12,124,3,83,0,41,4,78,169,1,114,113,0, - 0,0,70,84,41,13,114,105,0,0,0,114,106,0,0,0, - 114,1,0,0,0,114,98,0,0,0,114,108,0,0,0,218, - 7,95,79,82,73,71,73,78,218,10,95,95,99,97,99,104, - 101,100,95,95,218,4,108,105,115,116,218,8,95,95,112,97, - 116,104,95,95,114,112,0,0,0,114,118,0,0,0,114,123, - 0,0,0,114,117,0,0,0,41,8,114,96,0,0,0,114, - 109,0,0,0,114,113,0,0,0,114,95,0,0,0,114,17, - 0,0,0,90,8,108,111,99,97,116,105,111,110,114,123,0, - 0,0,114,117,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,17,95,115,112,101,99,95,102,114, - 111,109,95,109,111,100,117,108,101,176,1,0,0,115,72,0, - 0,0,0,2,2,1,10,1,14,1,6,2,8,1,4,2, - 6,1,8,1,2,1,10,1,14,2,6,1,2,1,10,1, - 14,1,10,1,8,1,8,1,2,1,10,1,14,1,12,2, - 4,1,2,1,10,1,14,1,10,1,2,1,14,1,16,1, - 10,2,14,1,20,1,6,1,6,1,114,142,0,0,0,70, - 169,1,218,8,111,118,101,114,114,105,100,101,99,2,0,0, - 0,1,0,0,0,5,0,0,0,8,0,0,0,67,0,0, - 0,115,226,1,0,0,124,2,115,20,116,0,124,1,100,1, - 100,0,131,3,100,0,107,8,114,54,122,12,124,0,106,1, - 124,1,95,2,87,0,110,20,4,0,116,3,107,10,114,52, - 1,0,1,0,1,0,89,0,110,2,88,0,124,2,115,74, - 116,0,124,1,100,2,100,0,131,3,100,0,107,8,114,178, - 124,0,106,4,125,3,124,3,100,0,107,8,114,146,124,0, - 106,5,100,0,107,9,114,146,116,6,100,0,107,8,114,110, - 116,7,130,1,116,6,106,8,125,4,124,4,160,9,124,4, - 161,1,125,3,124,0,106,5,124,3,95,10,124,3,124,0, - 95,4,100,0,124,1,95,11,122,10,124,3,124,1,95,12, - 87,0,110,20,4,0,116,3,107,10,114,176,1,0,1,0, - 1,0,89,0,110,2,88,0,124,2,115,198,116,0,124,1, - 100,3,100,0,131,3,100,0,107,8,114,232,122,12,124,0, - 106,13,124,1,95,14,87,0,110,20,4,0,116,3,107,10, - 114,230,1,0,1,0,1,0,89,0,110,2,88,0,122,10, - 124,0,124,1,95,15,87,0,110,22,4,0,116,3,107,10, - 144,1,114,8,1,0,1,0,1,0,89,0,110,2,88,0, - 124,2,144,1,115,34,116,0,124,1,100,4,100,0,131,3, - 100,0,107,8,144,1,114,82,124,0,106,5,100,0,107,9, - 144,1,114,82,122,12,124,0,106,5,124,1,95,16,87,0, - 110,22,4,0,116,3,107,10,144,1,114,80,1,0,1,0, - 1,0,89,0,110,2,88,0,124,0,106,17,144,1,114,222, - 124,2,144,1,115,114,116,0,124,1,100,5,100,0,131,3, - 100,0,107,8,144,1,114,150,122,12,124,0,106,18,124,1, - 95,11,87,0,110,22,4,0,116,3,107,10,144,1,114,148, - 1,0,1,0,1,0,89,0,110,2,88,0,124,2,144,1, - 115,174,116,0,124,1,100,6,100,0,131,3,100,0,107,8, - 144,1,114,222,124,0,106,19,100,0,107,9,144,1,114,222, - 122,12,124,0,106,19,124,1,95,20,87,0,110,22,4,0, - 116,3,107,10,144,1,114,220,1,0,1,0,1,0,89,0, - 110,2,88,0,124,1,83,0,41,7,78,114,1,0,0,0, - 114,98,0,0,0,218,11,95,95,112,97,99,107,97,103,101, - 95,95,114,141,0,0,0,114,108,0,0,0,114,139,0,0, - 0,41,21,114,6,0,0,0,114,17,0,0,0,114,1,0, - 0,0,114,106,0,0,0,114,109,0,0,0,114,117,0,0, - 0,114,126,0,0,0,114,127,0,0,0,218,16,95,78,97, - 109,101,115,112,97,99,101,76,111,97,100,101,114,218,7,95, - 95,110,101,119,95,95,90,5,95,112,97,116,104,114,108,0, - 0,0,114,98,0,0,0,114,130,0,0,0,114,145,0,0, - 0,114,105,0,0,0,114,141,0,0,0,114,124,0,0,0, - 114,113,0,0,0,114,123,0,0,0,114,139,0,0,0,41, - 5,114,95,0,0,0,114,96,0,0,0,114,144,0,0,0, - 114,109,0,0,0,114,146,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,18,95,105,110,105,116, - 95,109,111,100,117,108,101,95,97,116,116,114,115,221,1,0, - 0,115,96,0,0,0,0,4,20,1,2,1,12,1,14,1, - 6,2,20,1,6,1,8,2,10,1,8,1,4,1,6,2, - 10,1,8,1,6,11,6,1,2,1,10,1,14,1,6,2, - 20,1,2,1,12,1,14,1,6,2,2,1,10,1,16,1, - 6,2,24,1,12,1,2,1,12,1,16,1,6,2,8,1, - 24,1,2,1,12,1,16,1,6,2,24,1,12,1,2,1, - 12,1,16,1,6,1,114,148,0,0,0,99,1,0,0,0, - 0,0,0,0,2,0,0,0,3,0,0,0,67,0,0,0, - 115,82,0,0,0,100,1,125,1,116,0,124,0,106,1,100, - 2,131,2,114,30,124,0,106,1,160,2,124,0,161,1,125, - 1,110,20,116,0,124,0,106,1,100,3,131,2,114,50,116, - 3,100,4,131,1,130,1,124,1,100,1,107,8,114,68,116, - 4,124,0,106,5,131,1,125,1,116,6,124,0,124,1,131, - 2,1,0,124,1,83,0,41,5,122,43,67,114,101,97,116, - 101,32,97,32,109,111,100,117,108,101,32,98,97,115,101,100, - 32,111,110,32,116,104,101,32,112,114,111,118,105,100,101,100, - 32,115,112,101,99,46,78,218,13,99,114,101,97,116,101,95, - 109,111,100,117,108,101,218,11,101,120,101,99,95,109,111,100, - 117,108,101,122,66,108,111,97,100,101,114,115,32,116,104,97, - 116,32,100,101,102,105,110,101,32,101,120,101,99,95,109,111, - 100,117,108,101,40,41,32,109,117,115,116,32,97,108,115,111, - 32,100,101,102,105,110,101,32,99,114,101,97,116,101,95,109, - 111,100,117,108,101,40,41,41,7,114,4,0,0,0,114,109, - 0,0,0,114,149,0,0,0,114,79,0,0,0,114,18,0, - 0,0,114,17,0,0,0,114,148,0,0,0,169,2,114,95, - 0,0,0,114,96,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,218,16,109,111,100,117,108,101,95, - 102,114,111,109,95,115,112,101,99,37,2,0,0,115,18,0, - 0,0,0,3,4,1,12,3,14,1,12,1,8,2,8,1, - 10,1,10,1,114,152,0,0,0,99,1,0,0,0,0,0, + 2,114,91,0,0,0,99,3,0,0,0,0,0,0,0,0, + 0,0,0,8,0,0,0,8,0,0,0,67,0,0,0,115, + 56,1,0,0,122,10,124,0,106,0,125,3,87,0,110,20, + 4,0,116,1,107,10,114,30,1,0,1,0,1,0,89,0, + 110,14,88,0,124,3,100,0,107,9,114,44,124,3,83,0, + 124,0,106,2,125,4,124,1,100,0,107,8,114,90,122,10, + 124,0,106,3,125,1,87,0,110,20,4,0,116,1,107,10, + 114,88,1,0,1,0,1,0,89,0,110,2,88,0,122,10, + 124,0,106,4,125,5,87,0,110,24,4,0,116,1,107,10, + 114,124,1,0,1,0,1,0,100,0,125,5,89,0,110,2, + 88,0,124,2,100,0,107,8,114,184,124,5,100,0,107,8, + 114,180,122,10,124,1,106,5,125,2,87,0,113,184,4,0, + 116,1,107,10,114,176,1,0,1,0,1,0,100,0,125,2, + 89,0,113,184,88,0,110,4,124,5,125,2,122,10,124,0, + 106,6,125,6,87,0,110,24,4,0,116,1,107,10,114,218, + 1,0,1,0,1,0,100,0,125,6,89,0,110,2,88,0, + 122,14,116,7,124,0,106,8,131,1,125,7,87,0,110,26, + 4,0,116,1,107,10,144,1,114,4,1,0,1,0,1,0, + 100,0,125,7,89,0,110,2,88,0,116,9,124,4,124,1, + 124,2,100,1,141,3,125,3,124,5,100,0,107,8,144,1, + 114,34,100,2,110,2,100,3,124,3,95,10,124,6,124,3, + 95,11,124,7,124,3,95,12,124,3,83,0,41,4,78,169, + 1,114,113,0,0,0,70,84,41,13,114,105,0,0,0,114, + 106,0,0,0,114,1,0,0,0,114,98,0,0,0,114,108, + 0,0,0,218,7,95,79,82,73,71,73,78,218,10,95,95, + 99,97,99,104,101,100,95,95,218,4,108,105,115,116,218,8, + 95,95,112,97,116,104,95,95,114,112,0,0,0,114,118,0, + 0,0,114,123,0,0,0,114,117,0,0,0,41,8,114,96, + 0,0,0,114,109,0,0,0,114,113,0,0,0,114,95,0, + 0,0,114,17,0,0,0,90,8,108,111,99,97,116,105,111, + 110,114,123,0,0,0,114,117,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,218,17,95,115,112,101, + 99,95,102,114,111,109,95,109,111,100,117,108,101,176,1,0, + 0,115,72,0,0,0,0,2,2,1,10,1,14,1,6,2, + 8,1,4,2,6,1,8,1,2,1,10,1,14,2,6,1, + 2,1,10,1,14,1,10,1,8,1,8,1,2,1,10,1, + 14,1,12,2,4,1,2,1,10,1,14,1,10,1,2,1, + 14,1,16,1,10,2,14,1,20,1,6,1,6,1,114,142, + 0,0,0,70,169,1,218,8,111,118,101,114,114,105,100,101, + 99,2,0,0,0,0,0,0,0,1,0,0,0,5,0,0, + 0,8,0,0,0,67,0,0,0,115,226,1,0,0,124,2, + 115,20,116,0,124,1,100,1,100,0,131,3,100,0,107,8, + 114,54,122,12,124,0,106,1,124,1,95,2,87,0,110,20, + 4,0,116,3,107,10,114,52,1,0,1,0,1,0,89,0, + 110,2,88,0,124,2,115,74,116,0,124,1,100,2,100,0, + 131,3,100,0,107,8,114,178,124,0,106,4,125,3,124,3, + 100,0,107,8,114,146,124,0,106,5,100,0,107,9,114,146, + 116,6,100,0,107,8,114,110,116,7,130,1,116,6,106,8, + 125,4,124,4,160,9,124,4,161,1,125,3,124,0,106,5, + 124,3,95,10,124,3,124,0,95,4,100,0,124,1,95,11, + 122,10,124,3,124,1,95,12,87,0,110,20,4,0,116,3, + 107,10,114,176,1,0,1,0,1,0,89,0,110,2,88,0, + 124,2,115,198,116,0,124,1,100,3,100,0,131,3,100,0, + 107,8,114,232,122,12,124,0,106,13,124,1,95,14,87,0, + 110,20,4,0,116,3,107,10,114,230,1,0,1,0,1,0, + 89,0,110,2,88,0,122,10,124,0,124,1,95,15,87,0, + 110,22,4,0,116,3,107,10,144,1,114,8,1,0,1,0, + 1,0,89,0,110,2,88,0,124,2,144,1,115,34,116,0, + 124,1,100,4,100,0,131,3,100,0,107,8,144,1,114,82, + 124,0,106,5,100,0,107,9,144,1,114,82,122,12,124,0, + 106,5,124,1,95,16,87,0,110,22,4,0,116,3,107,10, + 144,1,114,80,1,0,1,0,1,0,89,0,110,2,88,0, + 124,0,106,17,144,1,114,222,124,2,144,1,115,114,116,0, + 124,1,100,5,100,0,131,3,100,0,107,8,144,1,114,150, + 122,12,124,0,106,18,124,1,95,11,87,0,110,22,4,0, + 116,3,107,10,144,1,114,148,1,0,1,0,1,0,89,0, + 110,2,88,0,124,2,144,1,115,174,116,0,124,1,100,6, + 100,0,131,3,100,0,107,8,144,1,114,222,124,0,106,19, + 100,0,107,9,144,1,114,222,122,12,124,0,106,19,124,1, + 95,20,87,0,110,22,4,0,116,3,107,10,144,1,114,220, + 1,0,1,0,1,0,89,0,110,2,88,0,124,1,83,0, + 41,7,78,114,1,0,0,0,114,98,0,0,0,218,11,95, + 95,112,97,99,107,97,103,101,95,95,114,141,0,0,0,114, + 108,0,0,0,114,139,0,0,0,41,21,114,6,0,0,0, + 114,17,0,0,0,114,1,0,0,0,114,106,0,0,0,114, + 109,0,0,0,114,117,0,0,0,114,126,0,0,0,114,127, + 0,0,0,218,16,95,78,97,109,101,115,112,97,99,101,76, + 111,97,100,101,114,218,7,95,95,110,101,119,95,95,90,5, + 95,112,97,116,104,114,108,0,0,0,114,98,0,0,0,114, + 130,0,0,0,114,145,0,0,0,114,105,0,0,0,114,141, + 0,0,0,114,124,0,0,0,114,113,0,0,0,114,123,0, + 0,0,114,139,0,0,0,41,5,114,95,0,0,0,114,96, + 0,0,0,114,144,0,0,0,114,109,0,0,0,114,146,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,218,18,95,105,110,105,116,95,109,111,100,117,108,101,95, + 97,116,116,114,115,221,1,0,0,115,96,0,0,0,0,4, + 20,1,2,1,12,1,14,1,6,2,20,1,6,1,8,2, + 10,1,8,1,4,1,6,2,10,1,8,1,6,11,6,1, + 2,1,10,1,14,1,6,2,20,1,2,1,12,1,14,1, + 6,2,2,1,10,1,16,1,6,2,24,1,12,1,2,1, + 12,1,16,1,6,2,8,1,24,1,2,1,12,1,16,1, + 6,2,24,1,12,1,2,1,12,1,16,1,6,1,114,148, + 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,3,0,0,0,67,0,0,0,115,82,0,0, + 0,100,1,125,1,116,0,124,0,106,1,100,2,131,2,114, + 30,124,0,106,1,160,2,124,0,161,1,125,1,110,20,116, + 0,124,0,106,1,100,3,131,2,114,50,116,3,100,4,131, + 1,130,1,124,1,100,1,107,8,114,68,116,4,124,0,106, + 5,131,1,125,1,116,6,124,0,124,1,131,2,1,0,124, + 1,83,0,41,5,122,43,67,114,101,97,116,101,32,97,32, + 109,111,100,117,108,101,32,98,97,115,101,100,32,111,110,32, + 116,104,101,32,112,114,111,118,105,100,101,100,32,115,112,101, + 99,46,78,218,13,99,114,101,97,116,101,95,109,111,100,117, + 108,101,218,11,101,120,101,99,95,109,111,100,117,108,101,122, + 66,108,111,97,100,101,114,115,32,116,104,97,116,32,100,101, + 102,105,110,101,32,101,120,101,99,95,109,111,100,117,108,101, + 40,41,32,109,117,115,116,32,97,108,115,111,32,100,101,102, + 105,110,101,32,99,114,101,97,116,101,95,109,111,100,117,108, + 101,40,41,41,7,114,4,0,0,0,114,109,0,0,0,114, + 149,0,0,0,114,79,0,0,0,114,18,0,0,0,114,17, + 0,0,0,114,148,0,0,0,169,2,114,95,0,0,0,114, + 96,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,218,16,109,111,100,117,108,101,95,102,114,111,109, + 95,115,112,101,99,37,2,0,0,115,18,0,0,0,0,3, + 4,1,12,3,14,1,12,1,8,2,8,1,10,1,10,1, + 114,152,0,0,0,99,1,0,0,0,0,0,0,0,0,0, 0,0,2,0,0,0,4,0,0,0,67,0,0,0,115,106, 0,0,0,124,0,106,0,100,1,107,8,114,14,100,2,110, 4,124,0,106,0,125,1,124,0,106,1,100,1,107,8,114, @@ -895,102 +906,103 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,114,11,0,0,0,114,107,0,0,0,54,2,0,0,115, 16,0,0,0,0,3,20,1,10,1,10,1,10,2,16,2, 6,1,14,2,114,107,0,0,0,99,2,0,0,0,0,0, - 0,0,4,0,0,0,10,0,0,0,67,0,0,0,115,204, - 0,0,0,124,0,106,0,125,2,116,1,124,2,131,1,143, - 180,1,0,116,2,106,3,160,4,124,2,161,1,124,1,107, - 9,114,54,100,1,160,5,124,2,161,1,125,3,116,6,124, - 3,124,2,100,2,141,2,130,1,122,106,124,0,106,7,100, - 3,107,8,114,106,124,0,106,8,100,3,107,8,114,90,116, - 6,100,4,124,0,106,0,100,2,141,2,130,1,116,9,124, - 0,124,1,100,5,100,6,141,3,1,0,110,52,116,9,124, - 0,124,1,100,5,100,6,141,3,1,0,116,10,124,0,106, - 7,100,7,131,2,115,146,124,0,106,7,160,11,124,2,161, - 1,1,0,110,12,124,0,106,7,160,12,124,1,161,1,1, - 0,87,0,53,0,116,2,106,3,160,13,124,0,106,0,161, - 1,125,1,124,1,116,2,106,3,124,0,106,0,60,0,88, - 0,87,0,53,0,81,0,82,0,88,0,124,1,83,0,41, - 8,122,70,69,120,101,99,117,116,101,32,116,104,101,32,115, - 112,101,99,39,115,32,115,112,101,99,105,102,105,101,100,32, - 109,111,100,117,108,101,32,105,110,32,97,110,32,101,120,105, - 115,116,105,110,103,32,109,111,100,117,108,101,39,115,32,110, - 97,109,101,115,112,97,99,101,46,122,30,109,111,100,117,108, - 101,32,123,33,114,125,32,110,111,116,32,105,110,32,115,121, - 115,46,109,111,100,117,108,101,115,114,16,0,0,0,78,250, - 14,109,105,115,115,105,110,103,32,108,111,97,100,101,114,84, - 114,143,0,0,0,114,150,0,0,0,41,14,114,17,0,0, - 0,114,50,0,0,0,114,15,0,0,0,114,92,0,0,0, - 114,34,0,0,0,114,45,0,0,0,114,79,0,0,0,114, - 109,0,0,0,114,117,0,0,0,114,148,0,0,0,114,4, - 0,0,0,218,11,108,111,97,100,95,109,111,100,117,108,101, - 114,150,0,0,0,218,3,112,111,112,41,4,114,95,0,0, - 0,114,96,0,0,0,114,17,0,0,0,218,3,109,115,103, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 93,0,0,0,71,2,0,0,115,34,0,0,0,0,2,6, - 1,10,1,16,1,10,1,12,1,2,1,10,1,10,1,14, - 2,16,2,14,1,12,4,14,2,16,4,14,1,24,1,114, - 93,0,0,0,99,1,0,0,0,0,0,0,0,2,0,0, - 0,8,0,0,0,67,0,0,0,115,26,1,0,0,122,18, - 124,0,106,0,160,1,124,0,106,2,161,1,1,0,87,0, - 110,52,1,0,1,0,1,0,124,0,106,2,116,3,106,4, - 107,6,114,64,116,3,106,4,160,5,124,0,106,2,161,1, - 125,1,124,1,116,3,106,4,124,0,106,2,60,0,130,0, - 89,0,110,2,88,0,116,3,106,4,160,5,124,0,106,2, - 161,1,125,1,124,1,116,3,106,4,124,0,106,2,60,0, - 116,6,124,1,100,1,100,0,131,3,100,0,107,8,114,148, - 122,12,124,0,106,0,124,1,95,7,87,0,110,20,4,0, - 116,8,107,10,114,146,1,0,1,0,1,0,89,0,110,2, - 88,0,116,6,124,1,100,2,100,0,131,3,100,0,107,8, - 114,226,122,40,124,1,106,9,124,1,95,10,116,11,124,1, - 100,3,131,2,115,202,124,0,106,2,160,12,100,4,161,1, - 100,5,25,0,124,1,95,10,87,0,110,20,4,0,116,8, - 107,10,114,224,1,0,1,0,1,0,89,0,110,2,88,0, - 116,6,124,1,100,6,100,0,131,3,100,0,107,8,144,1, - 114,22,122,10,124,0,124,1,95,13,87,0,110,22,4,0, - 116,8,107,10,144,1,114,20,1,0,1,0,1,0,89,0, - 110,2,88,0,124,1,83,0,41,7,78,114,98,0,0,0, - 114,145,0,0,0,114,141,0,0,0,114,128,0,0,0,114, - 22,0,0,0,114,105,0,0,0,41,14,114,109,0,0,0, - 114,155,0,0,0,114,17,0,0,0,114,15,0,0,0,114, - 92,0,0,0,114,156,0,0,0,114,6,0,0,0,114,98, - 0,0,0,114,106,0,0,0,114,1,0,0,0,114,145,0, - 0,0,114,4,0,0,0,114,129,0,0,0,114,105,0,0, - 0,114,151,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,218,25,95,108,111,97,100,95,98,97,99, - 107,119,97,114,100,95,99,111,109,112,97,116,105,98,108,101, - 101,2,0,0,115,54,0,0,0,0,4,2,1,18,1,6, - 1,12,1,14,1,12,1,8,3,14,1,12,1,16,1,2, - 1,12,1,14,1,6,1,16,1,2,4,8,1,10,1,22, - 1,14,1,6,1,18,1,2,1,10,1,16,1,6,1,114, - 158,0,0,0,99,1,0,0,0,0,0,0,0,2,0,0, - 0,11,0,0,0,67,0,0,0,115,220,0,0,0,124,0, - 106,0,100,0,107,9,114,30,116,1,124,0,106,0,100,1, - 131,2,115,30,116,2,124,0,131,1,83,0,116,3,124,0, - 131,1,125,1,100,2,124,0,95,4,122,162,124,1,116,5, - 106,6,124,0,106,7,60,0,122,52,124,0,106,0,100,0, - 107,8,114,96,124,0,106,8,100,0,107,8,114,108,116,9, - 100,3,124,0,106,7,100,4,141,2,130,1,110,12,124,0, - 106,0,160,10,124,1,161,1,1,0,87,0,110,50,1,0, - 1,0,1,0,122,14,116,5,106,6,124,0,106,7,61,0, - 87,0,110,20,4,0,116,11,107,10,114,152,1,0,1,0, - 1,0,89,0,110,2,88,0,130,0,89,0,110,2,88,0, - 116,5,106,6,160,12,124,0,106,7,161,1,125,1,124,1, - 116,5,106,6,124,0,106,7,60,0,116,13,100,5,124,0, - 106,7,124,0,106,0,131,3,1,0,87,0,53,0,100,6, - 124,0,95,4,88,0,124,1,83,0,41,7,78,114,150,0, - 0,0,84,114,154,0,0,0,114,16,0,0,0,122,18,105, - 109,112,111,114,116,32,123,33,114,125,32,35,32,123,33,114, - 125,70,41,14,114,109,0,0,0,114,4,0,0,0,114,158, - 0,0,0,114,152,0,0,0,90,13,95,105,110,105,116,105, - 97,108,105,122,105,110,103,114,15,0,0,0,114,92,0,0, - 0,114,17,0,0,0,114,117,0,0,0,114,79,0,0,0, - 114,150,0,0,0,114,63,0,0,0,114,156,0,0,0,114, - 76,0,0,0,114,151,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,218,14,95,108,111,97,100,95, - 117,110,108,111,99,107,101,100,138,2,0,0,115,46,0,0, - 0,0,2,10,2,12,1,8,2,8,5,6,1,2,1,12, - 1,2,1,10,1,10,1,16,3,16,1,6,1,2,1,14, - 1,14,1,6,1,8,5,14,1,12,1,20,2,8,2,114, - 159,0,0,0,99,1,0,0,0,0,0,0,0,1,0,0, + 0,0,0,0,0,0,4,0,0,0,10,0,0,0,67,0, + 0,0,115,204,0,0,0,124,0,106,0,125,2,116,1,124, + 2,131,1,143,180,1,0,116,2,106,3,160,4,124,2,161, + 1,124,1,107,9,114,54,100,1,160,5,124,2,161,1,125, + 3,116,6,124,3,124,2,100,2,141,2,130,1,122,106,124, + 0,106,7,100,3,107,8,114,106,124,0,106,8,100,3,107, + 8,114,90,116,6,100,4,124,0,106,0,100,2,141,2,130, + 1,116,9,124,0,124,1,100,5,100,6,141,3,1,0,110, + 52,116,9,124,0,124,1,100,5,100,6,141,3,1,0,116, + 10,124,0,106,7,100,7,131,2,115,146,124,0,106,7,160, + 11,124,2,161,1,1,0,110,12,124,0,106,7,160,12,124, + 1,161,1,1,0,87,0,53,0,116,2,106,3,160,13,124, + 0,106,0,161,1,125,1,124,1,116,2,106,3,124,0,106, + 0,60,0,88,0,87,0,53,0,81,0,82,0,88,0,124, + 1,83,0,41,8,122,70,69,120,101,99,117,116,101,32,116, + 104,101,32,115,112,101,99,39,115,32,115,112,101,99,105,102, + 105,101,100,32,109,111,100,117,108,101,32,105,110,32,97,110, + 32,101,120,105,115,116,105,110,103,32,109,111,100,117,108,101, + 39,115,32,110,97,109,101,115,112,97,99,101,46,122,30,109, + 111,100,117,108,101,32,123,33,114,125,32,110,111,116,32,105, + 110,32,115,121,115,46,109,111,100,117,108,101,115,114,16,0, + 0,0,78,250,14,109,105,115,115,105,110,103,32,108,111,97, + 100,101,114,84,114,143,0,0,0,114,150,0,0,0,41,14, + 114,17,0,0,0,114,50,0,0,0,114,15,0,0,0,114, + 92,0,0,0,114,34,0,0,0,114,45,0,0,0,114,79, + 0,0,0,114,109,0,0,0,114,117,0,0,0,114,148,0, + 0,0,114,4,0,0,0,218,11,108,111,97,100,95,109,111, + 100,117,108,101,114,150,0,0,0,218,3,112,111,112,41,4, + 114,95,0,0,0,114,96,0,0,0,114,17,0,0,0,218, + 3,109,115,103,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,93,0,0,0,71,2,0,0,115,34,0,0, + 0,0,2,6,1,10,1,16,1,10,1,12,1,2,1,10, + 1,10,1,14,2,16,2,14,1,12,4,14,2,16,4,14, + 1,24,1,114,93,0,0,0,99,1,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,8,0,0,0,67,0,0, + 0,115,26,1,0,0,122,18,124,0,106,0,160,1,124,0, + 106,2,161,1,1,0,87,0,110,52,1,0,1,0,1,0, + 124,0,106,2,116,3,106,4,107,6,114,64,116,3,106,4, + 160,5,124,0,106,2,161,1,125,1,124,1,116,3,106,4, + 124,0,106,2,60,0,130,0,89,0,110,2,88,0,116,3, + 106,4,160,5,124,0,106,2,161,1,125,1,124,1,116,3, + 106,4,124,0,106,2,60,0,116,6,124,1,100,1,100,0, + 131,3,100,0,107,8,114,148,122,12,124,0,106,0,124,1, + 95,7,87,0,110,20,4,0,116,8,107,10,114,146,1,0, + 1,0,1,0,89,0,110,2,88,0,116,6,124,1,100,2, + 100,0,131,3,100,0,107,8,114,226,122,40,124,1,106,9, + 124,1,95,10,116,11,124,1,100,3,131,2,115,202,124,0, + 106,2,160,12,100,4,161,1,100,5,25,0,124,1,95,10, + 87,0,110,20,4,0,116,8,107,10,114,224,1,0,1,0, + 1,0,89,0,110,2,88,0,116,6,124,1,100,6,100,0, + 131,3,100,0,107,8,144,1,114,22,122,10,124,0,124,1, + 95,13,87,0,110,22,4,0,116,8,107,10,144,1,114,20, + 1,0,1,0,1,0,89,0,110,2,88,0,124,1,83,0, + 41,7,78,114,98,0,0,0,114,145,0,0,0,114,141,0, + 0,0,114,128,0,0,0,114,22,0,0,0,114,105,0,0, + 0,41,14,114,109,0,0,0,114,155,0,0,0,114,17,0, + 0,0,114,15,0,0,0,114,92,0,0,0,114,156,0,0, + 0,114,6,0,0,0,114,98,0,0,0,114,106,0,0,0, + 114,1,0,0,0,114,145,0,0,0,114,4,0,0,0,114, + 129,0,0,0,114,105,0,0,0,114,151,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,218,25,95, + 108,111,97,100,95,98,97,99,107,119,97,114,100,95,99,111, + 109,112,97,116,105,98,108,101,101,2,0,0,115,54,0,0, + 0,0,4,2,1,18,1,6,1,12,1,14,1,12,1,8, + 3,14,1,12,1,16,1,2,1,12,1,14,1,6,1,16, + 1,2,4,8,1,10,1,22,1,14,1,6,1,18,1,2, + 1,10,1,16,1,6,1,114,158,0,0,0,99,1,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,11,0,0, + 0,67,0,0,0,115,220,0,0,0,124,0,106,0,100,0, + 107,9,114,30,116,1,124,0,106,0,100,1,131,2,115,30, + 116,2,124,0,131,1,83,0,116,3,124,0,131,1,125,1, + 100,2,124,0,95,4,122,162,124,1,116,5,106,6,124,0, + 106,7,60,0,122,52,124,0,106,0,100,0,107,8,114,96, + 124,0,106,8,100,0,107,8,114,108,116,9,100,3,124,0, + 106,7,100,4,141,2,130,1,110,12,124,0,106,0,160,10, + 124,1,161,1,1,0,87,0,110,50,1,0,1,0,1,0, + 122,14,116,5,106,6,124,0,106,7,61,0,87,0,110,20, + 4,0,116,11,107,10,114,152,1,0,1,0,1,0,89,0, + 110,2,88,0,130,0,89,0,110,2,88,0,116,5,106,6, + 160,12,124,0,106,7,161,1,125,1,124,1,116,5,106,6, + 124,0,106,7,60,0,116,13,100,5,124,0,106,7,124,0, + 106,0,131,3,1,0,87,0,53,0,100,6,124,0,95,4, + 88,0,124,1,83,0,41,7,78,114,150,0,0,0,84,114, + 154,0,0,0,114,16,0,0,0,122,18,105,109,112,111,114, + 116,32,123,33,114,125,32,35,32,123,33,114,125,70,41,14, + 114,109,0,0,0,114,4,0,0,0,114,158,0,0,0,114, + 152,0,0,0,90,13,95,105,110,105,116,105,97,108,105,122, + 105,110,103,114,15,0,0,0,114,92,0,0,0,114,17,0, + 0,0,114,117,0,0,0,114,79,0,0,0,114,150,0,0, + 0,114,63,0,0,0,114,156,0,0,0,114,76,0,0,0, + 114,151,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,14,95,108,111,97,100,95,117,110,108,111, + 99,107,101,100,138,2,0,0,115,46,0,0,0,0,2,10, + 2,12,1,8,2,8,5,6,1,2,1,12,1,2,1,10, + 1,10,1,16,3,16,1,6,1,2,1,14,1,14,1,6, + 1,8,5,14,1,12,1,20,2,8,2,114,159,0,0,0, + 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 0,10,0,0,0,67,0,0,0,115,42,0,0,0,116,0, 124,0,106,1,131,1,143,22,1,0,116,2,124,0,131,1, 87,0,2,0,53,0,81,0,82,0,163,0,83,0,81,0, @@ -1011,56 +1023,57 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 95,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, 0,0,0,114,94,0,0,0,180,2,0,0,115,4,0,0, 0,0,9,12,1,114,94,0,0,0,99,0,0,0,0,0, - 0,0,0,0,0,0,0,4,0,0,0,64,0,0,0,115, - 136,0,0,0,101,0,90,1,100,0,90,2,100,1,90,3, - 101,4,100,2,100,3,132,0,131,1,90,5,101,6,100,19, - 100,5,100,6,132,1,131,1,90,7,101,6,100,20,100,7, - 100,8,132,1,131,1,90,8,101,6,100,9,100,10,132,0, - 131,1,90,9,101,6,100,11,100,12,132,0,131,1,90,10, - 101,6,101,11,100,13,100,14,132,0,131,1,131,1,90,12, - 101,6,101,11,100,15,100,16,132,0,131,1,131,1,90,13, - 101,6,101,11,100,17,100,18,132,0,131,1,131,1,90,14, - 101,6,101,15,131,1,90,16,100,4,83,0,41,21,218,15, - 66,117,105,108,116,105,110,73,109,112,111,114,116,101,114,122, - 144,77,101,116,97,32,112,97,116,104,32,105,109,112,111,114, - 116,32,102,111,114,32,98,117,105,108,116,45,105,110,32,109, - 111,100,117,108,101,115,46,10,10,32,32,32,32,65,108,108, - 32,109,101,116,104,111,100,115,32,97,114,101,32,101,105,116, - 104,101,114,32,99,108,97,115,115,32,111,114,32,115,116,97, - 116,105,99,32,109,101,116,104,111,100,115,32,116,111,32,97, - 118,111,105,100,32,116,104,101,32,110,101,101,100,32,116,111, - 10,32,32,32,32,105,110,115,116,97,110,116,105,97,116,101, - 32,116,104,101,32,99,108,97,115,115,46,10,10,32,32,32, - 32,99,1,0,0,0,0,0,0,0,1,0,0,0,3,0, - 0,0,67,0,0,0,115,12,0,0,0,100,1,160,0,124, - 0,106,1,161,1,83,0,41,2,250,115,82,101,116,117,114, - 110,32,114,101,112,114,32,102,111,114,32,116,104,101,32,109, - 111,100,117,108,101,46,10,10,32,32,32,32,32,32,32,32, - 84,104,101,32,109,101,116,104,111,100,32,105,115,32,100,101, - 112,114,101,99,97,116,101,100,46,32,32,84,104,101,32,105, - 109,112,111,114,116,32,109,97,99,104,105,110,101,114,121,32, - 100,111,101,115,32,116,104,101,32,106,111,98,32,105,116,115, - 101,108,102,46,10,10,32,32,32,32,32,32,32,32,122,24, - 60,109,111,100,117,108,101,32,123,33,114,125,32,40,98,117, - 105,108,116,45,105,110,41,62,41,2,114,45,0,0,0,114, - 1,0,0,0,41,1,114,96,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,99,0,0,0,204, - 2,0,0,115,2,0,0,0,0,7,122,27,66,117,105,108, - 116,105,110,73,109,112,111,114,116,101,114,46,109,111,100,117, - 108,101,95,114,101,112,114,78,99,4,0,0,0,0,0,0, - 0,4,0,0,0,5,0,0,0,67,0,0,0,115,44,0, - 0,0,124,2,100,0,107,9,114,12,100,0,83,0,116,0, - 160,1,124,1,161,1,114,36,116,2,124,1,124,0,100,1, - 100,2,141,3,83,0,100,0,83,0,100,0,83,0,41,3, - 78,122,8,98,117,105,108,116,45,105,110,114,137,0,0,0, - 41,3,114,57,0,0,0,90,10,105,115,95,98,117,105,108, - 116,105,110,114,91,0,0,0,169,4,218,3,99,108,115,114, - 81,0,0,0,218,4,112,97,116,104,218,6,116,97,114,103, - 101,116,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,218,9,102,105,110,100,95,115,112,101,99,213,2,0,0, - 115,10,0,0,0,0,2,8,1,4,1,10,1,14,2,122, - 25,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, - 46,102,105,110,100,95,115,112,101,99,99,3,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,64, + 0,0,0,115,136,0,0,0,101,0,90,1,100,0,90,2, + 100,1,90,3,101,4,100,2,100,3,132,0,131,1,90,5, + 101,6,100,19,100,5,100,6,132,1,131,1,90,7,101,6, + 100,20,100,7,100,8,132,1,131,1,90,8,101,6,100,9, + 100,10,132,0,131,1,90,9,101,6,100,11,100,12,132,0, + 131,1,90,10,101,6,101,11,100,13,100,14,132,0,131,1, + 131,1,90,12,101,6,101,11,100,15,100,16,132,0,131,1, + 131,1,90,13,101,6,101,11,100,17,100,18,132,0,131,1, + 131,1,90,14,101,6,101,15,131,1,90,16,100,4,83,0, + 41,21,218,15,66,117,105,108,116,105,110,73,109,112,111,114, + 116,101,114,122,144,77,101,116,97,32,112,97,116,104,32,105, + 109,112,111,114,116,32,102,111,114,32,98,117,105,108,116,45, + 105,110,32,109,111,100,117,108,101,115,46,10,10,32,32,32, + 32,65,108,108,32,109,101,116,104,111,100,115,32,97,114,101, + 32,101,105,116,104,101,114,32,99,108,97,115,115,32,111,114, + 32,115,116,97,116,105,99,32,109,101,116,104,111,100,115,32, + 116,111,32,97,118,111,105,100,32,116,104,101,32,110,101,101, + 100,32,116,111,10,32,32,32,32,105,110,115,116,97,110,116, + 105,97,116,101,32,116,104,101,32,99,108,97,115,115,46,10, + 10,32,32,32,32,99,1,0,0,0,0,0,0,0,0,0, + 0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,12, + 0,0,0,100,1,160,0,124,0,106,1,161,1,83,0,41, + 2,250,115,82,101,116,117,114,110,32,114,101,112,114,32,102, + 111,114,32,116,104,101,32,109,111,100,117,108,101,46,10,10, + 32,32,32,32,32,32,32,32,84,104,101,32,109,101,116,104, + 111,100,32,105,115,32,100,101,112,114,101,99,97,116,101,100, + 46,32,32,84,104,101,32,105,109,112,111,114,116,32,109,97, + 99,104,105,110,101,114,121,32,100,111,101,115,32,116,104,101, + 32,106,111,98,32,105,116,115,101,108,102,46,10,10,32,32, + 32,32,32,32,32,32,122,24,60,109,111,100,117,108,101,32, + 123,33,114,125,32,40,98,117,105,108,116,45,105,110,41,62, + 41,2,114,45,0,0,0,114,1,0,0,0,41,1,114,96, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,114,99,0,0,0,204,2,0,0,115,2,0,0,0, + 0,7,122,27,66,117,105,108,116,105,110,73,109,112,111,114, + 116,101,114,46,109,111,100,117,108,101,95,114,101,112,114,78, + 99,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0, + 0,5,0,0,0,67,0,0,0,115,44,0,0,0,124,2, + 100,0,107,9,114,12,100,0,83,0,116,0,160,1,124,1, + 161,1,114,36,116,2,124,1,124,0,100,1,100,2,141,3, + 83,0,100,0,83,0,100,0,83,0,41,3,78,122,8,98, + 117,105,108,116,45,105,110,114,137,0,0,0,41,3,114,57, + 0,0,0,90,10,105,115,95,98,117,105,108,116,105,110,114, + 91,0,0,0,169,4,218,3,99,108,115,114,81,0,0,0, + 218,4,112,97,116,104,218,6,116,97,114,103,101,116,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,218,9,102, + 105,110,100,95,115,112,101,99,213,2,0,0,115,10,0,0, + 0,0,2,8,1,4,1,10,1,14,2,122,25,66,117,105, + 108,116,105,110,73,109,112,111,114,116,101,114,46,102,105,110, + 100,95,115,112,101,99,99,3,0,0,0,0,0,0,0,0, 0,0,0,4,0,0,0,4,0,0,0,67,0,0,0,115, 30,0,0,0,124,0,160,0,124,1,124,2,161,2,125,3, 124,3,100,1,107,9,114,26,124,3,106,1,83,0,100,1, @@ -1082,43 +1095,44 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 100,117,108,101,222,2,0,0,115,4,0,0,0,0,9,12, 1,122,27,66,117,105,108,116,105,110,73,109,112,111,114,116, 101,114,46,102,105,110,100,95,109,111,100,117,108,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,67, - 0,0,0,115,46,0,0,0,124,1,106,0,116,1,106,2, - 107,7,114,34,116,3,100,1,160,4,124,1,106,0,161,1, - 124,1,106,0,100,2,141,2,130,1,116,5,116,6,106,7, - 124,1,131,2,83,0,41,3,122,24,67,114,101,97,116,101, - 32,97,32,98,117,105,108,116,45,105,110,32,109,111,100,117, - 108,101,114,77,0,0,0,114,16,0,0,0,41,8,114,17, - 0,0,0,114,15,0,0,0,114,78,0,0,0,114,79,0, - 0,0,114,45,0,0,0,114,67,0,0,0,114,57,0,0, - 0,90,14,99,114,101,97,116,101,95,98,117,105,108,116,105, - 110,41,2,114,30,0,0,0,114,95,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,149,0,0, - 0,234,2,0,0,115,10,0,0,0,0,3,12,1,12,1, - 4,255,6,2,122,29,66,117,105,108,116,105,110,73,109,112, - 111,114,116,101,114,46,99,114,101,97,116,101,95,109,111,100, - 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, - 3,0,0,0,67,0,0,0,115,16,0,0,0,116,0,116, - 1,106,2,124,1,131,2,1,0,100,1,83,0,41,2,122, - 22,69,120,101,99,32,97,32,98,117,105,108,116,45,105,110, - 32,109,111,100,117,108,101,78,41,3,114,67,0,0,0,114, - 57,0,0,0,90,12,101,120,101,99,95,98,117,105,108,116, - 105,110,41,2,114,30,0,0,0,114,96,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,150,0, - 0,0,242,2,0,0,115,2,0,0,0,0,3,122,27,66, - 117,105,108,116,105,110,73,109,112,111,114,116,101,114,46,101, - 120,101,99,95,109,111,100,117,108,101,99,2,0,0,0,0, - 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, - 4,0,0,0,100,1,83,0,41,2,122,57,82,101,116,117, - 114,110,32,78,111,110,101,32,97,115,32,98,117,105,108,116, - 45,105,110,32,109,111,100,117,108,101,115,32,100,111,32,110, - 111,116,32,104,97,118,101,32,99,111,100,101,32,111,98,106, - 101,99,116,115,46,78,114,10,0,0,0,169,2,114,163,0, - 0,0,114,81,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,218,8,103,101,116,95,99,111,100,101, - 247,2,0,0,115,2,0,0,0,0,4,122,24,66,117,105, - 108,116,105,110,73,109,112,111,114,116,101,114,46,103,101,116, - 95,99,111,100,101,99,2,0,0,0,0,0,0,0,2,0, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,4, + 0,0,0,67,0,0,0,115,46,0,0,0,124,1,106,0, + 116,1,106,2,107,7,114,34,116,3,100,1,160,4,124,1, + 106,0,161,1,124,1,106,0,100,2,141,2,130,1,116,5, + 116,6,106,7,124,1,131,2,83,0,41,3,122,24,67,114, + 101,97,116,101,32,97,32,98,117,105,108,116,45,105,110,32, + 109,111,100,117,108,101,114,77,0,0,0,114,16,0,0,0, + 41,8,114,17,0,0,0,114,15,0,0,0,114,78,0,0, + 0,114,79,0,0,0,114,45,0,0,0,114,67,0,0,0, + 114,57,0,0,0,90,14,99,114,101,97,116,101,95,98,117, + 105,108,116,105,110,41,2,114,30,0,0,0,114,95,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 114,149,0,0,0,234,2,0,0,115,10,0,0,0,0,3, + 12,1,12,1,4,255,6,2,122,29,66,117,105,108,116,105, + 110,73,109,112,111,114,116,101,114,46,99,114,101,97,116,101, + 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, + 0,0,0,0,2,0,0,0,3,0,0,0,67,0,0,0, + 115,16,0,0,0,116,0,116,1,106,2,124,1,131,2,1, + 0,100,1,83,0,41,2,122,22,69,120,101,99,32,97,32, + 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,78, + 41,3,114,67,0,0,0,114,57,0,0,0,90,12,101,120, + 101,99,95,98,117,105,108,116,105,110,41,2,114,30,0,0, + 0,114,96,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,150,0,0,0,242,2,0,0,115,2, + 0,0,0,0,3,122,27,66,117,105,108,116,105,110,73,109, + 112,111,114,116,101,114,46,101,120,101,99,95,109,111,100,117, + 108,101,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, + 100,1,83,0,41,2,122,57,82,101,116,117,114,110,32,78, + 111,110,101,32,97,115,32,98,117,105,108,116,45,105,110,32, + 109,111,100,117,108,101,115,32,100,111,32,110,111,116,32,104, + 97,118,101,32,99,111,100,101,32,111,98,106,101,99,116,115, + 46,78,114,10,0,0,0,169,2,114,163,0,0,0,114,81, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,218,8,103,101,116,95,99,111,100,101,247,2,0,0, + 115,2,0,0,0,0,4,122,24,66,117,105,108,116,105,110, + 73,109,112,111,114,116,101,114,46,103,101,116,95,99,111,100, + 101,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, 1,83,0,41,2,122,56,82,101,116,117,114,110,32,78,111, 110,101,32,97,115,32,98,117,105,108,116,45,105,110,32,109, @@ -1129,58 +1143,59 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 111,117,114,99,101,253,2,0,0,115,2,0,0,0,0,4, 122,26,66,117,105,108,116,105,110,73,109,112,111,114,116,101, 114,46,103,101,116,95,115,111,117,114,99,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,115,4,0,0,0,100,1,83,0,41,2,122,52,82,101, - 116,117,114,110,32,70,97,108,115,101,32,97,115,32,98,117, - 105,108,116,45,105,110,32,109,111,100,117,108,101,115,32,97, - 114,101,32,110,101,118,101,114,32,112,97,99,107,97,103,101, - 115,46,70,114,10,0,0,0,114,168,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,115,0,0, - 0,3,3,0,0,115,2,0,0,0,0,4,122,26,66,117, - 105,108,116,105,110,73,109,112,111,114,116,101,114,46,105,115, - 95,112,97,99,107,97,103,101,41,2,78,78,41,1,78,41, - 17,114,1,0,0,0,114,0,0,0,0,114,2,0,0,0, - 114,3,0,0,0,218,12,115,116,97,116,105,99,109,101,116, - 104,111,100,114,99,0,0,0,218,11,99,108,97,115,115,109, - 101,116,104,111,100,114,166,0,0,0,114,167,0,0,0,114, - 149,0,0,0,114,150,0,0,0,114,86,0,0,0,114,169, - 0,0,0,114,170,0,0,0,114,115,0,0,0,114,97,0, - 0,0,114,155,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,160,0,0,0, - 195,2,0,0,115,42,0,0,0,8,2,4,7,2,1,10, - 8,2,1,12,8,2,1,12,11,2,1,10,7,2,1,10, - 4,2,1,2,1,12,4,2,1,2,1,12,4,2,1,2, - 1,12,4,114,160,0,0,0,99,0,0,0,0,0,0,0, - 0,0,0,0,0,4,0,0,0,64,0,0,0,115,144,0, - 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, - 90,4,101,5,100,3,100,4,132,0,131,1,90,6,101,7, - 100,22,100,6,100,7,132,1,131,1,90,8,101,7,100,23, - 100,8,100,9,132,1,131,1,90,9,101,7,100,10,100,11, - 132,0,131,1,90,10,101,5,100,12,100,13,132,0,131,1, - 90,11,101,7,100,14,100,15,132,0,131,1,90,12,101,7, - 101,13,100,16,100,17,132,0,131,1,131,1,90,14,101,7, - 101,13,100,18,100,19,132,0,131,1,131,1,90,15,101,7, - 101,13,100,20,100,21,132,0,131,1,131,1,90,16,100,5, - 83,0,41,24,218,14,70,114,111,122,101,110,73,109,112,111, - 114,116,101,114,122,142,77,101,116,97,32,112,97,116,104,32, - 105,109,112,111,114,116,32,102,111,114,32,102,114,111,122,101, - 110,32,109,111,100,117,108,101,115,46,10,10,32,32,32,32, - 65,108,108,32,109,101,116,104,111,100,115,32,97,114,101,32, - 101,105,116,104,101,114,32,99,108,97,115,115,32,111,114,32, - 115,116,97,116,105,99,32,109,101,116,104,111,100,115,32,116, - 111,32,97,118,111,105,100,32,116,104,101,32,110,101,101,100, - 32,116,111,10,32,32,32,32,105,110,115,116,97,110,116,105, - 97,116,101,32,116,104,101,32,99,108,97,115,115,46,10,10, - 32,32,32,32,90,6,102,114,111,122,101,110,99,1,0,0, - 0,0,0,0,0,1,0,0,0,4,0,0,0,67,0,0, - 0,115,16,0,0,0,100,1,160,0,124,0,106,1,116,2, - 106,3,161,2,83,0,41,2,114,161,0,0,0,114,153,0, - 0,0,41,4,114,45,0,0,0,114,1,0,0,0,114,173, - 0,0,0,114,138,0,0,0,41,1,218,1,109,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,99,0,0, - 0,23,3,0,0,115,2,0,0,0,0,7,122,26,70,114, - 111,122,101,110,73,109,112,111,114,116,101,114,46,109,111,100, - 117,108,101,95,114,101,112,114,78,99,4,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,1,0,0, + 0,67,0,0,0,115,4,0,0,0,100,1,83,0,41,2, + 122,52,82,101,116,117,114,110,32,70,97,108,115,101,32,97, + 115,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108, + 101,115,32,97,114,101,32,110,101,118,101,114,32,112,97,99, + 107,97,103,101,115,46,70,114,10,0,0,0,114,168,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 114,115,0,0,0,3,3,0,0,115,2,0,0,0,0,4, + 122,26,66,117,105,108,116,105,110,73,109,112,111,114,116,101, + 114,46,105,115,95,112,97,99,107,97,103,101,41,2,78,78, + 41,1,78,41,17,114,1,0,0,0,114,0,0,0,0,114, + 2,0,0,0,114,3,0,0,0,218,12,115,116,97,116,105, + 99,109,101,116,104,111,100,114,99,0,0,0,218,11,99,108, + 97,115,115,109,101,116,104,111,100,114,166,0,0,0,114,167, + 0,0,0,114,149,0,0,0,114,150,0,0,0,114,86,0, + 0,0,114,169,0,0,0,114,170,0,0,0,114,115,0,0, + 0,114,97,0,0,0,114,155,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, + 160,0,0,0,195,2,0,0,115,42,0,0,0,8,2,4, + 7,2,1,10,8,2,1,12,8,2,1,12,11,2,1,10, + 7,2,1,10,4,2,1,2,1,12,4,2,1,2,1,12, + 4,2,1,2,1,12,4,114,160,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, + 0,64,0,0,0,115,144,0,0,0,101,0,90,1,100,0, + 90,2,100,1,90,3,100,2,90,4,101,5,100,3,100,4, + 132,0,131,1,90,6,101,7,100,22,100,6,100,7,132,1, + 131,1,90,8,101,7,100,23,100,8,100,9,132,1,131,1, + 90,9,101,7,100,10,100,11,132,0,131,1,90,10,101,5, + 100,12,100,13,132,0,131,1,90,11,101,7,100,14,100,15, + 132,0,131,1,90,12,101,7,101,13,100,16,100,17,132,0, + 131,1,131,1,90,14,101,7,101,13,100,18,100,19,132,0, + 131,1,131,1,90,15,101,7,101,13,100,20,100,21,132,0, + 131,1,131,1,90,16,100,5,83,0,41,24,218,14,70,114, + 111,122,101,110,73,109,112,111,114,116,101,114,122,142,77,101, + 116,97,32,112,97,116,104,32,105,109,112,111,114,116,32,102, + 111,114,32,102,114,111,122,101,110,32,109,111,100,117,108,101, + 115,46,10,10,32,32,32,32,65,108,108,32,109,101,116,104, + 111,100,115,32,97,114,101,32,101,105,116,104,101,114,32,99, + 108,97,115,115,32,111,114,32,115,116,97,116,105,99,32,109, + 101,116,104,111,100,115,32,116,111,32,97,118,111,105,100,32, + 116,104,101,32,110,101,101,100,32,116,111,10,32,32,32,32, + 105,110,115,116,97,110,116,105,97,116,101,32,116,104,101,32, + 99,108,97,115,115,46,10,10,32,32,32,32,90,6,102,114, + 111,122,101,110,99,1,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,4,0,0,0,67,0,0,0,115,16,0, + 0,0,100,1,160,0,124,0,106,1,116,2,106,3,161,2, + 83,0,41,2,114,161,0,0,0,114,153,0,0,0,41,4, + 114,45,0,0,0,114,1,0,0,0,114,173,0,0,0,114, + 138,0,0,0,41,1,218,1,109,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,99,0,0,0,23,3,0, + 0,115,2,0,0,0,0,7,122,26,70,114,111,122,101,110, + 73,109,112,111,114,116,101,114,46,109,111,100,117,108,101,95, + 114,101,112,114,78,99,4,0,0,0,0,0,0,0,0,0, 0,0,4,0,0,0,5,0,0,0,67,0,0,0,115,34, 0,0,0,116,0,160,1,124,1,161,1,114,26,116,2,124, 1,124,0,124,0,106,3,100,1,141,3,83,0,100,0,83, @@ -1190,47 +1205,48 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,114,11,0,0,0,114,166,0,0,0,32,3,0,0, 115,6,0,0,0,0,2,10,1,16,2,122,24,70,114,111, 122,101,110,73,109,112,111,114,116,101,114,46,102,105,110,100, - 95,115,112,101,99,99,3,0,0,0,0,0,0,0,3,0, - 0,0,3,0,0,0,67,0,0,0,115,18,0,0,0,116, - 0,160,1,124,1,161,1,114,14,124,0,83,0,100,1,83, - 0,41,2,122,93,70,105,110,100,32,97,32,102,114,111,122, - 101,110,32,109,111,100,117,108,101,46,10,10,32,32,32,32, - 32,32,32,32,84,104,105,115,32,109,101,116,104,111,100,32, - 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,32, - 85,115,101,32,102,105,110,100,95,115,112,101,99,40,41,32, - 105,110,115,116,101,97,100,46,10,10,32,32,32,32,32,32, - 32,32,78,41,2,114,57,0,0,0,114,88,0,0,0,41, - 3,114,163,0,0,0,114,81,0,0,0,114,164,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 167,0,0,0,39,3,0,0,115,2,0,0,0,0,7,122, - 26,70,114,111,122,101,110,73,109,112,111,114,116,101,114,46, - 102,105,110,100,95,109,111,100,117,108,101,99,2,0,0,0, - 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, - 115,4,0,0,0,100,1,83,0,41,2,122,42,85,115,101, - 32,100,101,102,97,117,108,116,32,115,101,109,97,110,116,105, - 99,115,32,102,111,114,32,109,111,100,117,108,101,32,99,114, - 101,97,116,105,111,110,46,78,114,10,0,0,0,41,2,114, - 163,0,0,0,114,95,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,149,0,0,0,48,3,0, - 0,115,2,0,0,0,0,2,122,28,70,114,111,122,101,110, - 73,109,112,111,114,116,101,114,46,99,114,101,97,116,101,95, - 109,111,100,117,108,101,99,1,0,0,0,0,0,0,0,3, - 0,0,0,4,0,0,0,67,0,0,0,115,64,0,0,0, - 124,0,106,0,106,1,125,1,116,2,160,3,124,1,161,1, - 115,36,116,4,100,1,160,5,124,1,161,1,124,1,100,2, - 141,2,130,1,116,6,116,2,106,7,124,1,131,2,125,2, - 116,8,124,2,124,0,106,9,131,2,1,0,100,0,83,0, - 114,87,0,0,0,41,10,114,105,0,0,0,114,17,0,0, - 0,114,57,0,0,0,114,88,0,0,0,114,79,0,0,0, - 114,45,0,0,0,114,67,0,0,0,218,17,103,101,116,95, - 102,114,111,122,101,110,95,111,98,106,101,99,116,218,4,101, - 120,101,99,114,7,0,0,0,41,3,114,96,0,0,0,114, - 17,0,0,0,218,4,99,111,100,101,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,150,0,0,0,52,3, - 0,0,115,14,0,0,0,0,2,8,1,10,1,10,1,2, - 255,6,2,12,1,122,26,70,114,111,122,101,110,73,109,112, - 111,114,116,101,114,46,101,120,101,99,95,109,111,100,117,108, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,3,0, + 95,115,112,101,99,99,3,0,0,0,0,0,0,0,0,0, + 0,0,3,0,0,0,3,0,0,0,67,0,0,0,115,18, + 0,0,0,116,0,160,1,124,1,161,1,114,14,124,0,83, + 0,100,1,83,0,41,2,122,93,70,105,110,100,32,97,32, + 102,114,111,122,101,110,32,109,111,100,117,108,101,46,10,10, + 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, + 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, + 100,46,32,32,85,115,101,32,102,105,110,100,95,115,112,101, + 99,40,41,32,105,110,115,116,101,97,100,46,10,10,32,32, + 32,32,32,32,32,32,78,41,2,114,57,0,0,0,114,88, + 0,0,0,41,3,114,163,0,0,0,114,81,0,0,0,114, + 164,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,167,0,0,0,39,3,0,0,115,2,0,0, + 0,0,7,122,26,70,114,111,122,101,110,73,109,112,111,114, + 116,101,114,46,102,105,110,100,95,109,111,100,117,108,101,99, + 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,83, + 0,41,2,122,42,85,115,101,32,100,101,102,97,117,108,116, + 32,115,101,109,97,110,116,105,99,115,32,102,111,114,32,109, + 111,100,117,108,101,32,99,114,101,97,116,105,111,110,46,78, + 114,10,0,0,0,41,2,114,163,0,0,0,114,95,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 114,149,0,0,0,48,3,0,0,115,2,0,0,0,0,2, + 122,28,70,114,111,122,101,110,73,109,112,111,114,116,101,114, + 46,99,114,101,97,116,101,95,109,111,100,117,108,101,99,1, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,4, + 0,0,0,67,0,0,0,115,64,0,0,0,124,0,106,0, + 106,1,125,1,116,2,160,3,124,1,161,1,115,36,116,4, + 100,1,160,5,124,1,161,1,124,1,100,2,141,2,130,1, + 116,6,116,2,106,7,124,1,131,2,125,2,116,8,124,2, + 124,0,106,9,131,2,1,0,100,0,83,0,114,87,0,0, + 0,41,10,114,105,0,0,0,114,17,0,0,0,114,57,0, + 0,0,114,88,0,0,0,114,79,0,0,0,114,45,0,0, + 0,114,67,0,0,0,218,17,103,101,116,95,102,114,111,122, + 101,110,95,111,98,106,101,99,116,218,4,101,120,101,99,114, + 7,0,0,0,41,3,114,96,0,0,0,114,17,0,0,0, + 218,4,99,111,100,101,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,150,0,0,0,52,3,0,0,115,14, + 0,0,0,0,2,8,1,10,1,10,1,2,255,6,2,12, + 1,122,26,70,114,111,122,101,110,73,109,112,111,114,116,101, + 114,46,101,120,101,99,95,109,111,100,117,108,101,99,2,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0, 0,0,67,0,0,0,115,10,0,0,0,116,0,124,0,124, 1,131,2,83,0,41,1,122,95,76,111,97,100,32,97,32, 102,114,111,122,101,110,32,109,111,100,117,108,101,46,10,10, @@ -1243,48 +1259,49 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,0,114,155,0,0,0,61,3,0,0,115,2,0,0, 0,0,7,122,26,70,114,111,122,101,110,73,109,112,111,114, 116,101,114,46,108,111,97,100,95,109,111,100,117,108,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, - 67,0,0,0,115,10,0,0,0,116,0,160,1,124,1,161, - 1,83,0,41,1,122,45,82,101,116,117,114,110,32,116,104, - 101,32,99,111,100,101,32,111,98,106,101,99,116,32,102,111, - 114,32,116,104,101,32,102,114,111,122,101,110,32,109,111,100, - 117,108,101,46,41,2,114,57,0,0,0,114,175,0,0,0, - 114,168,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,169,0,0,0,70,3,0,0,115,2,0, - 0,0,0,4,122,23,70,114,111,122,101,110,73,109,112,111, - 114,116,101,114,46,103,101,116,95,99,111,100,101,99,2,0, - 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, - 0,0,115,4,0,0,0,100,1,83,0,41,2,122,54,82, - 101,116,117,114,110,32,78,111,110,101,32,97,115,32,102,114, - 111,122,101,110,32,109,111,100,117,108,101,115,32,100,111,32, - 110,111,116,32,104,97,118,101,32,115,111,117,114,99,101,32, - 99,111,100,101,46,78,114,10,0,0,0,114,168,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 170,0,0,0,76,3,0,0,115,2,0,0,0,0,4,122, - 25,70,114,111,122,101,110,73,109,112,111,114,116,101,114,46, - 103,101,116,95,115,111,117,114,99,101,99,2,0,0,0,0, - 0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115, - 10,0,0,0,116,0,160,1,124,1,161,1,83,0,41,1, - 122,46,82,101,116,117,114,110,32,84,114,117,101,32,105,102, - 32,116,104,101,32,102,114,111,122,101,110,32,109,111,100,117, - 108,101,32,105,115,32,97,32,112,97,99,107,97,103,101,46, - 41,2,114,57,0,0,0,90,17,105,115,95,102,114,111,122, - 101,110,95,112,97,99,107,97,103,101,114,168,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,115, - 0,0,0,82,3,0,0,115,2,0,0,0,0,4,122,25, - 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,105, - 115,95,112,97,99,107,97,103,101,41,2,78,78,41,1,78, - 41,17,114,1,0,0,0,114,0,0,0,0,114,2,0,0, - 0,114,3,0,0,0,114,138,0,0,0,114,171,0,0,0, - 114,99,0,0,0,114,172,0,0,0,114,166,0,0,0,114, - 167,0,0,0,114,149,0,0,0,114,150,0,0,0,114,155, - 0,0,0,114,90,0,0,0,114,169,0,0,0,114,170,0, - 0,0,114,115,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,173,0,0,0, - 12,3,0,0,115,46,0,0,0,8,2,4,7,4,2,2, - 1,10,8,2,1,12,6,2,1,12,8,2,1,10,3,2, - 1,10,8,2,1,10,8,2,1,2,1,12,4,2,1,2, - 1,12,4,2,1,2,1,114,173,0,0,0,99,0,0,0, + 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 3,0,0,0,67,0,0,0,115,10,0,0,0,116,0,160, + 1,124,1,161,1,83,0,41,1,122,45,82,101,116,117,114, + 110,32,116,104,101,32,99,111,100,101,32,111,98,106,101,99, + 116,32,102,111,114,32,116,104,101,32,102,114,111,122,101,110, + 32,109,111,100,117,108,101,46,41,2,114,57,0,0,0,114, + 175,0,0,0,114,168,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,169,0,0,0,70,3,0, + 0,115,2,0,0,0,0,4,122,23,70,114,111,122,101,110, + 73,109,112,111,114,116,101,114,46,103,101,116,95,99,111,100, + 101,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, + 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, + 1,83,0,41,2,122,54,82,101,116,117,114,110,32,78,111, + 110,101,32,97,115,32,102,114,111,122,101,110,32,109,111,100, + 117,108,101,115,32,100,111,32,110,111,116,32,104,97,118,101, + 32,115,111,117,114,99,101,32,99,111,100,101,46,78,114,10, + 0,0,0,114,168,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,170,0,0,0,76,3,0,0, + 115,2,0,0,0,0,4,122,25,70,114,111,122,101,110,73, + 109,112,111,114,116,101,114,46,103,101,116,95,115,111,117,114, + 99,101,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,3,0,0,0,67,0,0,0,115,10,0,0,0, + 116,0,160,1,124,1,161,1,83,0,41,1,122,46,82,101, + 116,117,114,110,32,84,114,117,101,32,105,102,32,116,104,101, + 32,102,114,111,122,101,110,32,109,111,100,117,108,101,32,105, + 115,32,97,32,112,97,99,107,97,103,101,46,41,2,114,57, + 0,0,0,90,17,105,115,95,102,114,111,122,101,110,95,112, + 97,99,107,97,103,101,114,168,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,115,0,0,0,82, + 3,0,0,115,2,0,0,0,0,4,122,25,70,114,111,122, + 101,110,73,109,112,111,114,116,101,114,46,105,115,95,112,97, + 99,107,97,103,101,41,2,78,78,41,1,78,41,17,114,1, + 0,0,0,114,0,0,0,0,114,2,0,0,0,114,3,0, + 0,0,114,138,0,0,0,114,171,0,0,0,114,99,0,0, + 0,114,172,0,0,0,114,166,0,0,0,114,167,0,0,0, + 114,149,0,0,0,114,150,0,0,0,114,155,0,0,0,114, + 90,0,0,0,114,169,0,0,0,114,170,0,0,0,114,115, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,173,0,0,0,12,3,0,0, + 115,46,0,0,0,8,2,4,7,4,2,2,1,10,8,2, + 1,12,6,2,1,12,8,2,1,10,3,2,1,10,8,2, + 1,10,8,2,1,2,1,12,4,2,1,2,1,12,4,2, + 1,2,1,114,173,0,0,0,99,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0, 0,115,32,0,0,0,101,0,90,1,100,0,90,2,100,1, 90,3,100,2,100,3,132,0,90,4,100,4,100,5,132,0, @@ -1292,55 +1309,56 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 116,76,111,99,107,67,111,110,116,101,120,116,122,36,67,111, 110,116,101,120,116,32,109,97,110,97,103,101,114,32,102,111, 114,32,116,104,101,32,105,109,112,111,114,116,32,108,111,99, - 107,46,99,1,0,0,0,0,0,0,0,1,0,0,0,2, - 0,0,0,67,0,0,0,115,12,0,0,0,116,0,160,1, - 161,0,1,0,100,1,83,0,41,2,122,24,65,99,113,117, - 105,114,101,32,116,104,101,32,105,109,112,111,114,116,32,108, - 111,99,107,46,78,41,2,114,57,0,0,0,114,58,0,0, - 0,114,47,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,54,0,0,0,95,3,0,0,115,2, - 0,0,0,0,2,122,28,95,73,109,112,111,114,116,76,111, - 99,107,67,111,110,116,101,120,116,46,95,95,101,110,116,101, - 114,95,95,99,4,0,0,0,0,0,0,0,4,0,0,0, - 2,0,0,0,67,0,0,0,115,12,0,0,0,116,0,160, - 1,161,0,1,0,100,1,83,0,41,2,122,60,82,101,108, - 101,97,115,101,32,116,104,101,32,105,109,112,111,114,116,32, - 108,111,99,107,32,114,101,103,97,114,100,108,101,115,115,32, - 111,102,32,97,110,121,32,114,97,105,115,101,100,32,101,120, - 99,101,112,116,105,111,110,115,46,78,41,2,114,57,0,0, - 0,114,60,0,0,0,41,4,114,30,0,0,0,90,8,101, - 120,99,95,116,121,112,101,90,9,101,120,99,95,118,97,108, - 117,101,90,13,101,120,99,95,116,114,97,99,101,98,97,99, - 107,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,56,0,0,0,99,3,0,0,115,2,0,0,0,0,2, - 122,27,95,73,109,112,111,114,116,76,111,99,107,67,111,110, - 116,101,120,116,46,95,95,101,120,105,116,95,95,78,41,6, - 114,1,0,0,0,114,0,0,0,0,114,2,0,0,0,114, - 3,0,0,0,114,54,0,0,0,114,56,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,178,0,0,0,91,3,0,0,115,6,0,0,0, - 8,2,4,2,8,4,114,178,0,0,0,99,3,0,0,0, - 0,0,0,0,5,0,0,0,5,0,0,0,67,0,0,0, - 115,64,0,0,0,124,1,160,0,100,1,124,2,100,2,24, - 0,161,2,125,3,116,1,124,3,131,1,124,2,107,0,114, - 36,116,2,100,3,131,1,130,1,124,3,100,4,25,0,125, - 4,124,0,114,60,100,5,160,3,124,4,124,0,161,2,83, - 0,124,4,83,0,41,6,122,50,82,101,115,111,108,118,101, - 32,97,32,114,101,108,97,116,105,118,101,32,109,111,100,117, - 108,101,32,110,97,109,101,32,116,111,32,97,110,32,97,98, - 115,111,108,117,116,101,32,111,110,101,46,114,128,0,0,0, - 114,37,0,0,0,122,50,97,116,116,101,109,112,116,101,100, - 32,114,101,108,97,116,105,118,101,32,105,109,112,111,114,116, - 32,98,101,121,111,110,100,32,116,111,112,45,108,101,118,101, - 108,32,112,97,99,107,97,103,101,114,22,0,0,0,250,5, - 123,125,46,123,125,41,4,218,6,114,115,112,108,105,116,218, - 3,108,101,110,218,10,86,97,108,117,101,69,114,114,111,114, - 114,45,0,0,0,41,5,114,17,0,0,0,218,7,112,97, - 99,107,97,103,101,218,5,108,101,118,101,108,90,4,98,105, - 116,115,90,4,98,97,115,101,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,218,13,95,114,101,115,111,108,118, - 101,95,110,97,109,101,104,3,0,0,115,10,0,0,0,0, - 2,16,1,12,1,8,1,8,1,114,185,0,0,0,99,3, + 107,46,99,1,0,0,0,0,0,0,0,0,0,0,0,1, + 0,0,0,2,0,0,0,67,0,0,0,115,12,0,0,0, + 116,0,160,1,161,0,1,0,100,1,83,0,41,2,122,24, + 65,99,113,117,105,114,101,32,116,104,101,32,105,109,112,111, + 114,116,32,108,111,99,107,46,78,41,2,114,57,0,0,0, + 114,58,0,0,0,114,47,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,54,0,0,0,95,3, + 0,0,115,2,0,0,0,0,2,122,28,95,73,109,112,111, + 114,116,76,111,99,107,67,111,110,116,101,120,116,46,95,95, + 101,110,116,101,114,95,95,99,4,0,0,0,0,0,0,0, + 0,0,0,0,4,0,0,0,2,0,0,0,67,0,0,0, + 115,12,0,0,0,116,0,160,1,161,0,1,0,100,1,83, + 0,41,2,122,60,82,101,108,101,97,115,101,32,116,104,101, + 32,105,109,112,111,114,116,32,108,111,99,107,32,114,101,103, + 97,114,100,108,101,115,115,32,111,102,32,97,110,121,32,114, + 97,105,115,101,100,32,101,120,99,101,112,116,105,111,110,115, + 46,78,41,2,114,57,0,0,0,114,60,0,0,0,41,4, + 114,30,0,0,0,90,8,101,120,99,95,116,121,112,101,90, + 9,101,120,99,95,118,97,108,117,101,90,13,101,120,99,95, + 116,114,97,99,101,98,97,99,107,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,56,0,0,0,99,3,0, + 0,115,2,0,0,0,0,2,122,27,95,73,109,112,111,114, + 116,76,111,99,107,67,111,110,116,101,120,116,46,95,95,101, + 120,105,116,95,95,78,41,6,114,1,0,0,0,114,0,0, + 0,0,114,2,0,0,0,114,3,0,0,0,114,54,0,0, + 0,114,56,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,178,0,0,0,91, + 3,0,0,115,6,0,0,0,8,2,4,2,8,4,114,178, + 0,0,0,99,3,0,0,0,0,0,0,0,0,0,0,0, + 5,0,0,0,5,0,0,0,67,0,0,0,115,64,0,0, + 0,124,1,160,0,100,1,124,2,100,2,24,0,161,2,125, + 3,116,1,124,3,131,1,124,2,107,0,114,36,116,2,100, + 3,131,1,130,1,124,3,100,4,25,0,125,4,124,0,114, + 60,100,5,160,3,124,4,124,0,161,2,83,0,124,4,83, + 0,41,6,122,50,82,101,115,111,108,118,101,32,97,32,114, + 101,108,97,116,105,118,101,32,109,111,100,117,108,101,32,110, + 97,109,101,32,116,111,32,97,110,32,97,98,115,111,108,117, + 116,101,32,111,110,101,46,114,128,0,0,0,114,37,0,0, + 0,122,50,97,116,116,101,109,112,116,101,100,32,114,101,108, + 97,116,105,118,101,32,105,109,112,111,114,116,32,98,101,121, + 111,110,100,32,116,111,112,45,108,101,118,101,108,32,112,97, + 99,107,97,103,101,114,22,0,0,0,250,5,123,125,46,123, + 125,41,4,218,6,114,115,112,108,105,116,218,3,108,101,110, + 218,10,86,97,108,117,101,69,114,114,111,114,114,45,0,0, + 0,41,5,114,17,0,0,0,218,7,112,97,99,107,97,103, + 101,218,5,108,101,118,101,108,90,4,98,105,116,115,90,4, + 98,97,115,101,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,218,13,95,114,101,115,111,108,118,101,95,110,97, + 109,101,104,3,0,0,115,10,0,0,0,0,2,16,1,12, + 1,8,1,8,1,114,185,0,0,0,99,3,0,0,0,0, 0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67, 0,0,0,115,34,0,0,0,124,0,160,0,124,1,124,2, 161,2,125,3,124,3,100,0,107,8,114,24,100,0,83,0, @@ -1351,110 +1369,111 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,0,218,17,95,102,105,110,100,95,115,112,101,99,95, 108,101,103,97,99,121,113,3,0,0,115,8,0,0,0,0, 3,12,1,8,1,4,1,114,187,0,0,0,99,3,0,0, - 0,0,0,0,0,10,0,0,0,10,0,0,0,67,0,0, - 0,115,12,1,0,0,116,0,106,1,125,3,124,3,100,1, - 107,8,114,22,116,2,100,2,131,1,130,1,124,3,115,38, - 116,3,160,4,100,3,116,5,161,2,1,0,124,0,116,0, - 106,6,107,6,125,4,124,3,68,0,93,210,125,5,116,7, - 131,0,143,84,1,0,122,10,124,5,106,8,125,6,87,0, - 110,54,4,0,116,9,107,10,114,128,1,0,1,0,1,0, - 116,10,124,5,124,0,124,1,131,3,125,7,124,7,100,1, - 107,8,114,124,89,0,87,0,53,0,81,0,82,0,163,0, - 113,52,89,0,110,14,88,0,124,6,124,0,124,1,124,2, - 131,3,125,7,87,0,53,0,81,0,82,0,88,0,124,7, - 100,1,107,9,114,52,124,4,144,0,115,254,124,0,116,0, - 106,6,107,6,144,0,114,254,116,0,106,6,124,0,25,0, - 125,8,122,10,124,8,106,11,125,9,87,0,110,28,4,0, - 116,9,107,10,114,226,1,0,1,0,1,0,124,7,6,0, - 89,0,2,0,1,0,83,0,88,0,124,9,100,1,107,8, - 114,244,124,7,2,0,1,0,83,0,124,9,2,0,1,0, - 83,0,113,52,124,7,2,0,1,0,83,0,113,52,100,1, - 83,0,41,4,122,21,70,105,110,100,32,97,32,109,111,100, - 117,108,101,39,115,32,115,112,101,99,46,78,122,53,115,121, - 115,46,109,101,116,97,95,112,97,116,104,32,105,115,32,78, - 111,110,101,44,32,80,121,116,104,111,110,32,105,115,32,108, - 105,107,101,108,121,32,115,104,117,116,116,105,110,103,32,100, - 111,119,110,122,22,115,121,115,46,109,101,116,97,95,112,97, - 116,104,32,105,115,32,101,109,112,116,121,41,12,114,15,0, - 0,0,218,9,109,101,116,97,95,112,97,116,104,114,79,0, - 0,0,218,9,95,119,97,114,110,105,110,103,115,218,4,119, - 97,114,110,218,13,73,109,112,111,114,116,87,97,114,110,105, - 110,103,114,92,0,0,0,114,178,0,0,0,114,166,0,0, - 0,114,106,0,0,0,114,187,0,0,0,114,105,0,0,0, - 41,10,114,17,0,0,0,114,164,0,0,0,114,165,0,0, - 0,114,188,0,0,0,90,9,105,115,95,114,101,108,111,97, - 100,114,186,0,0,0,114,166,0,0,0,114,95,0,0,0, - 114,96,0,0,0,114,105,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,10,95,102,105,110,100, - 95,115,112,101,99,122,3,0,0,115,54,0,0,0,0,2, - 6,1,8,2,8,3,4,1,12,5,10,1,8,1,8,1, - 2,1,10,1,14,1,12,1,8,1,20,2,22,1,8,2, - 18,1,10,1,2,1,10,1,14,4,14,2,8,1,8,2, - 10,2,10,2,114,192,0,0,0,99,3,0,0,0,0,0, - 0,0,3,0,0,0,5,0,0,0,67,0,0,0,115,108, - 0,0,0,116,0,124,0,116,1,131,2,115,28,116,2,100, - 1,160,3,116,4,124,0,131,1,161,1,131,1,130,1,124, - 2,100,2,107,0,114,44,116,5,100,3,131,1,130,1,124, - 2,100,2,107,4,114,84,116,0,124,1,116,1,131,2,115, - 72,116,2,100,4,131,1,130,1,110,12,124,1,115,84,116, - 6,100,5,131,1,130,1,124,0,115,104,124,2,100,2,107, - 2,114,104,116,5,100,6,131,1,130,1,100,7,83,0,41, - 8,122,28,86,101,114,105,102,121,32,97,114,103,117,109,101, - 110,116,115,32,97,114,101,32,34,115,97,110,101,34,46,122, - 31,109,111,100,117,108,101,32,110,97,109,101,32,109,117,115, - 116,32,98,101,32,115,116,114,44,32,110,111,116,32,123,125, - 114,22,0,0,0,122,18,108,101,118,101,108,32,109,117,115, - 116,32,98,101,32,62,61,32,48,122,31,95,95,112,97,99, - 107,97,103,101,95,95,32,110,111,116,32,115,101,116,32,116, - 111,32,97,32,115,116,114,105,110,103,122,54,97,116,116,101, - 109,112,116,101,100,32,114,101,108,97,116,105,118,101,32,105, - 109,112,111,114,116,32,119,105,116,104,32,110,111,32,107,110, - 111,119,110,32,112,97,114,101,110,116,32,112,97,99,107,97, - 103,101,122,17,69,109,112,116,121,32,109,111,100,117,108,101, - 32,110,97,109,101,78,41,7,218,10,105,115,105,110,115,116, - 97,110,99,101,218,3,115,116,114,218,9,84,121,112,101,69, - 114,114,111,114,114,45,0,0,0,114,14,0,0,0,114,182, - 0,0,0,114,79,0,0,0,169,3,114,17,0,0,0,114, - 183,0,0,0,114,184,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,218,13,95,115,97,110,105,116, - 121,95,99,104,101,99,107,169,3,0,0,115,22,0,0,0, - 0,2,10,1,18,1,8,1,8,1,8,1,10,1,10,1, - 4,1,8,2,12,1,114,197,0,0,0,122,16,78,111,32, - 109,111,100,117,108,101,32,110,97,109,101,100,32,122,4,123, - 33,114,125,99,2,0,0,0,0,0,0,0,8,0,0,0, - 8,0,0,0,67,0,0,0,115,220,0,0,0,100,0,125, - 2,124,0,160,0,100,1,161,1,100,2,25,0,125,3,124, - 3,114,134,124,3,116,1,106,2,107,7,114,42,116,3,124, - 1,124,3,131,2,1,0,124,0,116,1,106,2,107,6,114, - 62,116,1,106,2,124,0,25,0,83,0,116,1,106,2,124, - 3,25,0,125,4,122,10,124,4,106,4,125,2,87,0,110, - 50,4,0,116,5,107,10,114,132,1,0,1,0,1,0,116, - 6,100,3,23,0,160,7,124,0,124,3,161,2,125,5,116, - 8,124,5,124,0,100,4,141,2,100,0,130,2,89,0,110, - 2,88,0,116,9,124,0,124,2,131,2,125,6,124,6,100, - 0,107,8,114,172,116,8,116,6,160,7,124,0,161,1,124, - 0,100,4,141,2,130,1,110,8,116,10,124,6,131,1,125, - 7,124,3,114,216,116,1,106,2,124,3,25,0,125,4,116, - 11,124,4,124,0,160,0,100,1,161,1,100,5,25,0,124, - 7,131,3,1,0,124,7,83,0,41,6,78,114,128,0,0, - 0,114,22,0,0,0,122,23,59,32,123,33,114,125,32,105, - 115,32,110,111,116,32,97,32,112,97,99,107,97,103,101,114, - 16,0,0,0,233,2,0,0,0,41,12,114,129,0,0,0, - 114,15,0,0,0,114,92,0,0,0,114,67,0,0,0,114, - 141,0,0,0,114,106,0,0,0,218,8,95,69,82,82,95, - 77,83,71,114,45,0,0,0,218,19,77,111,100,117,108,101, - 78,111,116,70,111,117,110,100,69,114,114,111,114,114,192,0, - 0,0,114,159,0,0,0,114,5,0,0,0,41,8,114,17, - 0,0,0,218,7,105,109,112,111,114,116,95,114,164,0,0, - 0,114,130,0,0,0,90,13,112,97,114,101,110,116,95,109, - 111,100,117,108,101,114,157,0,0,0,114,95,0,0,0,114, - 96,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,218,23,95,102,105,110,100,95,97,110,100,95,108, - 111,97,100,95,117,110,108,111,99,107,101,100,188,3,0,0, - 115,42,0,0,0,0,1,4,1,14,1,4,1,10,1,10, - 2,10,1,10,1,10,1,2,1,10,1,14,1,16,1,20, - 1,10,1,8,1,20,2,8,1,4,2,10,1,22,1,114, - 202,0,0,0,99,2,0,0,0,0,0,0,0,4,0,0, + 0,0,0,0,0,0,0,0,0,10,0,0,0,10,0,0, + 0,67,0,0,0,115,12,1,0,0,116,0,106,1,125,3, + 124,3,100,1,107,8,114,22,116,2,100,2,131,1,130,1, + 124,3,115,38,116,3,160,4,100,3,116,5,161,2,1,0, + 124,0,116,0,106,6,107,6,125,4,124,3,68,0,93,210, + 125,5,116,7,131,0,143,84,1,0,122,10,124,5,106,8, + 125,6,87,0,110,54,4,0,116,9,107,10,114,128,1,0, + 1,0,1,0,116,10,124,5,124,0,124,1,131,3,125,7, + 124,7,100,1,107,8,114,124,89,0,87,0,53,0,81,0, + 82,0,163,0,113,52,89,0,110,14,88,0,124,6,124,0, + 124,1,124,2,131,3,125,7,87,0,53,0,81,0,82,0, + 88,0,124,7,100,1,107,9,114,52,124,4,144,0,115,254, + 124,0,116,0,106,6,107,6,144,0,114,254,116,0,106,6, + 124,0,25,0,125,8,122,10,124,8,106,11,125,9,87,0, + 110,28,4,0,116,9,107,10,114,226,1,0,1,0,1,0, + 124,7,6,0,89,0,2,0,1,0,83,0,88,0,124,9, + 100,1,107,8,114,244,124,7,2,0,1,0,83,0,124,9, + 2,0,1,0,83,0,113,52,124,7,2,0,1,0,83,0, + 113,52,100,1,83,0,41,4,122,21,70,105,110,100,32,97, + 32,109,111,100,117,108,101,39,115,32,115,112,101,99,46,78, + 122,53,115,121,115,46,109,101,116,97,95,112,97,116,104,32, + 105,115,32,78,111,110,101,44,32,80,121,116,104,111,110,32, + 105,115,32,108,105,107,101,108,121,32,115,104,117,116,116,105, + 110,103,32,100,111,119,110,122,22,115,121,115,46,109,101,116, + 97,95,112,97,116,104,32,105,115,32,101,109,112,116,121,41, + 12,114,15,0,0,0,218,9,109,101,116,97,95,112,97,116, + 104,114,79,0,0,0,218,9,95,119,97,114,110,105,110,103, + 115,218,4,119,97,114,110,218,13,73,109,112,111,114,116,87, + 97,114,110,105,110,103,114,92,0,0,0,114,178,0,0,0, + 114,166,0,0,0,114,106,0,0,0,114,187,0,0,0,114, + 105,0,0,0,41,10,114,17,0,0,0,114,164,0,0,0, + 114,165,0,0,0,114,188,0,0,0,90,9,105,115,95,114, + 101,108,111,97,100,114,186,0,0,0,114,166,0,0,0,114, + 95,0,0,0,114,96,0,0,0,114,105,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,218,10,95, + 102,105,110,100,95,115,112,101,99,122,3,0,0,115,54,0, + 0,0,0,2,6,1,8,2,8,3,4,1,12,5,10,1, + 8,1,8,1,2,1,10,1,14,1,12,1,8,1,20,2, + 22,1,8,2,18,1,10,1,2,1,10,1,14,4,14,2, + 8,1,8,2,10,2,10,2,114,192,0,0,0,99,3,0, + 0,0,0,0,0,0,0,0,0,0,3,0,0,0,5,0, + 0,0,67,0,0,0,115,108,0,0,0,116,0,124,0,116, + 1,131,2,115,28,116,2,100,1,160,3,116,4,124,0,131, + 1,161,1,131,1,130,1,124,2,100,2,107,0,114,44,116, + 5,100,3,131,1,130,1,124,2,100,2,107,4,114,84,116, + 0,124,1,116,1,131,2,115,72,116,2,100,4,131,1,130, + 1,110,12,124,1,115,84,116,6,100,5,131,1,130,1,124, + 0,115,104,124,2,100,2,107,2,114,104,116,5,100,6,131, + 1,130,1,100,7,83,0,41,8,122,28,86,101,114,105,102, + 121,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32, + 34,115,97,110,101,34,46,122,31,109,111,100,117,108,101,32, + 110,97,109,101,32,109,117,115,116,32,98,101,32,115,116,114, + 44,32,110,111,116,32,123,125,114,22,0,0,0,122,18,108, + 101,118,101,108,32,109,117,115,116,32,98,101,32,62,61,32, + 48,122,31,95,95,112,97,99,107,97,103,101,95,95,32,110, + 111,116,32,115,101,116,32,116,111,32,97,32,115,116,114,105, + 110,103,122,54,97,116,116,101,109,112,116,101,100,32,114,101, + 108,97,116,105,118,101,32,105,109,112,111,114,116,32,119,105, + 116,104,32,110,111,32,107,110,111,119,110,32,112,97,114,101, + 110,116,32,112,97,99,107,97,103,101,122,17,69,109,112,116, + 121,32,109,111,100,117,108,101,32,110,97,109,101,78,41,7, + 218,10,105,115,105,110,115,116,97,110,99,101,218,3,115,116, + 114,218,9,84,121,112,101,69,114,114,111,114,114,45,0,0, + 0,114,14,0,0,0,114,182,0,0,0,114,79,0,0,0, + 169,3,114,17,0,0,0,114,183,0,0,0,114,184,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 218,13,95,115,97,110,105,116,121,95,99,104,101,99,107,169, + 3,0,0,115,22,0,0,0,0,2,10,1,18,1,8,1, + 8,1,8,1,10,1,10,1,4,1,8,2,12,1,114,197, + 0,0,0,122,16,78,111,32,109,111,100,117,108,101,32,110, + 97,109,101,100,32,122,4,123,33,114,125,99,2,0,0,0, + 0,0,0,0,0,0,0,0,8,0,0,0,8,0,0,0, + 67,0,0,0,115,220,0,0,0,100,0,125,2,124,0,160, + 0,100,1,161,1,100,2,25,0,125,3,124,3,114,134,124, + 3,116,1,106,2,107,7,114,42,116,3,124,1,124,3,131, + 2,1,0,124,0,116,1,106,2,107,6,114,62,116,1,106, + 2,124,0,25,0,83,0,116,1,106,2,124,3,25,0,125, + 4,122,10,124,4,106,4,125,2,87,0,110,50,4,0,116, + 5,107,10,114,132,1,0,1,0,1,0,116,6,100,3,23, + 0,160,7,124,0,124,3,161,2,125,5,116,8,124,5,124, + 0,100,4,141,2,100,0,130,2,89,0,110,2,88,0,116, + 9,124,0,124,2,131,2,125,6,124,6,100,0,107,8,114, + 172,116,8,116,6,160,7,124,0,161,1,124,0,100,4,141, + 2,130,1,110,8,116,10,124,6,131,1,125,7,124,3,114, + 216,116,1,106,2,124,3,25,0,125,4,116,11,124,4,124, + 0,160,0,100,1,161,1,100,5,25,0,124,7,131,3,1, + 0,124,7,83,0,41,6,78,114,128,0,0,0,114,22,0, + 0,0,122,23,59,32,123,33,114,125,32,105,115,32,110,111, + 116,32,97,32,112,97,99,107,97,103,101,114,16,0,0,0, + 233,2,0,0,0,41,12,114,129,0,0,0,114,15,0,0, + 0,114,92,0,0,0,114,67,0,0,0,114,141,0,0,0, + 114,106,0,0,0,218,8,95,69,82,82,95,77,83,71,114, + 45,0,0,0,218,19,77,111,100,117,108,101,78,111,116,70, + 111,117,110,100,69,114,114,111,114,114,192,0,0,0,114,159, + 0,0,0,114,5,0,0,0,41,8,114,17,0,0,0,218, + 7,105,109,112,111,114,116,95,114,164,0,0,0,114,130,0, + 0,0,90,13,112,97,114,101,110,116,95,109,111,100,117,108, + 101,114,157,0,0,0,114,95,0,0,0,114,96,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218, + 23,95,102,105,110,100,95,97,110,100,95,108,111,97,100,95, + 117,110,108,111,99,107,101,100,188,3,0,0,115,42,0,0, + 0,0,1,4,1,14,1,4,1,10,1,10,2,10,1,10, + 1,10,1,2,1,10,1,14,1,16,1,20,1,10,1,8, + 1,20,2,8,1,4,2,10,1,22,1,114,202,0,0,0, + 99,2,0,0,0,0,0,0,0,0,0,0,0,4,0,0, 0,10,0,0,0,67,0,0,0,115,106,0,0,0,116,0, 124,0,131,1,143,50,1,0,116,1,106,2,160,3,124,0, 116,4,161,2,125,2,124,2,116,4,107,8,114,54,116,5, @@ -1477,128 +1496,129 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 108,111,97,100,218,3,0,0,115,22,0,0,0,0,2,10, 1,14,1,8,1,32,2,8,1,4,1,2,255,4,2,12, 2,8,1,114,204,0,0,0,114,22,0,0,0,99,3,0, - 0,0,0,0,0,0,3,0,0,0,4,0,0,0,67,0, - 0,0,115,42,0,0,0,116,0,124,0,124,1,124,2,131, - 3,1,0,124,2,100,1,107,4,114,32,116,1,124,0,124, - 1,124,2,131,3,125,0,116,2,124,0,116,3,131,2,83, - 0,41,2,97,50,1,0,0,73,109,112,111,114,116,32,97, - 110,100,32,114,101,116,117,114,110,32,116,104,101,32,109,111, - 100,117,108,101,32,98,97,115,101,100,32,111,110,32,105,116, - 115,32,110,97,109,101,44,32,116,104,101,32,112,97,99,107, - 97,103,101,32,116,104,101,32,99,97,108,108,32,105,115,10, - 32,32,32,32,98,101,105,110,103,32,109,97,100,101,32,102, - 114,111,109,44,32,97,110,100,32,116,104,101,32,108,101,118, - 101,108,32,97,100,106,117,115,116,109,101,110,116,46,10,10, - 32,32,32,32,84,104,105,115,32,102,117,110,99,116,105,111, - 110,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101, - 32,103,114,101,97,116,101,115,116,32,99,111,109,109,111,110, - 32,100,101,110,111,109,105,110,97,116,111,114,32,111,102,32, - 102,117,110,99,116,105,111,110,97,108,105,116,121,10,32,32, - 32,32,98,101,116,119,101,101,110,32,105,109,112,111,114,116, - 95,109,111,100,117,108,101,32,97,110,100,32,95,95,105,109, - 112,111,114,116,95,95,46,32,84,104,105,115,32,105,110,99, - 108,117,100,101,115,32,115,101,116,116,105,110,103,32,95,95, - 112,97,99,107,97,103,101,95,95,32,105,102,10,32,32,32, - 32,116,104,101,32,108,111,97,100,101,114,32,100,105,100,32, - 110,111,116,46,10,10,32,32,32,32,114,22,0,0,0,41, - 4,114,197,0,0,0,114,185,0,0,0,114,204,0,0,0, - 218,11,95,103,99,100,95,105,109,112,111,114,116,114,196,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,205,0,0,0,234,3,0,0,115,8,0,0,0,0, - 9,12,1,8,1,12,1,114,205,0,0,0,169,1,218,9, - 114,101,99,117,114,115,105,118,101,99,3,0,0,0,1,0, - 0,0,8,0,0,0,11,0,0,0,67,0,0,0,115,226, - 0,0,0,124,1,68,0,93,216,125,4,116,0,124,4,116, - 1,131,2,115,66,124,3,114,34,124,0,106,2,100,1,23, - 0,125,5,110,4,100,2,125,5,116,3,100,3,124,5,155, - 0,100,4,116,4,124,4,131,1,106,2,155,0,157,4,131, - 1,130,1,110,154,124,4,100,5,107,2,114,108,124,3,115, - 106,116,5,124,0,100,6,131,2,114,106,116,6,124,0,124, - 0,106,7,124,2,100,7,100,8,141,4,1,0,110,112,116, - 5,124,0,124,4,131,2,115,220,100,9,160,8,124,0,106, - 2,124,4,161,2,125,6,122,14,116,9,124,2,124,6,131, - 2,1,0,87,0,110,72,4,0,116,10,107,10,114,218,1, - 0,125,7,1,0,122,42,124,7,106,11,124,6,107,2,114, - 200,116,12,106,13,160,14,124,6,116,15,161,2,100,10,107, - 9,114,200,87,0,89,0,162,8,113,4,130,0,87,0,53, - 0,100,10,125,7,126,7,88,0,89,0,110,2,88,0,113, - 4,124,0,83,0,41,11,122,238,70,105,103,117,114,101,32, - 111,117,116,32,119,104,97,116,32,95,95,105,109,112,111,114, - 116,95,95,32,115,104,111,117,108,100,32,114,101,116,117,114, - 110,46,10,10,32,32,32,32,84,104,101,32,105,109,112,111, - 114,116,95,32,112,97,114,97,109,101,116,101,114,32,105,115, - 32,97,32,99,97,108,108,97,98,108,101,32,119,104,105,99, - 104,32,116,97,107,101,115,32,116,104,101,32,110,97,109,101, - 32,111,102,32,109,111,100,117,108,101,32,116,111,10,32,32, - 32,32,105,109,112,111,114,116,46,32,73,116,32,105,115,32, - 114,101,113,117,105,114,101,100,32,116,111,32,100,101,99,111, - 117,112,108,101,32,116,104,101,32,102,117,110,99,116,105,111, - 110,32,102,114,111,109,32,97,115,115,117,109,105,110,103,32, - 105,109,112,111,114,116,108,105,98,39,115,10,32,32,32,32, - 105,109,112,111,114,116,32,105,109,112,108,101,109,101,110,116, - 97,116,105,111,110,32,105,115,32,100,101,115,105,114,101,100, - 46,10,10,32,32,32,32,122,8,46,95,95,97,108,108,95, - 95,122,13,96,96,102,114,111,109,32,108,105,115,116,39,39, - 122,8,73,116,101,109,32,105,110,32,122,18,32,109,117,115, - 116,32,98,101,32,115,116,114,44,32,110,111,116,32,250,1, - 42,218,7,95,95,97,108,108,95,95,84,114,206,0,0,0, - 114,179,0,0,0,78,41,16,114,193,0,0,0,114,194,0, - 0,0,114,1,0,0,0,114,195,0,0,0,114,14,0,0, - 0,114,4,0,0,0,218,16,95,104,97,110,100,108,101,95, - 102,114,111,109,108,105,115,116,114,209,0,0,0,114,45,0, - 0,0,114,67,0,0,0,114,200,0,0,0,114,17,0,0, - 0,114,15,0,0,0,114,92,0,0,0,114,34,0,0,0, - 114,203,0,0,0,41,8,114,96,0,0,0,218,8,102,114, - 111,109,108,105,115,116,114,201,0,0,0,114,207,0,0,0, - 218,1,120,90,5,119,104,101,114,101,90,9,102,114,111,109, - 95,110,97,109,101,90,3,101,120,99,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,210,0,0,0,249,3, - 0,0,115,44,0,0,0,0,10,8,1,10,1,4,1,12, - 2,4,1,28,2,8,1,14,1,10,1,2,255,8,2,10, - 1,14,1,2,1,14,1,16,4,10,1,16,255,2,2,8, - 1,22,1,114,210,0,0,0,99,1,0,0,0,0,0,0, - 0,3,0,0,0,6,0,0,0,67,0,0,0,115,146,0, - 0,0,124,0,160,0,100,1,161,1,125,1,124,0,160,0, - 100,2,161,1,125,2,124,1,100,3,107,9,114,82,124,2, - 100,3,107,9,114,78,124,1,124,2,106,1,107,3,114,78, - 116,2,106,3,100,4,124,1,155,2,100,5,124,2,106,1, - 155,2,100,6,157,5,116,4,100,7,100,8,141,3,1,0, - 124,1,83,0,124,2,100,3,107,9,114,96,124,2,106,1, - 83,0,116,2,106,3,100,9,116,4,100,7,100,8,141,3, - 1,0,124,0,100,10,25,0,125,1,100,11,124,0,107,7, - 114,142,124,1,160,5,100,12,161,1,100,13,25,0,125,1, - 124,1,83,0,41,14,122,167,67,97,108,99,117,108,97,116, - 101,32,119,104,97,116,32,95,95,112,97,99,107,97,103,101, - 95,95,32,115,104,111,117,108,100,32,98,101,46,10,10,32, - 32,32,32,95,95,112,97,99,107,97,103,101,95,95,32,105, - 115,32,110,111,116,32,103,117,97,114,97,110,116,101,101,100, - 32,116,111,32,98,101,32,100,101,102,105,110,101,100,32,111, - 114,32,99,111,117,108,100,32,98,101,32,115,101,116,32,116, - 111,32,78,111,110,101,10,32,32,32,32,116,111,32,114,101, - 112,114,101,115,101,110,116,32,116,104,97,116,32,105,116,115, - 32,112,114,111,112,101,114,32,118,97,108,117,101,32,105,115, - 32,117,110,107,110,111,119,110,46,10,10,32,32,32,32,114, - 145,0,0,0,114,105,0,0,0,78,122,32,95,95,112,97, - 99,107,97,103,101,95,95,32,33,61,32,95,95,115,112,101, - 99,95,95,46,112,97,114,101,110,116,32,40,122,4,32,33, - 61,32,250,1,41,233,3,0,0,0,41,1,90,10,115,116, - 97,99,107,108,101,118,101,108,122,89,99,97,110,39,116,32, - 114,101,115,111,108,118,101,32,112,97,99,107,97,103,101,32, - 102,114,111,109,32,95,95,115,112,101,99,95,95,32,111,114, - 32,95,95,112,97,99,107,97,103,101,95,95,44,32,102,97, - 108,108,105,110,103,32,98,97,99,107,32,111,110,32,95,95, - 110,97,109,101,95,95,32,97,110,100,32,95,95,112,97,116, - 104,95,95,114,1,0,0,0,114,141,0,0,0,114,128,0, - 0,0,114,22,0,0,0,41,6,114,34,0,0,0,114,130, - 0,0,0,114,189,0,0,0,114,190,0,0,0,114,191,0, - 0,0,114,129,0,0,0,41,3,218,7,103,108,111,98,97, - 108,115,114,183,0,0,0,114,95,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,218,17,95,99,97, - 108,99,95,95,95,112,97,99,107,97,103,101,95,95,30,4, - 0,0,115,38,0,0,0,0,7,10,1,10,1,8,1,18, - 1,22,2,2,0,2,254,6,3,4,1,8,1,6,2,6, - 2,2,0,2,254,6,3,8,1,8,1,14,1,114,216,0, - 0,0,114,10,0,0,0,99,5,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,3,0,0,0,4,0, + 0,0,67,0,0,0,115,42,0,0,0,116,0,124,0,124, + 1,124,2,131,3,1,0,124,2,100,1,107,4,114,32,116, + 1,124,0,124,1,124,2,131,3,125,0,116,2,124,0,116, + 3,131,2,83,0,41,2,97,50,1,0,0,73,109,112,111, + 114,116,32,97,110,100,32,114,101,116,117,114,110,32,116,104, + 101,32,109,111,100,117,108,101,32,98,97,115,101,100,32,111, + 110,32,105,116,115,32,110,97,109,101,44,32,116,104,101,32, + 112,97,99,107,97,103,101,32,116,104,101,32,99,97,108,108, + 32,105,115,10,32,32,32,32,98,101,105,110,103,32,109,97, + 100,101,32,102,114,111,109,44,32,97,110,100,32,116,104,101, + 32,108,101,118,101,108,32,97,100,106,117,115,116,109,101,110, + 116,46,10,10,32,32,32,32,84,104,105,115,32,102,117,110, + 99,116,105,111,110,32,114,101,112,114,101,115,101,110,116,115, + 32,116,104,101,32,103,114,101,97,116,101,115,116,32,99,111, + 109,109,111,110,32,100,101,110,111,109,105,110,97,116,111,114, + 32,111,102,32,102,117,110,99,116,105,111,110,97,108,105,116, + 121,10,32,32,32,32,98,101,116,119,101,101,110,32,105,109, + 112,111,114,116,95,109,111,100,117,108,101,32,97,110,100,32, + 95,95,105,109,112,111,114,116,95,95,46,32,84,104,105,115, + 32,105,110,99,108,117,100,101,115,32,115,101,116,116,105,110, + 103,32,95,95,112,97,99,107,97,103,101,95,95,32,105,102, + 10,32,32,32,32,116,104,101,32,108,111,97,100,101,114,32, + 100,105,100,32,110,111,116,46,10,10,32,32,32,32,114,22, + 0,0,0,41,4,114,197,0,0,0,114,185,0,0,0,114, + 204,0,0,0,218,11,95,103,99,100,95,105,109,112,111,114, + 116,114,196,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,205,0,0,0,234,3,0,0,115,8, + 0,0,0,0,9,12,1,8,1,12,1,114,205,0,0,0, + 169,1,218,9,114,101,99,117,114,115,105,118,101,99,3,0, + 0,0,0,0,0,0,1,0,0,0,8,0,0,0,11,0, + 0,0,67,0,0,0,115,226,0,0,0,124,1,68,0,93, + 216,125,4,116,0,124,4,116,1,131,2,115,66,124,3,114, + 34,124,0,106,2,100,1,23,0,125,5,110,4,100,2,125, + 5,116,3,100,3,124,5,155,0,100,4,116,4,124,4,131, + 1,106,2,155,0,157,4,131,1,130,1,110,154,124,4,100, + 5,107,2,114,108,124,3,115,106,116,5,124,0,100,6,131, + 2,114,106,116,6,124,0,124,0,106,7,124,2,100,7,100, + 8,141,4,1,0,110,112,116,5,124,0,124,4,131,2,115, + 220,100,9,160,8,124,0,106,2,124,4,161,2,125,6,122, + 14,116,9,124,2,124,6,131,2,1,0,87,0,110,72,4, + 0,116,10,107,10,114,218,1,0,125,7,1,0,122,42,124, + 7,106,11,124,6,107,2,114,200,116,12,106,13,160,14,124, + 6,116,15,161,2,100,10,107,9,114,200,87,0,89,0,162, + 8,113,4,130,0,87,0,53,0,100,10,125,7,126,7,88, + 0,89,0,110,2,88,0,113,4,124,0,83,0,41,11,122, + 238,70,105,103,117,114,101,32,111,117,116,32,119,104,97,116, + 32,95,95,105,109,112,111,114,116,95,95,32,115,104,111,117, + 108,100,32,114,101,116,117,114,110,46,10,10,32,32,32,32, + 84,104,101,32,105,109,112,111,114,116,95,32,112,97,114,97, + 109,101,116,101,114,32,105,115,32,97,32,99,97,108,108,97, + 98,108,101,32,119,104,105,99,104,32,116,97,107,101,115,32, + 116,104,101,32,110,97,109,101,32,111,102,32,109,111,100,117, + 108,101,32,116,111,10,32,32,32,32,105,109,112,111,114,116, + 46,32,73,116,32,105,115,32,114,101,113,117,105,114,101,100, + 32,116,111,32,100,101,99,111,117,112,108,101,32,116,104,101, + 32,102,117,110,99,116,105,111,110,32,102,114,111,109,32,97, + 115,115,117,109,105,110,103,32,105,109,112,111,114,116,108,105, + 98,39,115,10,32,32,32,32,105,109,112,111,114,116,32,105, + 109,112,108,101,109,101,110,116,97,116,105,111,110,32,105,115, + 32,100,101,115,105,114,101,100,46,10,10,32,32,32,32,122, + 8,46,95,95,97,108,108,95,95,122,13,96,96,102,114,111, + 109,32,108,105,115,116,39,39,122,8,73,116,101,109,32,105, + 110,32,122,18,32,109,117,115,116,32,98,101,32,115,116,114, + 44,32,110,111,116,32,250,1,42,218,7,95,95,97,108,108, + 95,95,84,114,206,0,0,0,114,179,0,0,0,78,41,16, + 114,193,0,0,0,114,194,0,0,0,114,1,0,0,0,114, + 195,0,0,0,114,14,0,0,0,114,4,0,0,0,218,16, + 95,104,97,110,100,108,101,95,102,114,111,109,108,105,115,116, + 114,209,0,0,0,114,45,0,0,0,114,67,0,0,0,114, + 200,0,0,0,114,17,0,0,0,114,15,0,0,0,114,92, + 0,0,0,114,34,0,0,0,114,203,0,0,0,41,8,114, + 96,0,0,0,218,8,102,114,111,109,108,105,115,116,114,201, + 0,0,0,114,207,0,0,0,218,1,120,90,5,119,104,101, + 114,101,90,9,102,114,111,109,95,110,97,109,101,90,3,101, + 120,99,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,210,0,0,0,249,3,0,0,115,44,0,0,0,0, + 10,8,1,10,1,4,1,12,2,4,1,28,2,8,1,14, + 1,10,1,2,255,8,2,10,1,14,1,2,1,14,1,16, + 4,10,1,16,255,2,2,8,1,22,1,114,210,0,0,0, + 99,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,6,0,0,0,67,0,0,0,115,146,0,0,0,124,0, + 160,0,100,1,161,1,125,1,124,0,160,0,100,2,161,1, + 125,2,124,1,100,3,107,9,114,82,124,2,100,3,107,9, + 114,78,124,1,124,2,106,1,107,3,114,78,116,2,106,3, + 100,4,124,1,155,2,100,5,124,2,106,1,155,2,100,6, + 157,5,116,4,100,7,100,8,141,3,1,0,124,1,83,0, + 124,2,100,3,107,9,114,96,124,2,106,1,83,0,116,2, + 106,3,100,9,116,4,100,7,100,8,141,3,1,0,124,0, + 100,10,25,0,125,1,100,11,124,0,107,7,114,142,124,1, + 160,5,100,12,161,1,100,13,25,0,125,1,124,1,83,0, + 41,14,122,167,67,97,108,99,117,108,97,116,101,32,119,104, + 97,116,32,95,95,112,97,99,107,97,103,101,95,95,32,115, + 104,111,117,108,100,32,98,101,46,10,10,32,32,32,32,95, + 95,112,97,99,107,97,103,101,95,95,32,105,115,32,110,111, + 116,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32, + 98,101,32,100,101,102,105,110,101,100,32,111,114,32,99,111, + 117,108,100,32,98,101,32,115,101,116,32,116,111,32,78,111, + 110,101,10,32,32,32,32,116,111,32,114,101,112,114,101,115, + 101,110,116,32,116,104,97,116,32,105,116,115,32,112,114,111, + 112,101,114,32,118,97,108,117,101,32,105,115,32,117,110,107, + 110,111,119,110,46,10,10,32,32,32,32,114,145,0,0,0, + 114,105,0,0,0,78,122,32,95,95,112,97,99,107,97,103, + 101,95,95,32,33,61,32,95,95,115,112,101,99,95,95,46, + 112,97,114,101,110,116,32,40,122,4,32,33,61,32,250,1, + 41,233,3,0,0,0,41,1,90,10,115,116,97,99,107,108, + 101,118,101,108,122,89,99,97,110,39,116,32,114,101,115,111, + 108,118,101,32,112,97,99,107,97,103,101,32,102,114,111,109, + 32,95,95,115,112,101,99,95,95,32,111,114,32,95,95,112, + 97,99,107,97,103,101,95,95,44,32,102,97,108,108,105,110, + 103,32,98,97,99,107,32,111,110,32,95,95,110,97,109,101, + 95,95,32,97,110,100,32,95,95,112,97,116,104,95,95,114, + 1,0,0,0,114,141,0,0,0,114,128,0,0,0,114,22, + 0,0,0,41,6,114,34,0,0,0,114,130,0,0,0,114, + 189,0,0,0,114,190,0,0,0,114,191,0,0,0,114,129, + 0,0,0,41,3,218,7,103,108,111,98,97,108,115,114,183, + 0,0,0,114,95,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,218,17,95,99,97,108,99,95,95, + 95,112,97,99,107,97,103,101,95,95,30,4,0,0,115,38, + 0,0,0,0,7,10,1,10,1,8,1,18,1,22,2,2, + 0,2,254,6,3,4,1,8,1,6,2,6,2,2,0,2, + 254,6,3,8,1,8,1,14,1,114,216,0,0,0,114,10, + 0,0,0,99,5,0,0,0,0,0,0,0,0,0,0,0, 9,0,0,0,5,0,0,0,67,0,0,0,115,180,0,0, 0,124,4,100,1,107,2,114,18,116,0,124,0,131,1,125, 5,110,36,124,1,100,2,107,9,114,30,124,1,110,2,105, @@ -1654,76 +1674,77 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,115,30,0,0,0,0,11,8,1,10,2,16,1,8, 1,12,1,4,3,8,1,18,1,4,1,4,4,26,3,32, 1,10,1,12,2,114,219,0,0,0,99,1,0,0,0,0, - 0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115, - 38,0,0,0,116,0,160,1,124,0,161,1,125,1,124,1, - 100,0,107,8,114,30,116,2,100,1,124,0,23,0,131,1, - 130,1,116,3,124,1,131,1,83,0,41,2,78,122,25,110, - 111,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108, - 101,32,110,97,109,101,100,32,41,4,114,160,0,0,0,114, - 166,0,0,0,114,79,0,0,0,114,159,0,0,0,41,2, - 114,17,0,0,0,114,95,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,218,18,95,98,117,105,108, - 116,105,110,95,102,114,111,109,95,110,97,109,101,94,4,0, - 0,115,8,0,0,0,0,1,10,1,8,1,12,1,114,220, - 0,0,0,99,2,0,0,0,0,0,0,0,10,0,0,0, - 5,0,0,0,67,0,0,0,115,166,0,0,0,124,1,97, - 0,124,0,97,1,116,2,116,1,131,1,125,2,116,1,106, - 3,160,4,161,0,68,0,93,72,92,2,125,3,125,4,116, - 5,124,4,124,2,131,2,114,26,124,3,116,1,106,6,107, - 6,114,60,116,7,125,5,110,18,116,0,160,8,124,3,161, - 1,114,26,116,9,125,5,110,2,113,26,116,10,124,4,124, - 5,131,2,125,6,116,11,124,6,124,4,131,2,1,0,113, - 26,116,1,106,3,116,12,25,0,125,7,100,1,68,0,93, - 46,125,8,124,8,116,1,106,3,107,7,114,138,116,13,124, - 8,131,1,125,9,110,10,116,1,106,3,124,8,25,0,125, - 9,116,14,124,7,124,8,124,9,131,3,1,0,113,114,100, - 2,83,0,41,3,122,250,83,101,116,117,112,32,105,109,112, - 111,114,116,108,105,98,32,98,121,32,105,109,112,111,114,116, - 105,110,103,32,110,101,101,100,101,100,32,98,117,105,108,116, - 45,105,110,32,109,111,100,117,108,101,115,32,97,110,100,32, - 105,110,106,101,99,116,105,110,103,32,116,104,101,109,10,32, - 32,32,32,105,110,116,111,32,116,104,101,32,103,108,111,98, - 97,108,32,110,97,109,101,115,112,97,99,101,46,10,10,32, - 32,32,32,65,115,32,115,121,115,32,105,115,32,110,101,101, - 100,101,100,32,102,111,114,32,115,121,115,46,109,111,100,117, - 108,101,115,32,97,99,99,101,115,115,32,97,110,100,32,95, - 105,109,112,32,105,115,32,110,101,101,100,101,100,32,116,111, - 32,108,111,97,100,32,98,117,105,108,116,45,105,110,10,32, - 32,32,32,109,111,100,117,108,101,115,44,32,116,104,111,115, - 101,32,116,119,111,32,109,111,100,117,108,101,115,32,109,117, - 115,116,32,98,101,32,101,120,112,108,105,99,105,116,108,121, - 32,112,97,115,115,101,100,32,105,110,46,10,10,32,32,32, - 32,41,3,114,23,0,0,0,114,189,0,0,0,114,64,0, - 0,0,78,41,15,114,57,0,0,0,114,15,0,0,0,114, - 14,0,0,0,114,92,0,0,0,218,5,105,116,101,109,115, - 114,193,0,0,0,114,78,0,0,0,114,160,0,0,0,114, - 88,0,0,0,114,173,0,0,0,114,142,0,0,0,114,148, - 0,0,0,114,1,0,0,0,114,220,0,0,0,114,5,0, - 0,0,41,10,218,10,115,121,115,95,109,111,100,117,108,101, - 218,11,95,105,109,112,95,109,111,100,117,108,101,90,11,109, - 111,100,117,108,101,95,116,121,112,101,114,17,0,0,0,114, - 96,0,0,0,114,109,0,0,0,114,95,0,0,0,90,11, - 115,101,108,102,95,109,111,100,117,108,101,90,12,98,117,105, - 108,116,105,110,95,110,97,109,101,90,14,98,117,105,108,116, - 105,110,95,109,111,100,117,108,101,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,218,6,95,115,101,116,117,112, - 101,4,0,0,115,36,0,0,0,0,9,4,1,4,3,8, - 1,18,1,10,1,10,1,6,1,10,1,6,2,2,1,10, - 1,12,3,10,1,8,1,10,1,10,2,10,1,114,224,0, - 0,0,99,2,0,0,0,0,0,0,0,2,0,0,0,3, - 0,0,0,67,0,0,0,115,38,0,0,0,116,0,124,0, - 124,1,131,2,1,0,116,1,106,2,160,3,116,4,161,1, - 1,0,116,1,106,2,160,3,116,5,161,1,1,0,100,1, - 83,0,41,2,122,48,73,110,115,116,97,108,108,32,105,109, - 112,111,114,116,101,114,115,32,102,111,114,32,98,117,105,108, - 116,105,110,32,97,110,100,32,102,114,111,122,101,110,32,109, - 111,100,117,108,101,115,78,41,6,114,224,0,0,0,114,15, - 0,0,0,114,188,0,0,0,114,120,0,0,0,114,160,0, - 0,0,114,173,0,0,0,41,2,114,222,0,0,0,114,223, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,8,95,105,110,115,116,97,108,108,136,4,0,0, - 115,6,0,0,0,0,2,10,2,12,1,114,225,0,0,0, - 99,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, + 0,0,0,115,38,0,0,0,116,0,160,1,124,0,161,1, + 125,1,124,1,100,0,107,8,114,30,116,2,100,1,124,0, + 23,0,131,1,130,1,116,3,124,1,131,1,83,0,41,2, + 78,122,25,110,111,32,98,117,105,108,116,45,105,110,32,109, + 111,100,117,108,101,32,110,97,109,101,100,32,41,4,114,160, + 0,0,0,114,166,0,0,0,114,79,0,0,0,114,159,0, + 0,0,41,2,114,17,0,0,0,114,95,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,218,18,95, + 98,117,105,108,116,105,110,95,102,114,111,109,95,110,97,109, + 101,94,4,0,0,115,8,0,0,0,0,1,10,1,8,1, + 12,1,114,220,0,0,0,99,2,0,0,0,0,0,0,0, + 0,0,0,0,10,0,0,0,5,0,0,0,67,0,0,0, + 115,166,0,0,0,124,1,97,0,124,0,97,1,116,2,116, + 1,131,1,125,2,116,1,106,3,160,4,161,0,68,0,93, + 72,92,2,125,3,125,4,116,5,124,4,124,2,131,2,114, + 26,124,3,116,1,106,6,107,6,114,60,116,7,125,5,110, + 18,116,0,160,8,124,3,161,1,114,26,116,9,125,5,110, + 2,113,26,116,10,124,4,124,5,131,2,125,6,116,11,124, + 6,124,4,131,2,1,0,113,26,116,1,106,3,116,12,25, + 0,125,7,100,1,68,0,93,46,125,8,124,8,116,1,106, + 3,107,7,114,138,116,13,124,8,131,1,125,9,110,10,116, + 1,106,3,124,8,25,0,125,9,116,14,124,7,124,8,124, + 9,131,3,1,0,113,114,100,2,83,0,41,3,122,250,83, + 101,116,117,112,32,105,109,112,111,114,116,108,105,98,32,98, + 121,32,105,109,112,111,114,116,105,110,103,32,110,101,101,100, + 101,100,32,98,117,105,108,116,45,105,110,32,109,111,100,117, + 108,101,115,32,97,110,100,32,105,110,106,101,99,116,105,110, + 103,32,116,104,101,109,10,32,32,32,32,105,110,116,111,32, + 116,104,101,32,103,108,111,98,97,108,32,110,97,109,101,115, + 112,97,99,101,46,10,10,32,32,32,32,65,115,32,115,121, + 115,32,105,115,32,110,101,101,100,101,100,32,102,111,114,32, + 115,121,115,46,109,111,100,117,108,101,115,32,97,99,99,101, + 115,115,32,97,110,100,32,95,105,109,112,32,105,115,32,110, + 101,101,100,101,100,32,116,111,32,108,111,97,100,32,98,117, + 105,108,116,45,105,110,10,32,32,32,32,109,111,100,117,108, + 101,115,44,32,116,104,111,115,101,32,116,119,111,32,109,111, + 100,117,108,101,115,32,109,117,115,116,32,98,101,32,101,120, + 112,108,105,99,105,116,108,121,32,112,97,115,115,101,100,32, + 105,110,46,10,10,32,32,32,32,41,3,114,23,0,0,0, + 114,189,0,0,0,114,64,0,0,0,78,41,15,114,57,0, + 0,0,114,15,0,0,0,114,14,0,0,0,114,92,0,0, + 0,218,5,105,116,101,109,115,114,193,0,0,0,114,78,0, + 0,0,114,160,0,0,0,114,88,0,0,0,114,173,0,0, + 0,114,142,0,0,0,114,148,0,0,0,114,1,0,0,0, + 114,220,0,0,0,114,5,0,0,0,41,10,218,10,115,121, + 115,95,109,111,100,117,108,101,218,11,95,105,109,112,95,109, + 111,100,117,108,101,90,11,109,111,100,117,108,101,95,116,121, + 112,101,114,17,0,0,0,114,96,0,0,0,114,109,0,0, + 0,114,95,0,0,0,90,11,115,101,108,102,95,109,111,100, + 117,108,101,90,12,98,117,105,108,116,105,110,95,110,97,109, + 101,90,14,98,117,105,108,116,105,110,95,109,111,100,117,108, + 101,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 218,6,95,115,101,116,117,112,101,4,0,0,115,36,0,0, + 0,0,9,4,1,4,3,8,1,18,1,10,1,10,1,6, + 1,10,1,6,2,2,1,10,1,12,3,10,1,8,1,10, + 1,10,2,10,1,114,224,0,0,0,99,2,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, + 0,0,0,115,38,0,0,0,116,0,124,0,124,1,131,2, + 1,0,116,1,106,2,160,3,116,4,161,1,1,0,116,1, + 106,2,160,3,116,5,161,1,1,0,100,1,83,0,41,2, + 122,48,73,110,115,116,97,108,108,32,105,109,112,111,114,116, + 101,114,115,32,102,111,114,32,98,117,105,108,116,105,110,32, + 97,110,100,32,102,114,111,122,101,110,32,109,111,100,117,108, + 101,115,78,41,6,114,224,0,0,0,114,15,0,0,0,114, + 188,0,0,0,114,120,0,0,0,114,160,0,0,0,114,173, + 0,0,0,41,2,114,222,0,0,0,114,223,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,8, + 95,105,110,115,116,97,108,108,136,4,0,0,115,6,0,0, + 0,0,2,10,2,12,1,114,225,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, 0,67,0,0,0,115,32,0,0,0,100,1,100,2,108,0, 125,0,124,0,97,1,124,0,160,2,116,3,106,4,116,5, 25,0,161,1,1,0,100,2,83,0,41,3,122,57,73,110, diff --git a/Python/importlib_external.h b/Python/importlib_external.h index ea4d8953490072..b5b4df228057a3 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -1,88 +1,89 @@ /* Auto-generated by Programs/_freeze_importlib.c */ const unsigned char _Py_M__importlib_bootstrap_external[] = { - 99,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0, - 0,64,0,0,0,115,52,2,0,0,100,0,90,0,100,1, - 90,1,100,2,90,2,101,2,101,1,23,0,90,3,100,3, - 100,4,132,0,90,4,100,5,100,6,132,0,90,5,100,7, - 100,8,132,0,90,6,100,9,100,10,132,0,90,7,100,11, - 100,12,132,0,90,8,100,13,100,14,132,0,90,9,100,15, - 100,16,132,0,90,10,100,17,100,18,132,0,90,11,100,19, - 100,20,132,0,90,12,100,21,100,22,132,0,90,13,100,23, - 100,24,132,0,90,14,100,25,102,1,100,26,100,27,132,1, - 90,15,101,16,101,15,106,17,131,1,90,18,100,28,160,19, - 100,29,100,30,161,2,100,31,23,0,90,20,101,21,160,22, - 101,20,100,30,161,2,90,23,100,32,90,24,100,33,90,25, - 100,34,103,1,90,26,100,35,103,1,90,27,101,27,4,0, - 90,28,90,29,100,36,102,1,100,36,100,37,156,1,100,38, - 100,39,132,3,90,30,100,40,100,41,132,0,90,31,100,42, - 100,43,132,0,90,32,100,44,100,45,132,0,90,33,100,46, - 100,47,132,0,90,34,100,48,100,49,132,0,90,35,100,50, - 100,51,132,0,90,36,100,52,100,53,132,0,90,37,100,54, - 100,55,132,0,90,38,100,56,100,57,132,0,90,39,100,36, - 100,36,100,36,102,3,100,58,100,59,132,1,90,40,100,60, - 100,60,102,2,100,61,100,62,132,1,90,41,100,63,102,1, - 100,64,100,65,132,1,90,42,100,66,100,67,132,0,90,43, - 101,44,131,0,90,45,100,36,102,1,100,36,101,45,100,68, - 156,2,100,69,100,70,132,3,90,46,71,0,100,71,100,72, - 132,0,100,72,131,2,90,47,71,0,100,73,100,74,132,0, - 100,74,131,2,90,48,71,0,100,75,100,76,132,0,100,76, - 101,48,131,3,90,49,71,0,100,77,100,78,132,0,100,78, - 131,2,90,50,71,0,100,79,100,80,132,0,100,80,101,50, - 101,49,131,4,90,51,71,0,100,81,100,82,132,0,100,82, - 101,50,101,48,131,4,90,52,103,0,90,53,71,0,100,83, - 100,84,132,0,100,84,101,50,101,48,131,4,90,54,71,0, - 100,85,100,86,132,0,100,86,131,2,90,55,71,0,100,87, - 100,88,132,0,100,88,131,2,90,56,71,0,100,89,100,90, - 132,0,100,90,131,2,90,57,71,0,100,91,100,92,132,0, - 100,92,131,2,90,58,100,36,102,1,100,93,100,94,132,1, - 90,59,100,95,100,96,132,0,90,60,100,97,100,98,132,0, - 90,61,100,99,100,100,132,0,90,62,100,36,83,0,41,101, - 97,94,1,0,0,67,111,114,101,32,105,109,112,108,101,109, - 101,110,116,97,116,105,111,110,32,111,102,32,112,97,116,104, - 45,98,97,115,101,100,32,105,109,112,111,114,116,46,10,10, - 84,104,105,115,32,109,111,100,117,108,101,32,105,115,32,78, - 79,84,32,109,101,97,110,116,32,116,111,32,98,101,32,100, - 105,114,101,99,116,108,121,32,105,109,112,111,114,116,101,100, - 33,32,73,116,32,104,97,115,32,98,101,101,110,32,100,101, - 115,105,103,110,101,100,32,115,117,99,104,10,116,104,97,116, - 32,105,116,32,99,97,110,32,98,101,32,98,111,111,116,115, - 116,114,97,112,112,101,100,32,105,110,116,111,32,80,121,116, - 104,111,110,32,97,115,32,116,104,101,32,105,109,112,108,101, - 109,101,110,116,97,116,105,111,110,32,111,102,32,105,109,112, - 111,114,116,46,32,65,115,10,115,117,99,104,32,105,116,32, - 114,101,113,117,105,114,101,115,32,116,104,101,32,105,110,106, - 101,99,116,105,111,110,32,111,102,32,115,112,101,99,105,102, - 105,99,32,109,111,100,117,108,101,115,32,97,110,100,32,97, - 116,116,114,105,98,117,116,101,115,32,105,110,32,111,114,100, - 101,114,32,116,111,10,119,111,114,107,46,32,79,110,101,32, - 115,104,111,117,108,100,32,117,115,101,32,105,109,112,111,114, - 116,108,105,98,32,97,115,32,116,104,101,32,112,117,98,108, - 105,99,45,102,97,99,105,110,103,32,118,101,114,115,105,111, - 110,32,111,102,32,116,104,105,115,32,109,111,100,117,108,101, - 46,10,10,41,1,218,3,119,105,110,41,2,90,6,99,121, - 103,119,105,110,90,6,100,97,114,119,105,110,99,0,0,0, - 0,0,0,0,0,1,0,0,0,3,0,0,0,3,0,0, - 0,115,60,0,0,0,116,0,106,1,160,2,116,3,161,1, - 114,48,116,0,106,1,160,2,116,4,161,1,114,30,100,1, - 137,0,110,4,100,2,137,0,135,0,102,1,100,3,100,4, - 132,8,125,0,110,8,100,5,100,4,132,0,125,0,124,0, - 83,0,41,6,78,90,12,80,89,84,72,79,78,67,65,83, - 69,79,75,115,12,0,0,0,80,89,84,72,79,78,67,65, - 83,69,79,75,99,0,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,19,0,0,0,115,10,0,0,0,136,0, - 116,0,106,1,107,6,83,0,41,1,250,53,84,114,117,101, - 32,105,102,32,102,105,108,101,110,97,109,101,115,32,109,117, - 115,116,32,98,101,32,99,104,101,99,107,101,100,32,99,97, - 115,101,45,105,110,115,101,110,115,105,116,105,118,101,108,121, - 46,41,2,218,3,95,111,115,90,7,101,110,118,105,114,111, - 110,169,0,169,1,218,3,107,101,121,114,3,0,0,0,250, - 38,60,102,114,111,122,101,110,32,105,109,112,111,114,116,108, - 105,98,46,95,98,111,111,116,115,116,114,97,112,95,101,120, - 116,101,114,110,97,108,62,218,11,95,114,101,108,97,120,95, - 99,97,115,101,36,0,0,0,115,2,0,0,0,0,2,122, - 37,95,109,97,107,101,95,114,101,108,97,120,95,99,97,115, - 101,46,60,108,111,99,97,108,115,62,46,95,114,101,108,97, - 120,95,99,97,115,101,99,0,0,0,0,0,0,0,0,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,5,0,0,0,64,0,0,0,115,52,2,0,0,100,0, + 90,0,100,1,90,1,100,2,90,2,101,2,101,1,23,0, + 90,3,100,3,100,4,132,0,90,4,100,5,100,6,132,0, + 90,5,100,7,100,8,132,0,90,6,100,9,100,10,132,0, + 90,7,100,11,100,12,132,0,90,8,100,13,100,14,132,0, + 90,9,100,15,100,16,132,0,90,10,100,17,100,18,132,0, + 90,11,100,19,100,20,132,0,90,12,100,21,100,22,132,0, + 90,13,100,23,100,24,132,0,90,14,100,25,102,1,100,26, + 100,27,132,1,90,15,101,16,101,15,106,17,131,1,90,18, + 100,28,160,19,100,29,100,30,161,2,100,31,23,0,90,20, + 101,21,160,22,101,20,100,30,161,2,90,23,100,32,90,24, + 100,33,90,25,100,34,103,1,90,26,100,35,103,1,90,27, + 101,27,4,0,90,28,90,29,100,36,102,1,100,36,100,37, + 156,1,100,38,100,39,132,3,90,30,100,40,100,41,132,0, + 90,31,100,42,100,43,132,0,90,32,100,44,100,45,132,0, + 90,33,100,46,100,47,132,0,90,34,100,48,100,49,132,0, + 90,35,100,50,100,51,132,0,90,36,100,52,100,53,132,0, + 90,37,100,54,100,55,132,0,90,38,100,56,100,57,132,0, + 90,39,100,36,100,36,100,36,102,3,100,58,100,59,132,1, + 90,40,100,60,100,60,102,2,100,61,100,62,132,1,90,41, + 100,63,102,1,100,64,100,65,132,1,90,42,100,66,100,67, + 132,0,90,43,101,44,131,0,90,45,100,36,102,1,100,36, + 101,45,100,68,156,2,100,69,100,70,132,3,90,46,71,0, + 100,71,100,72,132,0,100,72,131,2,90,47,71,0,100,73, + 100,74,132,0,100,74,131,2,90,48,71,0,100,75,100,76, + 132,0,100,76,101,48,131,3,90,49,71,0,100,77,100,78, + 132,0,100,78,131,2,90,50,71,0,100,79,100,80,132,0, + 100,80,101,50,101,49,131,4,90,51,71,0,100,81,100,82, + 132,0,100,82,101,50,101,48,131,4,90,52,103,0,90,53, + 71,0,100,83,100,84,132,0,100,84,101,50,101,48,131,4, + 90,54,71,0,100,85,100,86,132,0,100,86,131,2,90,55, + 71,0,100,87,100,88,132,0,100,88,131,2,90,56,71,0, + 100,89,100,90,132,0,100,90,131,2,90,57,71,0,100,91, + 100,92,132,0,100,92,131,2,90,58,100,36,102,1,100,93, + 100,94,132,1,90,59,100,95,100,96,132,0,90,60,100,97, + 100,98,132,0,90,61,100,99,100,100,132,0,90,62,100,36, + 83,0,41,101,97,94,1,0,0,67,111,114,101,32,105,109, + 112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32, + 112,97,116,104,45,98,97,115,101,100,32,105,109,112,111,114, + 116,46,10,10,84,104,105,115,32,109,111,100,117,108,101,32, + 105,115,32,78,79,84,32,109,101,97,110,116,32,116,111,32, + 98,101,32,100,105,114,101,99,116,108,121,32,105,109,112,111, + 114,116,101,100,33,32,73,116,32,104,97,115,32,98,101,101, + 110,32,100,101,115,105,103,110,101,100,32,115,117,99,104,10, + 116,104,97,116,32,105,116,32,99,97,110,32,98,101,32,98, + 111,111,116,115,116,114,97,112,112,101,100,32,105,110,116,111, + 32,80,121,116,104,111,110,32,97,115,32,116,104,101,32,105, + 109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102, + 32,105,109,112,111,114,116,46,32,65,115,10,115,117,99,104, + 32,105,116,32,114,101,113,117,105,114,101,115,32,116,104,101, + 32,105,110,106,101,99,116,105,111,110,32,111,102,32,115,112, + 101,99,105,102,105,99,32,109,111,100,117,108,101,115,32,97, + 110,100,32,97,116,116,114,105,98,117,116,101,115,32,105,110, + 32,111,114,100,101,114,32,116,111,10,119,111,114,107,46,32, + 79,110,101,32,115,104,111,117,108,100,32,117,115,101,32,105, + 109,112,111,114,116,108,105,98,32,97,115,32,116,104,101,32, + 112,117,98,108,105,99,45,102,97,99,105,110,103,32,118,101, + 114,115,105,111,110,32,111,102,32,116,104,105,115,32,109,111, + 100,117,108,101,46,10,10,41,1,218,3,119,105,110,41,2, + 90,6,99,121,103,119,105,110,90,6,100,97,114,119,105,110, + 99,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, + 0,3,0,0,0,3,0,0,0,115,60,0,0,0,116,0, + 106,1,160,2,116,3,161,1,114,48,116,0,106,1,160,2, + 116,4,161,1,114,30,100,1,137,0,110,4,100,2,137,0, + 135,0,102,1,100,3,100,4,132,8,125,0,110,8,100,5, + 100,4,132,0,125,0,124,0,83,0,41,6,78,90,12,80, + 89,84,72,79,78,67,65,83,69,79,75,115,12,0,0,0, + 80,89,84,72,79,78,67,65,83,69,79,75,99,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,19,0,0,0,115,10,0,0,0,136,0,116,0,106,1, + 107,6,83,0,41,1,250,53,84,114,117,101,32,105,102,32, + 102,105,108,101,110,97,109,101,115,32,109,117,115,116,32,98, + 101,32,99,104,101,99,107,101,100,32,99,97,115,101,45,105, + 110,115,101,110,115,105,116,105,118,101,108,121,46,41,2,218, + 3,95,111,115,90,7,101,110,118,105,114,111,110,169,0,169, + 1,218,3,107,101,121,114,3,0,0,0,250,38,60,102,114, + 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, + 98,111,111,116,115,116,114,97,112,95,101,120,116,101,114,110, + 97,108,62,218,11,95,114,101,108,97,120,95,99,97,115,101, + 36,0,0,0,115,2,0,0,0,0,2,122,37,95,109,97, + 107,101,95,114,101,108,97,120,95,99,97,115,101,46,60,108, + 111,99,97,108,115,62,46,95,114,101,108,97,120,95,99,97, + 115,101,99,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,83,0,0,0,115,4,0,0,0, 100,1,83,0,41,2,114,1,0,0,0,70,114,3,0,0, 0,114,3,0,0,0,114,3,0,0,0,114,3,0,0,0, @@ -98,96 +99,98 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 101,95,114,101,108,97,120,95,99,97,115,101,29,0,0,0, 115,14,0,0,0,0,1,12,1,12,1,6,2,4,2,14, 4,8,3,114,13,0,0,0,99,1,0,0,0,0,0,0, - 0,1,0,0,0,4,0,0,0,67,0,0,0,115,20,0, - 0,0,116,0,124,0,131,1,100,1,64,0,160,1,100,2, - 100,3,161,2,83,0,41,4,122,42,67,111,110,118,101,114, - 116,32,97,32,51,50,45,98,105,116,32,105,110,116,101,103, - 101,114,32,116,111,32,108,105,116,116,108,101,45,101,110,100, - 105,97,110,46,236,3,0,0,0,255,127,255,127,3,0,233, - 4,0,0,0,218,6,108,105,116,116,108,101,41,2,218,3, - 105,110,116,218,8,116,111,95,98,121,116,101,115,41,1,218, - 1,120,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,218,12,95,112,97,99,107,95,117,105,110,116,51,50,46, - 0,0,0,115,2,0,0,0,0,2,114,20,0,0,0,99, - 1,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0, + 0,0,0,0,0,1,0,0,0,4,0,0,0,67,0,0, + 0,115,20,0,0,0,116,0,124,0,131,1,100,1,64,0, + 160,1,100,2,100,3,161,2,83,0,41,4,122,42,67,111, + 110,118,101,114,116,32,97,32,51,50,45,98,105,116,32,105, + 110,116,101,103,101,114,32,116,111,32,108,105,116,116,108,101, + 45,101,110,100,105,97,110,46,236,3,0,0,0,255,127,255, + 127,3,0,233,4,0,0,0,218,6,108,105,116,116,108,101, + 41,2,218,3,105,110,116,218,8,116,111,95,98,121,116,101, + 115,41,1,218,1,120,114,3,0,0,0,114,3,0,0,0, + 114,6,0,0,0,218,12,95,112,97,99,107,95,117,105,110, + 116,51,50,46,0,0,0,115,2,0,0,0,0,2,114,20, + 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, + 1,0,0,0,4,0,0,0,67,0,0,0,115,28,0,0, + 0,116,0,124,0,131,1,100,1,107,2,115,16,116,1,130, + 1,116,2,160,3,124,0,100,2,161,2,83,0,41,3,122, + 47,67,111,110,118,101,114,116,32,52,32,98,121,116,101,115, + 32,105,110,32,108,105,116,116,108,101,45,101,110,100,105,97, + 110,32,116,111,32,97,110,32,105,110,116,101,103,101,114,46, + 114,15,0,0,0,114,16,0,0,0,169,4,218,3,108,101, + 110,218,14,65,115,115,101,114,116,105,111,110,69,114,114,111, + 114,114,17,0,0,0,218,10,102,114,111,109,95,98,121,116, + 101,115,169,1,218,4,100,97,116,97,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,218,14,95,117,110,112,97, + 99,107,95,117,105,110,116,51,50,51,0,0,0,115,4,0, + 0,0,0,2,16,1,114,27,0,0,0,99,1,0,0,0, + 0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0, 67,0,0,0,115,28,0,0,0,116,0,124,0,131,1,100, 1,107,2,115,16,116,1,130,1,116,2,160,3,124,0,100, 2,161,2,83,0,41,3,122,47,67,111,110,118,101,114,116, - 32,52,32,98,121,116,101,115,32,105,110,32,108,105,116,116, + 32,50,32,98,121,116,101,115,32,105,110,32,108,105,116,116, 108,101,45,101,110,100,105,97,110,32,116,111,32,97,110,32, - 105,110,116,101,103,101,114,46,114,15,0,0,0,114,16,0, - 0,0,169,4,218,3,108,101,110,218,14,65,115,115,101,114, - 116,105,111,110,69,114,114,111,114,114,17,0,0,0,218,10, - 102,114,111,109,95,98,121,116,101,115,169,1,218,4,100,97, - 116,97,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,218,14,95,117,110,112,97,99,107,95,117,105,110,116,51, - 50,51,0,0,0,115,4,0,0,0,0,2,16,1,114,27, - 0,0,0,99,1,0,0,0,0,0,0,0,1,0,0,0, - 4,0,0,0,67,0,0,0,115,28,0,0,0,116,0,124, - 0,131,1,100,1,107,2,115,16,116,1,130,1,116,2,160, - 3,124,0,100,2,161,2,83,0,41,3,122,47,67,111,110, - 118,101,114,116,32,50,32,98,121,116,101,115,32,105,110,32, - 108,105,116,116,108,101,45,101,110,100,105,97,110,32,116,111, - 32,97,110,32,105,110,116,101,103,101,114,46,233,2,0,0, - 0,114,16,0,0,0,114,21,0,0,0,114,25,0,0,0, - 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,218, - 14,95,117,110,112,97,99,107,95,117,105,110,116,49,54,56, - 0,0,0,115,4,0,0,0,0,2,16,1,114,29,0,0, - 0,99,0,0,0,0,0,0,0,0,1,0,0,0,4,0, + 105,110,116,101,103,101,114,46,233,2,0,0,0,114,16,0, + 0,0,114,21,0,0,0,114,25,0,0,0,114,3,0,0, + 0,114,3,0,0,0,114,6,0,0,0,218,14,95,117,110, + 112,97,99,107,95,117,105,110,116,49,54,56,0,0,0,115, + 4,0,0,0,0,2,16,1,114,29,0,0,0,99,0,0, + 0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0, 0,0,71,0,0,0,115,20,0,0,0,116,0,160,1,100, 1,100,2,132,0,124,0,68,0,131,1,161,1,83,0,41, 3,122,31,82,101,112,108,97,99,101,109,101,110,116,32,102, 111,114,32,111,115,46,112,97,116,104,46,106,111,105,110,40, - 41,46,99,1,0,0,0,0,0,0,0,2,0,0,0,5, - 0,0,0,83,0,0,0,115,26,0,0,0,103,0,124,0, - 93,18,125,1,124,1,114,22,124,1,160,0,116,1,161,1, - 145,2,113,4,83,0,114,3,0,0,0,41,2,218,6,114, - 115,116,114,105,112,218,15,112,97,116,104,95,115,101,112,97, - 114,97,116,111,114,115,41,2,218,2,46,48,218,4,112,97, - 114,116,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,218,10,60,108,105,115,116,99,111,109,112,62,64,0,0, - 0,115,6,0,0,0,6,1,2,0,4,255,122,30,95,112, - 97,116,104,95,106,111,105,110,46,60,108,111,99,97,108,115, - 62,46,60,108,105,115,116,99,111,109,112,62,41,2,218,8, - 112,97,116,104,95,115,101,112,218,4,106,111,105,110,41,1, - 218,10,112,97,116,104,95,112,97,114,116,115,114,3,0,0, - 0,114,3,0,0,0,114,6,0,0,0,218,10,95,112,97, - 116,104,95,106,111,105,110,62,0,0,0,115,6,0,0,0, - 0,2,10,1,2,255,114,38,0,0,0,99,1,0,0,0, - 0,0,0,0,5,0,0,0,5,0,0,0,67,0,0,0, - 115,96,0,0,0,116,0,116,1,131,1,100,1,107,2,114, - 36,124,0,160,2,116,3,161,1,92,3,125,1,125,2,125, - 3,124,1,124,3,102,2,83,0,116,4,124,0,131,1,68, - 0,93,42,125,4,124,4,116,1,107,6,114,44,124,0,106, - 5,124,4,100,1,100,2,141,2,92,2,125,1,125,3,124, - 1,124,3,102,2,2,0,1,0,83,0,113,44,100,3,124, - 0,102,2,83,0,41,4,122,32,82,101,112,108,97,99,101, - 109,101,110,116,32,102,111,114,32,111,115,46,112,97,116,104, - 46,115,112,108,105,116,40,41,46,233,1,0,0,0,41,1, - 90,8,109,97,120,115,112,108,105,116,218,0,41,6,114,22, - 0,0,0,114,31,0,0,0,218,10,114,112,97,114,116,105, - 116,105,111,110,114,35,0,0,0,218,8,114,101,118,101,114, - 115,101,100,218,6,114,115,112,108,105,116,41,5,218,4,112, - 97,116,104,90,5,102,114,111,110,116,218,1,95,218,4,116, - 97,105,108,114,19,0,0,0,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,218,11,95,112,97,116,104,95,115, - 112,108,105,116,68,0,0,0,115,16,0,0,0,0,2,12, - 1,16,1,8,1,12,1,8,1,18,1,14,1,114,47,0, - 0,0,99,1,0,0,0,0,0,0,0,1,0,0,0,3, - 0,0,0,67,0,0,0,115,10,0,0,0,116,0,160,1, - 124,0,161,1,83,0,41,1,122,126,83,116,97,116,32,116, - 104,101,32,112,97,116,104,46,10,10,32,32,32,32,77,97, - 100,101,32,97,32,115,101,112,97,114,97,116,101,32,102,117, - 110,99,116,105,111,110,32,116,111,32,109,97,107,101,32,105, - 116,32,101,97,115,105,101,114,32,116,111,32,111,118,101,114, - 114,105,100,101,32,105,110,32,101,120,112,101,114,105,109,101, - 110,116,115,10,32,32,32,32,40,101,46,103,46,32,99,97, - 99,104,101,32,115,116,97,116,32,114,101,115,117,108,116,115, - 41,46,10,10,32,32,32,32,41,2,114,2,0,0,0,90, - 4,115,116,97,116,169,1,114,44,0,0,0,114,3,0,0, - 0,114,3,0,0,0,114,6,0,0,0,218,10,95,112,97, - 116,104,95,115,116,97,116,80,0,0,0,115,2,0,0,0, - 0,7,114,49,0,0,0,99,2,0,0,0,0,0,0,0, + 41,46,99,1,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,5,0,0,0,83,0,0,0,115,26,0,0,0, + 103,0,124,0,93,18,125,1,124,1,114,22,124,1,160,0, + 116,1,161,1,145,2,113,4,83,0,114,3,0,0,0,41, + 2,218,6,114,115,116,114,105,112,218,15,112,97,116,104,95, + 115,101,112,97,114,97,116,111,114,115,41,2,218,2,46,48, + 218,4,112,97,114,116,114,3,0,0,0,114,3,0,0,0, + 114,6,0,0,0,218,10,60,108,105,115,116,99,111,109,112, + 62,64,0,0,0,115,6,0,0,0,6,1,2,0,4,255, + 122,30,95,112,97,116,104,95,106,111,105,110,46,60,108,111, + 99,97,108,115,62,46,60,108,105,115,116,99,111,109,112,62, + 41,2,218,8,112,97,116,104,95,115,101,112,218,4,106,111, + 105,110,41,1,218,10,112,97,116,104,95,112,97,114,116,115, + 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,218, + 10,95,112,97,116,104,95,106,111,105,110,62,0,0,0,115, + 6,0,0,0,0,2,10,1,2,255,114,38,0,0,0,99, + 1,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, + 5,0,0,0,67,0,0,0,115,96,0,0,0,116,0,116, + 1,131,1,100,1,107,2,114,36,124,0,160,2,116,3,161, + 1,92,3,125,1,125,2,125,3,124,1,124,3,102,2,83, + 0,116,4,124,0,131,1,68,0,93,42,125,4,124,4,116, + 1,107,6,114,44,124,0,106,5,124,4,100,1,100,2,141, + 2,92,2,125,1,125,3,124,1,124,3,102,2,2,0,1, + 0,83,0,113,44,100,3,124,0,102,2,83,0,41,4,122, + 32,82,101,112,108,97,99,101,109,101,110,116,32,102,111,114, + 32,111,115,46,112,97,116,104,46,115,112,108,105,116,40,41, + 46,233,1,0,0,0,41,1,90,8,109,97,120,115,112,108, + 105,116,218,0,41,6,114,22,0,0,0,114,31,0,0,0, + 218,10,114,112,97,114,116,105,116,105,111,110,114,35,0,0, + 0,218,8,114,101,118,101,114,115,101,100,218,6,114,115,112, + 108,105,116,41,5,218,4,112,97,116,104,90,5,102,114,111, + 110,116,218,1,95,218,4,116,97,105,108,114,19,0,0,0, + 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,218, + 11,95,112,97,116,104,95,115,112,108,105,116,68,0,0,0, + 115,16,0,0,0,0,2,12,1,16,1,8,1,12,1,8, + 1,18,1,14,1,114,47,0,0,0,99,1,0,0,0,0, + 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, + 0,0,0,115,10,0,0,0,116,0,160,1,124,0,161,1, + 83,0,41,1,122,126,83,116,97,116,32,116,104,101,32,112, + 97,116,104,46,10,10,32,32,32,32,77,97,100,101,32,97, + 32,115,101,112,97,114,97,116,101,32,102,117,110,99,116,105, + 111,110,32,116,111,32,109,97,107,101,32,105,116,32,101,97, + 115,105,101,114,32,116,111,32,111,118,101,114,114,105,100,101, + 32,105,110,32,101,120,112,101,114,105,109,101,110,116,115,10, + 32,32,32,32,40,101,46,103,46,32,99,97,99,104,101,32, + 115,116,97,116,32,114,101,115,117,108,116,115,41,46,10,10, + 32,32,32,32,41,2,114,2,0,0,0,90,4,115,116,97, + 116,169,1,114,44,0,0,0,114,3,0,0,0,114,3,0, + 0,0,114,6,0,0,0,218,10,95,112,97,116,104,95,115, + 116,97,116,80,0,0,0,115,2,0,0,0,0,7,114,49, + 0,0,0,99,2,0,0,0,0,0,0,0,0,0,0,0, 3,0,0,0,8,0,0,0,67,0,0,0,115,50,0,0, 0,122,12,116,0,124,0,131,1,125,2,87,0,110,22,4, 0,116,1,107,10,114,34,1,0,1,0,1,0,89,0,100, @@ -203,43 +206,44 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 95,112,97,116,104,95,105,115,95,109,111,100,101,95,116,121, 112,101,90,0,0,0,115,10,0,0,0,0,2,2,1,12, 1,14,1,8,1,114,53,0,0,0,99,1,0,0,0,0, - 0,0,0,1,0,0,0,3,0,0,0,67,0,0,0,115, - 10,0,0,0,116,0,124,0,100,1,131,2,83,0,41,2, - 122,31,82,101,112,108,97,99,101,109,101,110,116,32,102,111, - 114,32,111,115,46,112,97,116,104,46,105,115,102,105,108,101, - 46,105,0,128,0,0,41,1,114,53,0,0,0,114,48,0, + 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, + 0,0,0,115,10,0,0,0,116,0,124,0,100,1,131,2, + 83,0,41,2,122,31,82,101,112,108,97,99,101,109,101,110, + 116,32,102,111,114,32,111,115,46,112,97,116,104,46,105,115, + 102,105,108,101,46,105,0,128,0,0,41,1,114,53,0,0, + 0,114,48,0,0,0,114,3,0,0,0,114,3,0,0,0, + 114,6,0,0,0,218,12,95,112,97,116,104,95,105,115,102, + 105,108,101,99,0,0,0,115,2,0,0,0,0,2,114,54, + 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,67,0,0,0,115,22,0,0, + 0,124,0,115,12,116,0,160,1,161,0,125,0,116,2,124, + 0,100,1,131,2,83,0,41,2,122,30,82,101,112,108,97, + 99,101,109,101,110,116,32,102,111,114,32,111,115,46,112,97, + 116,104,46,105,115,100,105,114,46,105,0,64,0,0,41,3, + 114,2,0,0,0,218,6,103,101,116,99,119,100,114,53,0, + 0,0,114,48,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,218,11,95,112,97,116,104,95,105,115, + 100,105,114,104,0,0,0,115,6,0,0,0,0,2,4,1, + 8,1,114,56,0,0,0,99,1,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, + 115,26,0,0,0,124,0,160,0,116,1,161,1,112,24,124, + 0,100,1,100,2,133,2,25,0,116,2,107,6,83,0,41, + 3,122,142,82,101,112,108,97,99,101,109,101,110,116,32,102, + 111,114,32,111,115,46,112,97,116,104,46,105,115,97,98,115, + 46,10,10,32,32,32,32,67,111,110,115,105,100,101,114,115, + 32,97,32,87,105,110,100,111,119,115,32,100,114,105,118,101, + 45,114,101,108,97,116,105,118,101,32,112,97,116,104,32,40, + 110,111,32,100,114,105,118,101,44,32,98,117,116,32,115,116, + 97,114,116,115,32,119,105,116,104,32,115,108,97,115,104,41, + 32,116,111,10,32,32,32,32,115,116,105,108,108,32,98,101, + 32,34,97,98,115,111,108,117,116,101,34,46,10,32,32,32, + 32,114,39,0,0,0,233,3,0,0,0,41,3,114,10,0, + 0,0,114,31,0,0,0,218,20,95,112,97,116,104,115,101, + 112,115,95,119,105,116,104,95,99,111,108,111,110,114,48,0, 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,218,12,95,112,97,116,104,95,105,115,102,105,108,101,99, - 0,0,0,115,2,0,0,0,0,2,114,54,0,0,0,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,22,0,0,0,124,0,115,12,116,0,160, - 1,161,0,125,0,116,2,124,0,100,1,131,2,83,0,41, - 2,122,30,82,101,112,108,97,99,101,109,101,110,116,32,102, - 111,114,32,111,115,46,112,97,116,104,46,105,115,100,105,114, - 46,105,0,64,0,0,41,3,114,2,0,0,0,218,6,103, - 101,116,99,119,100,114,53,0,0,0,114,48,0,0,0,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,218,11, - 95,112,97,116,104,95,105,115,100,105,114,104,0,0,0,115, - 6,0,0,0,0,2,4,1,8,1,114,56,0,0,0,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,26,0,0,0,124,0,160,0,116,1,161, - 1,112,24,124,0,100,1,100,2,133,2,25,0,116,2,107, - 6,83,0,41,3,122,142,82,101,112,108,97,99,101,109,101, - 110,116,32,102,111,114,32,111,115,46,112,97,116,104,46,105, - 115,97,98,115,46,10,10,32,32,32,32,67,111,110,115,105, - 100,101,114,115,32,97,32,87,105,110,100,111,119,115,32,100, - 114,105,118,101,45,114,101,108,97,116,105,118,101,32,112,97, - 116,104,32,40,110,111,32,100,114,105,118,101,44,32,98,117, - 116,32,115,116,97,114,116,115,32,119,105,116,104,32,115,108, - 97,115,104,41,32,116,111,10,32,32,32,32,115,116,105,108, - 108,32,98,101,32,34,97,98,115,111,108,117,116,101,34,46, - 10,32,32,32,32,114,39,0,0,0,233,3,0,0,0,41, - 3,114,10,0,0,0,114,31,0,0,0,218,20,95,112,97, - 116,104,115,101,112,115,95,119,105,116,104,95,99,111,108,111, - 110,114,48,0,0,0,114,3,0,0,0,114,3,0,0,0, - 114,6,0,0,0,218,11,95,112,97,116,104,95,105,115,97, - 98,115,111,0,0,0,115,2,0,0,0,0,6,114,59,0, - 0,0,233,182,1,0,0,99,3,0,0,0,0,0,0,0, + 0,218,11,95,112,97,116,104,95,105,115,97,98,115,111,0, + 0,0,115,2,0,0,0,0,6,114,59,0,0,0,233,182, + 1,0,0,99,3,0,0,0,0,0,0,0,0,0,0,0, 6,0,0,0,11,0,0,0,67,0,0,0,115,162,0,0, 0,100,1,160,0,124,0,116,1,124,0,131,1,161,2,125, 3,116,2,160,3,124,3,116,2,106,4,116,2,106,5,66, @@ -275,239 +279,240 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,105,116,101,95,97,116,111,109,105,99,120,0,0,0,115, 30,0,0,0,0,5,16,1,6,1,16,0,6,255,4,2, 2,3,14,1,20,1,16,1,14,1,2,1,14,1,14,1, - 6,1,114,69,0,0,0,105,73,13,0,0,114,28,0,0, + 6,1,114,69,0,0,0,105,82,13,0,0,114,28,0,0, 0,114,16,0,0,0,115,2,0,0,0,13,10,90,11,95, 95,112,121,99,97,99,104,101,95,95,122,4,111,112,116,45, 122,3,46,112,121,122,4,46,112,121,99,78,41,1,218,12, 111,112,116,105,109,105,122,97,116,105,111,110,99,2,0,0, - 0,1,0,0,0,12,0,0,0,5,0,0,0,67,0,0, - 0,115,88,1,0,0,124,1,100,1,107,9,114,52,116,0, - 160,1,100,2,116,2,161,2,1,0,124,2,100,1,107,9, - 114,40,100,3,125,3,116,3,124,3,131,1,130,1,124,1, - 114,48,100,4,110,2,100,5,125,2,116,4,160,5,124,0, - 161,1,125,0,116,6,124,0,131,1,92,2,125,4,125,5, - 124,5,160,7,100,6,161,1,92,3,125,6,125,7,125,8, - 116,8,106,9,106,10,125,9,124,9,100,1,107,8,114,114, - 116,11,100,7,131,1,130,1,100,4,160,12,124,6,114,126, - 124,6,110,2,124,8,124,7,124,9,103,3,161,1,125,10, - 124,2,100,1,107,8,114,172,116,8,106,13,106,14,100,8, - 107,2,114,164,100,4,125,2,110,8,116,8,106,13,106,14, - 125,2,116,15,124,2,131,1,125,2,124,2,100,4,107,3, - 114,224,124,2,160,16,161,0,115,210,116,17,100,9,160,18, - 124,2,161,1,131,1,130,1,100,10,160,18,124,10,116,19, - 124,2,161,3,125,10,124,10,116,20,100,8,25,0,23,0, - 125,11,116,8,106,21,100,1,107,9,144,1,114,76,116,22, - 124,4,131,1,144,1,115,16,116,23,116,4,160,24,161,0, - 124,4,131,2,125,4,124,4,100,5,25,0,100,11,107,2, - 144,1,114,56,124,4,100,8,25,0,116,25,107,7,144,1, - 114,56,124,4,100,12,100,1,133,2,25,0,125,4,116,23, - 116,8,106,21,124,4,160,26,116,25,161,1,124,11,131,3, - 83,0,116,23,124,4,116,27,124,11,131,3,83,0,41,13, - 97,254,2,0,0,71,105,118,101,110,32,116,104,101,32,112, - 97,116,104,32,116,111,32,97,32,46,112,121,32,102,105,108, - 101,44,32,114,101,116,117,114,110,32,116,104,101,32,112,97, - 116,104,32,116,111,32,105,116,115,32,46,112,121,99,32,102, - 105,108,101,46,10,10,32,32,32,32,84,104,101,32,46,112, - 121,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32, - 110,101,101,100,32,116,111,32,101,120,105,115,116,59,32,116, - 104,105,115,32,115,105,109,112,108,121,32,114,101,116,117,114, - 110,115,32,116,104,101,32,112,97,116,104,32,116,111,32,116, - 104,101,10,32,32,32,32,46,112,121,99,32,102,105,108,101, - 32,99,97,108,99,117,108,97,116,101,100,32,97,115,32,105, - 102,32,116,104,101,32,46,112,121,32,102,105,108,101,32,119, - 101,114,101,32,105,109,112,111,114,116,101,100,46,10,10,32, - 32,32,32,84,104,101,32,39,111,112,116,105,109,105,122,97, - 116,105,111,110,39,32,112,97,114,97,109,101,116,101,114,32, - 99,111,110,116,114,111,108,115,32,116,104,101,32,112,114,101, - 115,117,109,101,100,32,111,112,116,105,109,105,122,97,116,105, - 111,110,32,108,101,118,101,108,32,111,102,10,32,32,32,32, - 116,104,101,32,98,121,116,101,99,111,100,101,32,102,105,108, - 101,46,32,73,102,32,39,111,112,116,105,109,105,122,97,116, - 105,111,110,39,32,105,115,32,110,111,116,32,78,111,110,101, - 44,32,116,104,101,32,115,116,114,105,110,103,32,114,101,112, - 114,101,115,101,110,116,97,116,105,111,110,10,32,32,32,32, - 111,102,32,116,104,101,32,97,114,103,117,109,101,110,116,32, - 105,115,32,116,97,107,101,110,32,97,110,100,32,118,101,114, - 105,102,105,101,100,32,116,111,32,98,101,32,97,108,112,104, - 97,110,117,109,101,114,105,99,32,40,101,108,115,101,32,86, - 97,108,117,101,69,114,114,111,114,10,32,32,32,32,105,115, - 32,114,97,105,115,101,100,41,46,10,10,32,32,32,32,84, - 104,101,32,100,101,98,117,103,95,111,118,101,114,114,105,100, - 101,32,112,97,114,97,109,101,116,101,114,32,105,115,32,100, - 101,112,114,101,99,97,116,101,100,46,32,73,102,32,100,101, - 98,117,103,95,111,118,101,114,114,105,100,101,32,105,115,32, - 110,111,116,32,78,111,110,101,44,10,32,32,32,32,97,32, - 84,114,117,101,32,118,97,108,117,101,32,105,115,32,116,104, - 101,32,115,97,109,101,32,97,115,32,115,101,116,116,105,110, - 103,32,39,111,112,116,105,109,105,122,97,116,105,111,110,39, - 32,116,111,32,116,104,101,32,101,109,112,116,121,32,115,116, - 114,105,110,103,10,32,32,32,32,119,104,105,108,101,32,97, - 32,70,97,108,115,101,32,118,97,108,117,101,32,105,115,32, - 101,113,117,105,118,97,108,101,110,116,32,116,111,32,115,101, + 0,0,0,0,0,1,0,0,0,12,0,0,0,5,0,0, + 0,67,0,0,0,115,88,1,0,0,124,1,100,1,107,9, + 114,52,116,0,160,1,100,2,116,2,161,2,1,0,124,2, + 100,1,107,9,114,40,100,3,125,3,116,3,124,3,131,1, + 130,1,124,1,114,48,100,4,110,2,100,5,125,2,116,4, + 160,5,124,0,161,1,125,0,116,6,124,0,131,1,92,2, + 125,4,125,5,124,5,160,7,100,6,161,1,92,3,125,6, + 125,7,125,8,116,8,106,9,106,10,125,9,124,9,100,1, + 107,8,114,114,116,11,100,7,131,1,130,1,100,4,160,12, + 124,6,114,126,124,6,110,2,124,8,124,7,124,9,103,3, + 161,1,125,10,124,2,100,1,107,8,114,172,116,8,106,13, + 106,14,100,8,107,2,114,164,100,4,125,2,110,8,116,8, + 106,13,106,14,125,2,116,15,124,2,131,1,125,2,124,2, + 100,4,107,3,114,224,124,2,160,16,161,0,115,210,116,17, + 100,9,160,18,124,2,161,1,131,1,130,1,100,10,160,18, + 124,10,116,19,124,2,161,3,125,10,124,10,116,20,100,8, + 25,0,23,0,125,11,116,8,106,21,100,1,107,9,144,1, + 114,76,116,22,124,4,131,1,144,1,115,16,116,23,116,4, + 160,24,161,0,124,4,131,2,125,4,124,4,100,5,25,0, + 100,11,107,2,144,1,114,56,124,4,100,8,25,0,116,25, + 107,7,144,1,114,56,124,4,100,12,100,1,133,2,25,0, + 125,4,116,23,116,8,106,21,124,4,160,26,116,25,161,1, + 124,11,131,3,83,0,116,23,124,4,116,27,124,11,131,3, + 83,0,41,13,97,254,2,0,0,71,105,118,101,110,32,116, + 104,101,32,112,97,116,104,32,116,111,32,97,32,46,112,121, + 32,102,105,108,101,44,32,114,101,116,117,114,110,32,116,104, + 101,32,112,97,116,104,32,116,111,32,105,116,115,32,46,112, + 121,99,32,102,105,108,101,46,10,10,32,32,32,32,84,104, + 101,32,46,112,121,32,102,105,108,101,32,100,111,101,115,32, + 110,111,116,32,110,101,101,100,32,116,111,32,101,120,105,115, + 116,59,32,116,104,105,115,32,115,105,109,112,108,121,32,114, + 101,116,117,114,110,115,32,116,104,101,32,112,97,116,104,32, + 116,111,32,116,104,101,10,32,32,32,32,46,112,121,99,32, + 102,105,108,101,32,99,97,108,99,117,108,97,116,101,100,32, + 97,115,32,105,102,32,116,104,101,32,46,112,121,32,102,105, + 108,101,32,119,101,114,101,32,105,109,112,111,114,116,101,100, + 46,10,10,32,32,32,32,84,104,101,32,39,111,112,116,105, + 109,105,122,97,116,105,111,110,39,32,112,97,114,97,109,101, + 116,101,114,32,99,111,110,116,114,111,108,115,32,116,104,101, + 32,112,114,101,115,117,109,101,100,32,111,112,116,105,109,105, + 122,97,116,105,111,110,32,108,101,118,101,108,32,111,102,10, + 32,32,32,32,116,104,101,32,98,121,116,101,99,111,100,101, + 32,102,105,108,101,46,32,73,102,32,39,111,112,116,105,109, + 105,122,97,116,105,111,110,39,32,105,115,32,110,111,116,32, + 78,111,110,101,44,32,116,104,101,32,115,116,114,105,110,103, + 32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,10, + 32,32,32,32,111,102,32,116,104,101,32,97,114,103,117,109, + 101,110,116,32,105,115,32,116,97,107,101,110,32,97,110,100, + 32,118,101,114,105,102,105,101,100,32,116,111,32,98,101,32, + 97,108,112,104,97,110,117,109,101,114,105,99,32,40,101,108, + 115,101,32,86,97,108,117,101,69,114,114,111,114,10,32,32, + 32,32,105,115,32,114,97,105,115,101,100,41,46,10,10,32, + 32,32,32,84,104,101,32,100,101,98,117,103,95,111,118,101, + 114,114,105,100,101,32,112,97,114,97,109,101,116,101,114,32, + 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,73, + 102,32,100,101,98,117,103,95,111,118,101,114,114,105,100,101, + 32,105,115,32,110,111,116,32,78,111,110,101,44,10,32,32, + 32,32,97,32,84,114,117,101,32,118,97,108,117,101,32,105, + 115,32,116,104,101,32,115,97,109,101,32,97,115,32,115,101, 116,116,105,110,103,32,39,111,112,116,105,109,105,122,97,116, - 105,111,110,39,32,116,111,32,39,49,39,46,10,10,32,32, - 32,32,73,102,32,115,121,115,46,105,109,112,108,101,109,101, + 105,111,110,39,32,116,111,32,116,104,101,32,101,109,112,116, + 121,32,115,116,114,105,110,103,10,32,32,32,32,119,104,105, + 108,101,32,97,32,70,97,108,115,101,32,118,97,108,117,101, + 32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116, + 111,32,115,101,116,116,105,110,103,32,39,111,112,116,105,109, + 105,122,97,116,105,111,110,39,32,116,111,32,39,49,39,46, + 10,10,32,32,32,32,73,102,32,115,121,115,46,105,109,112, + 108,101,109,101,110,116,97,116,105,111,110,46,99,97,99,104, + 101,95,116,97,103,32,105,115,32,78,111,110,101,32,116,104, + 101,110,32,78,111,116,73,109,112,108,101,109,101,110,116,101, + 100,69,114,114,111,114,32,105,115,32,114,97,105,115,101,100, + 46,10,10,32,32,32,32,78,122,70,116,104,101,32,100,101, + 98,117,103,95,111,118,101,114,114,105,100,101,32,112,97,114, + 97,109,101,116,101,114,32,105,115,32,100,101,112,114,101,99, + 97,116,101,100,59,32,117,115,101,32,39,111,112,116,105,109, + 105,122,97,116,105,111,110,39,32,105,110,115,116,101,97,100, + 122,50,100,101,98,117,103,95,111,118,101,114,114,105,100,101, + 32,111,114,32,111,112,116,105,109,105,122,97,116,105,111,110, + 32,109,117,115,116,32,98,101,32,115,101,116,32,116,111,32, + 78,111,110,101,114,40,0,0,0,114,39,0,0,0,218,1, + 46,250,36,115,121,115,46,105,109,112,108,101,109,101,110,116, + 97,116,105,111,110,46,99,97,99,104,101,95,116,97,103,32, + 105,115,32,78,111,110,101,233,0,0,0,0,122,24,123,33, + 114,125,32,105,115,32,110,111,116,32,97,108,112,104,97,110, + 117,109,101,114,105,99,122,7,123,125,46,123,125,123,125,250, + 1,58,114,28,0,0,0,41,28,218,9,95,119,97,114,110, + 105,110,103,115,218,4,119,97,114,110,218,18,68,101,112,114, + 101,99,97,116,105,111,110,87,97,114,110,105,110,103,218,9, + 84,121,112,101,69,114,114,111,114,114,2,0,0,0,218,6, + 102,115,112,97,116,104,114,47,0,0,0,114,41,0,0,0, + 114,8,0,0,0,218,14,105,109,112,108,101,109,101,110,116, + 97,116,105,111,110,218,9,99,97,99,104,101,95,116,97,103, + 218,19,78,111,116,73,109,112,108,101,109,101,110,116,101,100, + 69,114,114,111,114,114,36,0,0,0,218,5,102,108,97,103, + 115,218,8,111,112,116,105,109,105,122,101,218,3,115,116,114, + 218,7,105,115,97,108,110,117,109,218,10,86,97,108,117,101, + 69,114,114,111,114,114,62,0,0,0,218,4,95,79,80,84, + 218,17,66,89,84,69,67,79,68,69,95,83,85,70,70,73, + 88,69,83,218,14,112,121,99,97,99,104,101,95,112,114,101, + 102,105,120,114,59,0,0,0,114,38,0,0,0,114,55,0, + 0,0,114,31,0,0,0,218,6,108,115,116,114,105,112,218, + 8,95,80,89,67,65,67,72,69,41,12,114,44,0,0,0, + 90,14,100,101,98,117,103,95,111,118,101,114,114,105,100,101, + 114,70,0,0,0,218,7,109,101,115,115,97,103,101,218,4, + 104,101,97,100,114,46,0,0,0,90,4,98,97,115,101,218, + 3,115,101,112,218,4,114,101,115,116,90,3,116,97,103,90, + 15,97,108,109,111,115,116,95,102,105,108,101,110,97,109,101, + 218,8,102,105,108,101,110,97,109,101,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,218,17,99,97,99,104,101, + 95,102,114,111,109,95,115,111,117,114,99,101,33,1,0,0, + 115,72,0,0,0,0,18,8,1,6,1,2,255,4,2,8, + 1,4,1,8,1,12,1,10,1,12,1,16,1,8,1,8, + 1,8,1,24,1,8,1,12,1,6,2,8,1,8,1,8, + 1,8,1,14,1,14,1,12,1,12,9,10,1,14,5,28, + 1,12,4,2,1,4,1,8,1,2,253,4,5,114,98,0, + 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,10, + 0,0,0,5,0,0,0,67,0,0,0,115,46,1,0,0, + 116,0,106,1,106,2,100,1,107,8,114,20,116,3,100,2, + 131,1,130,1,116,4,160,5,124,0,161,1,125,0,116,6, + 124,0,131,1,92,2,125,1,125,2,100,3,125,3,116,0, + 106,7,100,1,107,9,114,102,116,0,106,7,160,8,116,9, + 161,1,125,4,124,1,160,10,124,4,116,11,23,0,161,1, + 114,102,124,1,116,12,124,4,131,1,100,1,133,2,25,0, + 125,1,100,4,125,3,124,3,115,144,116,6,124,1,131,1, + 92,2,125,1,125,5,124,5,116,13,107,3,114,144,116,14, + 116,13,155,0,100,5,124,0,155,2,157,3,131,1,130,1, + 124,2,160,15,100,6,161,1,125,6,124,6,100,7,107,7, + 114,178,116,14,100,8,124,2,155,2,157,2,131,1,130,1, + 110,92,124,6,100,9,107,2,144,1,114,14,124,2,160,16, + 100,6,100,10,161,2,100,11,25,0,125,7,124,7,160,10, + 116,17,161,1,115,228,116,14,100,12,116,17,155,2,157,2, + 131,1,130,1,124,7,116,12,116,17,131,1,100,1,133,2, + 25,0,125,8,124,8,160,18,161,0,144,1,115,14,116,14, + 100,13,124,7,155,2,100,14,157,3,131,1,130,1,124,2, + 160,19,100,6,161,1,100,15,25,0,125,9,116,20,124,1, + 124,9,116,21,100,15,25,0,23,0,131,2,83,0,41,16, + 97,110,1,0,0,71,105,118,101,110,32,116,104,101,32,112, + 97,116,104,32,116,111,32,97,32,46,112,121,99,46,32,102, + 105,108,101,44,32,114,101,116,117,114,110,32,116,104,101,32, + 112,97,116,104,32,116,111,32,105,116,115,32,46,112,121,32, + 102,105,108,101,46,10,10,32,32,32,32,84,104,101,32,46, + 112,121,99,32,102,105,108,101,32,100,111,101,115,32,110,111, + 116,32,110,101,101,100,32,116,111,32,101,120,105,115,116,59, + 32,116,104,105,115,32,115,105,109,112,108,121,32,114,101,116, + 117,114,110,115,32,116,104,101,32,112,97,116,104,32,116,111, + 10,32,32,32,32,116,104,101,32,46,112,121,32,102,105,108, + 101,32,99,97,108,99,117,108,97,116,101,100,32,116,111,32, + 99,111,114,114,101,115,112,111,110,100,32,116,111,32,116,104, + 101,32,46,112,121,99,32,102,105,108,101,46,32,32,73,102, + 32,112,97,116,104,32,100,111,101,115,10,32,32,32,32,110, + 111,116,32,99,111,110,102,111,114,109,32,116,111,32,80,69, + 80,32,51,49,52,55,47,52,56,56,32,102,111,114,109,97, + 116,44,32,86,97,108,117,101,69,114,114,111,114,32,119,105, + 108,108,32,98,101,32,114,97,105,115,101,100,46,32,73,102, + 10,32,32,32,32,115,121,115,46,105,109,112,108,101,109,101, 110,116,97,116,105,111,110,46,99,97,99,104,101,95,116,97, 103,32,105,115,32,78,111,110,101,32,116,104,101,110,32,78, 111,116,73,109,112,108,101,109,101,110,116,101,100,69,114,114, 111,114,32,105,115,32,114,97,105,115,101,100,46,10,10,32, - 32,32,32,78,122,70,116,104,101,32,100,101,98,117,103,95, - 111,118,101,114,114,105,100,101,32,112,97,114,97,109,101,116, - 101,114,32,105,115,32,100,101,112,114,101,99,97,116,101,100, - 59,32,117,115,101,32,39,111,112,116,105,109,105,122,97,116, - 105,111,110,39,32,105,110,115,116,101,97,100,122,50,100,101, - 98,117,103,95,111,118,101,114,114,105,100,101,32,111,114,32, - 111,112,116,105,109,105,122,97,116,105,111,110,32,109,117,115, - 116,32,98,101,32,115,101,116,32,116,111,32,78,111,110,101, - 114,40,0,0,0,114,39,0,0,0,218,1,46,250,36,115, - 121,115,46,105,109,112,108,101,109,101,110,116,97,116,105,111, - 110,46,99,97,99,104,101,95,116,97,103,32,105,115,32,78, - 111,110,101,233,0,0,0,0,122,24,123,33,114,125,32,105, - 115,32,110,111,116,32,97,108,112,104,97,110,117,109,101,114, - 105,99,122,7,123,125,46,123,125,123,125,250,1,58,114,28, - 0,0,0,41,28,218,9,95,119,97,114,110,105,110,103,115, - 218,4,119,97,114,110,218,18,68,101,112,114,101,99,97,116, - 105,111,110,87,97,114,110,105,110,103,218,9,84,121,112,101, - 69,114,114,111,114,114,2,0,0,0,218,6,102,115,112,97, - 116,104,114,47,0,0,0,114,41,0,0,0,114,8,0,0, - 0,218,14,105,109,112,108,101,109,101,110,116,97,116,105,111, - 110,218,9,99,97,99,104,101,95,116,97,103,218,19,78,111, - 116,73,109,112,108,101,109,101,110,116,101,100,69,114,114,111, - 114,114,36,0,0,0,218,5,102,108,97,103,115,218,8,111, - 112,116,105,109,105,122,101,218,3,115,116,114,218,7,105,115, - 97,108,110,117,109,218,10,86,97,108,117,101,69,114,114,111, - 114,114,62,0,0,0,218,4,95,79,80,84,218,17,66,89, - 84,69,67,79,68,69,95,83,85,70,70,73,88,69,83,218, - 14,112,121,99,97,99,104,101,95,112,114,101,102,105,120,114, - 59,0,0,0,114,38,0,0,0,114,55,0,0,0,114,31, - 0,0,0,218,6,108,115,116,114,105,112,218,8,95,80,89, - 67,65,67,72,69,41,12,114,44,0,0,0,90,14,100,101, - 98,117,103,95,111,118,101,114,114,105,100,101,114,70,0,0, - 0,218,7,109,101,115,115,97,103,101,218,4,104,101,97,100, - 114,46,0,0,0,90,4,98,97,115,101,218,3,115,101,112, - 218,4,114,101,115,116,90,3,116,97,103,90,15,97,108,109, - 111,115,116,95,102,105,108,101,110,97,109,101,218,8,102,105, - 108,101,110,97,109,101,114,3,0,0,0,114,3,0,0,0, - 114,6,0,0,0,218,17,99,97,99,104,101,95,102,114,111, - 109,95,115,111,117,114,99,101,32,1,0,0,115,72,0,0, - 0,0,18,8,1,6,1,2,255,4,2,8,1,4,1,8, - 1,12,1,10,1,12,1,16,1,8,1,8,1,8,1,24, - 1,8,1,12,1,6,2,8,1,8,1,8,1,8,1,14, - 1,14,1,12,1,12,9,10,1,14,5,28,1,12,4,2, - 1,4,1,8,1,2,253,4,5,114,98,0,0,0,99,1, - 0,0,0,0,0,0,0,10,0,0,0,5,0,0,0,67, - 0,0,0,115,46,1,0,0,116,0,106,1,106,2,100,1, - 107,8,114,20,116,3,100,2,131,1,130,1,116,4,160,5, - 124,0,161,1,125,0,116,6,124,0,131,1,92,2,125,1, - 125,2,100,3,125,3,116,0,106,7,100,1,107,9,114,102, - 116,0,106,7,160,8,116,9,161,1,125,4,124,1,160,10, - 124,4,116,11,23,0,161,1,114,102,124,1,116,12,124,4, - 131,1,100,1,133,2,25,0,125,1,100,4,125,3,124,3, - 115,144,116,6,124,1,131,1,92,2,125,1,125,5,124,5, - 116,13,107,3,114,144,116,14,116,13,155,0,100,5,124,0, - 155,2,157,3,131,1,130,1,124,2,160,15,100,6,161,1, - 125,6,124,6,100,7,107,7,114,178,116,14,100,8,124,2, - 155,2,157,2,131,1,130,1,110,92,124,6,100,9,107,2, - 144,1,114,14,124,2,160,16,100,6,100,10,161,2,100,11, - 25,0,125,7,124,7,160,10,116,17,161,1,115,228,116,14, - 100,12,116,17,155,2,157,2,131,1,130,1,124,7,116,12, - 116,17,131,1,100,1,133,2,25,0,125,8,124,8,160,18, - 161,0,144,1,115,14,116,14,100,13,124,7,155,2,100,14, - 157,3,131,1,130,1,124,2,160,19,100,6,161,1,100,15, - 25,0,125,9,116,20,124,1,124,9,116,21,100,15,25,0, - 23,0,131,2,83,0,41,16,97,110,1,0,0,71,105,118, - 101,110,32,116,104,101,32,112,97,116,104,32,116,111,32,97, - 32,46,112,121,99,46,32,102,105,108,101,44,32,114,101,116, - 117,114,110,32,116,104,101,32,112,97,116,104,32,116,111,32, - 105,116,115,32,46,112,121,32,102,105,108,101,46,10,10,32, - 32,32,32,84,104,101,32,46,112,121,99,32,102,105,108,101, - 32,100,111,101,115,32,110,111,116,32,110,101,101,100,32,116, - 111,32,101,120,105,115,116,59,32,116,104,105,115,32,115,105, - 109,112,108,121,32,114,101,116,117,114,110,115,32,116,104,101, - 32,112,97,116,104,32,116,111,10,32,32,32,32,116,104,101, - 32,46,112,121,32,102,105,108,101,32,99,97,108,99,117,108, - 97,116,101,100,32,116,111,32,99,111,114,114,101,115,112,111, - 110,100,32,116,111,32,116,104,101,32,46,112,121,99,32,102, - 105,108,101,46,32,32,73,102,32,112,97,116,104,32,100,111, - 101,115,10,32,32,32,32,110,111,116,32,99,111,110,102,111, - 114,109,32,116,111,32,80,69,80,32,51,49,52,55,47,52, - 56,56,32,102,111,114,109,97,116,44,32,86,97,108,117,101, - 69,114,114,111,114,32,119,105,108,108,32,98,101,32,114,97, - 105,115,101,100,46,32,73,102,10,32,32,32,32,115,121,115, - 46,105,109,112,108,101,109,101,110,116,97,116,105,111,110,46, - 99,97,99,104,101,95,116,97,103,32,105,115,32,78,111,110, - 101,32,116,104,101,110,32,78,111,116,73,109,112,108,101,109, - 101,110,116,101,100,69,114,114,111,114,32,105,115,32,114,97, - 105,115,101,100,46,10,10,32,32,32,32,78,114,72,0,0, - 0,70,84,122,31,32,110,111,116,32,98,111,116,116,111,109, - 45,108,101,118,101,108,32,100,105,114,101,99,116,111,114,121, - 32,105,110,32,114,71,0,0,0,62,2,0,0,0,114,28, - 0,0,0,114,57,0,0,0,122,29,101,120,112,101,99,116, - 101,100,32,111,110,108,121,32,50,32,111,114,32,51,32,100, - 111,116,115,32,105,110,32,114,57,0,0,0,114,28,0,0, - 0,233,254,255,255,255,122,53,111,112,116,105,109,105,122,97, - 116,105,111,110,32,112,111,114,116,105,111,110,32,111,102,32, - 102,105,108,101,110,97,109,101,32,100,111,101,115,32,110,111, - 116,32,115,116,97,114,116,32,119,105,116,104,32,122,19,111, - 112,116,105,109,105,122,97,116,105,111,110,32,108,101,118,101, - 108,32,122,29,32,105,115,32,110,111,116,32,97,110,32,97, - 108,112,104,97,110,117,109,101,114,105,99,32,118,97,108,117, - 101,114,73,0,0,0,41,22,114,8,0,0,0,114,80,0, - 0,0,114,81,0,0,0,114,82,0,0,0,114,2,0,0, - 0,114,79,0,0,0,114,47,0,0,0,114,90,0,0,0, - 114,30,0,0,0,114,31,0,0,0,114,10,0,0,0,114, - 35,0,0,0,114,22,0,0,0,114,92,0,0,0,114,87, - 0,0,0,218,5,99,111,117,110,116,114,43,0,0,0,114, - 88,0,0,0,114,86,0,0,0,218,9,112,97,114,116,105, - 116,105,111,110,114,38,0,0,0,218,15,83,79,85,82,67, - 69,95,83,85,70,70,73,88,69,83,41,10,114,44,0,0, - 0,114,94,0,0,0,90,16,112,121,99,97,99,104,101,95, - 102,105,108,101,110,97,109,101,90,23,102,111,117,110,100,95, - 105,110,95,112,121,99,97,99,104,101,95,112,114,101,102,105, - 120,90,13,115,116,114,105,112,112,101,100,95,112,97,116,104, - 90,7,112,121,99,97,99,104,101,90,9,100,111,116,95,99, - 111,117,110,116,114,70,0,0,0,90,9,111,112,116,95,108, - 101,118,101,108,90,13,98,97,115,101,95,102,105,108,101,110, - 97,109,101,114,3,0,0,0,114,3,0,0,0,114,6,0, - 0,0,218,17,115,111,117,114,99,101,95,102,114,111,109,95, - 99,97,99,104,101,103,1,0,0,115,52,0,0,0,0,9, - 12,1,8,1,10,1,12,1,4,1,10,1,12,1,14,1, - 16,1,4,1,4,1,12,1,8,1,18,2,10,1,8,1, - 16,1,10,1,16,1,10,1,14,2,16,1,10,1,16,2, - 14,1,114,103,0,0,0,99,1,0,0,0,0,0,0,0, - 5,0,0,0,9,0,0,0,67,0,0,0,115,126,0,0, - 0,116,0,124,0,131,1,100,1,107,2,114,16,100,2,83, - 0,124,0,160,1,100,3,161,1,92,3,125,1,125,2,125, - 3,124,1,114,56,124,3,160,2,161,0,100,4,100,5,133, - 2,25,0,100,6,107,3,114,60,124,0,83,0,122,12,116, - 3,124,0,131,1,125,4,87,0,110,36,4,0,116,4,116, - 5,102,2,107,10,114,108,1,0,1,0,1,0,124,0,100, - 2,100,5,133,2,25,0,125,4,89,0,110,2,88,0,116, - 6,124,4,131,1,114,122,124,4,83,0,124,0,83,0,41, - 7,122,188,67,111,110,118,101,114,116,32,97,32,98,121,116, - 101,99,111,100,101,32,102,105,108,101,32,112,97,116,104,32, - 116,111,32,97,32,115,111,117,114,99,101,32,112,97,116,104, - 32,40,105,102,32,112,111,115,115,105,98,108,101,41,46,10, - 10,32,32,32,32,84,104,105,115,32,102,117,110,99,116,105, - 111,110,32,101,120,105,115,116,115,32,112,117,114,101,108,121, - 32,102,111,114,32,98,97,99,107,119,97,114,100,115,45,99, - 111,109,112,97,116,105,98,105,108,105,116,121,32,102,111,114, - 10,32,32,32,32,80,121,73,109,112,111,114,116,95,69,120, - 101,99,67,111,100,101,77,111,100,117,108,101,87,105,116,104, - 70,105,108,101,110,97,109,101,115,40,41,32,105,110,32,116, - 104,101,32,67,32,65,80,73,46,10,10,32,32,32,32,114, - 73,0,0,0,78,114,71,0,0,0,233,253,255,255,255,233, - 255,255,255,255,90,2,112,121,41,7,114,22,0,0,0,114, - 41,0,0,0,218,5,108,111,119,101,114,114,103,0,0,0, - 114,82,0,0,0,114,87,0,0,0,114,54,0,0,0,41, - 5,218,13,98,121,116,101,99,111,100,101,95,112,97,116,104, - 114,96,0,0,0,114,45,0,0,0,90,9,101,120,116,101, - 110,115,105,111,110,218,11,115,111,117,114,99,101,95,112,97, - 116,104,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,218,15,95,103,101,116,95,115,111,117,114,99,101,102,105, - 108,101,143,1,0,0,115,20,0,0,0,0,7,12,1,4, - 1,16,1,24,1,4,1,2,1,12,1,18,1,18,1,114, - 109,0,0,0,99,1,0,0,0,0,0,0,0,1,0,0, + 32,32,32,78,114,72,0,0,0,70,84,122,31,32,110,111, + 116,32,98,111,116,116,111,109,45,108,101,118,101,108,32,100, + 105,114,101,99,116,111,114,121,32,105,110,32,114,71,0,0, + 0,62,2,0,0,0,114,28,0,0,0,114,57,0,0,0, + 122,29,101,120,112,101,99,116,101,100,32,111,110,108,121,32, + 50,32,111,114,32,51,32,100,111,116,115,32,105,110,32,114, + 57,0,0,0,114,28,0,0,0,233,254,255,255,255,122,53, + 111,112,116,105,109,105,122,97,116,105,111,110,32,112,111,114, + 116,105,111,110,32,111,102,32,102,105,108,101,110,97,109,101, + 32,100,111,101,115,32,110,111,116,32,115,116,97,114,116,32, + 119,105,116,104,32,122,19,111,112,116,105,109,105,122,97,116, + 105,111,110,32,108,101,118,101,108,32,122,29,32,105,115,32, + 110,111,116,32,97,110,32,97,108,112,104,97,110,117,109,101, + 114,105,99,32,118,97,108,117,101,114,73,0,0,0,41,22, + 114,8,0,0,0,114,80,0,0,0,114,81,0,0,0,114, + 82,0,0,0,114,2,0,0,0,114,79,0,0,0,114,47, + 0,0,0,114,90,0,0,0,114,30,0,0,0,114,31,0, + 0,0,114,10,0,0,0,114,35,0,0,0,114,22,0,0, + 0,114,92,0,0,0,114,87,0,0,0,218,5,99,111,117, + 110,116,114,43,0,0,0,114,88,0,0,0,114,86,0,0, + 0,218,9,112,97,114,116,105,116,105,111,110,114,38,0,0, + 0,218,15,83,79,85,82,67,69,95,83,85,70,70,73,88, + 69,83,41,10,114,44,0,0,0,114,94,0,0,0,90,16, + 112,121,99,97,99,104,101,95,102,105,108,101,110,97,109,101, + 90,23,102,111,117,110,100,95,105,110,95,112,121,99,97,99, + 104,101,95,112,114,101,102,105,120,90,13,115,116,114,105,112, + 112,101,100,95,112,97,116,104,90,7,112,121,99,97,99,104, + 101,90,9,100,111,116,95,99,111,117,110,116,114,70,0,0, + 0,90,9,111,112,116,95,108,101,118,101,108,90,13,98,97, + 115,101,95,102,105,108,101,110,97,109,101,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,218,17,115,111,117,114, + 99,101,95,102,114,111,109,95,99,97,99,104,101,104,1,0, + 0,115,52,0,0,0,0,9,12,1,8,1,10,1,12,1, + 4,1,10,1,12,1,14,1,16,1,4,1,4,1,12,1, + 8,1,18,2,10,1,8,1,16,1,10,1,16,1,10,1, + 14,2,16,1,10,1,16,2,14,1,114,103,0,0,0,99, + 1,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, + 9,0,0,0,67,0,0,0,115,126,0,0,0,116,0,124, + 0,131,1,100,1,107,2,114,16,100,2,83,0,124,0,160, + 1,100,3,161,1,92,3,125,1,125,2,125,3,124,1,114, + 56,124,3,160,2,161,0,100,4,100,5,133,2,25,0,100, + 6,107,3,114,60,124,0,83,0,122,12,116,3,124,0,131, + 1,125,4,87,0,110,36,4,0,116,4,116,5,102,2,107, + 10,114,108,1,0,1,0,1,0,124,0,100,2,100,5,133, + 2,25,0,125,4,89,0,110,2,88,0,116,6,124,4,131, + 1,114,122,124,4,83,0,124,0,83,0,41,7,122,188,67, + 111,110,118,101,114,116,32,97,32,98,121,116,101,99,111,100, + 101,32,102,105,108,101,32,112,97,116,104,32,116,111,32,97, + 32,115,111,117,114,99,101,32,112,97,116,104,32,40,105,102, + 32,112,111,115,115,105,98,108,101,41,46,10,10,32,32,32, + 32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,101, + 120,105,115,116,115,32,112,117,114,101,108,121,32,102,111,114, + 32,98,97,99,107,119,97,114,100,115,45,99,111,109,112,97, + 116,105,98,105,108,105,116,121,32,102,111,114,10,32,32,32, + 32,80,121,73,109,112,111,114,116,95,69,120,101,99,67,111, + 100,101,77,111,100,117,108,101,87,105,116,104,70,105,108,101, + 110,97,109,101,115,40,41,32,105,110,32,116,104,101,32,67, + 32,65,80,73,46,10,10,32,32,32,32,114,73,0,0,0, + 78,114,71,0,0,0,233,253,255,255,255,233,255,255,255,255, + 90,2,112,121,41,7,114,22,0,0,0,114,41,0,0,0, + 218,5,108,111,119,101,114,114,103,0,0,0,114,82,0,0, + 0,114,87,0,0,0,114,54,0,0,0,41,5,218,13,98, + 121,116,101,99,111,100,101,95,112,97,116,104,114,96,0,0, + 0,114,45,0,0,0,90,9,101,120,116,101,110,115,105,111, + 110,218,11,115,111,117,114,99,101,95,112,97,116,104,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,218,15,95, + 103,101,116,95,115,111,117,114,99,101,102,105,108,101,144,1, + 0,0,115,20,0,0,0,0,7,12,1,4,1,16,1,24, + 1,4,1,2,1,12,1,18,1,18,1,114,109,0,0,0, + 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 0,8,0,0,0,67,0,0,0,115,74,0,0,0,124,0, 160,0,116,1,116,2,131,1,161,1,114,48,122,10,116,3, 124,0,131,1,87,0,83,0,4,0,116,4,107,10,114,44, @@ -518,63 +523,64 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,114,98,0,0,0,114,82,0,0,0,114,89,0, 0,0,41,1,114,97,0,0,0,114,3,0,0,0,114,3, 0,0,0,114,6,0,0,0,218,11,95,103,101,116,95,99, - 97,99,104,101,100,162,1,0,0,115,16,0,0,0,0,1, + 97,99,104,101,100,163,1,0,0,115,16,0,0,0,0,1, 14,1,2,1,10,1,14,1,8,1,14,1,4,2,114,113, - 0,0,0,99,1,0,0,0,0,0,0,0,2,0,0,0, - 8,0,0,0,67,0,0,0,115,52,0,0,0,122,14,116, - 0,124,0,131,1,106,1,125,1,87,0,110,24,4,0,116, - 2,107,10,114,38,1,0,1,0,1,0,100,1,125,1,89, - 0,110,2,88,0,124,1,100,2,79,0,125,1,124,1,83, - 0,41,3,122,51,67,97,108,99,117,108,97,116,101,32,116, - 104,101,32,109,111,100,101,32,112,101,114,109,105,115,115,105, - 111,110,115,32,102,111,114,32,97,32,98,121,116,101,99,111, - 100,101,32,102,105,108,101,46,114,60,0,0,0,233,128,0, - 0,0,41,3,114,49,0,0,0,114,51,0,0,0,114,50, - 0,0,0,41,2,114,44,0,0,0,114,52,0,0,0,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,218,10, - 95,99,97,108,99,95,109,111,100,101,174,1,0,0,115,12, - 0,0,0,0,2,2,1,14,1,14,1,10,3,8,1,114, - 115,0,0,0,99,1,0,0,0,0,0,0,0,3,0,0, - 0,8,0,0,0,3,0,0,0,115,68,0,0,0,100,6, - 135,0,102,1,100,2,100,3,132,9,125,1,122,10,116,0, - 106,1,125,2,87,0,110,28,4,0,116,2,107,10,114,52, - 1,0,1,0,1,0,100,4,100,5,132,0,125,2,89,0, - 110,2,88,0,124,2,124,1,136,0,131,2,1,0,124,1, - 83,0,41,7,122,252,68,101,99,111,114,97,116,111,114,32, - 116,111,32,118,101,114,105,102,121,32,116,104,97,116,32,116, - 104,101,32,109,111,100,117,108,101,32,98,101,105,110,103,32, - 114,101,113,117,101,115,116,101,100,32,109,97,116,99,104,101, - 115,32,116,104,101,32,111,110,101,32,116,104,101,10,32,32, - 32,32,108,111,97,100,101,114,32,99,97,110,32,104,97,110, - 100,108,101,46,10,10,32,32,32,32,84,104,101,32,102,105, - 114,115,116,32,97,114,103,117,109,101,110,116,32,40,115,101, - 108,102,41,32,109,117,115,116,32,100,101,102,105,110,101,32, - 95,110,97,109,101,32,119,104,105,99,104,32,116,104,101,32, - 115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,32, - 105,115,10,32,32,32,32,99,111,109,112,97,114,101,100,32, - 97,103,97,105,110,115,116,46,32,73,102,32,116,104,101,32, - 99,111,109,112,97,114,105,115,111,110,32,102,97,105,108,115, - 32,116,104,101,110,32,73,109,112,111,114,116,69,114,114,111, - 114,32,105,115,32,114,97,105,115,101,100,46,10,10,32,32, - 32,32,78,99,2,0,0,0,0,0,0,0,4,0,0,0, - 4,0,0,0,31,0,0,0,115,66,0,0,0,124,1,100, - 0,107,8,114,16,124,0,106,0,125,1,110,32,124,0,106, - 0,124,1,107,3,114,48,116,1,100,1,124,0,106,0,124, - 1,102,2,22,0,124,1,100,2,141,2,130,1,136,0,124, - 0,124,1,102,2,124,2,158,2,124,3,142,1,83,0,41, - 3,78,122,30,108,111,97,100,101,114,32,102,111,114,32,37, - 115,32,99,97,110,110,111,116,32,104,97,110,100,108,101,32, - 37,115,169,1,218,4,110,97,109,101,41,2,114,117,0,0, - 0,218,11,73,109,112,111,114,116,69,114,114,111,114,41,4, - 218,4,115,101,108,102,114,117,0,0,0,218,4,97,114,103, - 115,90,6,107,119,97,114,103,115,169,1,218,6,109,101,116, - 104,111,100,114,3,0,0,0,114,6,0,0,0,218,19,95, - 99,104,101,99,107,95,110,97,109,101,95,119,114,97,112,112, - 101,114,194,1,0,0,115,18,0,0,0,0,1,8,1,8, - 1,10,1,4,1,8,255,2,1,2,255,6,2,122,40,95, - 99,104,101,99,107,95,110,97,109,101,46,60,108,111,99,97, - 108,115,62,46,95,99,104,101,99,107,95,110,97,109,101,95, - 119,114,97,112,112,101,114,99,2,0,0,0,0,0,0,0, + 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,8,0,0,0,67,0,0,0,115,52,0,0, + 0,122,14,116,0,124,0,131,1,106,1,125,1,87,0,110, + 24,4,0,116,2,107,10,114,38,1,0,1,0,1,0,100, + 1,125,1,89,0,110,2,88,0,124,1,100,2,79,0,125, + 1,124,1,83,0,41,3,122,51,67,97,108,99,117,108,97, + 116,101,32,116,104,101,32,109,111,100,101,32,112,101,114,109, + 105,115,115,105,111,110,115,32,102,111,114,32,97,32,98,121, + 116,101,99,111,100,101,32,102,105,108,101,46,114,60,0,0, + 0,233,128,0,0,0,41,3,114,49,0,0,0,114,51,0, + 0,0,114,50,0,0,0,41,2,114,44,0,0,0,114,52, + 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, + 0,0,218,10,95,99,97,108,99,95,109,111,100,101,175,1, + 0,0,115,12,0,0,0,0,2,2,1,14,1,14,1,10, + 3,8,1,114,115,0,0,0,99,1,0,0,0,0,0,0, + 0,0,0,0,0,3,0,0,0,8,0,0,0,3,0,0, + 0,115,68,0,0,0,100,6,135,0,102,1,100,2,100,3, + 132,9,125,1,122,10,116,0,106,1,125,2,87,0,110,28, + 4,0,116,2,107,10,114,52,1,0,1,0,1,0,100,4, + 100,5,132,0,125,2,89,0,110,2,88,0,124,2,124,1, + 136,0,131,2,1,0,124,1,83,0,41,7,122,252,68,101, + 99,111,114,97,116,111,114,32,116,111,32,118,101,114,105,102, + 121,32,116,104,97,116,32,116,104,101,32,109,111,100,117,108, + 101,32,98,101,105,110,103,32,114,101,113,117,101,115,116,101, + 100,32,109,97,116,99,104,101,115,32,116,104,101,32,111,110, + 101,32,116,104,101,10,32,32,32,32,108,111,97,100,101,114, + 32,99,97,110,32,104,97,110,100,108,101,46,10,10,32,32, + 32,32,84,104,101,32,102,105,114,115,116,32,97,114,103,117, + 109,101,110,116,32,40,115,101,108,102,41,32,109,117,115,116, + 32,100,101,102,105,110,101,32,95,110,97,109,101,32,119,104, + 105,99,104,32,116,104,101,32,115,101,99,111,110,100,32,97, + 114,103,117,109,101,110,116,32,105,115,10,32,32,32,32,99, + 111,109,112,97,114,101,100,32,97,103,97,105,110,115,116,46, + 32,73,102,32,116,104,101,32,99,111,109,112,97,114,105,115, + 111,110,32,102,97,105,108,115,32,116,104,101,110,32,73,109, + 112,111,114,116,69,114,114,111,114,32,105,115,32,114,97,105, + 115,101,100,46,10,10,32,32,32,32,78,99,2,0,0,0, + 0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, + 31,0,0,0,115,66,0,0,0,124,1,100,0,107,8,114, + 16,124,0,106,0,125,1,110,32,124,0,106,0,124,1,107, + 3,114,48,116,1,100,1,124,0,106,0,124,1,102,2,22, + 0,124,1,100,2,141,2,130,1,136,0,124,0,124,1,102, + 2,124,2,158,2,124,3,142,1,83,0,41,3,78,122,30, + 108,111,97,100,101,114,32,102,111,114,32,37,115,32,99,97, + 110,110,111,116,32,104,97,110,100,108,101,32,37,115,169,1, + 218,4,110,97,109,101,41,2,114,117,0,0,0,218,11,73, + 109,112,111,114,116,69,114,114,111,114,41,4,218,4,115,101, + 108,102,114,117,0,0,0,218,4,97,114,103,115,90,6,107, + 119,97,114,103,115,169,1,218,6,109,101,116,104,111,100,114, + 3,0,0,0,114,6,0,0,0,218,19,95,99,104,101,99, + 107,95,110,97,109,101,95,119,114,97,112,112,101,114,195,1, + 0,0,115,18,0,0,0,0,1,8,1,8,1,10,1,4, + 1,8,255,2,1,2,255,6,2,122,40,95,99,104,101,99, + 107,95,110,97,109,101,46,60,108,111,99,97,108,115,62,46, + 95,99,104,101,99,107,95,110,97,109,101,95,119,114,97,112, + 112,101,114,99,2,0,0,0,0,0,0,0,0,0,0,0, 3,0,0,0,7,0,0,0,83,0,0,0,115,56,0,0, 0,100,1,68,0,93,32,125,2,116,0,124,1,124,2,131, 2,114,4,116,1,124,0,124,2,116,2,124,1,124,2,131, @@ -588,165 +594,166 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 95,95,218,6,117,112,100,97,116,101,41,3,90,3,110,101, 119,90,3,111,108,100,114,67,0,0,0,114,3,0,0,0, 114,3,0,0,0,114,6,0,0,0,218,5,95,119,114,97, - 112,205,1,0,0,115,8,0,0,0,0,1,8,1,10,1, + 112,206,1,0,0,115,8,0,0,0,0,1,8,1,10,1, 20,1,122,26,95,99,104,101,99,107,95,110,97,109,101,46, 60,108,111,99,97,108,115,62,46,95,119,114,97,112,41,1, 78,41,3,218,10,95,98,111,111,116,115,116,114,97,112,114, 133,0,0,0,218,9,78,97,109,101,69,114,114,111,114,41, 3,114,122,0,0,0,114,123,0,0,0,114,133,0,0,0, 114,3,0,0,0,114,121,0,0,0,114,6,0,0,0,218, - 11,95,99,104,101,99,107,95,110,97,109,101,186,1,0,0, + 11,95,99,104,101,99,107,95,110,97,109,101,187,1,0,0, 115,14,0,0,0,0,8,14,7,2,1,10,1,14,2,14, 5,10,1,114,136,0,0,0,99,2,0,0,0,0,0,0, - 0,5,0,0,0,6,0,0,0,67,0,0,0,115,60,0, - 0,0,124,0,160,0,124,1,161,1,92,2,125,2,125,3, - 124,2,100,1,107,8,114,56,116,1,124,3,131,1,114,56, - 100,2,125,4,116,2,160,3,124,4,160,4,124,3,100,3, - 25,0,161,1,116,5,161,2,1,0,124,2,83,0,41,4, - 122,155,84,114,121,32,116,111,32,102,105,110,100,32,97,32, - 108,111,97,100,101,114,32,102,111,114,32,116,104,101,32,115, - 112,101,99,105,102,105,101,100,32,109,111,100,117,108,101,32, - 98,121,32,100,101,108,101,103,97,116,105,110,103,32,116,111, - 10,32,32,32,32,115,101,108,102,46,102,105,110,100,95,108, - 111,97,100,101,114,40,41,46,10,10,32,32,32,32,84,104, - 105,115,32,109,101,116,104,111,100,32,105,115,32,100,101,112, - 114,101,99,97,116,101,100,32,105,110,32,102,97,118,111,114, - 32,111,102,32,102,105,110,100,101,114,46,102,105,110,100,95, - 115,112,101,99,40,41,46,10,10,32,32,32,32,78,122,44, - 78,111,116,32,105,109,112,111,114,116,105,110,103,32,100,105, - 114,101,99,116,111,114,121,32,123,125,58,32,109,105,115,115, - 105,110,103,32,95,95,105,110,105,116,95,95,114,73,0,0, - 0,41,6,218,11,102,105,110,100,95,108,111,97,100,101,114, - 114,22,0,0,0,114,75,0,0,0,114,76,0,0,0,114, - 62,0,0,0,218,13,73,109,112,111,114,116,87,97,114,110, - 105,110,103,41,5,114,119,0,0,0,218,8,102,117,108,108, - 110,97,109,101,218,6,108,111,97,100,101,114,218,8,112,111, - 114,116,105,111,110,115,218,3,109,115,103,114,3,0,0,0, - 114,3,0,0,0,114,6,0,0,0,218,17,95,102,105,110, - 100,95,109,111,100,117,108,101,95,115,104,105,109,214,1,0, - 0,115,10,0,0,0,0,10,14,1,16,1,4,1,22,1, - 114,143,0,0,0,99,3,0,0,0,0,0,0,0,6,0, - 0,0,4,0,0,0,67,0,0,0,115,158,0,0,0,124, - 0,100,1,100,2,133,2,25,0,125,3,124,3,116,0,107, - 3,114,60,100,3,124,1,155,2,100,4,124,3,155,2,157, - 4,125,4,116,1,160,2,100,5,124,4,161,2,1,0,116, - 3,124,4,102,1,124,2,142,1,130,1,116,4,124,0,131, - 1,100,6,107,0,114,102,100,7,124,1,155,2,157,2,125, - 4,116,1,160,2,100,5,124,4,161,2,1,0,116,5,124, - 4,131,1,130,1,116,6,124,0,100,2,100,8,133,2,25, - 0,131,1,125,5,124,5,100,9,64,0,114,154,100,10,124, - 5,155,2,100,11,124,1,155,2,157,4,125,4,116,3,124, - 4,102,1,124,2,142,1,130,1,124,5,83,0,41,12,97, - 84,2,0,0,80,101,114,102,111,114,109,32,98,97,115,105, - 99,32,118,97,108,105,100,105,116,121,32,99,104,101,99,107, - 105,110,103,32,111,102,32,97,32,112,121,99,32,104,101,97, - 100,101,114,32,97,110,100,32,114,101,116,117,114,110,32,116, - 104,101,32,102,108,97,103,115,32,102,105,101,108,100,44,10, - 32,32,32,32,119,104,105,99,104,32,100,101,116,101,114,109, - 105,110,101,115,32,104,111,119,32,116,104,101,32,112,121,99, - 32,115,104,111,117,108,100,32,98,101,32,102,117,114,116,104, - 101,114,32,118,97,108,105,100,97,116,101,100,32,97,103,97, - 105,110,115,116,32,116,104,101,32,115,111,117,114,99,101,46, - 10,10,32,32,32,32,42,100,97,116,97,42,32,105,115,32, - 116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32, - 116,104,101,32,112,121,99,32,102,105,108,101,46,32,40,79, - 110,108,121,32,116,104,101,32,102,105,114,115,116,32,49,54, - 32,98,121,116,101,115,32,97,114,101,10,32,32,32,32,114, - 101,113,117,105,114,101,100,44,32,116,104,111,117,103,104,46, - 41,10,10,32,32,32,32,42,110,97,109,101,42,32,105,115, - 32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101, - 32,109,111,100,117,108,101,32,98,101,105,110,103,32,105,109, - 112,111,114,116,101,100,46,32,73,116,32,105,115,32,117,115, - 101,100,32,102,111,114,32,108,111,103,103,105,110,103,46,10, - 10,32,32,32,32,42,101,120,99,95,100,101,116,97,105,108, - 115,42,32,105,115,32,97,32,100,105,99,116,105,111,110,97, - 114,121,32,112,97,115,115,101,100,32,116,111,32,73,109,112, - 111,114,116,69,114,114,111,114,32,105,102,32,105,116,32,114, - 97,105,115,101,100,32,102,111,114,10,32,32,32,32,105,109, - 112,114,111,118,101,100,32,100,101,98,117,103,103,105,110,103, - 46,10,10,32,32,32,32,73,109,112,111,114,116,69,114,114, - 111,114,32,105,115,32,114,97,105,115,101,100,32,119,104,101, - 110,32,116,104,101,32,109,97,103,105,99,32,110,117,109,98, - 101,114,32,105,115,32,105,110,99,111,114,114,101,99,116,32, - 111,114,32,119,104,101,110,32,116,104,101,32,102,108,97,103, - 115,10,32,32,32,32,102,105,101,108,100,32,105,115,32,105, - 110,118,97,108,105,100,46,32,69,79,70,69,114,114,111,114, - 32,105,115,32,114,97,105,115,101,100,32,119,104,101,110,32, - 116,104,101,32,100,97,116,97,32,105,115,32,102,111,117,110, - 100,32,116,111,32,98,101,32,116,114,117,110,99,97,116,101, - 100,46,10,10,32,32,32,32,78,114,15,0,0,0,122,20, - 98,97,100,32,109,97,103,105,99,32,110,117,109,98,101,114, - 32,105,110,32,122,2,58,32,250,2,123,125,233,16,0,0, - 0,122,40,114,101,97,99,104,101,100,32,69,79,70,32,119, - 104,105,108,101,32,114,101,97,100,105,110,103,32,112,121,99, - 32,104,101,97,100,101,114,32,111,102,32,233,8,0,0,0, - 233,252,255,255,255,122,14,105,110,118,97,108,105,100,32,102, - 108,97,103,115,32,122,4,32,105,110,32,41,7,218,12,77, - 65,71,73,67,95,78,85,77,66,69,82,114,134,0,0,0, - 218,16,95,118,101,114,98,111,115,101,95,109,101,115,115,97, - 103,101,114,118,0,0,0,114,22,0,0,0,218,8,69,79, - 70,69,114,114,111,114,114,27,0,0,0,41,6,114,26,0, - 0,0,114,117,0,0,0,218,11,101,120,99,95,100,101,116, - 97,105,108,115,90,5,109,97,103,105,99,114,93,0,0,0, - 114,83,0,0,0,114,3,0,0,0,114,3,0,0,0,114, - 6,0,0,0,218,13,95,99,108,97,115,115,105,102,121,95, - 112,121,99,231,1,0,0,115,28,0,0,0,0,16,12,1, - 8,1,16,1,12,1,12,1,12,1,10,1,12,1,8,1, - 16,2,8,1,16,1,12,1,114,152,0,0,0,99,5,0, + 0,0,0,0,0,5,0,0,0,6,0,0,0,67,0,0, + 0,115,60,0,0,0,124,0,160,0,124,1,161,1,92,2, + 125,2,125,3,124,2,100,1,107,8,114,56,116,1,124,3, + 131,1,114,56,100,2,125,4,116,2,160,3,124,4,160,4, + 124,3,100,3,25,0,161,1,116,5,161,2,1,0,124,2, + 83,0,41,4,122,155,84,114,121,32,116,111,32,102,105,110, + 100,32,97,32,108,111,97,100,101,114,32,102,111,114,32,116, + 104,101,32,115,112,101,99,105,102,105,101,100,32,109,111,100, + 117,108,101,32,98,121,32,100,101,108,101,103,97,116,105,110, + 103,32,116,111,10,32,32,32,32,115,101,108,102,46,102,105, + 110,100,95,108,111,97,100,101,114,40,41,46,10,10,32,32, + 32,32,84,104,105,115,32,109,101,116,104,111,100,32,105,115, + 32,100,101,112,114,101,99,97,116,101,100,32,105,110,32,102, + 97,118,111,114,32,111,102,32,102,105,110,100,101,114,46,102, + 105,110,100,95,115,112,101,99,40,41,46,10,10,32,32,32, + 32,78,122,44,78,111,116,32,105,109,112,111,114,116,105,110, + 103,32,100,105,114,101,99,116,111,114,121,32,123,125,58,32, + 109,105,115,115,105,110,103,32,95,95,105,110,105,116,95,95, + 114,73,0,0,0,41,6,218,11,102,105,110,100,95,108,111, + 97,100,101,114,114,22,0,0,0,114,75,0,0,0,114,76, + 0,0,0,114,62,0,0,0,218,13,73,109,112,111,114,116, + 87,97,114,110,105,110,103,41,5,114,119,0,0,0,218,8, + 102,117,108,108,110,97,109,101,218,6,108,111,97,100,101,114, + 218,8,112,111,114,116,105,111,110,115,218,3,109,115,103,114, + 3,0,0,0,114,3,0,0,0,114,6,0,0,0,218,17, + 95,102,105,110,100,95,109,111,100,117,108,101,95,115,104,105, + 109,215,1,0,0,115,10,0,0,0,0,10,14,1,16,1, + 4,1,22,1,114,143,0,0,0,99,3,0,0,0,0,0, 0,0,0,0,0,0,6,0,0,0,4,0,0,0,67,0, - 0,0,115,112,0,0,0,116,0,124,0,100,1,100,2,133, - 2,25,0,131,1,124,1,100,3,64,0,107,3,114,58,100, - 4,124,3,155,2,157,2,125,5,116,1,160,2,100,5,124, - 5,161,2,1,0,116,3,124,5,102,1,124,4,142,1,130, - 1,124,2,100,6,107,9,114,108,116,0,124,0,100,2,100, - 7,133,2,25,0,131,1,124,2,100,3,64,0,107,3,114, - 108,116,3,100,4,124,3,155,2,157,2,102,1,124,4,142, - 1,130,1,100,6,83,0,41,8,97,7,2,0,0,86,97, - 108,105,100,97,116,101,32,97,32,112,121,99,32,97,103,97, - 105,110,115,116,32,116,104,101,32,115,111,117,114,99,101,32, - 108,97,115,116,45,109,111,100,105,102,105,101,100,32,116,105, - 109,101,46,10,10,32,32,32,32,42,100,97,116,97,42,32, - 105,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32, - 111,102,32,116,104,101,32,112,121,99,32,102,105,108,101,46, - 32,40,79,110,108,121,32,116,104,101,32,102,105,114,115,116, - 32,49,54,32,98,121,116,101,115,32,97,114,101,10,32,32, - 32,32,114,101,113,117,105,114,101,100,46,41,10,10,32,32, - 32,32,42,115,111,117,114,99,101,95,109,116,105,109,101,42, - 32,105,115,32,116,104,101,32,108,97,115,116,32,109,111,100, - 105,102,105,101,100,32,116,105,109,101,115,116,97,109,112,32, - 111,102,32,116,104,101,32,115,111,117,114,99,101,32,102,105, - 108,101,46,10,10,32,32,32,32,42,115,111,117,114,99,101, - 95,115,105,122,101,42,32,105,115,32,78,111,110,101,32,111, - 114,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104, - 101,32,115,111,117,114,99,101,32,102,105,108,101,32,105,110, - 32,98,121,116,101,115,46,10,10,32,32,32,32,42,110,97, - 109,101,42,32,105,115,32,116,104,101,32,110,97,109,101,32, - 111,102,32,116,104,101,32,109,111,100,117,108,101,32,98,101, - 105,110,103,32,105,109,112,111,114,116,101,100,46,32,73,116, - 32,105,115,32,117,115,101,100,32,102,111,114,32,108,111,103, - 103,105,110,103,46,10,10,32,32,32,32,42,101,120,99,95, - 100,101,116,97,105,108,115,42,32,105,115,32,97,32,100,105, - 99,116,105,111,110,97,114,121,32,112,97,115,115,101,100,32, - 116,111,32,73,109,112,111,114,116,69,114,114,111,114,32,105, - 102,32,105,116,32,114,97,105,115,101,100,32,102,111,114,10, - 32,32,32,32,105,109,112,114,111,118,101,100,32,100,101,98, - 117,103,103,105,110,103,46,10,10,32,32,32,32,65,110,32, - 73,109,112,111,114,116,69,114,114,111,114,32,105,115,32,114, - 97,105,115,101,100,32,105,102,32,116,104,101,32,98,121,116, - 101,99,111,100,101,32,105,115,32,115,116,97,108,101,46,10, - 10,32,32,32,32,114,146,0,0,0,233,12,0,0,0,114, - 14,0,0,0,122,22,98,121,116,101,99,111,100,101,32,105, - 115,32,115,116,97,108,101,32,102,111,114,32,114,144,0,0, - 0,78,114,145,0,0,0,41,4,114,27,0,0,0,114,134, - 0,0,0,114,149,0,0,0,114,118,0,0,0,41,6,114, - 26,0,0,0,218,12,115,111,117,114,99,101,95,109,116,105, - 109,101,218,11,115,111,117,114,99,101,95,115,105,122,101,114, - 117,0,0,0,114,151,0,0,0,114,93,0,0,0,114,3, - 0,0,0,114,3,0,0,0,114,6,0,0,0,218,23,95, - 118,97,108,105,100,97,116,101,95,116,105,109,101,115,116,97, - 109,112,95,112,121,99,8,2,0,0,115,16,0,0,0,0, - 19,24,1,10,1,12,1,12,1,8,1,22,255,2,2,114, - 156,0,0,0,99,4,0,0,0,0,0,0,0,4,0,0, + 0,0,115,158,0,0,0,124,0,100,1,100,2,133,2,25, + 0,125,3,124,3,116,0,107,3,114,60,100,3,124,1,155, + 2,100,4,124,3,155,2,157,4,125,4,116,1,160,2,100, + 5,124,4,161,2,1,0,116,3,124,4,102,1,124,2,142, + 1,130,1,116,4,124,0,131,1,100,6,107,0,114,102,100, + 7,124,1,155,2,157,2,125,4,116,1,160,2,100,5,124, + 4,161,2,1,0,116,5,124,4,131,1,130,1,116,6,124, + 0,100,2,100,8,133,2,25,0,131,1,125,5,124,5,100, + 9,64,0,114,154,100,10,124,5,155,2,100,11,124,1,155, + 2,157,4,125,4,116,3,124,4,102,1,124,2,142,1,130, + 1,124,5,83,0,41,12,97,84,2,0,0,80,101,114,102, + 111,114,109,32,98,97,115,105,99,32,118,97,108,105,100,105, + 116,121,32,99,104,101,99,107,105,110,103,32,111,102,32,97, + 32,112,121,99,32,104,101,97,100,101,114,32,97,110,100,32, + 114,101,116,117,114,110,32,116,104,101,32,102,108,97,103,115, + 32,102,105,101,108,100,44,10,32,32,32,32,119,104,105,99, + 104,32,100,101,116,101,114,109,105,110,101,115,32,104,111,119, + 32,116,104,101,32,112,121,99,32,115,104,111,117,108,100,32, + 98,101,32,102,117,114,116,104,101,114,32,118,97,108,105,100, + 97,116,101,100,32,97,103,97,105,110,115,116,32,116,104,101, + 32,115,111,117,114,99,101,46,10,10,32,32,32,32,42,100, + 97,116,97,42,32,105,115,32,116,104,101,32,99,111,110,116, + 101,110,116,115,32,111,102,32,116,104,101,32,112,121,99,32, + 102,105,108,101,46,32,40,79,110,108,121,32,116,104,101,32, + 102,105,114,115,116,32,49,54,32,98,121,116,101,115,32,97, + 114,101,10,32,32,32,32,114,101,113,117,105,114,101,100,44, + 32,116,104,111,117,103,104,46,41,10,10,32,32,32,32,42, + 110,97,109,101,42,32,105,115,32,116,104,101,32,110,97,109, + 101,32,111,102,32,116,104,101,32,109,111,100,117,108,101,32, + 98,101,105,110,103,32,105,109,112,111,114,116,101,100,46,32, + 73,116,32,105,115,32,117,115,101,100,32,102,111,114,32,108, + 111,103,103,105,110,103,46,10,10,32,32,32,32,42,101,120, + 99,95,100,101,116,97,105,108,115,42,32,105,115,32,97,32, + 100,105,99,116,105,111,110,97,114,121,32,112,97,115,115,101, + 100,32,116,111,32,73,109,112,111,114,116,69,114,114,111,114, + 32,105,102,32,105,116,32,114,97,105,115,101,100,32,102,111, + 114,10,32,32,32,32,105,109,112,114,111,118,101,100,32,100, + 101,98,117,103,103,105,110,103,46,10,10,32,32,32,32,73, + 109,112,111,114,116,69,114,114,111,114,32,105,115,32,114,97, + 105,115,101,100,32,119,104,101,110,32,116,104,101,32,109,97, + 103,105,99,32,110,117,109,98,101,114,32,105,115,32,105,110, + 99,111,114,114,101,99,116,32,111,114,32,119,104,101,110,32, + 116,104,101,32,102,108,97,103,115,10,32,32,32,32,102,105, + 101,108,100,32,105,115,32,105,110,118,97,108,105,100,46,32, + 69,79,70,69,114,114,111,114,32,105,115,32,114,97,105,115, + 101,100,32,119,104,101,110,32,116,104,101,32,100,97,116,97, + 32,105,115,32,102,111,117,110,100,32,116,111,32,98,101,32, + 116,114,117,110,99,97,116,101,100,46,10,10,32,32,32,32, + 78,114,15,0,0,0,122,20,98,97,100,32,109,97,103,105, + 99,32,110,117,109,98,101,114,32,105,110,32,122,2,58,32, + 250,2,123,125,233,16,0,0,0,122,40,114,101,97,99,104, + 101,100,32,69,79,70,32,119,104,105,108,101,32,114,101,97, + 100,105,110,103,32,112,121,99,32,104,101,97,100,101,114,32, + 111,102,32,233,8,0,0,0,233,252,255,255,255,122,14,105, + 110,118,97,108,105,100,32,102,108,97,103,115,32,122,4,32, + 105,110,32,41,7,218,12,77,65,71,73,67,95,78,85,77, + 66,69,82,114,134,0,0,0,218,16,95,118,101,114,98,111, + 115,101,95,109,101,115,115,97,103,101,114,118,0,0,0,114, + 22,0,0,0,218,8,69,79,70,69,114,114,111,114,114,27, + 0,0,0,41,6,114,26,0,0,0,114,117,0,0,0,218, + 11,101,120,99,95,100,101,116,97,105,108,115,90,5,109,97, + 103,105,99,114,93,0,0,0,114,83,0,0,0,114,3,0, + 0,0,114,3,0,0,0,114,6,0,0,0,218,13,95,99, + 108,97,115,115,105,102,121,95,112,121,99,232,1,0,0,115, + 28,0,0,0,0,16,12,1,8,1,16,1,12,1,12,1, + 12,1,10,1,12,1,8,1,16,2,8,1,16,1,12,1, + 114,152,0,0,0,99,5,0,0,0,0,0,0,0,0,0, + 0,0,6,0,0,0,4,0,0,0,67,0,0,0,115,112, + 0,0,0,116,0,124,0,100,1,100,2,133,2,25,0,131, + 1,124,1,100,3,64,0,107,3,114,58,100,4,124,3,155, + 2,157,2,125,5,116,1,160,2,100,5,124,5,161,2,1, + 0,116,3,124,5,102,1,124,4,142,1,130,1,124,2,100, + 6,107,9,114,108,116,0,124,0,100,2,100,7,133,2,25, + 0,131,1,124,2,100,3,64,0,107,3,114,108,116,3,100, + 4,124,3,155,2,157,2,102,1,124,4,142,1,130,1,100, + 6,83,0,41,8,97,7,2,0,0,86,97,108,105,100,97, + 116,101,32,97,32,112,121,99,32,97,103,97,105,110,115,116, + 32,116,104,101,32,115,111,117,114,99,101,32,108,97,115,116, + 45,109,111,100,105,102,105,101,100,32,116,105,109,101,46,10, + 10,32,32,32,32,42,100,97,116,97,42,32,105,115,32,116, + 104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116, + 104,101,32,112,121,99,32,102,105,108,101,46,32,40,79,110, + 108,121,32,116,104,101,32,102,105,114,115,116,32,49,54,32, + 98,121,116,101,115,32,97,114,101,10,32,32,32,32,114,101, + 113,117,105,114,101,100,46,41,10,10,32,32,32,32,42,115, + 111,117,114,99,101,95,109,116,105,109,101,42,32,105,115,32, + 116,104,101,32,108,97,115,116,32,109,111,100,105,102,105,101, + 100,32,116,105,109,101,115,116,97,109,112,32,111,102,32,116, + 104,101,32,115,111,117,114,99,101,32,102,105,108,101,46,10, + 10,32,32,32,32,42,115,111,117,114,99,101,95,115,105,122, + 101,42,32,105,115,32,78,111,110,101,32,111,114,32,116,104, + 101,32,115,105,122,101,32,111,102,32,116,104,101,32,115,111, + 117,114,99,101,32,102,105,108,101,32,105,110,32,98,121,116, + 101,115,46,10,10,32,32,32,32,42,110,97,109,101,42,32, + 105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116, + 104,101,32,109,111,100,117,108,101,32,98,101,105,110,103,32, + 105,109,112,111,114,116,101,100,46,32,73,116,32,105,115,32, + 117,115,101,100,32,102,111,114,32,108,111,103,103,105,110,103, + 46,10,10,32,32,32,32,42,101,120,99,95,100,101,116,97, + 105,108,115,42,32,105,115,32,97,32,100,105,99,116,105,111, + 110,97,114,121,32,112,97,115,115,101,100,32,116,111,32,73, + 109,112,111,114,116,69,114,114,111,114,32,105,102,32,105,116, + 32,114,97,105,115,101,100,32,102,111,114,10,32,32,32,32, + 105,109,112,114,111,118,101,100,32,100,101,98,117,103,103,105, + 110,103,46,10,10,32,32,32,32,65,110,32,73,109,112,111, + 114,116,69,114,114,111,114,32,105,115,32,114,97,105,115,101, + 100,32,105,102,32,116,104,101,32,98,121,116,101,99,111,100, + 101,32,105,115,32,115,116,97,108,101,46,10,10,32,32,32, + 32,114,146,0,0,0,233,12,0,0,0,114,14,0,0,0, + 122,22,98,121,116,101,99,111,100,101,32,105,115,32,115,116, + 97,108,101,32,102,111,114,32,114,144,0,0,0,78,114,145, + 0,0,0,41,4,114,27,0,0,0,114,134,0,0,0,114, + 149,0,0,0,114,118,0,0,0,41,6,114,26,0,0,0, + 218,12,115,111,117,114,99,101,95,109,116,105,109,101,218,11, + 115,111,117,114,99,101,95,115,105,122,101,114,117,0,0,0, + 114,151,0,0,0,114,93,0,0,0,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,218,23,95,118,97,108,105, + 100,97,116,101,95,116,105,109,101,115,116,97,109,112,95,112, + 121,99,9,2,0,0,115,16,0,0,0,0,19,24,1,10, + 1,12,1,12,1,8,1,22,255,2,2,114,156,0,0,0, + 99,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0, 0,3,0,0,0,67,0,0,0,115,38,0,0,0,124,0, 100,1,100,2,133,2,25,0,124,1,107,3,114,34,116,0, 100,3,124,2,155,2,157,2,102,1,124,3,142,1,130,1, @@ -790,69 +797,70 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 104,97,115,104,114,117,0,0,0,114,151,0,0,0,114,3, 0,0,0,114,3,0,0,0,114,6,0,0,0,218,18,95, 118,97,108,105,100,97,116,101,95,104,97,115,104,95,112,121, - 99,36,2,0,0,115,12,0,0,0,0,17,16,1,2,1, + 99,37,2,0,0,115,12,0,0,0,0,17,16,1,2,1, 8,255,2,2,2,254,114,158,0,0,0,99,4,0,0,0, + 0,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0, + 67,0,0,0,115,82,0,0,0,116,0,160,1,124,0,161, + 1,125,4,116,2,124,4,116,3,131,2,114,58,116,4,160, + 5,100,1,124,2,161,2,1,0,124,3,100,2,107,9,114, + 52,116,6,160,7,124,4,124,3,161,2,1,0,124,4,83, + 0,110,20,116,8,100,3,160,9,124,2,161,1,124,1,124, + 2,100,4,141,3,130,1,100,2,83,0,41,5,122,35,67, + 111,109,112,105,108,101,32,98,121,116,101,99,111,100,101,32, + 97,115,32,102,111,117,110,100,32,105,110,32,97,32,112,121, + 99,46,122,21,99,111,100,101,32,111,98,106,101,99,116,32, + 102,114,111,109,32,123,33,114,125,78,122,23,78,111,110,45, + 99,111,100,101,32,111,98,106,101,99,116,32,105,110,32,123, + 33,114,125,169,2,114,117,0,0,0,114,44,0,0,0,41, + 10,218,7,109,97,114,115,104,97,108,90,5,108,111,97,100, + 115,218,10,105,115,105,110,115,116,97,110,99,101,218,10,95, + 99,111,100,101,95,116,121,112,101,114,134,0,0,0,114,149, + 0,0,0,218,4,95,105,109,112,90,16,95,102,105,120,95, + 99,111,95,102,105,108,101,110,97,109,101,114,118,0,0,0, + 114,62,0,0,0,41,5,114,26,0,0,0,114,117,0,0, + 0,114,107,0,0,0,114,108,0,0,0,218,4,99,111,100, + 101,114,3,0,0,0,114,3,0,0,0,114,6,0,0,0, + 218,17,95,99,111,109,112,105,108,101,95,98,121,116,101,99, + 111,100,101,61,2,0,0,115,20,0,0,0,0,2,10,1, + 10,1,12,1,8,1,12,1,6,2,10,1,2,0,2,255, + 114,165,0,0,0,114,73,0,0,0,99,3,0,0,0,0, + 0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,67, + 0,0,0,115,70,0,0,0,116,0,116,1,131,1,125,3, + 124,3,160,2,116,3,100,1,131,1,161,1,1,0,124,3, + 160,2,116,3,124,1,131,1,161,1,1,0,124,3,160,2, + 116,3,124,2,131,1,161,1,1,0,124,3,160,2,116,4, + 160,5,124,0,161,1,161,1,1,0,124,3,83,0,41,2, + 122,43,80,114,111,100,117,99,101,32,116,104,101,32,100,97, + 116,97,32,102,111,114,32,97,32,116,105,109,101,115,116,97, + 109,112,45,98,97,115,101,100,32,112,121,99,46,114,73,0, + 0,0,41,6,218,9,98,121,116,101,97,114,114,97,121,114, + 148,0,0,0,218,6,101,120,116,101,110,100,114,20,0,0, + 0,114,160,0,0,0,218,5,100,117,109,112,115,41,4,114, + 164,0,0,0,218,5,109,116,105,109,101,114,155,0,0,0, + 114,26,0,0,0,114,3,0,0,0,114,3,0,0,0,114, + 6,0,0,0,218,22,95,99,111,100,101,95,116,111,95,116, + 105,109,101,115,116,97,109,112,95,112,121,99,74,2,0,0, + 115,12,0,0,0,0,2,8,1,14,1,14,1,14,1,16, + 1,114,170,0,0,0,84,99,3,0,0,0,0,0,0,0, 0,0,0,0,5,0,0,0,5,0,0,0,67,0,0,0, - 115,82,0,0,0,116,0,160,1,124,0,161,1,125,4,116, - 2,124,4,116,3,131,2,114,58,116,4,160,5,100,1,124, - 2,161,2,1,0,124,3,100,2,107,9,114,52,116,6,160, - 7,124,4,124,3,161,2,1,0,124,4,83,0,110,20,116, - 8,100,3,160,9,124,2,161,1,124,1,124,2,100,4,141, - 3,130,1,100,2,83,0,41,5,122,35,67,111,109,112,105, - 108,101,32,98,121,116,101,99,111,100,101,32,97,115,32,102, - 111,117,110,100,32,105,110,32,97,32,112,121,99,46,122,21, - 99,111,100,101,32,111,98,106,101,99,116,32,102,114,111,109, - 32,123,33,114,125,78,122,23,78,111,110,45,99,111,100,101, - 32,111,98,106,101,99,116,32,105,110,32,123,33,114,125,169, - 2,114,117,0,0,0,114,44,0,0,0,41,10,218,7,109, - 97,114,115,104,97,108,90,5,108,111,97,100,115,218,10,105, - 115,105,110,115,116,97,110,99,101,218,10,95,99,111,100,101, - 95,116,121,112,101,114,134,0,0,0,114,149,0,0,0,218, - 4,95,105,109,112,90,16,95,102,105,120,95,99,111,95,102, - 105,108,101,110,97,109,101,114,118,0,0,0,114,62,0,0, - 0,41,5,114,26,0,0,0,114,117,0,0,0,114,107,0, - 0,0,114,108,0,0,0,218,4,99,111,100,101,114,3,0, - 0,0,114,3,0,0,0,114,6,0,0,0,218,17,95,99, - 111,109,112,105,108,101,95,98,121,116,101,99,111,100,101,60, - 2,0,0,115,20,0,0,0,0,2,10,1,10,1,12,1, - 8,1,12,1,6,2,10,1,2,0,2,255,114,165,0,0, - 0,114,73,0,0,0,99,3,0,0,0,0,0,0,0,4, - 0,0,0,5,0,0,0,67,0,0,0,115,70,0,0,0, - 116,0,116,1,131,1,125,3,124,3,160,2,116,3,100,1, - 131,1,161,1,1,0,124,3,160,2,116,3,124,1,131,1, - 161,1,1,0,124,3,160,2,116,3,124,2,131,1,161,1, - 1,0,124,3,160,2,116,4,160,5,124,0,161,1,161,1, - 1,0,124,3,83,0,41,2,122,43,80,114,111,100,117,99, - 101,32,116,104,101,32,100,97,116,97,32,102,111,114,32,97, - 32,116,105,109,101,115,116,97,109,112,45,98,97,115,101,100, - 32,112,121,99,46,114,73,0,0,0,41,6,218,9,98,121, - 116,101,97,114,114,97,121,114,148,0,0,0,218,6,101,120, - 116,101,110,100,114,20,0,0,0,114,160,0,0,0,218,5, - 100,117,109,112,115,41,4,114,164,0,0,0,218,5,109,116, - 105,109,101,114,155,0,0,0,114,26,0,0,0,114,3,0, - 0,0,114,3,0,0,0,114,6,0,0,0,218,22,95,99, - 111,100,101,95,116,111,95,116,105,109,101,115,116,97,109,112, - 95,112,121,99,73,2,0,0,115,12,0,0,0,0,2,8, - 1,14,1,14,1,14,1,16,1,114,170,0,0,0,84,99, - 3,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0, - 67,0,0,0,115,80,0,0,0,116,0,116,1,131,1,125, - 3,100,1,124,2,100,1,62,0,66,0,125,4,124,3,160, - 2,116,3,124,4,131,1,161,1,1,0,116,4,124,1,131, - 1,100,2,107,2,115,50,116,5,130,1,124,3,160,2,124, - 1,161,1,1,0,124,3,160,2,116,6,160,7,124,0,161, - 1,161,1,1,0,124,3,83,0,41,3,122,38,80,114,111, - 100,117,99,101,32,116,104,101,32,100,97,116,97,32,102,111, - 114,32,97,32,104,97,115,104,45,98,97,115,101,100,32,112, - 121,99,46,114,39,0,0,0,114,146,0,0,0,41,8,114, - 166,0,0,0,114,148,0,0,0,114,167,0,0,0,114,20, - 0,0,0,114,22,0,0,0,114,23,0,0,0,114,160,0, - 0,0,114,168,0,0,0,41,5,114,164,0,0,0,114,157, - 0,0,0,90,7,99,104,101,99,107,101,100,114,26,0,0, - 0,114,83,0,0,0,114,3,0,0,0,114,3,0,0,0, - 114,6,0,0,0,218,17,95,99,111,100,101,95,116,111,95, - 104,97,115,104,95,112,121,99,83,2,0,0,115,14,0,0, - 0,0,2,8,1,12,1,14,1,16,1,10,1,16,1,114, - 171,0,0,0,99,1,0,0,0,0,0,0,0,5,0,0, + 115,80,0,0,0,116,0,116,1,131,1,125,3,100,1,124, + 2,100,1,62,0,66,0,125,4,124,3,160,2,116,3,124, + 4,131,1,161,1,1,0,116,4,124,1,131,1,100,2,107, + 2,115,50,116,5,130,1,124,3,160,2,124,1,161,1,1, + 0,124,3,160,2,116,6,160,7,124,0,161,1,161,1,1, + 0,124,3,83,0,41,3,122,38,80,114,111,100,117,99,101, + 32,116,104,101,32,100,97,116,97,32,102,111,114,32,97,32, + 104,97,115,104,45,98,97,115,101,100,32,112,121,99,46,114, + 39,0,0,0,114,146,0,0,0,41,8,114,166,0,0,0, + 114,148,0,0,0,114,167,0,0,0,114,20,0,0,0,114, + 22,0,0,0,114,23,0,0,0,114,160,0,0,0,114,168, + 0,0,0,41,5,114,164,0,0,0,114,157,0,0,0,90, + 7,99,104,101,99,107,101,100,114,26,0,0,0,114,83,0, + 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, + 0,218,17,95,99,111,100,101,95,116,111,95,104,97,115,104, + 95,112,121,99,84,2,0,0,115,14,0,0,0,0,2,8, + 1,12,1,14,1,16,1,10,1,16,1,114,171,0,0,0, + 99,1,0,0,0,0,0,0,0,0,0,0,0,5,0,0, 0,6,0,0,0,67,0,0,0,115,62,0,0,0,100,1, 100,2,108,0,125,1,116,1,160,2,124,0,161,1,106,3, 125,2,124,1,160,4,124,2,161,1,125,3,116,1,160,5, @@ -877,110 +885,111 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 108,105,110,101,218,8,101,110,99,111,100,105,110,103,90,15, 110,101,119,108,105,110,101,95,100,101,99,111,100,101,114,114, 3,0,0,0,114,3,0,0,0,114,6,0,0,0,218,13, - 100,101,99,111,100,101,95,115,111,117,114,99,101,94,2,0, + 100,101,99,111,100,101,95,115,111,117,114,99,101,95,2,0, 0,115,10,0,0,0,0,5,8,1,12,1,10,1,12,1, 114,176,0,0,0,169,2,114,140,0,0,0,218,26,115,117, 98,109,111,100,117,108,101,95,115,101,97,114,99,104,95,108, - 111,99,97,116,105,111,110,115,99,2,0,0,0,2,0,0, - 0,9,0,0,0,8,0,0,0,67,0,0,0,115,16,1, - 0,0,124,1,100,1,107,8,114,60,100,2,125,1,116,0, - 124,2,100,3,131,2,114,70,122,14,124,2,160,1,124,0, - 161,1,125,1,87,0,113,70,4,0,116,2,107,10,114,56, - 1,0,1,0,1,0,89,0,113,70,88,0,110,10,116,3, - 160,4,124,1,161,1,125,1,116,5,106,6,124,0,124,2, - 124,1,100,4,141,3,125,4,100,5,124,4,95,7,124,2, - 100,1,107,8,114,154,116,8,131,0,68,0,93,42,92,2, - 125,5,125,6,124,1,160,9,116,10,124,6,131,1,161,1, - 114,106,124,5,124,0,124,1,131,2,125,2,124,2,124,4, - 95,11,1,0,113,154,113,106,100,1,83,0,124,3,116,12, - 107,8,114,220,116,0,124,2,100,6,131,2,114,226,122,14, - 124,2,160,13,124,0,161,1,125,7,87,0,110,20,4,0, - 116,2,107,10,114,206,1,0,1,0,1,0,89,0,113,226, - 88,0,124,7,114,226,103,0,124,4,95,14,110,6,124,3, - 124,4,95,14,124,4,106,14,103,0,107,2,144,1,114,12, - 124,1,144,1,114,12,116,15,124,1,131,1,100,7,25,0, - 125,8,124,4,106,14,160,16,124,8,161,1,1,0,124,4, - 83,0,41,8,97,61,1,0,0,82,101,116,117,114,110,32, - 97,32,109,111,100,117,108,101,32,115,112,101,99,32,98,97, - 115,101,100,32,111,110,32,97,32,102,105,108,101,32,108,111, - 99,97,116,105,111,110,46,10,10,32,32,32,32,84,111,32, - 105,110,100,105,99,97,116,101,32,116,104,97,116,32,116,104, - 101,32,109,111,100,117,108,101,32,105,115,32,97,32,112,97, - 99,107,97,103,101,44,32,115,101,116,10,32,32,32,32,115, - 117,98,109,111,100,117,108,101,95,115,101,97,114,99,104,95, - 108,111,99,97,116,105,111,110,115,32,116,111,32,97,32,108, - 105,115,116,32,111,102,32,100,105,114,101,99,116,111,114,121, - 32,112,97,116,104,115,46,32,32,65,110,10,32,32,32,32, - 101,109,112,116,121,32,108,105,115,116,32,105,115,32,115,117, - 102,102,105,99,105,101,110,116,44,32,116,104,111,117,103,104, - 32,105,116,115,32,110,111,116,32,111,116,104,101,114,119,105, - 115,101,32,117,115,101,102,117,108,32,116,111,32,116,104,101, - 10,32,32,32,32,105,109,112,111,114,116,32,115,121,115,116, - 101,109,46,10,10,32,32,32,32,84,104,101,32,108,111,97, - 100,101,114,32,109,117,115,116,32,116,97,107,101,32,97,32, - 115,112,101,99,32,97,115,32,105,116,115,32,111,110,108,121, - 32,95,95,105,110,105,116,95,95,40,41,32,97,114,103,46, - 10,10,32,32,32,32,78,122,9,60,117,110,107,110,111,119, - 110,62,218,12,103,101,116,95,102,105,108,101,110,97,109,101, - 169,1,218,6,111,114,105,103,105,110,84,218,10,105,115,95, - 112,97,99,107,97,103,101,114,73,0,0,0,41,17,114,128, - 0,0,0,114,179,0,0,0,114,118,0,0,0,114,2,0, - 0,0,114,79,0,0,0,114,134,0,0,0,218,10,77,111, - 100,117,108,101,83,112,101,99,90,13,95,115,101,116,95,102, - 105,108,101,97,116,116,114,218,27,95,103,101,116,95,115,117, - 112,112,111,114,116,101,100,95,102,105,108,101,95,108,111,97, - 100,101,114,115,114,111,0,0,0,114,112,0,0,0,114,140, - 0,0,0,218,9,95,80,79,80,85,76,65,84,69,114,182, - 0,0,0,114,178,0,0,0,114,47,0,0,0,218,6,97, - 112,112,101,110,100,41,9,114,117,0,0,0,90,8,108,111, - 99,97,116,105,111,110,114,140,0,0,0,114,178,0,0,0, - 218,4,115,112,101,99,218,12,108,111,97,100,101,114,95,99, - 108,97,115,115,218,8,115,117,102,102,105,120,101,115,114,182, - 0,0,0,90,7,100,105,114,110,97,109,101,114,3,0,0, - 0,114,3,0,0,0,114,6,0,0,0,218,23,115,112,101, - 99,95,102,114,111,109,95,102,105,108,101,95,108,111,99,97, - 116,105,111,110,111,2,0,0,115,62,0,0,0,0,12,8, - 4,4,1,10,2,2,1,14,1,14,1,8,2,10,8,16, - 1,6,3,8,1,14,1,14,1,10,1,6,1,6,2,4, - 3,8,2,10,1,2,1,14,1,14,1,6,2,4,1,8, - 2,6,1,12,1,6,1,12,1,12,2,114,190,0,0,0, - 99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, - 0,64,0,0,0,115,86,0,0,0,101,0,90,1,100,0, - 90,2,100,1,90,3,100,2,90,4,100,3,90,5,100,4, - 90,6,101,7,100,5,100,6,132,0,131,1,90,8,101,7, - 100,7,100,8,132,0,131,1,90,9,101,7,100,9,100,9, - 102,2,100,10,100,11,132,1,131,1,90,10,101,7,100,9, - 102,1,100,12,100,13,132,1,131,1,90,11,100,9,83,0, - 41,14,218,21,87,105,110,100,111,119,115,82,101,103,105,115, - 116,114,121,70,105,110,100,101,114,122,62,77,101,116,97,32, - 112,97,116,104,32,102,105,110,100,101,114,32,102,111,114,32, - 109,111,100,117,108,101,115,32,100,101,99,108,97,114,101,100, - 32,105,110,32,116,104,101,32,87,105,110,100,111,119,115,32, - 114,101,103,105,115,116,114,121,46,122,59,83,111,102,116,119, - 97,114,101,92,80,121,116,104,111,110,92,80,121,116,104,111, - 110,67,111,114,101,92,123,115,121,115,95,118,101,114,115,105, - 111,110,125,92,77,111,100,117,108,101,115,92,123,102,117,108, - 108,110,97,109,101,125,122,65,83,111,102,116,119,97,114,101, - 92,80,121,116,104,111,110,92,80,121,116,104,111,110,67,111, - 114,101,92,123,115,121,115,95,118,101,114,115,105,111,110,125, - 92,77,111,100,117,108,101,115,92,123,102,117,108,108,110,97, - 109,101,125,92,68,101,98,117,103,70,99,2,0,0,0,0, - 0,0,0,2,0,0,0,8,0,0,0,67,0,0,0,115, - 56,0,0,0,122,16,116,0,160,1,116,0,106,2,124,1, - 161,2,87,0,83,0,4,0,116,3,107,10,114,50,1,0, - 1,0,1,0,116,0,160,1,116,0,106,4,124,1,161,2, - 6,0,89,0,83,0,88,0,100,0,83,0,114,110,0,0, - 0,41,5,218,7,95,119,105,110,114,101,103,90,7,79,112, - 101,110,75,101,121,90,17,72,75,69,89,95,67,85,82,82, - 69,78,84,95,85,83,69,82,114,50,0,0,0,90,18,72, - 75,69,89,95,76,79,67,65,76,95,77,65,67,72,73,78, - 69,41,2,218,3,99,108,115,114,5,0,0,0,114,3,0, - 0,0,114,3,0,0,0,114,6,0,0,0,218,14,95,111, - 112,101,110,95,114,101,103,105,115,116,114,121,191,2,0,0, - 115,8,0,0,0,0,2,2,1,16,1,14,1,122,36,87, - 105,110,100,111,119,115,82,101,103,105,115,116,114,121,70,105, - 110,100,101,114,46,95,111,112,101,110,95,114,101,103,105,115, - 116,114,121,99,2,0,0,0,0,0,0,0,6,0,0,0, + 111,99,97,116,105,111,110,115,99,2,0,0,0,0,0,0, + 0,2,0,0,0,9,0,0,0,8,0,0,0,67,0,0, + 0,115,16,1,0,0,124,1,100,1,107,8,114,60,100,2, + 125,1,116,0,124,2,100,3,131,2,114,70,122,14,124,2, + 160,1,124,0,161,1,125,1,87,0,113,70,4,0,116,2, + 107,10,114,56,1,0,1,0,1,0,89,0,113,70,88,0, + 110,10,116,3,160,4,124,1,161,1,125,1,116,5,106,6, + 124,0,124,2,124,1,100,4,141,3,125,4,100,5,124,4, + 95,7,124,2,100,1,107,8,114,154,116,8,131,0,68,0, + 93,42,92,2,125,5,125,6,124,1,160,9,116,10,124,6, + 131,1,161,1,114,106,124,5,124,0,124,1,131,2,125,2, + 124,2,124,4,95,11,1,0,113,154,113,106,100,1,83,0, + 124,3,116,12,107,8,114,220,116,0,124,2,100,6,131,2, + 114,226,122,14,124,2,160,13,124,0,161,1,125,7,87,0, + 110,20,4,0,116,2,107,10,114,206,1,0,1,0,1,0, + 89,0,113,226,88,0,124,7,114,226,103,0,124,4,95,14, + 110,6,124,3,124,4,95,14,124,4,106,14,103,0,107,2, + 144,1,114,12,124,1,144,1,114,12,116,15,124,1,131,1, + 100,7,25,0,125,8,124,4,106,14,160,16,124,8,161,1, + 1,0,124,4,83,0,41,8,97,61,1,0,0,82,101,116, + 117,114,110,32,97,32,109,111,100,117,108,101,32,115,112,101, + 99,32,98,97,115,101,100,32,111,110,32,97,32,102,105,108, + 101,32,108,111,99,97,116,105,111,110,46,10,10,32,32,32, + 32,84,111,32,105,110,100,105,99,97,116,101,32,116,104,97, + 116,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32, + 97,32,112,97,99,107,97,103,101,44,32,115,101,116,10,32, + 32,32,32,115,117,98,109,111,100,117,108,101,95,115,101,97, + 114,99,104,95,108,111,99,97,116,105,111,110,115,32,116,111, + 32,97,32,108,105,115,116,32,111,102,32,100,105,114,101,99, + 116,111,114,121,32,112,97,116,104,115,46,32,32,65,110,10, + 32,32,32,32,101,109,112,116,121,32,108,105,115,116,32,105, + 115,32,115,117,102,102,105,99,105,101,110,116,44,32,116,104, + 111,117,103,104,32,105,116,115,32,110,111,116,32,111,116,104, + 101,114,119,105,115,101,32,117,115,101,102,117,108,32,116,111, + 32,116,104,101,10,32,32,32,32,105,109,112,111,114,116,32, + 115,121,115,116,101,109,46,10,10,32,32,32,32,84,104,101, + 32,108,111,97,100,101,114,32,109,117,115,116,32,116,97,107, + 101,32,97,32,115,112,101,99,32,97,115,32,105,116,115,32, + 111,110,108,121,32,95,95,105,110,105,116,95,95,40,41,32, + 97,114,103,46,10,10,32,32,32,32,78,122,9,60,117,110, + 107,110,111,119,110,62,218,12,103,101,116,95,102,105,108,101, + 110,97,109,101,169,1,218,6,111,114,105,103,105,110,84,218, + 10,105,115,95,112,97,99,107,97,103,101,114,73,0,0,0, + 41,17,114,128,0,0,0,114,179,0,0,0,114,118,0,0, + 0,114,2,0,0,0,114,79,0,0,0,114,134,0,0,0, + 218,10,77,111,100,117,108,101,83,112,101,99,90,13,95,115, + 101,116,95,102,105,108,101,97,116,116,114,218,27,95,103,101, + 116,95,115,117,112,112,111,114,116,101,100,95,102,105,108,101, + 95,108,111,97,100,101,114,115,114,111,0,0,0,114,112,0, + 0,0,114,140,0,0,0,218,9,95,80,79,80,85,76,65, + 84,69,114,182,0,0,0,114,178,0,0,0,114,47,0,0, + 0,218,6,97,112,112,101,110,100,41,9,114,117,0,0,0, + 90,8,108,111,99,97,116,105,111,110,114,140,0,0,0,114, + 178,0,0,0,218,4,115,112,101,99,218,12,108,111,97,100, + 101,114,95,99,108,97,115,115,218,8,115,117,102,102,105,120, + 101,115,114,182,0,0,0,90,7,100,105,114,110,97,109,101, + 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,218, + 23,115,112,101,99,95,102,114,111,109,95,102,105,108,101,95, + 108,111,99,97,116,105,111,110,112,2,0,0,115,62,0,0, + 0,0,12,8,4,4,1,10,2,2,1,14,1,14,1,8, + 2,10,8,16,1,6,3,8,1,14,1,14,1,10,1,6, + 1,6,2,4,3,8,2,10,1,2,1,14,1,14,1,6, + 2,4,1,8,2,6,1,12,1,6,1,12,1,12,2,114, + 190,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,4,0,0,0,64,0,0,0,115,86,0, + 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, + 90,4,100,3,90,5,100,4,90,6,101,7,100,5,100,6, + 132,0,131,1,90,8,101,7,100,7,100,8,132,0,131,1, + 90,9,101,7,100,9,100,9,102,2,100,10,100,11,132,1, + 131,1,90,10,101,7,100,9,102,1,100,12,100,13,132,1, + 131,1,90,11,100,9,83,0,41,14,218,21,87,105,110,100, + 111,119,115,82,101,103,105,115,116,114,121,70,105,110,100,101, + 114,122,62,77,101,116,97,32,112,97,116,104,32,102,105,110, + 100,101,114,32,102,111,114,32,109,111,100,117,108,101,115,32, + 100,101,99,108,97,114,101,100,32,105,110,32,116,104,101,32, + 87,105,110,100,111,119,115,32,114,101,103,105,115,116,114,121, + 46,122,59,83,111,102,116,119,97,114,101,92,80,121,116,104, + 111,110,92,80,121,116,104,111,110,67,111,114,101,92,123,115, + 121,115,95,118,101,114,115,105,111,110,125,92,77,111,100,117, + 108,101,115,92,123,102,117,108,108,110,97,109,101,125,122,65, + 83,111,102,116,119,97,114,101,92,80,121,116,104,111,110,92, + 80,121,116,104,111,110,67,111,114,101,92,123,115,121,115,95, + 118,101,114,115,105,111,110,125,92,77,111,100,117,108,101,115, + 92,123,102,117,108,108,110,97,109,101,125,92,68,101,98,117, + 103,70,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,8,0,0,0,67,0,0,0,115,56,0,0,0, + 122,16,116,0,160,1,116,0,106,2,124,1,161,2,87,0, + 83,0,4,0,116,3,107,10,114,50,1,0,1,0,1,0, + 116,0,160,1,116,0,106,4,124,1,161,2,6,0,89,0, + 83,0,88,0,100,0,83,0,114,110,0,0,0,41,5,218, + 7,95,119,105,110,114,101,103,90,7,79,112,101,110,75,101, + 121,90,17,72,75,69,89,95,67,85,82,82,69,78,84,95, + 85,83,69,82,114,50,0,0,0,90,18,72,75,69,89,95, + 76,79,67,65,76,95,77,65,67,72,73,78,69,41,2,218, + 3,99,108,115,114,5,0,0,0,114,3,0,0,0,114,3, + 0,0,0,114,6,0,0,0,218,14,95,111,112,101,110,95, + 114,101,103,105,115,116,114,121,192,2,0,0,115,8,0,0, + 0,0,2,2,1,16,1,14,1,122,36,87,105,110,100,111, + 119,115,82,101,103,105,115,116,114,121,70,105,110,100,101,114, + 46,95,111,112,101,110,95,114,101,103,105,115,116,114,121,99, + 2,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0, 9,0,0,0,67,0,0,0,115,118,0,0,0,124,0,106, 0,114,14,124,0,106,1,125,2,110,6,124,0,106,2,125, 2,124,2,106,3,124,1,100,1,116,4,106,5,100,0,100, @@ -1002,72 +1011,73 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 105,115,116,114,121,95,107,101,121,114,5,0,0,0,90,4, 104,107,101,121,218,8,102,105,108,101,112,97,116,104,114,3, 0,0,0,114,3,0,0,0,114,6,0,0,0,218,16,95, - 115,101,97,114,99,104,95,114,101,103,105,115,116,114,121,198, + 115,101,97,114,99,104,95,114,101,103,105,115,116,114,121,199, 2,0,0,115,24,0,0,0,0,2,6,1,8,2,6,1, 6,1,16,255,6,2,2,1,12,1,26,1,14,1,12,1, 122,38,87,105,110,100,111,119,115,82,101,103,105,115,116,114, 121,70,105,110,100,101,114,46,95,115,101,97,114,99,104,95, 114,101,103,105,115,116,114,121,78,99,4,0,0,0,0,0, - 0,0,8,0,0,0,8,0,0,0,67,0,0,0,115,122, - 0,0,0,124,0,160,0,124,1,161,1,125,4,124,4,100, - 0,107,8,114,22,100,0,83,0,122,12,116,1,124,4,131, - 1,1,0,87,0,110,22,4,0,116,2,107,10,114,56,1, - 0,1,0,1,0,89,0,100,0,83,0,88,0,116,3,131, - 0,68,0,93,52,92,2,125,5,125,6,124,4,160,4,116, - 5,124,6,131,1,161,1,114,64,116,6,106,7,124,1,124, - 5,124,1,124,4,131,2,124,4,100,1,141,3,125,7,124, - 7,2,0,1,0,83,0,113,64,100,0,83,0,41,2,78, - 114,180,0,0,0,41,8,114,200,0,0,0,114,49,0,0, - 0,114,50,0,0,0,114,184,0,0,0,114,111,0,0,0, - 114,112,0,0,0,114,134,0,0,0,218,16,115,112,101,99, - 95,102,114,111,109,95,108,111,97,100,101,114,41,8,114,193, - 0,0,0,114,139,0,0,0,114,44,0,0,0,218,6,116, - 97,114,103,101,116,114,199,0,0,0,114,140,0,0,0,114, - 189,0,0,0,114,187,0,0,0,114,3,0,0,0,114,3, - 0,0,0,114,6,0,0,0,218,9,102,105,110,100,95,115, - 112,101,99,213,2,0,0,115,28,0,0,0,0,2,10,1, - 8,1,4,1,2,1,12,1,14,1,8,1,14,1,14,1, - 6,1,8,1,2,254,6,3,122,31,87,105,110,100,111,119, - 115,82,101,103,105,115,116,114,121,70,105,110,100,101,114,46, - 102,105,110,100,95,115,112,101,99,99,3,0,0,0,0,0, - 0,0,4,0,0,0,4,0,0,0,67,0,0,0,115,34, - 0,0,0,124,0,160,0,124,1,124,2,161,2,125,3,124, - 3,100,1,107,9,114,26,124,3,106,1,83,0,100,1,83, - 0,100,1,83,0,41,2,122,108,70,105,110,100,32,109,111, - 100,117,108,101,32,110,97,109,101,100,32,105,110,32,116,104, - 101,32,114,101,103,105,115,116,114,121,46,10,10,32,32,32, - 32,32,32,32,32,84,104,105,115,32,109,101,116,104,111,100, - 32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32, - 32,85,115,101,32,101,120,101,99,95,109,111,100,117,108,101, - 40,41,32,105,110,115,116,101,97,100,46,10,10,32,32,32, - 32,32,32,32,32,78,169,2,114,203,0,0,0,114,140,0, - 0,0,169,4,114,193,0,0,0,114,139,0,0,0,114,44, - 0,0,0,114,187,0,0,0,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,218,11,102,105,110,100,95,109,111, - 100,117,108,101,229,2,0,0,115,8,0,0,0,0,7,12, - 1,8,1,6,2,122,33,87,105,110,100,111,119,115,82,101, - 103,105,115,116,114,121,70,105,110,100,101,114,46,102,105,110, - 100,95,109,111,100,117,108,101,41,12,114,125,0,0,0,114, - 124,0,0,0,114,126,0,0,0,114,127,0,0,0,114,197, - 0,0,0,114,196,0,0,0,114,195,0,0,0,218,11,99, - 108,97,115,115,109,101,116,104,111,100,114,194,0,0,0,114, - 200,0,0,0,114,203,0,0,0,114,206,0,0,0,114,3, - 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, - 0,0,114,191,0,0,0,179,2,0,0,115,28,0,0,0, - 8,2,4,3,2,255,2,4,2,255,2,3,4,2,2,1, - 10,6,2,1,10,14,2,1,16,15,2,1,114,191,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,64,0,0,0,115,48,0,0,0,101,0,90,1,100, - 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, - 4,100,5,132,0,90,5,100,6,100,7,132,0,90,6,100, - 8,100,9,132,0,90,7,100,10,83,0,41,11,218,13,95, - 76,111,97,100,101,114,66,97,115,105,99,115,122,83,66,97, - 115,101,32,99,108,97,115,115,32,111,102,32,99,111,109,109, - 111,110,32,99,111,100,101,32,110,101,101,100,101,100,32,98, - 121,32,98,111,116,104,32,83,111,117,114,99,101,76,111,97, - 100,101,114,32,97,110,100,10,32,32,32,32,83,111,117,114, - 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, - 46,99,2,0,0,0,0,0,0,0,5,0,0,0,4,0, + 0,0,0,0,0,0,8,0,0,0,8,0,0,0,67,0, + 0,0,115,122,0,0,0,124,0,160,0,124,1,161,1,125, + 4,124,4,100,0,107,8,114,22,100,0,83,0,122,12,116, + 1,124,4,131,1,1,0,87,0,110,22,4,0,116,2,107, + 10,114,56,1,0,1,0,1,0,89,0,100,0,83,0,88, + 0,116,3,131,0,68,0,93,52,92,2,125,5,125,6,124, + 4,160,4,116,5,124,6,131,1,161,1,114,64,116,6,106, + 7,124,1,124,5,124,1,124,4,131,2,124,4,100,1,141, + 3,125,7,124,7,2,0,1,0,83,0,113,64,100,0,83, + 0,41,2,78,114,180,0,0,0,41,8,114,200,0,0,0, + 114,49,0,0,0,114,50,0,0,0,114,184,0,0,0,114, + 111,0,0,0,114,112,0,0,0,114,134,0,0,0,218,16, + 115,112,101,99,95,102,114,111,109,95,108,111,97,100,101,114, + 41,8,114,193,0,0,0,114,139,0,0,0,114,44,0,0, + 0,218,6,116,97,114,103,101,116,114,199,0,0,0,114,140, + 0,0,0,114,189,0,0,0,114,187,0,0,0,114,3,0, + 0,0,114,3,0,0,0,114,6,0,0,0,218,9,102,105, + 110,100,95,115,112,101,99,214,2,0,0,115,28,0,0,0, + 0,2,10,1,8,1,4,1,2,1,12,1,14,1,8,1, + 14,1,14,1,6,1,8,1,2,254,6,3,122,31,87,105, + 110,100,111,119,115,82,101,103,105,115,116,114,121,70,105,110, + 100,101,114,46,102,105,110,100,95,115,112,101,99,99,3,0, + 0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0, + 0,0,67,0,0,0,115,34,0,0,0,124,0,160,0,124, + 1,124,2,161,2,125,3,124,3,100,1,107,9,114,26,124, + 3,106,1,83,0,100,1,83,0,100,1,83,0,41,2,122, + 108,70,105,110,100,32,109,111,100,117,108,101,32,110,97,109, + 101,100,32,105,110,32,116,104,101,32,114,101,103,105,115,116, + 114,121,46,10,10,32,32,32,32,32,32,32,32,84,104,105, + 115,32,109,101,116,104,111,100,32,105,115,32,100,101,112,114, + 101,99,97,116,101,100,46,32,32,85,115,101,32,101,120,101, + 99,95,109,111,100,117,108,101,40,41,32,105,110,115,116,101, + 97,100,46,10,10,32,32,32,32,32,32,32,32,78,169,2, + 114,203,0,0,0,114,140,0,0,0,169,4,114,193,0,0, + 0,114,139,0,0,0,114,44,0,0,0,114,187,0,0,0, + 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,218, + 11,102,105,110,100,95,109,111,100,117,108,101,230,2,0,0, + 115,8,0,0,0,0,7,12,1,8,1,6,2,122,33,87, + 105,110,100,111,119,115,82,101,103,105,115,116,114,121,70,105, + 110,100,101,114,46,102,105,110,100,95,109,111,100,117,108,101, + 41,12,114,125,0,0,0,114,124,0,0,0,114,126,0,0, + 0,114,127,0,0,0,114,197,0,0,0,114,196,0,0,0, + 114,195,0,0,0,218,11,99,108,97,115,115,109,101,116,104, + 111,100,114,194,0,0,0,114,200,0,0,0,114,203,0,0, + 0,114,206,0,0,0,114,3,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,191,0,0,0,180, + 2,0,0,115,28,0,0,0,8,2,4,3,2,255,2,4, + 2,255,2,3,4,2,2,1,10,6,2,1,10,14,2,1, + 16,15,2,1,114,191,0,0,0,99,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,64,0, + 0,0,115,48,0,0,0,101,0,90,1,100,0,90,2,100, + 1,90,3,100,2,100,3,132,0,90,4,100,4,100,5,132, + 0,90,5,100,6,100,7,132,0,90,6,100,8,100,9,132, + 0,90,7,100,10,83,0,41,11,218,13,95,76,111,97,100, + 101,114,66,97,115,105,99,115,122,83,66,97,115,101,32,99, + 108,97,115,115,32,111,102,32,99,111,109,109,111,110,32,99, + 111,100,101,32,110,101,101,100,101,100,32,98,121,32,98,111, + 116,104,32,83,111,117,114,99,101,76,111,97,100,101,114,32, + 97,110,100,10,32,32,32,32,83,111,117,114,99,101,108,101, + 115,115,70,105,108,101,76,111,97,100,101,114,46,99,2,0, + 0,0,0,0,0,0,0,0,0,0,5,0,0,0,4,0, 0,0,67,0,0,0,115,64,0,0,0,116,0,124,0,160, 1,124,1,161,1,131,1,100,1,25,0,125,2,124,2,160, 2,100,2,100,1,161,2,100,3,25,0,125,3,124,1,160, @@ -1088,57 +1098,58 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 41,5,114,119,0,0,0,114,139,0,0,0,114,97,0,0, 0,90,13,102,105,108,101,110,97,109,101,95,98,97,115,101, 90,9,116,97,105,108,95,110,97,109,101,114,3,0,0,0, - 114,3,0,0,0,114,6,0,0,0,114,182,0,0,0,248, + 114,3,0,0,0,114,6,0,0,0,114,182,0,0,0,249, 2,0,0,115,8,0,0,0,0,3,18,1,16,1,14,1, 122,24,95,76,111,97,100,101,114,66,97,115,105,99,115,46, 105,115,95,112,97,99,107,97,103,101,99,2,0,0,0,0, - 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, - 4,0,0,0,100,1,83,0,169,2,122,42,85,115,101,32, - 100,101,102,97,117,108,116,32,115,101,109,97,110,116,105,99, - 115,32,102,111,114,32,109,111,100,117,108,101,32,99,114,101, - 97,116,105,111,110,46,78,114,3,0,0,0,169,2,114,119, - 0,0,0,114,187,0,0,0,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,218,13,99,114,101,97,116,101,95, - 109,111,100,117,108,101,0,3,0,0,115,2,0,0,0,0, - 1,122,27,95,76,111,97,100,101,114,66,97,115,105,99,115, - 46,99,114,101,97,116,101,95,109,111,100,117,108,101,99,2, - 0,0,0,0,0,0,0,3,0,0,0,5,0,0,0,67, - 0,0,0,115,56,0,0,0,124,0,160,0,124,1,106,1, - 161,1,125,2,124,2,100,1,107,8,114,36,116,2,100,2, - 160,3,124,1,106,1,161,1,131,1,130,1,116,4,160,5, - 116,6,124,2,124,1,106,7,161,3,1,0,100,1,83,0, - 41,3,122,19,69,120,101,99,117,116,101,32,116,104,101,32, - 109,111,100,117,108,101,46,78,122,52,99,97,110,110,111,116, - 32,108,111,97,100,32,109,111,100,117,108,101,32,123,33,114, - 125,32,119,104,101,110,32,103,101,116,95,99,111,100,101,40, - 41,32,114,101,116,117,114,110,115,32,78,111,110,101,41,8, - 218,8,103,101,116,95,99,111,100,101,114,125,0,0,0,114, - 118,0,0,0,114,62,0,0,0,114,134,0,0,0,218,25, - 95,99,97,108,108,95,119,105,116,104,95,102,114,97,109,101, - 115,95,114,101,109,111,118,101,100,218,4,101,120,101,99,114, - 131,0,0,0,41,3,114,119,0,0,0,218,6,109,111,100, - 117,108,101,114,164,0,0,0,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,218,11,101,120,101,99,95,109,111, - 100,117,108,101,3,3,0,0,115,12,0,0,0,0,2,12, - 1,8,1,6,1,4,255,6,2,122,25,95,76,111,97,100, - 101,114,66,97,115,105,99,115,46,101,120,101,99,95,109,111, - 100,117,108,101,99,2,0,0,0,0,0,0,0,2,0,0, - 0,4,0,0,0,67,0,0,0,115,12,0,0,0,116,0, - 160,1,124,0,124,1,161,2,83,0,41,1,122,26,84,104, - 105,115,32,109,111,100,117,108,101,32,105,115,32,100,101,112, - 114,101,99,97,116,101,100,46,41,2,114,134,0,0,0,218, - 17,95,108,111,97,100,95,109,111,100,117,108,101,95,115,104, - 105,109,169,2,114,119,0,0,0,114,139,0,0,0,114,3, - 0,0,0,114,3,0,0,0,114,6,0,0,0,218,11,108, - 111,97,100,95,109,111,100,117,108,101,11,3,0,0,115,2, - 0,0,0,0,2,122,25,95,76,111,97,100,101,114,66,97, - 115,105,99,115,46,108,111,97,100,95,109,111,100,117,108,101, - 78,41,8,114,125,0,0,0,114,124,0,0,0,114,126,0, - 0,0,114,127,0,0,0,114,182,0,0,0,114,212,0,0, - 0,114,217,0,0,0,114,220,0,0,0,114,3,0,0,0, - 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, - 208,0,0,0,243,2,0,0,115,10,0,0,0,8,2,4, - 3,8,8,8,3,8,8,114,208,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, + 0,0,0,115,4,0,0,0,100,1,83,0,169,2,122,42, + 85,115,101,32,100,101,102,97,117,108,116,32,115,101,109,97, + 110,116,105,99,115,32,102,111,114,32,109,111,100,117,108,101, + 32,99,114,101,97,116,105,111,110,46,78,114,3,0,0,0, + 169,2,114,119,0,0,0,114,187,0,0,0,114,3,0,0, + 0,114,3,0,0,0,114,6,0,0,0,218,13,99,114,101, + 97,116,101,95,109,111,100,117,108,101,1,3,0,0,115,2, + 0,0,0,0,1,122,27,95,76,111,97,100,101,114,66,97, + 115,105,99,115,46,99,114,101,97,116,101,95,109,111,100,117, + 108,101,99,2,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,5,0,0,0,67,0,0,0,115,56,0,0,0, + 124,0,160,0,124,1,106,1,161,1,125,2,124,2,100,1, + 107,8,114,36,116,2,100,2,160,3,124,1,106,1,161,1, + 131,1,130,1,116,4,160,5,116,6,124,2,124,1,106,7, + 161,3,1,0,100,1,83,0,41,3,122,19,69,120,101,99, + 117,116,101,32,116,104,101,32,109,111,100,117,108,101,46,78, + 122,52,99,97,110,110,111,116,32,108,111,97,100,32,109,111, + 100,117,108,101,32,123,33,114,125,32,119,104,101,110,32,103, + 101,116,95,99,111,100,101,40,41,32,114,101,116,117,114,110, + 115,32,78,111,110,101,41,8,218,8,103,101,116,95,99,111, + 100,101,114,125,0,0,0,114,118,0,0,0,114,62,0,0, + 0,114,134,0,0,0,218,25,95,99,97,108,108,95,119,105, + 116,104,95,102,114,97,109,101,115,95,114,101,109,111,118,101, + 100,218,4,101,120,101,99,114,131,0,0,0,41,3,114,119, + 0,0,0,218,6,109,111,100,117,108,101,114,164,0,0,0, + 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,218, + 11,101,120,101,99,95,109,111,100,117,108,101,4,3,0,0, + 115,12,0,0,0,0,2,12,1,8,1,6,1,4,255,6, + 2,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, + 46,101,120,101,99,95,109,111,100,117,108,101,99,2,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, + 0,67,0,0,0,115,12,0,0,0,116,0,160,1,124,0, + 124,1,161,2,83,0,41,1,122,26,84,104,105,115,32,109, + 111,100,117,108,101,32,105,115,32,100,101,112,114,101,99,97, + 116,101,100,46,41,2,114,134,0,0,0,218,17,95,108,111, + 97,100,95,109,111,100,117,108,101,95,115,104,105,109,169,2, + 114,119,0,0,0,114,139,0,0,0,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,218,11,108,111,97,100,95, + 109,111,100,117,108,101,12,3,0,0,115,2,0,0,0,0, + 2,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, + 46,108,111,97,100,95,109,111,100,117,108,101,78,41,8,114, + 125,0,0,0,114,124,0,0,0,114,126,0,0,0,114,127, + 0,0,0,114,182,0,0,0,114,212,0,0,0,114,217,0, + 0,0,114,220,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,3,0,0,0,114,6,0,0,0,114,208,0,0,0, + 244,2,0,0,115,10,0,0,0,8,2,4,3,8,8,8, + 3,8,8,114,208,0,0,0,99,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,3,0,0,0,64,0,0, 0,115,74,0,0,0,101,0,90,1,100,0,90,2,100,1, 100,2,132,0,90,3,100,3,100,4,132,0,90,4,100,5, @@ -1146,82 +1157,83 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 100,10,132,0,90,7,100,11,100,12,156,1,100,13,100,14, 132,2,90,8,100,15,100,16,132,0,90,9,100,17,83,0, 41,18,218,12,83,111,117,114,99,101,76,111,97,100,101,114, - 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, - 0,67,0,0,0,115,8,0,0,0,116,0,130,1,100,1, - 83,0,41,2,122,165,79,112,116,105,111,110,97,108,32,109, - 101,116,104,111,100,32,116,104,97,116,32,114,101,116,117,114, - 110,115,32,116,104,101,32,109,111,100,105,102,105,99,97,116, - 105,111,110,32,116,105,109,101,32,40,97,110,32,105,110,116, - 41,32,102,111,114,32,116,104,101,10,32,32,32,32,32,32, - 32,32,115,112,101,99,105,102,105,101,100,32,112,97,116,104, - 32,40,97,32,115,116,114,41,46,10,10,32,32,32,32,32, - 32,32,32,82,97,105,115,101,115,32,79,83,69,114,114,111, - 114,32,119,104,101,110,32,116,104,101,32,112,97,116,104,32, - 99,97,110,110,111,116,32,98,101,32,104,97,110,100,108,101, - 100,46,10,32,32,32,32,32,32,32,32,78,41,1,114,50, - 0,0,0,169,2,114,119,0,0,0,114,44,0,0,0,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,218,10, - 112,97,116,104,95,109,116,105,109,101,18,3,0,0,115,2, - 0,0,0,0,6,122,23,83,111,117,114,99,101,76,111,97, - 100,101,114,46,112,97,116,104,95,109,116,105,109,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,67, - 0,0,0,115,14,0,0,0,100,1,124,0,160,0,124,1, - 161,1,105,1,83,0,41,2,97,158,1,0,0,79,112,116, - 105,111,110,97,108,32,109,101,116,104,111,100,32,114,101,116, - 117,114,110,105,110,103,32,97,32,109,101,116,97,100,97,116, - 97,32,100,105,99,116,32,102,111,114,32,116,104,101,32,115, - 112,101,99,105,102,105,101,100,10,32,32,32,32,32,32,32, - 32,112,97,116,104,32,40,97,32,115,116,114,41,46,10,10, - 32,32,32,32,32,32,32,32,80,111,115,115,105,98,108,101, - 32,107,101,121,115,58,10,32,32,32,32,32,32,32,32,45, - 32,39,109,116,105,109,101,39,32,40,109,97,110,100,97,116, - 111,114,121,41,32,105,115,32,116,104,101,32,110,117,109,101, - 114,105,99,32,116,105,109,101,115,116,97,109,112,32,111,102, - 32,108,97,115,116,32,115,111,117,114,99,101,10,32,32,32, - 32,32,32,32,32,32,32,99,111,100,101,32,109,111,100,105, - 102,105,99,97,116,105,111,110,59,10,32,32,32,32,32,32, - 32,32,45,32,39,115,105,122,101,39,32,40,111,112,116,105, - 111,110,97,108,41,32,105,115,32,116,104,101,32,115,105,122, - 101,32,105,110,32,98,121,116,101,115,32,111,102,32,116,104, - 101,32,115,111,117,114,99,101,32,99,111,100,101,46,10,10, - 32,32,32,32,32,32,32,32,73,109,112,108,101,109,101,110, - 116,105,110,103,32,116,104,105,115,32,109,101,116,104,111,100, - 32,97,108,108,111,119,115,32,116,104,101,32,108,111,97,100, - 101,114,32,116,111,32,114,101,97,100,32,98,121,116,101,99, - 111,100,101,32,102,105,108,101,115,46,10,32,32,32,32,32, - 32,32,32,82,97,105,115,101,115,32,79,83,69,114,114,111, - 114,32,119,104,101,110,32,116,104,101,32,112,97,116,104,32, - 99,97,110,110,111,116,32,98,101,32,104,97,110,100,108,101, - 100,46,10,32,32,32,32,32,32,32,32,114,169,0,0,0, - 41,1,114,223,0,0,0,114,222,0,0,0,114,3,0,0, - 0,114,3,0,0,0,114,6,0,0,0,218,10,112,97,116, - 104,95,115,116,97,116,115,26,3,0,0,115,2,0,0,0, - 0,12,122,23,83,111,117,114,99,101,76,111,97,100,101,114, - 46,112,97,116,104,95,115,116,97,116,115,99,4,0,0,0, - 0,0,0,0,4,0,0,0,4,0,0,0,67,0,0,0, - 115,12,0,0,0,124,0,160,0,124,2,124,3,161,2,83, - 0,41,1,122,228,79,112,116,105,111,110,97,108,32,109,101, - 116,104,111,100,32,119,104,105,99,104,32,119,114,105,116,101, - 115,32,100,97,116,97,32,40,98,121,116,101,115,41,32,116, - 111,32,97,32,102,105,108,101,32,112,97,116,104,32,40,97, + 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,1,0,0,0,67,0,0,0,115,8,0,0,0,116,0, + 130,1,100,1,83,0,41,2,122,165,79,112,116,105,111,110, + 97,108,32,109,101,116,104,111,100,32,116,104,97,116,32,114, + 101,116,117,114,110,115,32,116,104,101,32,109,111,100,105,102, + 105,99,97,116,105,111,110,32,116,105,109,101,32,40,97,110, + 32,105,110,116,41,32,102,111,114,32,116,104,101,10,32,32, + 32,32,32,32,32,32,115,112,101,99,105,102,105,101,100,32, + 112,97,116,104,32,40,97,32,115,116,114,41,46,10,10,32, + 32,32,32,32,32,32,32,82,97,105,115,101,115,32,79,83, + 69,114,114,111,114,32,119,104,101,110,32,116,104,101,32,112, + 97,116,104,32,99,97,110,110,111,116,32,98,101,32,104,97, + 110,100,108,101,100,46,10,32,32,32,32,32,32,32,32,78, + 41,1,114,50,0,0,0,169,2,114,119,0,0,0,114,44, + 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, + 0,0,218,10,112,97,116,104,95,109,116,105,109,101,19,3, + 0,0,115,2,0,0,0,0,6,122,23,83,111,117,114,99, + 101,76,111,97,100,101,114,46,112,97,116,104,95,109,116,105, + 109,101,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,4,0,0,0,67,0,0,0,115,14,0,0,0, + 100,1,124,0,160,0,124,1,161,1,105,1,83,0,41,2, + 97,158,1,0,0,79,112,116,105,111,110,97,108,32,109,101, + 116,104,111,100,32,114,101,116,117,114,110,105,110,103,32,97, + 32,109,101,116,97,100,97,116,97,32,100,105,99,116,32,102, + 111,114,32,116,104,101,32,115,112,101,99,105,102,105,101,100, + 10,32,32,32,32,32,32,32,32,112,97,116,104,32,40,97, 32,115,116,114,41,46,10,10,32,32,32,32,32,32,32,32, + 80,111,115,115,105,98,108,101,32,107,101,121,115,58,10,32, + 32,32,32,32,32,32,32,45,32,39,109,116,105,109,101,39, + 32,40,109,97,110,100,97,116,111,114,121,41,32,105,115,32, + 116,104,101,32,110,117,109,101,114,105,99,32,116,105,109,101, + 115,116,97,109,112,32,111,102,32,108,97,115,116,32,115,111, + 117,114,99,101,10,32,32,32,32,32,32,32,32,32,32,99, + 111,100,101,32,109,111,100,105,102,105,99,97,116,105,111,110, + 59,10,32,32,32,32,32,32,32,32,45,32,39,115,105,122, + 101,39,32,40,111,112,116,105,111,110,97,108,41,32,105,115, + 32,116,104,101,32,115,105,122,101,32,105,110,32,98,121,116, + 101,115,32,111,102,32,116,104,101,32,115,111,117,114,99,101, + 32,99,111,100,101,46,10,10,32,32,32,32,32,32,32,32, 73,109,112,108,101,109,101,110,116,105,110,103,32,116,104,105, 115,32,109,101,116,104,111,100,32,97,108,108,111,119,115,32, - 102,111,114,32,116,104,101,32,119,114,105,116,105,110,103,32, - 111,102,32,98,121,116,101,99,111,100,101,32,102,105,108,101, - 115,46,10,10,32,32,32,32,32,32,32,32,84,104,101,32, - 115,111,117,114,99,101,32,112,97,116,104,32,105,115,32,110, - 101,101,100,101,100,32,105,110,32,111,114,100,101,114,32,116, - 111,32,99,111,114,114,101,99,116,108,121,32,116,114,97,110, - 115,102,101,114,32,112,101,114,109,105,115,115,105,111,110,115, - 10,32,32,32,32,32,32,32,32,41,1,218,8,115,101,116, - 95,100,97,116,97,41,4,114,119,0,0,0,114,108,0,0, - 0,90,10,99,97,99,104,101,95,112,97,116,104,114,26,0, - 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,218,15,95,99,97,99,104,101,95,98,121,116,101,99,111, - 100,101,40,3,0,0,115,2,0,0,0,0,8,122,28,83, - 111,117,114,99,101,76,111,97,100,101,114,46,95,99,97,99, - 104,101,95,98,121,116,101,99,111,100,101,99,3,0,0,0, + 116,104,101,32,108,111,97,100,101,114,32,116,111,32,114,101, + 97,100,32,98,121,116,101,99,111,100,101,32,102,105,108,101, + 115,46,10,32,32,32,32,32,32,32,32,82,97,105,115,101, + 115,32,79,83,69,114,114,111,114,32,119,104,101,110,32,116, + 104,101,32,112,97,116,104,32,99,97,110,110,111,116,32,98, + 101,32,104,97,110,100,108,101,100,46,10,32,32,32,32,32, + 32,32,32,114,169,0,0,0,41,1,114,223,0,0,0,114, + 222,0,0,0,114,3,0,0,0,114,3,0,0,0,114,6, + 0,0,0,218,10,112,97,116,104,95,115,116,97,116,115,27, + 3,0,0,115,2,0,0,0,0,12,122,23,83,111,117,114, + 99,101,76,111,97,100,101,114,46,112,97,116,104,95,115,116, + 97,116,115,99,4,0,0,0,0,0,0,0,0,0,0,0, + 4,0,0,0,4,0,0,0,67,0,0,0,115,12,0,0, + 0,124,0,160,0,124,2,124,3,161,2,83,0,41,1,122, + 228,79,112,116,105,111,110,97,108,32,109,101,116,104,111,100, + 32,119,104,105,99,104,32,119,114,105,116,101,115,32,100,97, + 116,97,32,40,98,121,116,101,115,41,32,116,111,32,97,32, + 102,105,108,101,32,112,97,116,104,32,40,97,32,115,116,114, + 41,46,10,10,32,32,32,32,32,32,32,32,73,109,112,108, + 101,109,101,110,116,105,110,103,32,116,104,105,115,32,109,101, + 116,104,111,100,32,97,108,108,111,119,115,32,102,111,114,32, + 116,104,101,32,119,114,105,116,105,110,103,32,111,102,32,98, + 121,116,101,99,111,100,101,32,102,105,108,101,115,46,10,10, + 32,32,32,32,32,32,32,32,84,104,101,32,115,111,117,114, + 99,101,32,112,97,116,104,32,105,115,32,110,101,101,100,101, + 100,32,105,110,32,111,114,100,101,114,32,116,111,32,99,111, + 114,114,101,99,116,108,121,32,116,114,97,110,115,102,101,114, + 32,112,101,114,109,105,115,115,105,111,110,115,10,32,32,32, + 32,32,32,32,32,41,1,218,8,115,101,116,95,100,97,116, + 97,41,4,114,119,0,0,0,114,108,0,0,0,90,10,99, + 97,99,104,101,95,112,97,116,104,114,26,0,0,0,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,218,15,95, + 99,97,99,104,101,95,98,121,116,101,99,111,100,101,41,3, + 0,0,115,2,0,0,0,0,8,122,28,83,111,117,114,99, + 101,76,111,97,100,101,114,46,95,99,97,99,104,101,95,98, + 121,116,101,99,111,100,101,99,3,0,0,0,0,0,0,0, 0,0,0,0,3,0,0,0,1,0,0,0,67,0,0,0, 115,4,0,0,0,100,1,83,0,41,2,122,150,79,112,116, 105,111,110,97,108,32,109,101,116,104,111,100,32,119,104,105, @@ -1235,146 +1247,147 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 111,100,101,32,102,105,108,101,115,46,10,32,32,32,32,32, 32,32,32,78,114,3,0,0,0,41,3,114,119,0,0,0, 114,44,0,0,0,114,26,0,0,0,114,3,0,0,0,114, - 3,0,0,0,114,6,0,0,0,114,225,0,0,0,50,3, + 3,0,0,0,114,6,0,0,0,114,225,0,0,0,51,3, 0,0,115,2,0,0,0,0,1,122,21,83,111,117,114,99, 101,76,111,97,100,101,114,46,115,101,116,95,100,97,116,97, - 99,2,0,0,0,0,0,0,0,5,0,0,0,10,0,0, - 0,67,0,0,0,115,82,0,0,0,124,0,160,0,124,1, - 161,1,125,2,122,14,124,0,160,1,124,2,161,1,125,3, - 87,0,110,48,4,0,116,2,107,10,114,72,1,0,125,4, - 1,0,122,18,116,3,100,1,124,1,100,2,141,2,124,4, - 130,2,87,0,53,0,100,3,125,4,126,4,88,0,89,0, - 110,2,88,0,116,4,124,3,131,1,83,0,41,4,122,52, - 67,111,110,99,114,101,116,101,32,105,109,112,108,101,109,101, - 110,116,97,116,105,111,110,32,111,102,32,73,110,115,112,101, - 99,116,76,111,97,100,101,114,46,103,101,116,95,115,111,117, - 114,99,101,46,122,39,115,111,117,114,99,101,32,110,111,116, - 32,97,118,97,105,108,97,98,108,101,32,116,104,114,111,117, - 103,104,32,103,101,116,95,100,97,116,97,40,41,114,116,0, - 0,0,78,41,5,114,179,0,0,0,218,8,103,101,116,95, - 100,97,116,97,114,50,0,0,0,114,118,0,0,0,114,176, - 0,0,0,41,5,114,119,0,0,0,114,139,0,0,0,114, - 44,0,0,0,114,174,0,0,0,218,3,101,120,99,114,3, - 0,0,0,114,3,0,0,0,114,6,0,0,0,218,10,103, - 101,116,95,115,111,117,114,99,101,57,3,0,0,115,20,0, - 0,0,0,2,10,1,2,1,14,1,16,1,4,1,2,255, - 4,1,2,255,20,2,122,23,83,111,117,114,99,101,76,111, - 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,114, - 105,0,0,0,41,1,218,9,95,111,112,116,105,109,105,122, - 101,99,3,0,0,0,1,0,0,0,4,0,0,0,8,0, - 0,0,67,0,0,0,115,22,0,0,0,116,0,106,1,116, - 2,124,1,124,2,100,1,100,2,124,3,100,3,141,6,83, - 0,41,4,122,130,82,101,116,117,114,110,32,116,104,101,32, - 99,111,100,101,32,111,98,106,101,99,116,32,99,111,109,112, - 105,108,101,100,32,102,114,111,109,32,115,111,117,114,99,101, - 46,10,10,32,32,32,32,32,32,32,32,84,104,101,32,39, - 100,97,116,97,39,32,97,114,103,117,109,101,110,116,32,99, - 97,110,32,98,101,32,97,110,121,32,111,98,106,101,99,116, - 32,116,121,112,101,32,116,104,97,116,32,99,111,109,112,105, - 108,101,40,41,32,115,117,112,112,111,114,116,115,46,10,32, - 32,32,32,32,32,32,32,114,215,0,0,0,84,41,2,218, - 12,100,111,110,116,95,105,110,104,101,114,105,116,114,84,0, - 0,0,41,3,114,134,0,0,0,114,214,0,0,0,218,7, - 99,111,109,112,105,108,101,41,4,114,119,0,0,0,114,26, - 0,0,0,114,44,0,0,0,114,230,0,0,0,114,3,0, - 0,0,114,3,0,0,0,114,6,0,0,0,218,14,115,111, - 117,114,99,101,95,116,111,95,99,111,100,101,67,3,0,0, - 115,8,0,0,0,0,5,12,1,2,0,2,255,122,27,83, - 111,117,114,99,101,76,111,97,100,101,114,46,115,111,117,114, - 99,101,95,116,111,95,99,111,100,101,99,2,0,0,0,0, - 0,0,0,15,0,0,0,9,0,0,0,67,0,0,0,115, - 34,2,0,0,124,0,160,0,124,1,161,1,125,2,100,1, - 125,3,100,1,125,4,100,1,125,5,100,2,125,6,100,3, - 125,7,122,12,116,1,124,2,131,1,125,8,87,0,110,26, - 4,0,116,2,107,10,114,68,1,0,1,0,1,0,100,1, - 125,8,89,0,144,1,110,48,88,0,122,14,124,0,160,3, - 124,2,161,1,125,9,87,0,110,22,4,0,116,4,107,10, - 114,106,1,0,1,0,1,0,89,0,144,1,110,10,88,0, - 116,5,124,9,100,4,25,0,131,1,125,3,122,14,124,0, - 160,6,124,8,161,1,125,10,87,0,110,20,4,0,116,4, - 107,10,114,154,1,0,1,0,1,0,89,0,110,218,88,0, - 124,1,124,8,100,5,156,2,125,11,122,148,116,7,124,10, - 124,1,124,11,131,3,125,12,116,8,124,10,131,1,100,6, - 100,1,133,2,25,0,125,13,124,12,100,7,64,0,100,8, - 107,3,125,6,124,6,144,1,114,36,124,12,100,9,64,0, - 100,8,107,3,125,7,116,9,106,10,100,10,107,3,144,1, - 114,34,124,7,115,254,116,9,106,10,100,11,107,2,144,1, - 114,34,124,0,160,6,124,2,161,1,125,4,116,9,160,11, - 116,12,124,4,161,2,125,5,116,13,124,10,124,5,124,1, - 124,11,131,4,1,0,110,20,116,14,124,10,124,3,124,9, - 100,12,25,0,124,1,124,11,131,5,1,0,87,0,110,26, - 4,0,116,15,116,16,102,2,107,10,144,1,114,84,1,0, - 1,0,1,0,89,0,110,32,88,0,116,17,160,18,100,13, - 124,8,124,2,161,3,1,0,116,19,124,13,124,1,124,8, - 124,2,100,14,141,4,83,0,124,4,100,1,107,8,144,1, - 114,136,124,0,160,6,124,2,161,1,125,4,124,0,160,20, - 124,4,124,2,161,2,125,14,116,17,160,18,100,15,124,2, - 161,2,1,0,116,21,106,22,144,2,115,30,124,8,100,1, - 107,9,144,2,114,30,124,3,100,1,107,9,144,2,114,30, - 124,6,144,1,114,228,124,5,100,1,107,8,144,1,114,214, - 116,9,160,11,124,4,161,1,125,5,116,23,124,14,124,5, - 124,7,131,3,125,10,110,16,116,24,124,14,124,3,116,25, - 124,4,131,1,131,3,125,10,122,18,124,0,160,26,124,2, - 124,8,124,10,161,3,1,0,87,0,110,22,4,0,116,2, - 107,10,144,2,114,28,1,0,1,0,1,0,89,0,110,2, - 88,0,124,14,83,0,41,16,122,190,67,111,110,99,114,101, - 116,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111, - 110,32,111,102,32,73,110,115,112,101,99,116,76,111,97,100, - 101,114,46,103,101,116,95,99,111,100,101,46,10,10,32,32, - 32,32,32,32,32,32,82,101,97,100,105,110,103,32,111,102, - 32,98,121,116,101,99,111,100,101,32,114,101,113,117,105,114, - 101,115,32,112,97,116,104,95,115,116,97,116,115,32,116,111, - 32,98,101,32,105,109,112,108,101,109,101,110,116,101,100,46, - 32,84,111,32,119,114,105,116,101,10,32,32,32,32,32,32, - 32,32,98,121,116,101,99,111,100,101,44,32,115,101,116,95, - 100,97,116,97,32,109,117,115,116,32,97,108,115,111,32,98, - 101,32,105,109,112,108,101,109,101,110,116,101,100,46,10,10, - 32,32,32,32,32,32,32,32,78,70,84,114,169,0,0,0, - 114,159,0,0,0,114,145,0,0,0,114,39,0,0,0,114, - 73,0,0,0,114,28,0,0,0,90,5,110,101,118,101,114, - 90,6,97,108,119,97,121,115,218,4,115,105,122,101,122,13, - 123,125,32,109,97,116,99,104,101,115,32,123,125,41,3,114, - 117,0,0,0,114,107,0,0,0,114,108,0,0,0,122,19, - 99,111,100,101,32,111,98,106,101,99,116,32,102,114,111,109, - 32,123,125,41,27,114,179,0,0,0,114,98,0,0,0,114, - 82,0,0,0,114,224,0,0,0,114,50,0,0,0,114,17, - 0,0,0,114,227,0,0,0,114,152,0,0,0,218,10,109, - 101,109,111,114,121,118,105,101,119,114,163,0,0,0,90,21, - 99,104,101,99,107,95,104,97,115,104,95,98,97,115,101,100, - 95,112,121,99,115,114,157,0,0,0,218,17,95,82,65,87, - 95,77,65,71,73,67,95,78,85,77,66,69,82,114,158,0, - 0,0,114,156,0,0,0,114,118,0,0,0,114,150,0,0, - 0,114,134,0,0,0,114,149,0,0,0,114,165,0,0,0, - 114,233,0,0,0,114,8,0,0,0,218,19,100,111,110,116, - 95,119,114,105,116,101,95,98,121,116,101,99,111,100,101,114, - 171,0,0,0,114,170,0,0,0,114,22,0,0,0,114,226, - 0,0,0,41,15,114,119,0,0,0,114,139,0,0,0,114, - 108,0,0,0,114,154,0,0,0,114,174,0,0,0,114,157, - 0,0,0,90,10,104,97,115,104,95,98,97,115,101,100,90, - 12,99,104,101,99,107,95,115,111,117,114,99,101,114,107,0, - 0,0,218,2,115,116,114,26,0,0,0,114,151,0,0,0, - 114,83,0,0,0,90,10,98,121,116,101,115,95,100,97,116, - 97,90,11,99,111,100,101,95,111,98,106,101,99,116,114,3, - 0,0,0,114,3,0,0,0,114,6,0,0,0,114,213,0, - 0,0,75,3,0,0,115,152,0,0,0,0,7,10,1,4, - 1,4,1,4,1,4,1,4,1,2,1,12,1,14,1,12, - 2,2,1,14,1,14,1,8,2,12,1,2,1,14,1,14, - 1,6,3,2,1,2,254,6,4,2,1,12,1,16,1,12, - 1,6,1,12,1,12,1,2,255,2,2,8,254,4,3,10, - 1,4,1,2,1,2,254,4,4,8,1,2,255,6,3,2, - 1,2,1,2,1,6,1,2,1,2,251,8,7,20,1,6, - 2,8,1,2,255,4,2,6,1,2,1,2,254,6,3,10, - 1,10,1,12,1,12,1,18,1,6,255,4,2,6,1,10, - 1,10,1,14,2,6,1,6,255,4,2,2,1,18,1,16, - 1,6,1,122,21,83,111,117,114,99,101,76,111,97,100,101, - 114,46,103,101,116,95,99,111,100,101,78,41,10,114,125,0, - 0,0,114,124,0,0,0,114,126,0,0,0,114,223,0,0, - 0,114,224,0,0,0,114,226,0,0,0,114,225,0,0,0, - 114,229,0,0,0,114,233,0,0,0,114,213,0,0,0,114, - 3,0,0,0,114,3,0,0,0,114,3,0,0,0,114,6, - 0,0,0,114,221,0,0,0,16,3,0,0,115,14,0,0, - 0,8,2,8,8,8,14,8,10,8,7,8,10,14,8,114, - 221,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, + 99,2,0,0,0,0,0,0,0,0,0,0,0,5,0,0, + 0,10,0,0,0,67,0,0,0,115,82,0,0,0,124,0, + 160,0,124,1,161,1,125,2,122,14,124,0,160,1,124,2, + 161,1,125,3,87,0,110,48,4,0,116,2,107,10,114,72, + 1,0,125,4,1,0,122,18,116,3,100,1,124,1,100,2, + 141,2,124,4,130,2,87,0,53,0,100,3,125,4,126,4, + 88,0,89,0,110,2,88,0,116,4,124,3,131,1,83,0, + 41,4,122,52,67,111,110,99,114,101,116,101,32,105,109,112, + 108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,73, + 110,115,112,101,99,116,76,111,97,100,101,114,46,103,101,116, + 95,115,111,117,114,99,101,46,122,39,115,111,117,114,99,101, + 32,110,111,116,32,97,118,97,105,108,97,98,108,101,32,116, + 104,114,111,117,103,104,32,103,101,116,95,100,97,116,97,40, + 41,114,116,0,0,0,78,41,5,114,179,0,0,0,218,8, + 103,101,116,95,100,97,116,97,114,50,0,0,0,114,118,0, + 0,0,114,176,0,0,0,41,5,114,119,0,0,0,114,139, + 0,0,0,114,44,0,0,0,114,174,0,0,0,218,3,101, + 120,99,114,3,0,0,0,114,3,0,0,0,114,6,0,0, + 0,218,10,103,101,116,95,115,111,117,114,99,101,58,3,0, + 0,115,20,0,0,0,0,2,10,1,2,1,14,1,16,1, + 4,1,2,255,4,1,2,255,20,2,122,23,83,111,117,114, + 99,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, + 114,99,101,114,105,0,0,0,41,1,218,9,95,111,112,116, + 105,109,105,122,101,99,3,0,0,0,0,0,0,0,1,0, + 0,0,4,0,0,0,8,0,0,0,67,0,0,0,115,22, + 0,0,0,116,0,106,1,116,2,124,1,124,2,100,1,100, + 2,124,3,100,3,141,6,83,0,41,4,122,130,82,101,116, + 117,114,110,32,116,104,101,32,99,111,100,101,32,111,98,106, + 101,99,116,32,99,111,109,112,105,108,101,100,32,102,114,111, + 109,32,115,111,117,114,99,101,46,10,10,32,32,32,32,32, + 32,32,32,84,104,101,32,39,100,97,116,97,39,32,97,114, + 103,117,109,101,110,116,32,99,97,110,32,98,101,32,97,110, + 121,32,111,98,106,101,99,116,32,116,121,112,101,32,116,104, + 97,116,32,99,111,109,112,105,108,101,40,41,32,115,117,112, + 112,111,114,116,115,46,10,32,32,32,32,32,32,32,32,114, + 215,0,0,0,84,41,2,218,12,100,111,110,116,95,105,110, + 104,101,114,105,116,114,84,0,0,0,41,3,114,134,0,0, + 0,114,214,0,0,0,218,7,99,111,109,112,105,108,101,41, + 4,114,119,0,0,0,114,26,0,0,0,114,44,0,0,0, + 114,230,0,0,0,114,3,0,0,0,114,3,0,0,0,114, + 6,0,0,0,218,14,115,111,117,114,99,101,95,116,111,95, + 99,111,100,101,68,3,0,0,115,8,0,0,0,0,5,12, + 1,2,0,2,255,122,27,83,111,117,114,99,101,76,111,97, + 100,101,114,46,115,111,117,114,99,101,95,116,111,95,99,111, + 100,101,99,2,0,0,0,0,0,0,0,0,0,0,0,15, + 0,0,0,9,0,0,0,67,0,0,0,115,34,2,0,0, + 124,0,160,0,124,1,161,1,125,2,100,1,125,3,100,1, + 125,4,100,1,125,5,100,2,125,6,100,3,125,7,122,12, + 116,1,124,2,131,1,125,8,87,0,110,26,4,0,116,2, + 107,10,114,68,1,0,1,0,1,0,100,1,125,8,89,0, + 144,1,110,48,88,0,122,14,124,0,160,3,124,2,161,1, + 125,9,87,0,110,22,4,0,116,4,107,10,114,106,1,0, + 1,0,1,0,89,0,144,1,110,10,88,0,116,5,124,9, + 100,4,25,0,131,1,125,3,122,14,124,0,160,6,124,8, + 161,1,125,10,87,0,110,20,4,0,116,4,107,10,114,154, + 1,0,1,0,1,0,89,0,110,218,88,0,124,1,124,8, + 100,5,156,2,125,11,122,148,116,7,124,10,124,1,124,11, + 131,3,125,12,116,8,124,10,131,1,100,6,100,1,133,2, + 25,0,125,13,124,12,100,7,64,0,100,8,107,3,125,6, + 124,6,144,1,114,36,124,12,100,9,64,0,100,8,107,3, + 125,7,116,9,106,10,100,10,107,3,144,1,114,34,124,7, + 115,254,116,9,106,10,100,11,107,2,144,1,114,34,124,0, + 160,6,124,2,161,1,125,4,116,9,160,11,116,12,124,4, + 161,2,125,5,116,13,124,10,124,5,124,1,124,11,131,4, + 1,0,110,20,116,14,124,10,124,3,124,9,100,12,25,0, + 124,1,124,11,131,5,1,0,87,0,110,26,4,0,116,15, + 116,16,102,2,107,10,144,1,114,84,1,0,1,0,1,0, + 89,0,110,32,88,0,116,17,160,18,100,13,124,8,124,2, + 161,3,1,0,116,19,124,13,124,1,124,8,124,2,100,14, + 141,4,83,0,124,4,100,1,107,8,144,1,114,136,124,0, + 160,6,124,2,161,1,125,4,124,0,160,20,124,4,124,2, + 161,2,125,14,116,17,160,18,100,15,124,2,161,2,1,0, + 116,21,106,22,144,2,115,30,124,8,100,1,107,9,144,2, + 114,30,124,3,100,1,107,9,144,2,114,30,124,6,144,1, + 114,228,124,5,100,1,107,8,144,1,114,214,116,9,160,11, + 124,4,161,1,125,5,116,23,124,14,124,5,124,7,131,3, + 125,10,110,16,116,24,124,14,124,3,116,25,124,4,131,1, + 131,3,125,10,122,18,124,0,160,26,124,2,124,8,124,10, + 161,3,1,0,87,0,110,22,4,0,116,2,107,10,144,2, + 114,28,1,0,1,0,1,0,89,0,110,2,88,0,124,14, + 83,0,41,16,122,190,67,111,110,99,114,101,116,101,32,105, + 109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102, + 32,73,110,115,112,101,99,116,76,111,97,100,101,114,46,103, + 101,116,95,99,111,100,101,46,10,10,32,32,32,32,32,32, + 32,32,82,101,97,100,105,110,103,32,111,102,32,98,121,116, + 101,99,111,100,101,32,114,101,113,117,105,114,101,115,32,112, + 97,116,104,95,115,116,97,116,115,32,116,111,32,98,101,32, + 105,109,112,108,101,109,101,110,116,101,100,46,32,84,111,32, + 119,114,105,116,101,10,32,32,32,32,32,32,32,32,98,121, + 116,101,99,111,100,101,44,32,115,101,116,95,100,97,116,97, + 32,109,117,115,116,32,97,108,115,111,32,98,101,32,105,109, + 112,108,101,109,101,110,116,101,100,46,10,10,32,32,32,32, + 32,32,32,32,78,70,84,114,169,0,0,0,114,159,0,0, + 0,114,145,0,0,0,114,39,0,0,0,114,73,0,0,0, + 114,28,0,0,0,90,5,110,101,118,101,114,90,6,97,108, + 119,97,121,115,218,4,115,105,122,101,122,13,123,125,32,109, + 97,116,99,104,101,115,32,123,125,41,3,114,117,0,0,0, + 114,107,0,0,0,114,108,0,0,0,122,19,99,111,100,101, + 32,111,98,106,101,99,116,32,102,114,111,109,32,123,125,41, + 27,114,179,0,0,0,114,98,0,0,0,114,82,0,0,0, + 114,224,0,0,0,114,50,0,0,0,114,17,0,0,0,114, + 227,0,0,0,114,152,0,0,0,218,10,109,101,109,111,114, + 121,118,105,101,119,114,163,0,0,0,90,21,99,104,101,99, + 107,95,104,97,115,104,95,98,97,115,101,100,95,112,121,99, + 115,114,157,0,0,0,218,17,95,82,65,87,95,77,65,71, + 73,67,95,78,85,77,66,69,82,114,158,0,0,0,114,156, + 0,0,0,114,118,0,0,0,114,150,0,0,0,114,134,0, + 0,0,114,149,0,0,0,114,165,0,0,0,114,233,0,0, + 0,114,8,0,0,0,218,19,100,111,110,116,95,119,114,105, + 116,101,95,98,121,116,101,99,111,100,101,114,171,0,0,0, + 114,170,0,0,0,114,22,0,0,0,114,226,0,0,0,41, + 15,114,119,0,0,0,114,139,0,0,0,114,108,0,0,0, + 114,154,0,0,0,114,174,0,0,0,114,157,0,0,0,90, + 10,104,97,115,104,95,98,97,115,101,100,90,12,99,104,101, + 99,107,95,115,111,117,114,99,101,114,107,0,0,0,218,2, + 115,116,114,26,0,0,0,114,151,0,0,0,114,83,0,0, + 0,90,10,98,121,116,101,115,95,100,97,116,97,90,11,99, + 111,100,101,95,111,98,106,101,99,116,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,114,213,0,0,0,76,3, + 0,0,115,152,0,0,0,0,7,10,1,4,1,4,1,4, + 1,4,1,4,1,2,1,12,1,14,1,12,2,2,1,14, + 1,14,1,8,2,12,1,2,1,14,1,14,1,6,3,2, + 1,2,254,6,4,2,1,12,1,16,1,12,1,6,1,12, + 1,12,1,2,255,2,2,8,254,4,3,10,1,4,1,2, + 1,2,254,4,4,8,1,2,255,6,3,2,1,2,1,2, + 1,6,1,2,1,2,251,8,7,20,1,6,2,8,1,2, + 255,4,2,6,1,2,1,2,254,6,3,10,1,10,1,12, + 1,12,1,18,1,6,255,4,2,6,1,10,1,10,1,14, + 2,6,1,6,255,4,2,2,1,18,1,16,1,6,1,122, + 21,83,111,117,114,99,101,76,111,97,100,101,114,46,103,101, + 116,95,99,111,100,101,78,41,10,114,125,0,0,0,114,124, + 0,0,0,114,126,0,0,0,114,223,0,0,0,114,224,0, + 0,0,114,226,0,0,0,114,225,0,0,0,114,229,0,0, + 0,114,233,0,0,0,114,213,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, + 221,0,0,0,17,3,0,0,115,14,0,0,0,8,2,8, + 8,8,14,8,10,8,7,8,10,14,8,114,221,0,0,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,4,0,0,0,0,0,0,0,115,124,0,0,0,101,0, 90,1,100,0,90,2,100,1,90,3,100,2,100,3,132,0, 90,4,100,4,100,5,132,0,90,5,100,6,100,7,132,0, @@ -1391,36 +1404,37 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 116,111,99,111,108,32,109,101,116,104,111,100,115,32,116,104, 97,116,10,32,32,32,32,114,101,113,117,105,114,101,32,102, 105,108,101,32,115,121,115,116,101,109,32,117,115,97,103,101, - 46,99,3,0,0,0,0,0,0,0,3,0,0,0,2,0, - 0,0,67,0,0,0,115,16,0,0,0,124,1,124,0,95, - 0,124,2,124,0,95,1,100,1,83,0,41,2,122,75,67, - 97,99,104,101,32,116,104,101,32,109,111,100,117,108,101,32, - 110,97,109,101,32,97,110,100,32,116,104,101,32,112,97,116, - 104,32,116,111,32,116,104,101,32,102,105,108,101,32,102,111, - 117,110,100,32,98,121,32,116,104,101,10,32,32,32,32,32, - 32,32,32,102,105,110,100,101,114,46,78,114,159,0,0,0, - 41,3,114,119,0,0,0,114,139,0,0,0,114,44,0,0, - 0,114,3,0,0,0,114,3,0,0,0,114,6,0,0,0, - 114,209,0,0,0,165,3,0,0,115,4,0,0,0,0,3, - 6,1,122,19,70,105,108,101,76,111,97,100,101,114,46,95, - 95,105,110,105,116,95,95,99,2,0,0,0,0,0,0,0, - 2,0,0,0,2,0,0,0,67,0,0,0,115,24,0,0, - 0,124,0,106,0,124,1,106,0,107,2,111,22,124,0,106, - 1,124,1,106,1,107,2,83,0,114,110,0,0,0,169,2, - 218,9,95,95,99,108,97,115,115,95,95,114,131,0,0,0, - 169,2,114,119,0,0,0,90,5,111,116,104,101,114,114,3, - 0,0,0,114,3,0,0,0,114,6,0,0,0,218,6,95, - 95,101,113,95,95,171,3,0,0,115,6,0,0,0,0,1, - 12,1,10,255,122,17,70,105,108,101,76,111,97,100,101,114, - 46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,20,0,0, - 0,116,0,124,0,106,1,131,1,116,0,124,0,106,2,131, - 1,65,0,83,0,114,110,0,0,0,169,3,218,4,104,97, - 115,104,114,117,0,0,0,114,44,0,0,0,169,1,114,119, - 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, - 0,0,218,8,95,95,104,97,115,104,95,95,175,3,0,0, - 115,2,0,0,0,0,1,122,19,70,105,108,101,76,111,97, - 100,101,114,46,95,95,104,97,115,104,95,95,99,2,0,0, + 46,99,3,0,0,0,0,0,0,0,0,0,0,0,3,0, + 0,0,2,0,0,0,67,0,0,0,115,16,0,0,0,124, + 1,124,0,95,0,124,2,124,0,95,1,100,1,83,0,41, + 2,122,75,67,97,99,104,101,32,116,104,101,32,109,111,100, + 117,108,101,32,110,97,109,101,32,97,110,100,32,116,104,101, + 32,112,97,116,104,32,116,111,32,116,104,101,32,102,105,108, + 101,32,102,111,117,110,100,32,98,121,32,116,104,101,10,32, + 32,32,32,32,32,32,32,102,105,110,100,101,114,46,78,114, + 159,0,0,0,41,3,114,119,0,0,0,114,139,0,0,0, + 114,44,0,0,0,114,3,0,0,0,114,3,0,0,0,114, + 6,0,0,0,114,209,0,0,0,166,3,0,0,115,4,0, + 0,0,0,3,6,1,122,19,70,105,108,101,76,111,97,100, + 101,114,46,95,95,105,110,105,116,95,95,99,2,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0, + 67,0,0,0,115,24,0,0,0,124,0,106,0,124,1,106, + 0,107,2,111,22,124,0,106,1,124,1,106,1,107,2,83, + 0,114,110,0,0,0,169,2,218,9,95,95,99,108,97,115, + 115,95,95,114,131,0,0,0,169,2,114,119,0,0,0,90, + 5,111,116,104,101,114,114,3,0,0,0,114,3,0,0,0, + 114,6,0,0,0,218,6,95,95,101,113,95,95,172,3,0, + 0,115,6,0,0,0,0,1,12,1,10,255,122,17,70,105, + 108,101,76,111,97,100,101,114,46,95,95,101,113,95,95,99, + 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,20,0,0,0,116,0,124, + 0,106,1,131,1,116,0,124,0,106,2,131,1,65,0,83, + 0,114,110,0,0,0,169,3,218,4,104,97,115,104,114,117, + 0,0,0,114,44,0,0,0,169,1,114,119,0,0,0,114, + 3,0,0,0,114,3,0,0,0,114,6,0,0,0,218,8, + 95,95,104,97,115,104,95,95,176,3,0,0,115,2,0,0, + 0,0,1,122,19,70,105,108,101,76,111,97,100,101,114,46, + 95,95,104,97,115,104,95,95,99,2,0,0,0,0,0,0, 0,0,0,0,0,2,0,0,0,3,0,0,0,3,0,0, 0,115,16,0,0,0,116,0,116,1,124,0,131,2,160,2, 124,1,161,1,83,0,41,1,122,100,76,111,97,100,32,97, @@ -1432,42 +1446,43 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 101,97,100,46,10,10,32,32,32,32,32,32,32,32,41,3, 218,5,115,117,112,101,114,114,239,0,0,0,114,220,0,0, 0,114,219,0,0,0,169,1,114,241,0,0,0,114,3,0, - 0,0,114,6,0,0,0,114,220,0,0,0,178,3,0,0, + 0,0,114,6,0,0,0,114,220,0,0,0,179,3,0,0, 115,2,0,0,0,0,10,122,22,70,105,108,101,76,111,97, 100,101,114,46,108,111,97,100,95,109,111,100,117,108,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,6,0,0,0,124,0,106,0,83,0,169, - 1,122,58,82,101,116,117,114,110,32,116,104,101,32,112,97, - 116,104,32,116,111,32,116,104,101,32,115,111,117,114,99,101, - 32,102,105,108,101,32,97,115,32,102,111,117,110,100,32,98, - 121,32,116,104,101,32,102,105,110,100,101,114,46,114,48,0, - 0,0,114,219,0,0,0,114,3,0,0,0,114,3,0,0, - 0,114,6,0,0,0,114,179,0,0,0,190,3,0,0,115, - 2,0,0,0,0,3,122,23,70,105,108,101,76,111,97,100, - 101,114,46,103,101,116,95,102,105,108,101,110,97,109,101,99, - 2,0,0,0,0,0,0,0,3,0,0,0,10,0,0,0, - 67,0,0,0,115,44,0,0,0,116,0,160,1,124,1,100, - 1,161,2,143,22,125,2,124,2,160,2,161,0,87,0,2, - 0,53,0,81,0,82,0,163,0,83,0,81,0,82,0,88, - 0,100,2,83,0,41,3,122,39,82,101,116,117,114,110,32, - 116,104,101,32,100,97,116,97,32,102,114,111,109,32,112,97, - 116,104,32,97,115,32,114,97,119,32,98,121,116,101,115,46, - 218,1,114,78,41,3,114,64,0,0,0,114,65,0,0,0, - 90,4,114,101,97,100,41,3,114,119,0,0,0,114,44,0, - 0,0,114,68,0,0,0,114,3,0,0,0,114,3,0,0, - 0,114,6,0,0,0,114,227,0,0,0,195,3,0,0,115, - 4,0,0,0,0,2,14,1,122,19,70,105,108,101,76,111, - 97,100,101,114,46,103,101,116,95,100,97,116,97,99,2,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,67,0, - 0,0,115,18,0,0,0,124,0,160,0,124,1,161,1,114, - 14,124,0,83,0,100,0,83,0,114,110,0,0,0,41,1, - 114,182,0,0,0,169,2,114,119,0,0,0,114,216,0,0, - 0,114,3,0,0,0,114,3,0,0,0,114,6,0,0,0, - 218,19,103,101,116,95,114,101,115,111,117,114,99,101,95,114, - 101,97,100,101,114,202,3,0,0,115,6,0,0,0,0,2, - 10,1,4,1,122,30,70,105,108,101,76,111,97,100,101,114, - 46,103,101,116,95,114,101,115,111,117,114,99,101,95,114,101, - 97,100,101,114,99,2,0,0,0,0,0,0,0,3,0,0, + 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,6,0,0,0,124,0,106, + 0,83,0,169,1,122,58,82,101,116,117,114,110,32,116,104, + 101,32,112,97,116,104,32,116,111,32,116,104,101,32,115,111, + 117,114,99,101,32,102,105,108,101,32,97,115,32,102,111,117, + 110,100,32,98,121,32,116,104,101,32,102,105,110,100,101,114, + 46,114,48,0,0,0,114,219,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,179,0,0,0,191, + 3,0,0,115,2,0,0,0,0,3,122,23,70,105,108,101, + 76,111,97,100,101,114,46,103,101,116,95,102,105,108,101,110, + 97,109,101,99,2,0,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,10,0,0,0,67,0,0,0,115,44,0,0, + 0,116,0,160,1,124,1,100,1,161,2,143,22,125,2,124, + 2,160,2,161,0,87,0,2,0,53,0,81,0,82,0,163, + 0,83,0,81,0,82,0,88,0,100,2,83,0,41,3,122, + 39,82,101,116,117,114,110,32,116,104,101,32,100,97,116,97, + 32,102,114,111,109,32,112,97,116,104,32,97,115,32,114,97, + 119,32,98,121,116,101,115,46,218,1,114,78,41,3,114,64, + 0,0,0,114,65,0,0,0,90,4,114,101,97,100,41,3, + 114,119,0,0,0,114,44,0,0,0,114,68,0,0,0,114, + 3,0,0,0,114,3,0,0,0,114,6,0,0,0,114,227, + 0,0,0,196,3,0,0,115,4,0,0,0,0,2,14,1, + 122,19,70,105,108,101,76,111,97,100,101,114,46,103,101,116, + 95,100,97,116,97,99,2,0,0,0,0,0,0,0,0,0, + 0,0,2,0,0,0,3,0,0,0,67,0,0,0,115,18, + 0,0,0,124,0,160,0,124,1,161,1,114,14,124,0,83, + 0,100,0,83,0,114,110,0,0,0,41,1,114,182,0,0, + 0,169,2,114,119,0,0,0,114,216,0,0,0,114,3,0, + 0,0,114,3,0,0,0,114,6,0,0,0,218,19,103,101, + 116,95,114,101,115,111,117,114,99,101,95,114,101,97,100,101, + 114,203,3,0,0,115,6,0,0,0,0,2,10,1,4,1, + 122,30,70,105,108,101,76,111,97,100,101,114,46,103,101,116, + 95,114,101,115,111,117,114,99,101,95,114,101,97,100,101,114, + 99,2,0,0,0,0,0,0,0,0,0,0,0,3,0,0, 0,4,0,0,0,67,0,0,0,115,32,0,0,0,116,0, 116,1,124,0,106,2,131,1,100,1,25,0,124,1,131,2, 125,2,116,3,160,4,124,2,100,2,161,2,83,0,41,3, @@ -1476,53 +1491,54 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,114,65,0,0,0,169,3,114,119,0,0,0,90,8,114, 101,115,111,117,114,99,101,114,44,0,0,0,114,3,0,0, 0,114,3,0,0,0,114,6,0,0,0,218,13,111,112,101, - 110,95,114,101,115,111,117,114,99,101,208,3,0,0,115,4, + 110,95,114,101,115,111,117,114,99,101,209,3,0,0,115,4, 0,0,0,0,1,20,1,122,24,70,105,108,101,76,111,97, 100,101,114,46,111,112,101,110,95,114,101,115,111,117,114,99, - 101,99,2,0,0,0,0,0,0,0,3,0,0,0,3,0, - 0,0,67,0,0,0,115,38,0,0,0,124,0,160,0,124, - 1,161,1,115,14,116,1,130,1,116,2,116,3,124,0,106, - 4,131,1,100,1,25,0,124,1,131,2,125,2,124,2,83, - 0,169,2,78,114,73,0,0,0,41,5,218,11,105,115,95, - 114,101,115,111,117,114,99,101,218,17,70,105,108,101,78,111, - 116,70,111,117,110,100,69,114,114,111,114,114,38,0,0,0, - 114,47,0,0,0,114,44,0,0,0,114,254,0,0,0,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,218,13, - 114,101,115,111,117,114,99,101,95,112,97,116,104,212,3,0, - 0,115,8,0,0,0,0,1,10,1,4,1,20,1,122,24, - 70,105,108,101,76,111,97,100,101,114,46,114,101,115,111,117, - 114,99,101,95,112,97,116,104,99,2,0,0,0,0,0,0, - 0,3,0,0,0,3,0,0,0,67,0,0,0,115,40,0, - 0,0,116,0,124,1,107,6,114,12,100,1,83,0,116,1, - 116,2,124,0,106,3,131,1,100,2,25,0,124,1,131,2, - 125,2,116,4,124,2,131,1,83,0,41,3,78,70,114,73, - 0,0,0,41,5,114,35,0,0,0,114,38,0,0,0,114, - 47,0,0,0,114,44,0,0,0,114,54,0,0,0,169,3, - 114,119,0,0,0,114,117,0,0,0,114,44,0,0,0,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,114,1, - 1,0,0,218,3,0,0,115,8,0,0,0,0,1,8,1, - 4,1,20,1,122,22,70,105,108,101,76,111,97,100,101,114, - 46,105,115,95,114,101,115,111,117,114,99,101,99,1,0,0, - 0,0,0,0,0,1,0,0,0,5,0,0,0,67,0,0, - 0,115,24,0,0,0,116,0,116,1,160,2,116,3,124,0, - 106,4,131,1,100,1,25,0,161,1,131,1,83,0,114,0, - 1,0,0,41,5,218,4,105,116,101,114,114,2,0,0,0, - 218,7,108,105,115,116,100,105,114,114,47,0,0,0,114,44, - 0,0,0,114,246,0,0,0,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,218,8,99,111,110,116,101,110,116, - 115,224,3,0,0,115,2,0,0,0,0,1,122,19,70,105, - 108,101,76,111,97,100,101,114,46,99,111,110,116,101,110,116, - 115,41,17,114,125,0,0,0,114,124,0,0,0,114,126,0, - 0,0,114,127,0,0,0,114,209,0,0,0,114,243,0,0, - 0,114,247,0,0,0,114,136,0,0,0,114,220,0,0,0, - 114,179,0,0,0,114,227,0,0,0,114,253,0,0,0,114, - 255,0,0,0,114,3,1,0,0,114,1,1,0,0,114,7, - 1,0,0,90,13,95,95,99,108,97,115,115,99,101,108,108, - 95,95,114,3,0,0,0,114,3,0,0,0,114,249,0,0, - 0,114,6,0,0,0,114,239,0,0,0,160,3,0,0,115, - 30,0,0,0,8,2,4,3,8,6,8,4,8,3,2,1, - 14,11,2,1,10,4,8,7,2,1,10,5,8,4,8,6, - 8,6,114,239,0,0,0,99,0,0,0,0,0,0,0,0, + 101,99,2,0,0,0,0,0,0,0,0,0,0,0,3,0, + 0,0,3,0,0,0,67,0,0,0,115,38,0,0,0,124, + 0,160,0,124,1,161,1,115,14,116,1,130,1,116,2,116, + 3,124,0,106,4,131,1,100,1,25,0,124,1,131,2,125, + 2,124,2,83,0,169,2,78,114,73,0,0,0,41,5,218, + 11,105,115,95,114,101,115,111,117,114,99,101,218,17,70,105, + 108,101,78,111,116,70,111,117,110,100,69,114,114,111,114,114, + 38,0,0,0,114,47,0,0,0,114,44,0,0,0,114,254, + 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, + 0,0,218,13,114,101,115,111,117,114,99,101,95,112,97,116, + 104,213,3,0,0,115,8,0,0,0,0,1,10,1,4,1, + 20,1,122,24,70,105,108,101,76,111,97,100,101,114,46,114, + 101,115,111,117,114,99,101,95,112,97,116,104,99,2,0,0, + 0,0,0,0,0,0,0,0,0,3,0,0,0,3,0,0, + 0,67,0,0,0,115,40,0,0,0,116,0,124,1,107,6, + 114,12,100,1,83,0,116,1,116,2,124,0,106,3,131,1, + 100,2,25,0,124,1,131,2,125,2,116,4,124,2,131,1, + 83,0,41,3,78,70,114,73,0,0,0,41,5,114,35,0, + 0,0,114,38,0,0,0,114,47,0,0,0,114,44,0,0, + 0,114,54,0,0,0,169,3,114,119,0,0,0,114,117,0, + 0,0,114,44,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,114,1,1,0,0,219,3,0,0,115, + 8,0,0,0,0,1,8,1,4,1,20,1,122,22,70,105, + 108,101,76,111,97,100,101,114,46,105,115,95,114,101,115,111, + 117,114,99,101,99,1,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,5,0,0,0,67,0,0,0,115,24,0, + 0,0,116,0,116,1,160,2,116,3,124,0,106,4,131,1, + 100,1,25,0,161,1,131,1,83,0,114,0,1,0,0,41, + 5,218,4,105,116,101,114,114,2,0,0,0,218,7,108,105, + 115,116,100,105,114,114,47,0,0,0,114,44,0,0,0,114, + 246,0,0,0,114,3,0,0,0,114,3,0,0,0,114,6, + 0,0,0,218,8,99,111,110,116,101,110,116,115,225,3,0, + 0,115,2,0,0,0,0,1,122,19,70,105,108,101,76,111, + 97,100,101,114,46,99,111,110,116,101,110,116,115,41,17,114, + 125,0,0,0,114,124,0,0,0,114,126,0,0,0,114,127, + 0,0,0,114,209,0,0,0,114,243,0,0,0,114,247,0, + 0,0,114,136,0,0,0,114,220,0,0,0,114,179,0,0, + 0,114,227,0,0,0,114,253,0,0,0,114,255,0,0,0, + 114,3,1,0,0,114,1,1,0,0,114,7,1,0,0,90, + 13,95,95,99,108,97,115,115,99,101,108,108,95,95,114,3, + 0,0,0,114,3,0,0,0,114,249,0,0,0,114,6,0, + 0,0,114,239,0,0,0,161,3,0,0,115,30,0,0,0, + 8,2,4,3,8,6,8,4,8,3,2,1,14,11,2,1, + 10,4,8,7,2,1,10,5,8,4,8,6,8,6,114,239, + 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,3,0,0,0,64,0,0,0,115,46,0,0, 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,100, 3,132,0,90,4,100,4,100,5,132,0,90,5,100,6,100, @@ -1532,72 +1548,73 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32, 83,111,117,114,99,101,76,111,97,100,101,114,32,117,115,105, 110,103,32,116,104,101,32,102,105,108,101,32,115,121,115,116, - 101,109,46,99,2,0,0,0,0,0,0,0,3,0,0,0, - 3,0,0,0,67,0,0,0,115,22,0,0,0,116,0,124, - 1,131,1,125,2,124,2,106,1,124,2,106,2,100,1,156, - 2,83,0,41,2,122,33,82,101,116,117,114,110,32,116,104, - 101,32,109,101,116,97,100,97,116,97,32,102,111,114,32,116, - 104,101,32,112,97,116,104,46,41,2,114,169,0,0,0,114, - 234,0,0,0,41,3,114,49,0,0,0,218,8,115,116,95, - 109,116,105,109,101,90,7,115,116,95,115,105,122,101,41,3, - 114,119,0,0,0,114,44,0,0,0,114,238,0,0,0,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,114,224, - 0,0,0,232,3,0,0,115,4,0,0,0,0,2,8,1, - 122,27,83,111,117,114,99,101,70,105,108,101,76,111,97,100, - 101,114,46,112,97,116,104,95,115,116,97,116,115,99,4,0, - 0,0,0,0,0,0,5,0,0,0,5,0,0,0,67,0, - 0,0,115,24,0,0,0,116,0,124,1,131,1,125,4,124, - 0,106,1,124,2,124,3,124,4,100,1,141,3,83,0,41, - 2,78,169,1,218,5,95,109,111,100,101,41,2,114,115,0, - 0,0,114,225,0,0,0,41,5,114,119,0,0,0,114,108, - 0,0,0,114,107,0,0,0,114,26,0,0,0,114,52,0, - 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,114,226,0,0,0,237,3,0,0,115,4,0,0,0,0, - 2,8,1,122,32,83,111,117,114,99,101,70,105,108,101,76, - 111,97,100,101,114,46,95,99,97,99,104,101,95,98,121,116, - 101,99,111,100,101,114,60,0,0,0,114,10,1,0,0,99, - 3,0,0,0,1,0,0,0,9,0,0,0,11,0,0,0, - 67,0,0,0,115,0,1,0,0,116,0,124,1,131,1,92, - 2,125,4,125,5,103,0,125,6,124,4,114,52,116,1,124, - 4,131,1,115,52,116,0,124,4,131,1,92,2,125,4,125, - 7,124,6,160,2,124,7,161,1,1,0,113,16,116,3,124, - 6,131,1,68,0,93,112,125,7,116,4,124,4,124,7,131, - 2,125,4,122,14,116,5,160,6,124,4,161,1,1,0,87, - 0,110,82,4,0,116,7,107,10,114,112,1,0,1,0,1, - 0,89,0,113,60,89,0,110,60,4,0,116,8,107,10,114, - 170,1,0,125,8,1,0,122,30,116,9,160,10,100,1,124, - 4,124,8,161,3,1,0,87,0,89,0,162,10,1,0,100, - 2,83,0,87,0,53,0,100,2,125,8,126,8,88,0,89, - 0,110,2,88,0,113,60,122,28,116,11,124,1,124,2,124, - 3,131,3,1,0,116,9,160,10,100,3,124,1,161,2,1, - 0,87,0,110,48,4,0,116,8,107,10,114,250,1,0,125, - 8,1,0,122,18,116,9,160,10,100,1,124,1,124,8,161, - 3,1,0,87,0,53,0,100,2,125,8,126,8,88,0,89, - 0,110,2,88,0,100,2,83,0,41,4,122,27,87,114,105, - 116,101,32,98,121,116,101,115,32,100,97,116,97,32,116,111, - 32,97,32,102,105,108,101,46,122,27,99,111,117,108,100,32, - 110,111,116,32,99,114,101,97,116,101,32,123,33,114,125,58, - 32,123,33,114,125,78,122,12,99,114,101,97,116,101,100,32, - 123,33,114,125,41,12,114,47,0,0,0,114,56,0,0,0, - 114,186,0,0,0,114,42,0,0,0,114,38,0,0,0,114, - 2,0,0,0,90,5,109,107,100,105,114,218,15,70,105,108, - 101,69,120,105,115,116,115,69,114,114,111,114,114,50,0,0, - 0,114,134,0,0,0,114,149,0,0,0,114,69,0,0,0, - 41,9,114,119,0,0,0,114,44,0,0,0,114,26,0,0, - 0,114,11,1,0,0,218,6,112,97,114,101,110,116,114,97, - 0,0,0,114,37,0,0,0,114,33,0,0,0,114,228,0, - 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,114,225,0,0,0,242,3,0,0,115,48,0,0,0,0, - 2,12,1,4,2,12,1,12,1,12,2,12,1,10,1,2, - 1,14,1,14,2,8,1,16,3,6,1,2,0,2,255,4, - 2,32,1,2,1,12,1,16,1,16,2,8,1,2,255,122, - 25,83,111,117,114,99,101,70,105,108,101,76,111,97,100,101, - 114,46,115,101,116,95,100,97,116,97,78,41,7,114,125,0, - 0,0,114,124,0,0,0,114,126,0,0,0,114,127,0,0, - 0,114,224,0,0,0,114,226,0,0,0,114,225,0,0,0, - 114,3,0,0,0,114,3,0,0,0,114,3,0,0,0,114, - 6,0,0,0,114,8,1,0,0,228,3,0,0,115,8,0, - 0,0,8,2,4,2,8,5,8,5,114,8,1,0,0,99, + 101,109,46,99,2,0,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,3,0,0,0,67,0,0,0,115,22,0,0, + 0,116,0,124,1,131,1,125,2,124,2,106,1,124,2,106, + 2,100,1,156,2,83,0,41,2,122,33,82,101,116,117,114, + 110,32,116,104,101,32,109,101,116,97,100,97,116,97,32,102, + 111,114,32,116,104,101,32,112,97,116,104,46,41,2,114,169, + 0,0,0,114,234,0,0,0,41,3,114,49,0,0,0,218, + 8,115,116,95,109,116,105,109,101,90,7,115,116,95,115,105, + 122,101,41,3,114,119,0,0,0,114,44,0,0,0,114,238, + 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, + 0,0,114,224,0,0,0,233,3,0,0,115,4,0,0,0, + 0,2,8,1,122,27,83,111,117,114,99,101,70,105,108,101, + 76,111,97,100,101,114,46,112,97,116,104,95,115,116,97,116, + 115,99,4,0,0,0,0,0,0,0,0,0,0,0,5,0, + 0,0,5,0,0,0,67,0,0,0,115,24,0,0,0,116, + 0,124,1,131,1,125,4,124,0,106,1,124,2,124,3,124, + 4,100,1,141,3,83,0,41,2,78,169,1,218,5,95,109, + 111,100,101,41,2,114,115,0,0,0,114,225,0,0,0,41, + 5,114,119,0,0,0,114,108,0,0,0,114,107,0,0,0, + 114,26,0,0,0,114,52,0,0,0,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,114,226,0,0,0,238,3, + 0,0,115,4,0,0,0,0,2,8,1,122,32,83,111,117, + 114,99,101,70,105,108,101,76,111,97,100,101,114,46,95,99, + 97,99,104,101,95,98,121,116,101,99,111,100,101,114,60,0, + 0,0,114,10,1,0,0,99,3,0,0,0,0,0,0,0, + 1,0,0,0,9,0,0,0,11,0,0,0,67,0,0,0, + 115,0,1,0,0,116,0,124,1,131,1,92,2,125,4,125, + 5,103,0,125,6,124,4,114,52,116,1,124,4,131,1,115, + 52,116,0,124,4,131,1,92,2,125,4,125,7,124,6,160, + 2,124,7,161,1,1,0,113,16,116,3,124,6,131,1,68, + 0,93,112,125,7,116,4,124,4,124,7,131,2,125,4,122, + 14,116,5,160,6,124,4,161,1,1,0,87,0,110,82,4, + 0,116,7,107,10,114,112,1,0,1,0,1,0,89,0,113, + 60,89,0,110,60,4,0,116,8,107,10,114,170,1,0,125, + 8,1,0,122,30,116,9,160,10,100,1,124,4,124,8,161, + 3,1,0,87,0,89,0,162,10,1,0,100,2,83,0,87, + 0,53,0,100,2,125,8,126,8,88,0,89,0,110,2,88, + 0,113,60,122,28,116,11,124,1,124,2,124,3,131,3,1, + 0,116,9,160,10,100,3,124,1,161,2,1,0,87,0,110, + 48,4,0,116,8,107,10,114,250,1,0,125,8,1,0,122, + 18,116,9,160,10,100,1,124,1,124,8,161,3,1,0,87, + 0,53,0,100,2,125,8,126,8,88,0,89,0,110,2,88, + 0,100,2,83,0,41,4,122,27,87,114,105,116,101,32,98, + 121,116,101,115,32,100,97,116,97,32,116,111,32,97,32,102, + 105,108,101,46,122,27,99,111,117,108,100,32,110,111,116,32, + 99,114,101,97,116,101,32,123,33,114,125,58,32,123,33,114, + 125,78,122,12,99,114,101,97,116,101,100,32,123,33,114,125, + 41,12,114,47,0,0,0,114,56,0,0,0,114,186,0,0, + 0,114,42,0,0,0,114,38,0,0,0,114,2,0,0,0, + 90,5,109,107,100,105,114,218,15,70,105,108,101,69,120,105, + 115,116,115,69,114,114,111,114,114,50,0,0,0,114,134,0, + 0,0,114,149,0,0,0,114,69,0,0,0,41,9,114,119, + 0,0,0,114,44,0,0,0,114,26,0,0,0,114,11,1, + 0,0,218,6,112,97,114,101,110,116,114,97,0,0,0,114, + 37,0,0,0,114,33,0,0,0,114,228,0,0,0,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,114,225,0, + 0,0,243,3,0,0,115,48,0,0,0,0,2,12,1,4, + 2,12,1,12,1,12,2,12,1,10,1,2,1,14,1,14, + 2,8,1,16,3,6,1,2,0,2,255,4,2,32,1,2, + 1,12,1,16,1,16,2,8,1,2,255,122,25,83,111,117, + 114,99,101,70,105,108,101,76,111,97,100,101,114,46,115,101, + 116,95,100,97,116,97,78,41,7,114,125,0,0,0,114,124, + 0,0,0,114,126,0,0,0,114,127,0,0,0,114,224,0, + 0,0,114,226,0,0,0,114,225,0,0,0,114,3,0,0, + 0,114,3,0,0,0,114,3,0,0,0,114,6,0,0,0, + 114,8,1,0,0,229,3,0,0,115,8,0,0,0,8,2, + 4,2,8,5,8,5,114,8,1,0,0,99,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, 64,0,0,0,115,32,0,0,0,101,0,90,1,100,0,90, 2,100,1,90,3,100,2,100,3,132,0,90,4,100,4,100, @@ -1606,93 +1623,95 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,122,45,76,111,97,100,101,114,32,119,104,105,99,104,32, 104,97,110,100,108,101,115,32,115,111,117,114,99,101,108,101, 115,115,32,102,105,108,101,32,105,109,112,111,114,116,115,46, - 99,2,0,0,0,0,0,0,0,5,0,0,0,5,0,0, - 0,67,0,0,0,115,68,0,0,0,124,0,160,0,124,1, - 161,1,125,2,124,0,160,1,124,2,161,1,125,3,124,1, - 124,2,100,1,156,2,125,4,116,2,124,3,124,1,124,4, - 131,3,1,0,116,3,116,4,124,3,131,1,100,2,100,0, - 133,2,25,0,124,1,124,2,100,3,141,3,83,0,41,4, - 78,114,159,0,0,0,114,145,0,0,0,41,2,114,117,0, - 0,0,114,107,0,0,0,41,5,114,179,0,0,0,114,227, - 0,0,0,114,152,0,0,0,114,165,0,0,0,114,235,0, - 0,0,41,5,114,119,0,0,0,114,139,0,0,0,114,44, - 0,0,0,114,26,0,0,0,114,151,0,0,0,114,3,0, - 0,0,114,3,0,0,0,114,6,0,0,0,114,213,0,0, - 0,21,4,0,0,115,22,0,0,0,0,1,10,1,10,4, - 2,1,2,254,6,4,12,1,2,1,14,1,2,1,2,253, - 122,29,83,111,117,114,99,101,108,101,115,115,70,105,108,101, - 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,4,0,0,0,100,1,83,0,41,2,122, - 39,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, - 116,104,101,114,101,32,105,115,32,110,111,32,115,111,117,114, - 99,101,32,99,111,100,101,46,78,114,3,0,0,0,114,219, - 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, - 0,0,114,229,0,0,0,37,4,0,0,115,2,0,0,0, - 0,2,122,31,83,111,117,114,99,101,108,101,115,115,70,105, - 108,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, - 114,99,101,78,41,6,114,125,0,0,0,114,124,0,0,0, - 114,126,0,0,0,114,127,0,0,0,114,213,0,0,0,114, - 229,0,0,0,114,3,0,0,0,114,3,0,0,0,114,3, - 0,0,0,114,6,0,0,0,114,14,1,0,0,17,4,0, - 0,115,6,0,0,0,8,2,4,2,8,16,114,14,1,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,3,0, - 0,0,64,0,0,0,115,92,0,0,0,101,0,90,1,100, - 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, - 4,100,5,132,0,90,5,100,6,100,7,132,0,90,6,100, - 8,100,9,132,0,90,7,100,10,100,11,132,0,90,8,100, - 12,100,13,132,0,90,9,100,14,100,15,132,0,90,10,100, - 16,100,17,132,0,90,11,101,12,100,18,100,19,132,0,131, - 1,90,13,100,20,83,0,41,21,218,19,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,122,93, - 76,111,97,100,101,114,32,102,111,114,32,101,120,116,101,110, - 115,105,111,110,32,109,111,100,117,108,101,115,46,10,10,32, - 32,32,32,84,104,101,32,99,111,110,115,116,114,117,99,116, - 111,114,32,105,115,32,100,101,115,105,103,110,101,100,32,116, - 111,32,119,111,114,107,32,119,105,116,104,32,70,105,108,101, - 70,105,110,100,101,114,46,10,10,32,32,32,32,99,3,0, + 99,2,0,0,0,0,0,0,0,0,0,0,0,5,0,0, + 0,5,0,0,0,67,0,0,0,115,68,0,0,0,124,0, + 160,0,124,1,161,1,125,2,124,0,160,1,124,2,161,1, + 125,3,124,1,124,2,100,1,156,2,125,4,116,2,124,3, + 124,1,124,4,131,3,1,0,116,3,116,4,124,3,131,1, + 100,2,100,0,133,2,25,0,124,1,124,2,100,3,141,3, + 83,0,41,4,78,114,159,0,0,0,114,145,0,0,0,41, + 2,114,117,0,0,0,114,107,0,0,0,41,5,114,179,0, + 0,0,114,227,0,0,0,114,152,0,0,0,114,165,0,0, + 0,114,235,0,0,0,41,5,114,119,0,0,0,114,139,0, + 0,0,114,44,0,0,0,114,26,0,0,0,114,151,0,0, + 0,114,3,0,0,0,114,3,0,0,0,114,6,0,0,0, + 114,213,0,0,0,22,4,0,0,115,22,0,0,0,0,1, + 10,1,10,4,2,1,2,254,6,4,12,1,2,1,14,1, + 2,1,2,253,122,29,83,111,117,114,99,101,108,101,115,115, + 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,99, + 111,100,101,99,2,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, + 0,100,1,83,0,41,2,122,39,82,101,116,117,114,110,32, + 78,111,110,101,32,97,115,32,116,104,101,114,101,32,105,115, + 32,110,111,32,115,111,117,114,99,101,32,99,111,100,101,46, + 78,114,3,0,0,0,114,219,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,229,0,0,0,38, + 4,0,0,115,2,0,0,0,0,2,122,31,83,111,117,114, + 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, + 46,103,101,116,95,115,111,117,114,99,101,78,41,6,114,125, + 0,0,0,114,124,0,0,0,114,126,0,0,0,114,127,0, + 0,0,114,213,0,0,0,114,229,0,0,0,114,3,0,0, + 0,114,3,0,0,0,114,3,0,0,0,114,6,0,0,0, + 114,14,1,0,0,18,4,0,0,115,6,0,0,0,8,2, + 4,2,8,16,114,14,1,0,0,99,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,3,0,0,0,64,0, + 0,0,115,92,0,0,0,101,0,90,1,100,0,90,2,100, + 1,90,3,100,2,100,3,132,0,90,4,100,4,100,5,132, + 0,90,5,100,6,100,7,132,0,90,6,100,8,100,9,132, + 0,90,7,100,10,100,11,132,0,90,8,100,12,100,13,132, + 0,90,9,100,14,100,15,132,0,90,10,100,16,100,17,132, + 0,90,11,101,12,100,18,100,19,132,0,131,1,90,13,100, + 20,83,0,41,21,218,19,69,120,116,101,110,115,105,111,110, + 70,105,108,101,76,111,97,100,101,114,122,93,76,111,97,100, + 101,114,32,102,111,114,32,101,120,116,101,110,115,105,111,110, + 32,109,111,100,117,108,101,115,46,10,10,32,32,32,32,84, + 104,101,32,99,111,110,115,116,114,117,99,116,111,114,32,105, + 115,32,100,101,115,105,103,110,101,100,32,116,111,32,119,111, + 114,107,32,119,105,116,104,32,70,105,108,101,70,105,110,100, + 101,114,46,10,10,32,32,32,32,99,3,0,0,0,0,0, 0,0,0,0,0,0,3,0,0,0,2,0,0,0,67,0, 0,0,115,16,0,0,0,124,1,124,0,95,0,124,2,124, 0,95,1,100,0,83,0,114,110,0,0,0,114,159,0,0, 0,114,4,1,0,0,114,3,0,0,0,114,3,0,0,0, - 114,6,0,0,0,114,209,0,0,0,54,4,0,0,115,4, + 114,6,0,0,0,114,209,0,0,0,55,4,0,0,115,4, 0,0,0,0,1,6,1,122,28,69,120,116,101,110,115,105, 111,110,70,105,108,101,76,111,97,100,101,114,46,95,95,105, - 110,105,116,95,95,99,2,0,0,0,0,0,0,0,2,0, - 0,0,2,0,0,0,67,0,0,0,115,24,0,0,0,124, - 0,106,0,124,1,106,0,107,2,111,22,124,0,106,1,124, - 1,106,1,107,2,83,0,114,110,0,0,0,114,240,0,0, - 0,114,242,0,0,0,114,3,0,0,0,114,3,0,0,0, - 114,6,0,0,0,114,243,0,0,0,58,4,0,0,115,6, - 0,0,0,0,1,12,1,10,255,122,26,69,120,116,101,110, + 110,105,116,95,95,99,2,0,0,0,0,0,0,0,0,0, + 0,0,2,0,0,0,2,0,0,0,67,0,0,0,115,24, + 0,0,0,124,0,106,0,124,1,106,0,107,2,111,22,124, + 0,106,1,124,1,106,1,107,2,83,0,114,110,0,0,0, + 114,240,0,0,0,114,242,0,0,0,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,114,243,0,0,0,59,4, + 0,0,115,6,0,0,0,0,1,12,1,10,255,122,26,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,46,95,95,101,113,95,95,99,1,0,0,0,0,0, + 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, + 0,0,115,20,0,0,0,116,0,124,0,106,1,131,1,116, + 0,124,0,106,2,131,1,65,0,83,0,114,110,0,0,0, + 114,244,0,0,0,114,246,0,0,0,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,114,247,0,0,0,63,4, + 0,0,115,2,0,0,0,0,1,122,28,69,120,116,101,110, 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,95, - 95,101,113,95,95,99,1,0,0,0,0,0,0,0,1,0, - 0,0,3,0,0,0,67,0,0,0,115,20,0,0,0,116, - 0,124,0,106,1,131,1,116,0,124,0,106,2,131,1,65, - 0,83,0,114,110,0,0,0,114,244,0,0,0,114,246,0, - 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,114,247,0,0,0,62,4,0,0,115,2,0,0,0,0, - 1,122,28,69,120,116,101,110,115,105,111,110,70,105,108,101, - 76,111,97,100,101,114,46,95,95,104,97,115,104,95,95,99, - 2,0,0,0,0,0,0,0,3,0,0,0,5,0,0,0, - 67,0,0,0,115,36,0,0,0,116,0,160,1,116,2,106, - 3,124,1,161,2,125,2,116,0,160,4,100,1,124,1,106, - 5,124,0,106,6,161,3,1,0,124,2,83,0,41,2,122, - 38,67,114,101,97,116,101,32,97,110,32,117,110,105,116,105, - 97,108,105,122,101,100,32,101,120,116,101,110,115,105,111,110, - 32,109,111,100,117,108,101,122,38,101,120,116,101,110,115,105, - 111,110,32,109,111,100,117,108,101,32,123,33,114,125,32,108, - 111,97,100,101,100,32,102,114,111,109,32,123,33,114,125,41, - 7,114,134,0,0,0,114,214,0,0,0,114,163,0,0,0, - 90,14,99,114,101,97,116,101,95,100,121,110,97,109,105,99, - 114,149,0,0,0,114,117,0,0,0,114,44,0,0,0,41, - 3,114,119,0,0,0,114,187,0,0,0,114,216,0,0,0, - 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, - 212,0,0,0,65,4,0,0,115,18,0,0,0,0,2,4, - 1,4,0,2,255,4,2,6,1,4,0,4,255,4,2,122, - 33,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,46,99,114,101,97,116,101,95,109,111,100,117, - 108,101,99,2,0,0,0,0,0,0,0,2,0,0,0,5, + 95,104,97,115,104,95,95,99,2,0,0,0,0,0,0,0, + 0,0,0,0,3,0,0,0,5,0,0,0,67,0,0,0, + 115,36,0,0,0,116,0,160,1,116,2,106,3,124,1,161, + 2,125,2,116,0,160,4,100,1,124,1,106,5,124,0,106, + 6,161,3,1,0,124,2,83,0,41,2,122,38,67,114,101, + 97,116,101,32,97,110,32,117,110,105,116,105,97,108,105,122, + 101,100,32,101,120,116,101,110,115,105,111,110,32,109,111,100, + 117,108,101,122,38,101,120,116,101,110,115,105,111,110,32,109, + 111,100,117,108,101,32,123,33,114,125,32,108,111,97,100,101, + 100,32,102,114,111,109,32,123,33,114,125,41,7,114,134,0, + 0,0,114,214,0,0,0,114,163,0,0,0,90,14,99,114, + 101,97,116,101,95,100,121,110,97,109,105,99,114,149,0,0, + 0,114,117,0,0,0,114,44,0,0,0,41,3,114,119,0, + 0,0,114,187,0,0,0,114,216,0,0,0,114,3,0,0, + 0,114,3,0,0,0,114,6,0,0,0,114,212,0,0,0, + 66,4,0,0,115,18,0,0,0,0,2,4,1,4,0,2, + 255,4,2,6,1,4,0,4,255,4,2,122,33,69,120,116, + 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, + 46,99,114,101,97,116,101,95,109,111,100,117,108,101,99,2, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,5, 0,0,0,67,0,0,0,115,36,0,0,0,116,0,160,1, 116,2,106,3,124,1,161,2,1,0,116,0,160,4,100,1, 124,0,106,5,124,0,106,6,161,3,1,0,100,2,83,0, @@ -1705,46 +1724,47 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 101,120,101,99,95,100,121,110,97,109,105,99,114,149,0,0, 0,114,117,0,0,0,114,44,0,0,0,114,252,0,0,0, 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, - 217,0,0,0,73,4,0,0,115,10,0,0,0,0,2,14, + 217,0,0,0,74,4,0,0,115,10,0,0,0,0,2,14, 1,6,1,4,0,4,255,122,31,69,120,116,101,110,115,105, 111,110,70,105,108,101,76,111,97,100,101,114,46,101,120,101, 99,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, - 0,2,0,0,0,4,0,0,0,3,0,0,0,115,36,0, - 0,0,116,0,124,0,106,1,131,1,100,1,25,0,137,0, - 116,2,135,0,102,1,100,2,100,3,132,8,116,3,68,0, - 131,1,131,1,83,0,41,4,122,49,82,101,116,117,114,110, - 32,84,114,117,101,32,105,102,32,116,104,101,32,101,120,116, - 101,110,115,105,111,110,32,109,111,100,117,108,101,32,105,115, - 32,97,32,112,97,99,107,97,103,101,46,114,39,0,0,0, - 99,1,0,0,0,0,0,0,0,2,0,0,0,4,0,0, - 0,51,0,0,0,115,26,0,0,0,124,0,93,18,125,1, - 136,0,100,0,124,1,23,0,107,2,86,0,1,0,113,2, - 100,1,83,0,41,2,114,209,0,0,0,78,114,3,0,0, - 0,169,2,114,32,0,0,0,218,6,115,117,102,102,105,120, - 169,1,90,9,102,105,108,101,95,110,97,109,101,114,3,0, - 0,0,114,6,0,0,0,218,9,60,103,101,110,101,120,112, - 114,62,82,4,0,0,115,4,0,0,0,4,1,2,255,122, - 49,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,46,105,115,95,112,97,99,107,97,103,101,46, - 60,108,111,99,97,108,115,62,46,60,103,101,110,101,120,112, - 114,62,41,4,114,47,0,0,0,114,44,0,0,0,218,3, - 97,110,121,218,18,69,88,84,69,78,83,73,79,78,95,83, - 85,70,70,73,88,69,83,114,219,0,0,0,114,3,0,0, - 0,114,18,1,0,0,114,6,0,0,0,114,182,0,0,0, - 79,4,0,0,115,8,0,0,0,0,2,14,1,12,1,2, - 255,122,30,69,120,116,101,110,115,105,111,110,70,105,108,101, - 76,111,97,100,101,114,46,105,115,95,112,97,99,107,97,103, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, - 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, - 2,122,63,82,101,116,117,114,110,32,78,111,110,101,32,97, - 115,32,97,110,32,101,120,116,101,110,115,105,111,110,32,109, - 111,100,117,108,101,32,99,97,110,110,111,116,32,99,114,101, - 97,116,101,32,97,32,99,111,100,101,32,111,98,106,101,99, - 116,46,78,114,3,0,0,0,114,219,0,0,0,114,3,0, - 0,0,114,3,0,0,0,114,6,0,0,0,114,213,0,0, - 0,85,4,0,0,115,2,0,0,0,0,2,122,28,69,120, - 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, - 114,46,103,101,116,95,99,111,100,101,99,2,0,0,0,0, + 0,0,0,0,0,2,0,0,0,4,0,0,0,3,0,0, + 0,115,36,0,0,0,116,0,124,0,106,1,131,1,100,1, + 25,0,137,0,116,2,135,0,102,1,100,2,100,3,132,8, + 116,3,68,0,131,1,131,1,83,0,41,4,122,49,82,101, + 116,117,114,110,32,84,114,117,101,32,105,102,32,116,104,101, + 32,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, + 101,32,105,115,32,97,32,112,97,99,107,97,103,101,46,114, + 39,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,4,0,0,0,51,0,0,0,115,26,0, + 0,0,124,0,93,18,125,1,136,0,100,0,124,1,23,0, + 107,2,86,0,1,0,113,2,100,1,83,0,41,2,114,209, + 0,0,0,78,114,3,0,0,0,169,2,114,32,0,0,0, + 218,6,115,117,102,102,105,120,169,1,90,9,102,105,108,101, + 95,110,97,109,101,114,3,0,0,0,114,6,0,0,0,218, + 9,60,103,101,110,101,120,112,114,62,83,4,0,0,115,4, + 0,0,0,4,1,2,255,122,49,69,120,116,101,110,115,105, + 111,110,70,105,108,101,76,111,97,100,101,114,46,105,115,95, + 112,97,99,107,97,103,101,46,60,108,111,99,97,108,115,62, + 46,60,103,101,110,101,120,112,114,62,41,4,114,47,0,0, + 0,114,44,0,0,0,218,3,97,110,121,218,18,69,88,84, + 69,78,83,73,79,78,95,83,85,70,70,73,88,69,83,114, + 219,0,0,0,114,3,0,0,0,114,18,1,0,0,114,6, + 0,0,0,114,182,0,0,0,80,4,0,0,115,8,0,0, + 0,0,2,14,1,12,1,2,255,122,30,69,120,116,101,110, + 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,105, + 115,95,112,97,99,107,97,103,101,99,2,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, + 0,0,115,4,0,0,0,100,1,83,0,41,2,122,63,82, + 101,116,117,114,110,32,78,111,110,101,32,97,115,32,97,110, + 32,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, + 101,32,99,97,110,110,111,116,32,99,114,101,97,116,101,32, + 97,32,99,111,100,101,32,111,98,106,101,99,116,46,78,114, + 3,0,0,0,114,219,0,0,0,114,3,0,0,0,114,3, + 0,0,0,114,6,0,0,0,114,213,0,0,0,86,4,0, + 0,115,2,0,0,0,0,2,122,28,69,120,116,101,110,115, + 105,111,110,70,105,108,101,76,111,97,100,101,114,46,103,101, + 116,95,99,111,100,101,99,2,0,0,0,0,0,0,0,0, 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, 4,0,0,0,100,1,83,0,41,2,122,53,82,101,116,117, 114,110,32,78,111,110,101,32,97,115,32,101,120,116,101,110, @@ -1752,67 +1772,68 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 101,32,110,111,32,115,111,117,114,99,101,32,99,111,100,101, 46,78,114,3,0,0,0,114,219,0,0,0,114,3,0,0, 0,114,3,0,0,0,114,6,0,0,0,114,229,0,0,0, - 89,4,0,0,115,2,0,0,0,0,2,122,30,69,120,116, + 90,4,0,0,115,2,0,0,0,0,2,122,30,69,120,116, 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, 46,103,101,116,95,115,111,117,114,99,101,99,2,0,0,0, - 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, - 115,6,0,0,0,124,0,106,0,83,0,114,250,0,0,0, - 114,48,0,0,0,114,219,0,0,0,114,3,0,0,0,114, - 3,0,0,0,114,6,0,0,0,114,179,0,0,0,93,4, - 0,0,115,2,0,0,0,0,3,122,32,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,103, - 101,116,95,102,105,108,101,110,97,109,101,78,41,14,114,125, - 0,0,0,114,124,0,0,0,114,126,0,0,0,114,127,0, - 0,0,114,209,0,0,0,114,243,0,0,0,114,247,0,0, - 0,114,212,0,0,0,114,217,0,0,0,114,182,0,0,0, - 114,213,0,0,0,114,229,0,0,0,114,136,0,0,0,114, - 179,0,0,0,114,3,0,0,0,114,3,0,0,0,114,3, - 0,0,0,114,6,0,0,0,114,15,1,0,0,46,4,0, - 0,115,22,0,0,0,8,2,4,6,8,4,8,4,8,3, - 8,8,8,6,8,6,8,4,8,4,2,1,114,15,1,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,64,0,0,0,115,104,0,0,0,101,0,90,1,100, - 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, - 4,100,5,132,0,90,5,100,6,100,7,132,0,90,6,100, - 8,100,9,132,0,90,7,100,10,100,11,132,0,90,8,100, - 12,100,13,132,0,90,9,100,14,100,15,132,0,90,10,100, - 16,100,17,132,0,90,11,100,18,100,19,132,0,90,12,100, - 20,100,21,132,0,90,13,100,22,100,23,132,0,90,14,100, - 24,83,0,41,25,218,14,95,78,97,109,101,115,112,97,99, - 101,80,97,116,104,97,38,1,0,0,82,101,112,114,101,115, - 101,110,116,115,32,97,32,110,97,109,101,115,112,97,99,101, - 32,112,97,99,107,97,103,101,39,115,32,112,97,116,104,46, - 32,32,73,116,32,117,115,101,115,32,116,104,101,32,109,111, - 100,117,108,101,32,110,97,109,101,10,32,32,32,32,116,111, - 32,102,105,110,100,32,105,116,115,32,112,97,114,101,110,116, - 32,109,111,100,117,108,101,44,32,97,110,100,32,102,114,111, - 109,32,116,104,101,114,101,32,105,116,32,108,111,111,107,115, - 32,117,112,32,116,104,101,32,112,97,114,101,110,116,39,115, - 10,32,32,32,32,95,95,112,97,116,104,95,95,46,32,32, - 87,104,101,110,32,116,104,105,115,32,99,104,97,110,103,101, - 115,44,32,116,104,101,32,109,111,100,117,108,101,39,115,32, - 111,119,110,32,112,97,116,104,32,105,115,32,114,101,99,111, - 109,112,117,116,101,100,44,10,32,32,32,32,117,115,105,110, - 103,32,112,97,116,104,95,102,105,110,100,101,114,46,32,32, - 70,111,114,32,116,111,112,45,108,101,118,101,108,32,109,111, - 100,117,108,101,115,44,32,116,104,101,32,112,97,114,101,110, - 116,32,109,111,100,117,108,101,39,115,32,112,97,116,104,10, - 32,32,32,32,105,115,32,115,121,115,46,112,97,116,104,46, - 99,4,0,0,0,0,0,0,0,4,0,0,0,3,0,0, - 0,67,0,0,0,115,36,0,0,0,124,1,124,0,95,0, - 124,2,124,0,95,1,116,2,124,0,160,3,161,0,131,1, - 124,0,95,4,124,3,124,0,95,5,100,0,83,0,114,110, - 0,0,0,41,6,218,5,95,110,97,109,101,218,5,95,112, - 97,116,104,114,112,0,0,0,218,16,95,103,101,116,95,112, - 97,114,101,110,116,95,112,97,116,104,218,17,95,108,97,115, - 116,95,112,97,114,101,110,116,95,112,97,116,104,218,12,95, - 112,97,116,104,95,102,105,110,100,101,114,169,4,114,119,0, - 0,0,114,117,0,0,0,114,44,0,0,0,90,11,112,97, - 116,104,95,102,105,110,100,101,114,114,3,0,0,0,114,3, - 0,0,0,114,6,0,0,0,114,209,0,0,0,106,4,0, - 0,115,8,0,0,0,0,1,6,1,6,1,14,1,122,23, - 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, - 95,105,110,105,116,95,95,99,1,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, + 67,0,0,0,115,6,0,0,0,124,0,106,0,83,0,114, + 250,0,0,0,114,48,0,0,0,114,219,0,0,0,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,114,179,0, + 0,0,94,4,0,0,115,2,0,0,0,0,3,122,32,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,46,103,101,116,95,102,105,108,101,110,97,109,101,78, + 41,14,114,125,0,0,0,114,124,0,0,0,114,126,0,0, + 0,114,127,0,0,0,114,209,0,0,0,114,243,0,0,0, + 114,247,0,0,0,114,212,0,0,0,114,217,0,0,0,114, + 182,0,0,0,114,213,0,0,0,114,229,0,0,0,114,136, + 0,0,0,114,179,0,0,0,114,3,0,0,0,114,3,0, + 0,0,114,3,0,0,0,114,6,0,0,0,114,15,1,0, + 0,47,4,0,0,115,22,0,0,0,8,2,4,6,8,4, + 8,4,8,3,8,8,8,6,8,6,8,4,8,4,2,1, + 114,15,1,0,0,99,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,104, + 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, + 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, + 6,100,7,132,0,90,6,100,8,100,9,132,0,90,7,100, + 10,100,11,132,0,90,8,100,12,100,13,132,0,90,9,100, + 14,100,15,132,0,90,10,100,16,100,17,132,0,90,11,100, + 18,100,19,132,0,90,12,100,20,100,21,132,0,90,13,100, + 22,100,23,132,0,90,14,100,24,83,0,41,25,218,14,95, + 78,97,109,101,115,112,97,99,101,80,97,116,104,97,38,1, + 0,0,82,101,112,114,101,115,101,110,116,115,32,97,32,110, + 97,109,101,115,112,97,99,101,32,112,97,99,107,97,103,101, + 39,115,32,112,97,116,104,46,32,32,73,116,32,117,115,101, + 115,32,116,104,101,32,109,111,100,117,108,101,32,110,97,109, + 101,10,32,32,32,32,116,111,32,102,105,110,100,32,105,116, + 115,32,112,97,114,101,110,116,32,109,111,100,117,108,101,44, + 32,97,110,100,32,102,114,111,109,32,116,104,101,114,101,32, + 105,116,32,108,111,111,107,115,32,117,112,32,116,104,101,32, + 112,97,114,101,110,116,39,115,10,32,32,32,32,95,95,112, + 97,116,104,95,95,46,32,32,87,104,101,110,32,116,104,105, + 115,32,99,104,97,110,103,101,115,44,32,116,104,101,32,109, + 111,100,117,108,101,39,115,32,111,119,110,32,112,97,116,104, + 32,105,115,32,114,101,99,111,109,112,117,116,101,100,44,10, + 32,32,32,32,117,115,105,110,103,32,112,97,116,104,95,102, + 105,110,100,101,114,46,32,32,70,111,114,32,116,111,112,45, + 108,101,118,101,108,32,109,111,100,117,108,101,115,44,32,116, + 104,101,32,112,97,114,101,110,116,32,109,111,100,117,108,101, + 39,115,32,112,97,116,104,10,32,32,32,32,105,115,32,115, + 121,115,46,112,97,116,104,46,99,4,0,0,0,0,0,0, + 0,0,0,0,0,4,0,0,0,3,0,0,0,67,0,0, + 0,115,36,0,0,0,124,1,124,0,95,0,124,2,124,0, + 95,1,116,2,124,0,160,3,161,0,131,1,124,0,95,4, + 124,3,124,0,95,5,100,0,83,0,114,110,0,0,0,41, + 6,218,5,95,110,97,109,101,218,5,95,112,97,116,104,114, + 112,0,0,0,218,16,95,103,101,116,95,112,97,114,101,110, + 116,95,112,97,116,104,218,17,95,108,97,115,116,95,112,97, + 114,101,110,116,95,112,97,116,104,218,12,95,112,97,116,104, + 95,102,105,110,100,101,114,169,4,114,119,0,0,0,114,117, + 0,0,0,114,44,0,0,0,90,11,112,97,116,104,95,102, + 105,110,100,101,114,114,3,0,0,0,114,3,0,0,0,114, + 6,0,0,0,114,209,0,0,0,107,4,0,0,115,8,0, + 0,0,0,1,6,1,6,1,14,1,122,23,95,78,97,109, + 101,115,112,97,99,101,80,97,116,104,46,95,95,105,110,105, + 116,95,95,99,1,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,3,0,0,0,67,0,0,0,115,38,0,0, 0,124,0,106,0,160,1,100,1,161,1,92,3,125,1,125, 2,125,3,124,2,100,2,107,2,114,30,100,3,83,0,124, @@ -1827,119 +1848,122 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,218,3,100,111,116,90,2,109,101,114,3,0,0,0,114, 3,0,0,0,114,6,0,0,0,218,23,95,102,105,110,100, 95,112,97,114,101,110,116,95,112,97,116,104,95,110,97,109, - 101,115,112,4,0,0,115,8,0,0,0,0,2,18,1,8, + 101,115,113,4,0,0,115,8,0,0,0,0,2,18,1,8, 2,4,3,122,38,95,78,97,109,101,115,112,97,99,101,80, 97,116,104,46,95,102,105,110,100,95,112,97,114,101,110,116, 95,112,97,116,104,95,110,97,109,101,115,99,1,0,0,0, - 0,0,0,0,3,0,0,0,3,0,0,0,67,0,0,0, - 115,28,0,0,0,124,0,160,0,161,0,92,2,125,1,125, - 2,116,1,116,2,106,3,124,1,25,0,124,2,131,2,83, - 0,114,110,0,0,0,41,4,114,30,1,0,0,114,130,0, - 0,0,114,8,0,0,0,218,7,109,111,100,117,108,101,115, - 41,3,114,119,0,0,0,90,18,112,97,114,101,110,116,95, - 109,111,100,117,108,101,95,110,97,109,101,90,14,112,97,116, - 104,95,97,116,116,114,95,110,97,109,101,114,3,0,0,0, - 114,3,0,0,0,114,6,0,0,0,114,25,1,0,0,122, - 4,0,0,115,4,0,0,0,0,1,12,1,122,31,95,78, - 97,109,101,115,112,97,99,101,80,97,116,104,46,95,103,101, - 116,95,112,97,114,101,110,116,95,112,97,116,104,99,1,0, - 0,0,0,0,0,0,3,0,0,0,4,0,0,0,67,0, - 0,0,115,80,0,0,0,116,0,124,0,160,1,161,0,131, - 1,125,1,124,1,124,0,106,2,107,3,114,74,124,0,160, - 3,124,0,106,4,124,1,161,2,125,2,124,2,100,0,107, - 9,114,68,124,2,106,5,100,0,107,8,114,68,124,2,106, - 6,114,68,124,2,106,6,124,0,95,7,124,1,124,0,95, - 2,124,0,106,7,83,0,114,110,0,0,0,41,8,114,112, - 0,0,0,114,25,1,0,0,114,26,1,0,0,114,27,1, - 0,0,114,23,1,0,0,114,140,0,0,0,114,178,0,0, - 0,114,24,1,0,0,41,3,114,119,0,0,0,90,11,112, - 97,114,101,110,116,95,112,97,116,104,114,187,0,0,0,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,218,12, - 95,114,101,99,97,108,99,117,108,97,116,101,126,4,0,0, - 115,16,0,0,0,0,2,12,1,10,1,14,3,18,1,6, - 1,8,1,6,1,122,27,95,78,97,109,101,115,112,97,99, - 101,80,97,116,104,46,95,114,101,99,97,108,99,117,108,97, - 116,101,99,1,0,0,0,0,0,0,0,1,0,0,0,3, - 0,0,0,67,0,0,0,115,12,0,0,0,116,0,124,0, - 160,1,161,0,131,1,83,0,114,110,0,0,0,41,2,114, - 5,1,0,0,114,32,1,0,0,114,246,0,0,0,114,3, - 0,0,0,114,3,0,0,0,114,6,0,0,0,218,8,95, - 95,105,116,101,114,95,95,139,4,0,0,115,2,0,0,0, - 0,1,122,23,95,78,97,109,101,115,112,97,99,101,80,97, - 116,104,46,95,95,105,116,101,114,95,95,99,2,0,0,0, + 0,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, + 67,0,0,0,115,28,0,0,0,124,0,160,0,161,0,92, + 2,125,1,125,2,116,1,116,2,106,3,124,1,25,0,124, + 2,131,2,83,0,114,110,0,0,0,41,4,114,30,1,0, + 0,114,130,0,0,0,114,8,0,0,0,218,7,109,111,100, + 117,108,101,115,41,3,114,119,0,0,0,90,18,112,97,114, + 101,110,116,95,109,111,100,117,108,101,95,110,97,109,101,90, + 14,112,97,116,104,95,97,116,116,114,95,110,97,109,101,114, + 3,0,0,0,114,3,0,0,0,114,6,0,0,0,114,25, + 1,0,0,123,4,0,0,115,4,0,0,0,0,1,12,1, + 122,31,95,78,97,109,101,115,112,97,99,101,80,97,116,104, + 46,95,103,101,116,95,112,97,114,101,110,116,95,112,97,116, + 104,99,1,0,0,0,0,0,0,0,0,0,0,0,3,0, + 0,0,4,0,0,0,67,0,0,0,115,80,0,0,0,116, + 0,124,0,160,1,161,0,131,1,125,1,124,1,124,0,106, + 2,107,3,114,74,124,0,160,3,124,0,106,4,124,1,161, + 2,125,2,124,2,100,0,107,9,114,68,124,2,106,5,100, + 0,107,8,114,68,124,2,106,6,114,68,124,2,106,6,124, + 0,95,7,124,1,124,0,95,2,124,0,106,7,83,0,114, + 110,0,0,0,41,8,114,112,0,0,0,114,25,1,0,0, + 114,26,1,0,0,114,27,1,0,0,114,23,1,0,0,114, + 140,0,0,0,114,178,0,0,0,114,24,1,0,0,41,3, + 114,119,0,0,0,90,11,112,97,114,101,110,116,95,112,97, + 116,104,114,187,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,218,12,95,114,101,99,97,108,99,117, + 108,97,116,101,127,4,0,0,115,16,0,0,0,0,2,12, + 1,10,1,14,3,18,1,6,1,8,1,6,1,122,27,95, + 78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,114, + 101,99,97,108,99,117,108,97,116,101,99,1,0,0,0,0, + 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, + 0,0,0,115,12,0,0,0,116,0,124,0,160,1,161,0, + 131,1,83,0,114,110,0,0,0,41,2,114,5,1,0,0, + 114,32,1,0,0,114,246,0,0,0,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,218,8,95,95,105,116,101, + 114,95,95,140,4,0,0,115,2,0,0,0,0,1,122,23, + 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, + 95,105,116,101,114,95,95,99,2,0,0,0,0,0,0,0, 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, 115,12,0,0,0,124,0,160,0,161,0,124,1,25,0,83, 0,114,110,0,0,0,169,1,114,32,1,0,0,41,2,114, 119,0,0,0,218,5,105,110,100,101,120,114,3,0,0,0, 114,3,0,0,0,114,6,0,0,0,218,11,95,95,103,101, - 116,105,116,101,109,95,95,142,4,0,0,115,2,0,0,0, + 116,105,116,101,109,95,95,143,4,0,0,115,2,0,0,0, 0,1,122,26,95,78,97,109,101,115,112,97,99,101,80,97, 116,104,46,95,95,103,101,116,105,116,101,109,95,95,99,3, - 0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,67, - 0,0,0,115,14,0,0,0,124,2,124,0,106,0,124,1, - 60,0,100,0,83,0,114,110,0,0,0,41,1,114,24,1, - 0,0,41,3,114,119,0,0,0,114,35,1,0,0,114,44, - 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, - 0,0,218,11,95,95,115,101,116,105,116,101,109,95,95,145, - 4,0,0,115,2,0,0,0,0,1,122,26,95,78,97,109, - 101,115,112,97,99,101,80,97,116,104,46,95,95,115,101,116, - 105,116,101,109,95,95,99,1,0,0,0,0,0,0,0,1, - 0,0,0,3,0,0,0,67,0,0,0,115,12,0,0,0, - 116,0,124,0,160,1,161,0,131,1,83,0,114,110,0,0, - 0,41,2,114,22,0,0,0,114,32,1,0,0,114,246,0, - 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,218,7,95,95,108,101,110,95,95,148,4,0,0,115,2, - 0,0,0,0,1,122,22,95,78,97,109,101,115,112,97,99, - 101,80,97,116,104,46,95,95,108,101,110,95,95,99,1,0, - 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, - 0,0,115,12,0,0,0,100,1,160,0,124,0,106,1,161, - 1,83,0,41,2,78,122,20,95,78,97,109,101,115,112,97, - 99,101,80,97,116,104,40,123,33,114,125,41,41,2,114,62, - 0,0,0,114,24,1,0,0,114,246,0,0,0,114,3,0, - 0,0,114,3,0,0,0,114,6,0,0,0,218,8,95,95, - 114,101,112,114,95,95,151,4,0,0,115,2,0,0,0,0, - 1,122,23,95,78,97,109,101,115,112,97,99,101,80,97,116, - 104,46,95,95,114,101,112,114,95,95,99,2,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,3, + 0,0,0,67,0,0,0,115,14,0,0,0,124,2,124,0, + 106,0,124,1,60,0,100,0,83,0,114,110,0,0,0,41, + 1,114,24,1,0,0,41,3,114,119,0,0,0,114,35,1, + 0,0,114,44,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,218,11,95,95,115,101,116,105,116,101, + 109,95,95,146,4,0,0,115,2,0,0,0,0,1,122,26, + 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, + 95,115,101,116,105,116,101,109,95,95,99,1,0,0,0,0, + 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, + 0,0,0,115,12,0,0,0,116,0,124,0,160,1,161,0, + 131,1,83,0,114,110,0,0,0,41,2,114,22,0,0,0, + 114,32,1,0,0,114,246,0,0,0,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,218,7,95,95,108,101,110, + 95,95,149,4,0,0,115,2,0,0,0,0,1,122,22,95, + 78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,95, + 108,101,110,95,95,99,1,0,0,0,0,0,0,0,0,0, + 0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,12, + 0,0,0,100,1,160,0,124,0,106,1,161,1,83,0,41, + 2,78,122,20,95,78,97,109,101,115,112,97,99,101,80,97, + 116,104,40,123,33,114,125,41,41,2,114,62,0,0,0,114, + 24,1,0,0,114,246,0,0,0,114,3,0,0,0,114,3, + 0,0,0,114,6,0,0,0,218,8,95,95,114,101,112,114, + 95,95,152,4,0,0,115,2,0,0,0,0,1,122,23,95, + 78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,95, + 114,101,112,114,95,95,99,2,0,0,0,0,0,0,0,0, 0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115, 12,0,0,0,124,1,124,0,160,0,161,0,107,6,83,0, 114,110,0,0,0,114,34,1,0,0,169,2,114,119,0,0, 0,218,4,105,116,101,109,114,3,0,0,0,114,3,0,0, 0,114,6,0,0,0,218,12,95,95,99,111,110,116,97,105, - 110,115,95,95,154,4,0,0,115,2,0,0,0,0,1,122, + 110,115,95,95,155,4,0,0,115,2,0,0,0,0,1,122, 27,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, 95,95,99,111,110,116,97,105,110,115,95,95,99,2,0,0, - 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, - 0,115,16,0,0,0,124,0,106,0,160,1,124,1,161,1, - 1,0,100,0,83,0,114,110,0,0,0,41,2,114,24,1, - 0,0,114,186,0,0,0,114,40,1,0,0,114,3,0,0, - 0,114,3,0,0,0,114,6,0,0,0,114,186,0,0,0, - 157,4,0,0,115,2,0,0,0,0,1,122,21,95,78,97, - 109,101,115,112,97,99,101,80,97,116,104,46,97,112,112,101, - 110,100,78,41,15,114,125,0,0,0,114,124,0,0,0,114, - 126,0,0,0,114,127,0,0,0,114,209,0,0,0,114,30, - 1,0,0,114,25,1,0,0,114,32,1,0,0,114,33,1, - 0,0,114,36,1,0,0,114,37,1,0,0,114,38,1,0, - 0,114,39,1,0,0,114,42,1,0,0,114,186,0,0,0, - 114,3,0,0,0,114,3,0,0,0,114,3,0,0,0,114, - 6,0,0,0,114,22,1,0,0,99,4,0,0,115,24,0, - 0,0,8,1,4,6,8,6,8,10,8,4,8,13,8,3, - 8,3,8,3,8,3,8,3,8,3,114,22,1,0,0,99, - 0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, - 64,0,0,0,115,80,0,0,0,101,0,90,1,100,0,90, - 2,100,1,100,2,132,0,90,3,101,4,100,3,100,4,132, - 0,131,1,90,5,100,5,100,6,132,0,90,6,100,7,100, - 8,132,0,90,7,100,9,100,10,132,0,90,8,100,11,100, - 12,132,0,90,9,100,13,100,14,132,0,90,10,100,15,100, - 16,132,0,90,11,100,17,83,0,41,18,218,16,95,78,97, - 109,101,115,112,97,99,101,76,111,97,100,101,114,99,4,0, - 0,0,0,0,0,0,4,0,0,0,4,0,0,0,67,0, - 0,0,115,18,0,0,0,116,0,124,1,124,2,124,3,131, - 3,124,0,95,1,100,0,83,0,114,110,0,0,0,41,2, - 114,22,1,0,0,114,24,1,0,0,114,28,1,0,0,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,114,209, - 0,0,0,163,4,0,0,115,2,0,0,0,0,1,122,25, - 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, - 46,95,95,105,110,105,116,95,95,99,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,0, + 0,67,0,0,0,115,16,0,0,0,124,0,106,0,160,1, + 124,1,161,1,1,0,100,0,83,0,114,110,0,0,0,41, + 2,114,24,1,0,0,114,186,0,0,0,114,40,1,0,0, + 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, + 186,0,0,0,158,4,0,0,115,2,0,0,0,0,1,122, + 21,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, + 97,112,112,101,110,100,78,41,15,114,125,0,0,0,114,124, + 0,0,0,114,126,0,0,0,114,127,0,0,0,114,209,0, + 0,0,114,30,1,0,0,114,25,1,0,0,114,32,1,0, + 0,114,33,1,0,0,114,36,1,0,0,114,37,1,0,0, + 114,38,1,0,0,114,39,1,0,0,114,42,1,0,0,114, + 186,0,0,0,114,3,0,0,0,114,3,0,0,0,114,3, + 0,0,0,114,6,0,0,0,114,22,1,0,0,100,4,0, + 0,115,24,0,0,0,8,1,4,6,8,6,8,10,8,4, + 8,13,8,3,8,3,8,3,8,3,8,3,8,3,114,22, + 1,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,3,0,0,0,64,0,0,0,115,80,0,0, + 0,101,0,90,1,100,0,90,2,100,1,100,2,132,0,90, + 3,101,4,100,3,100,4,132,0,131,1,90,5,100,5,100, + 6,132,0,90,6,100,7,100,8,132,0,90,7,100,9,100, + 10,132,0,90,8,100,11,100,12,132,0,90,9,100,13,100, + 14,132,0,90,10,100,15,100,16,132,0,90,11,100,17,83, + 0,41,18,218,16,95,78,97,109,101,115,112,97,99,101,76, + 111,97,100,101,114,99,4,0,0,0,0,0,0,0,0,0, + 0,0,4,0,0,0,4,0,0,0,67,0,0,0,115,18, + 0,0,0,116,0,124,1,124,2,124,3,131,3,124,0,95, + 1,100,0,83,0,114,110,0,0,0,41,2,114,22,1,0, + 0,114,24,1,0,0,114,28,1,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,209,0,0,0,164, + 4,0,0,115,2,0,0,0,0,1,122,25,95,78,97,109, + 101,115,112,97,99,101,76,111,97,100,101,114,46,95,95,105, + 110,105,116,95,95,99,2,0,0,0,0,0,0,0,0,0, 0,0,2,0,0,0,3,0,0,0,67,0,0,0,115,12, 0,0,0,100,1,160,0,124,1,106,1,161,1,83,0,41, 2,122,115,82,101,116,117,114,110,32,114,101,112,114,32,102, @@ -1954,84 +1978,86 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 62,41,2,114,62,0,0,0,114,125,0,0,0,41,2,114, 193,0,0,0,114,216,0,0,0,114,3,0,0,0,114,3, 0,0,0,114,6,0,0,0,218,11,109,111,100,117,108,101, - 95,114,101,112,114,166,4,0,0,115,2,0,0,0,0,7, + 95,114,101,112,114,167,4,0,0,115,2,0,0,0,0,7, 122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100, 101,114,46,109,111,100,117,108,101,95,114,101,112,114,99,2, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1, + 0,0,0,67,0,0,0,115,4,0,0,0,100,1,83,0, + 41,2,78,84,114,3,0,0,0,114,219,0,0,0,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,114,182,0, + 0,0,176,4,0,0,115,2,0,0,0,0,1,122,27,95, + 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, + 105,115,95,112,97,99,107,97,103,101,99,2,0,0,0,0, 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, - 0,0,0,115,4,0,0,0,100,1,83,0,41,2,78,84, - 114,3,0,0,0,114,219,0,0,0,114,3,0,0,0,114, - 3,0,0,0,114,6,0,0,0,114,182,0,0,0,175,4, - 0,0,115,2,0,0,0,0,1,122,27,95,78,97,109,101, - 115,112,97,99,101,76,111,97,100,101,114,46,105,115,95,112, - 97,99,107,97,103,101,99,2,0,0,0,0,0,0,0,2, - 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, - 100,1,83,0,41,2,78,114,40,0,0,0,114,3,0,0, - 0,114,219,0,0,0,114,3,0,0,0,114,3,0,0,0, - 114,6,0,0,0,114,229,0,0,0,178,4,0,0,115,2, - 0,0,0,0,1,122,27,95,78,97,109,101,115,112,97,99, - 101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, - 99,101,99,2,0,0,0,0,0,0,0,2,0,0,0,6, - 0,0,0,67,0,0,0,115,16,0,0,0,116,0,100,1, - 100,2,100,3,100,4,100,5,141,4,83,0,41,6,78,114, - 40,0,0,0,122,8,60,115,116,114,105,110,103,62,114,215, - 0,0,0,84,41,1,114,231,0,0,0,41,1,114,232,0, - 0,0,114,219,0,0,0,114,3,0,0,0,114,3,0,0, - 0,114,6,0,0,0,114,213,0,0,0,181,4,0,0,115, - 2,0,0,0,0,1,122,25,95,78,97,109,101,115,112,97, - 99,101,76,111,97,100,101,114,46,103,101,116,95,99,111,100, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, + 0,0,0,115,4,0,0,0,100,1,83,0,41,2,78,114, + 40,0,0,0,114,3,0,0,0,114,219,0,0,0,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,114,229,0, + 0,0,179,4,0,0,115,2,0,0,0,0,1,122,27,95, + 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, + 103,101,116,95,115,111,117,114,99,101,99,2,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,6,0,0,0,67, + 0,0,0,115,16,0,0,0,116,0,100,1,100,2,100,3, + 100,4,100,5,141,4,83,0,41,6,78,114,40,0,0,0, + 122,8,60,115,116,114,105,110,103,62,114,215,0,0,0,84, + 41,1,114,231,0,0,0,41,1,114,232,0,0,0,114,219, + 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, + 0,0,114,213,0,0,0,182,4,0,0,115,2,0,0,0, + 0,1,122,25,95,78,97,109,101,115,112,97,99,101,76,111, + 97,100,101,114,46,103,101,116,95,99,111,100,101,99,2,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,1,0, 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,114, 210,0,0,0,114,3,0,0,0,114,211,0,0,0,114,3, 0,0,0,114,3,0,0,0,114,6,0,0,0,114,212,0, - 0,0,184,4,0,0,115,2,0,0,0,0,1,122,30,95, + 0,0,185,4,0,0,115,2,0,0,0,0,1,122,30,95, 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, 99,114,101,97,116,101,95,109,111,100,117,108,101,99,2,0, - 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, - 0,0,115,4,0,0,0,100,0,83,0,114,110,0,0,0, - 114,3,0,0,0,114,252,0,0,0,114,3,0,0,0,114, - 3,0,0,0,114,6,0,0,0,114,217,0,0,0,187,4, - 0,0,115,2,0,0,0,0,1,122,28,95,78,97,109,101, - 115,112,97,99,101,76,111,97,100,101,114,46,101,120,101,99, - 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, - 2,0,0,0,4,0,0,0,67,0,0,0,115,26,0,0, - 0,116,0,160,1,100,1,124,0,106,2,161,2,1,0,116, - 0,160,3,124,0,124,1,161,2,83,0,41,2,122,98,76, - 111,97,100,32,97,32,110,97,109,101,115,112,97,99,101,32, - 109,111,100,117,108,101,46,10,10,32,32,32,32,32,32,32, - 32,84,104,105,115,32,109,101,116,104,111,100,32,105,115,32, - 100,101,112,114,101,99,97,116,101,100,46,32,32,85,115,101, - 32,101,120,101,99,95,109,111,100,117,108,101,40,41,32,105, - 110,115,116,101,97,100,46,10,10,32,32,32,32,32,32,32, - 32,122,38,110,97,109,101,115,112,97,99,101,32,109,111,100, - 117,108,101,32,108,111,97,100,101,100,32,119,105,116,104,32, - 112,97,116,104,32,123,33,114,125,41,4,114,134,0,0,0, - 114,149,0,0,0,114,24,1,0,0,114,218,0,0,0,114, - 219,0,0,0,114,3,0,0,0,114,3,0,0,0,114,6, - 0,0,0,114,220,0,0,0,190,4,0,0,115,8,0,0, - 0,0,7,6,1,4,255,4,2,122,28,95,78,97,109,101, - 115,112,97,99,101,76,111,97,100,101,114,46,108,111,97,100, - 95,109,111,100,117,108,101,78,41,12,114,125,0,0,0,114, - 124,0,0,0,114,126,0,0,0,114,209,0,0,0,114,207, - 0,0,0,114,44,1,0,0,114,182,0,0,0,114,229,0, - 0,0,114,213,0,0,0,114,212,0,0,0,114,217,0,0, - 0,114,220,0,0,0,114,3,0,0,0,114,3,0,0,0, - 114,3,0,0,0,114,6,0,0,0,114,43,1,0,0,162, - 4,0,0,115,18,0,0,0,8,1,8,3,2,1,10,8, - 8,3,8,3,8,3,8,3,8,3,114,43,1,0,0,99, - 0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, - 64,0,0,0,115,106,0,0,0,101,0,90,1,100,0,90, - 2,100,1,90,3,101,4,100,2,100,3,132,0,131,1,90, - 5,101,4,100,4,100,5,132,0,131,1,90,6,101,4,100, - 6,100,7,132,0,131,1,90,7,101,4,100,8,100,9,132, - 0,131,1,90,8,101,4,100,17,100,11,100,12,132,1,131, - 1,90,9,101,4,100,18,100,13,100,14,132,1,131,1,90, - 10,101,4,100,19,100,15,100,16,132,1,131,1,90,11,100, - 10,83,0,41,20,218,10,80,97,116,104,70,105,110,100,101, - 114,122,62,77,101,116,97,32,112,97,116,104,32,102,105,110, - 100,101,114,32,102,111,114,32,115,121,115,46,112,97,116,104, - 32,97,110,100,32,112,97,99,107,97,103,101,32,95,95,112, - 97,116,104,95,95,32,97,116,116,114,105,98,117,116,101,115, - 46,99,1,0,0,0,0,0,0,0,3,0,0,0,4,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,1,0, + 0,0,67,0,0,0,115,4,0,0,0,100,0,83,0,114, + 110,0,0,0,114,3,0,0,0,114,252,0,0,0,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,114,217,0, + 0,0,188,4,0,0,115,2,0,0,0,0,1,122,28,95, + 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, + 101,120,101,99,95,109,111,100,117,108,101,99,2,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, + 67,0,0,0,115,26,0,0,0,116,0,160,1,100,1,124, + 0,106,2,161,2,1,0,116,0,160,3,124,0,124,1,161, + 2,83,0,41,2,122,98,76,111,97,100,32,97,32,110,97, + 109,101,115,112,97,99,101,32,109,111,100,117,108,101,46,10, + 10,32,32,32,32,32,32,32,32,84,104,105,115,32,109,101, + 116,104,111,100,32,105,115,32,100,101,112,114,101,99,97,116, + 101,100,46,32,32,85,115,101,32,101,120,101,99,95,109,111, + 100,117,108,101,40,41,32,105,110,115,116,101,97,100,46,10, + 10,32,32,32,32,32,32,32,32,122,38,110,97,109,101,115, + 112,97,99,101,32,109,111,100,117,108,101,32,108,111,97,100, + 101,100,32,119,105,116,104,32,112,97,116,104,32,123,33,114, + 125,41,4,114,134,0,0,0,114,149,0,0,0,114,24,1, + 0,0,114,218,0,0,0,114,219,0,0,0,114,3,0,0, + 0,114,3,0,0,0,114,6,0,0,0,114,220,0,0,0, + 191,4,0,0,115,8,0,0,0,0,7,6,1,4,255,4, + 2,122,28,95,78,97,109,101,115,112,97,99,101,76,111,97, + 100,101,114,46,108,111,97,100,95,109,111,100,117,108,101,78, + 41,12,114,125,0,0,0,114,124,0,0,0,114,126,0,0, + 0,114,209,0,0,0,114,207,0,0,0,114,44,1,0,0, + 114,182,0,0,0,114,229,0,0,0,114,213,0,0,0,114, + 212,0,0,0,114,217,0,0,0,114,220,0,0,0,114,3, + 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, + 0,0,114,43,1,0,0,163,4,0,0,115,18,0,0,0, + 8,1,8,3,2,1,10,8,8,3,8,3,8,3,8,3, + 8,3,114,43,1,0,0,99,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,4,0,0,0,64,0,0,0, + 115,106,0,0,0,101,0,90,1,100,0,90,2,100,1,90, + 3,101,4,100,2,100,3,132,0,131,1,90,5,101,4,100, + 4,100,5,132,0,131,1,90,6,101,4,100,6,100,7,132, + 0,131,1,90,7,101,4,100,8,100,9,132,0,131,1,90, + 8,101,4,100,17,100,11,100,12,132,1,131,1,90,9,101, + 4,100,18,100,13,100,14,132,1,131,1,90,10,101,4,100, + 19,100,15,100,16,132,1,131,1,90,11,100,10,83,0,41, + 20,218,10,80,97,116,104,70,105,110,100,101,114,122,62,77, + 101,116,97,32,112,97,116,104,32,102,105,110,100,101,114,32, + 102,111,114,32,115,121,115,46,112,97,116,104,32,97,110,100, + 32,112,97,99,107,97,103,101,32,95,95,112,97,116,104,95, + 95,32,97,116,116,114,105,98,117,116,101,115,46,99,1,0, + 0,0,0,0,0,0,0,0,0,0,3,0,0,0,4,0, 0,0,67,0,0,0,115,64,0,0,0,116,0,116,1,106, 2,160,3,161,0,131,1,68,0,93,44,92,2,125,1,125, 2,124,2,100,1,107,8,114,40,116,1,106,2,124,1,61, @@ -2051,79 +2077,80 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 104,101,218,5,105,116,101,109,115,114,128,0,0,0,114,46, 1,0,0,41,3,114,193,0,0,0,114,117,0,0,0,218, 6,102,105,110,100,101,114,114,3,0,0,0,114,3,0,0, - 0,114,6,0,0,0,114,46,1,0,0,208,4,0,0,115, + 0,114,6,0,0,0,114,46,1,0,0,209,4,0,0,115, 10,0,0,0,0,4,22,1,8,1,10,1,10,1,122,28, 80,97,116,104,70,105,110,100,101,114,46,105,110,118,97,108, 105,100,97,116,101,95,99,97,99,104,101,115,99,2,0,0, - 0,0,0,0,0,3,0,0,0,9,0,0,0,67,0,0, - 0,115,84,0,0,0,116,0,106,1,100,1,107,9,114,28, - 116,0,106,1,115,28,116,2,160,3,100,2,116,4,161,2, - 1,0,116,0,106,1,68,0,93,44,125,2,122,14,124,2, - 124,1,131,1,87,0,2,0,1,0,83,0,4,0,116,5, - 107,10,114,76,1,0,1,0,1,0,89,0,113,34,89,0, - 113,34,88,0,113,34,100,1,83,0,41,3,122,46,83,101, - 97,114,99,104,32,115,121,115,46,112,97,116,104,95,104,111, - 111,107,115,32,102,111,114,32,97,32,102,105,110,100,101,114, - 32,102,111,114,32,39,112,97,116,104,39,46,78,122,23,115, - 121,115,46,112,97,116,104,95,104,111,111,107,115,32,105,115, - 32,101,109,112,116,121,41,6,114,8,0,0,0,218,10,112, - 97,116,104,95,104,111,111,107,115,114,75,0,0,0,114,76, - 0,0,0,114,138,0,0,0,114,118,0,0,0,41,3,114, - 193,0,0,0,114,44,0,0,0,90,4,104,111,111,107,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,218,11, - 95,112,97,116,104,95,104,111,111,107,115,218,4,0,0,115, - 16,0,0,0,0,3,16,1,12,1,10,1,2,1,14,1, - 14,1,12,2,122,22,80,97,116,104,70,105,110,100,101,114, - 46,95,112,97,116,104,95,104,111,111,107,115,99,2,0,0, - 0,0,0,0,0,3,0,0,0,8,0,0,0,67,0,0, - 0,115,104,0,0,0,124,1,100,1,107,2,114,44,122,12, - 116,0,160,1,161,0,125,1,87,0,110,22,4,0,116,2, - 107,10,114,42,1,0,1,0,1,0,89,0,100,2,83,0, - 88,0,122,14,116,3,106,4,124,1,25,0,125,2,87,0, - 110,40,4,0,116,5,107,10,114,98,1,0,1,0,1,0, - 124,0,160,6,124,1,161,1,125,2,124,2,116,3,106,4, - 124,1,60,0,89,0,110,2,88,0,124,2,83,0,41,3, - 122,210,71,101,116,32,116,104,101,32,102,105,110,100,101,114, - 32,102,111,114,32,116,104,101,32,112,97,116,104,32,101,110, - 116,114,121,32,102,114,111,109,32,115,121,115,46,112,97,116, - 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, - 46,10,10,32,32,32,32,32,32,32,32,73,102,32,116,104, - 101,32,112,97,116,104,32,101,110,116,114,121,32,105,115,32, - 110,111,116,32,105,110,32,116,104,101,32,99,97,99,104,101, - 44,32,102,105,110,100,32,116,104,101,32,97,112,112,114,111, - 112,114,105,97,116,101,32,102,105,110,100,101,114,10,32,32, - 32,32,32,32,32,32,97,110,100,32,99,97,99,104,101,32, - 105,116,46,32,73,102,32,110,111,32,102,105,110,100,101,114, - 32,105,115,32,97,118,97,105,108,97,98,108,101,44,32,115, - 116,111,114,101,32,78,111,110,101,46,10,10,32,32,32,32, - 32,32,32,32,114,40,0,0,0,78,41,7,114,2,0,0, - 0,114,55,0,0,0,114,2,1,0,0,114,8,0,0,0, - 114,48,1,0,0,218,8,75,101,121,69,114,114,111,114,114, - 52,1,0,0,41,3,114,193,0,0,0,114,44,0,0,0, - 114,50,1,0,0,114,3,0,0,0,114,3,0,0,0,114, - 6,0,0,0,218,20,95,112,97,116,104,95,105,109,112,111, - 114,116,101,114,95,99,97,99,104,101,231,4,0,0,115,22, - 0,0,0,0,8,8,1,2,1,12,1,14,3,8,1,2, - 1,14,1,14,1,10,1,16,1,122,31,80,97,116,104,70, - 105,110,100,101,114,46,95,112,97,116,104,95,105,109,112,111, - 114,116,101,114,95,99,97,99,104,101,99,3,0,0,0,0, - 0,0,0,6,0,0,0,4,0,0,0,67,0,0,0,115, - 82,0,0,0,116,0,124,2,100,1,131,2,114,26,124,2, - 160,1,124,1,161,1,92,2,125,3,125,4,110,14,124,2, - 160,2,124,1,161,1,125,3,103,0,125,4,124,3,100,0, - 107,9,114,60,116,3,160,4,124,1,124,3,161,2,83,0, - 116,3,160,5,124,1,100,0,161,2,125,5,124,4,124,5, - 95,6,124,5,83,0,41,2,78,114,137,0,0,0,41,7, - 114,128,0,0,0,114,137,0,0,0,114,206,0,0,0,114, - 134,0,0,0,114,201,0,0,0,114,183,0,0,0,114,178, - 0,0,0,41,6,114,193,0,0,0,114,139,0,0,0,114, - 50,1,0,0,114,140,0,0,0,114,141,0,0,0,114,187, - 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, - 0,0,218,16,95,108,101,103,97,99,121,95,103,101,116,95, - 115,112,101,99,253,4,0,0,115,18,0,0,0,0,4,10, - 1,16,2,10,1,4,1,8,1,12,1,12,1,6,1,122, - 27,80,97,116,104,70,105,110,100,101,114,46,95,108,101,103, - 97,99,121,95,103,101,116,95,115,112,101,99,78,99,4,0, + 0,0,0,0,0,0,0,0,0,3,0,0,0,9,0,0, + 0,67,0,0,0,115,84,0,0,0,116,0,106,1,100,1, + 107,9,114,28,116,0,106,1,115,28,116,2,160,3,100,2, + 116,4,161,2,1,0,116,0,106,1,68,0,93,44,125,2, + 122,14,124,2,124,1,131,1,87,0,2,0,1,0,83,0, + 4,0,116,5,107,10,114,76,1,0,1,0,1,0,89,0, + 113,34,89,0,113,34,88,0,113,34,100,1,83,0,41,3, + 122,46,83,101,97,114,99,104,32,115,121,115,46,112,97,116, + 104,95,104,111,111,107,115,32,102,111,114,32,97,32,102,105, + 110,100,101,114,32,102,111,114,32,39,112,97,116,104,39,46, + 78,122,23,115,121,115,46,112,97,116,104,95,104,111,111,107, + 115,32,105,115,32,101,109,112,116,121,41,6,114,8,0,0, + 0,218,10,112,97,116,104,95,104,111,111,107,115,114,75,0, + 0,0,114,76,0,0,0,114,138,0,0,0,114,118,0,0, + 0,41,3,114,193,0,0,0,114,44,0,0,0,90,4,104, + 111,111,107,114,3,0,0,0,114,3,0,0,0,114,6,0, + 0,0,218,11,95,112,97,116,104,95,104,111,111,107,115,219, + 4,0,0,115,16,0,0,0,0,3,16,1,12,1,10,1, + 2,1,14,1,14,1,12,2,122,22,80,97,116,104,70,105, + 110,100,101,114,46,95,112,97,116,104,95,104,111,111,107,115, + 99,2,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,8,0,0,0,67,0,0,0,115,104,0,0,0,124,1, + 100,1,107,2,114,44,122,12,116,0,160,1,161,0,125,1, + 87,0,110,22,4,0,116,2,107,10,114,42,1,0,1,0, + 1,0,89,0,100,2,83,0,88,0,122,14,116,3,106,4, + 124,1,25,0,125,2,87,0,110,40,4,0,116,5,107,10, + 114,98,1,0,1,0,1,0,124,0,160,6,124,1,161,1, + 125,2,124,2,116,3,106,4,124,1,60,0,89,0,110,2, + 88,0,124,2,83,0,41,3,122,210,71,101,116,32,116,104, + 101,32,102,105,110,100,101,114,32,102,111,114,32,116,104,101, + 32,112,97,116,104,32,101,110,116,114,121,32,102,114,111,109, + 32,115,121,115,46,112,97,116,104,95,105,109,112,111,114,116, + 101,114,95,99,97,99,104,101,46,10,10,32,32,32,32,32, + 32,32,32,73,102,32,116,104,101,32,112,97,116,104,32,101, + 110,116,114,121,32,105,115,32,110,111,116,32,105,110,32,116, + 104,101,32,99,97,99,104,101,44,32,102,105,110,100,32,116, + 104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,102, + 105,110,100,101,114,10,32,32,32,32,32,32,32,32,97,110, + 100,32,99,97,99,104,101,32,105,116,46,32,73,102,32,110, + 111,32,102,105,110,100,101,114,32,105,115,32,97,118,97,105, + 108,97,98,108,101,44,32,115,116,111,114,101,32,78,111,110, + 101,46,10,10,32,32,32,32,32,32,32,32,114,40,0,0, + 0,78,41,7,114,2,0,0,0,114,55,0,0,0,114,2, + 1,0,0,114,8,0,0,0,114,48,1,0,0,218,8,75, + 101,121,69,114,114,111,114,114,52,1,0,0,41,3,114,193, + 0,0,0,114,44,0,0,0,114,50,1,0,0,114,3,0, + 0,0,114,3,0,0,0,114,6,0,0,0,218,20,95,112, + 97,116,104,95,105,109,112,111,114,116,101,114,95,99,97,99, + 104,101,232,4,0,0,115,22,0,0,0,0,8,8,1,2, + 1,12,1,14,3,8,1,2,1,14,1,14,1,10,1,16, + 1,122,31,80,97,116,104,70,105,110,100,101,114,46,95,112, + 97,116,104,95,105,109,112,111,114,116,101,114,95,99,97,99, + 104,101,99,3,0,0,0,0,0,0,0,0,0,0,0,6, + 0,0,0,4,0,0,0,67,0,0,0,115,82,0,0,0, + 116,0,124,2,100,1,131,2,114,26,124,2,160,1,124,1, + 161,1,92,2,125,3,125,4,110,14,124,2,160,2,124,1, + 161,1,125,3,103,0,125,4,124,3,100,0,107,9,114,60, + 116,3,160,4,124,1,124,3,161,2,83,0,116,3,160,5, + 124,1,100,0,161,2,125,5,124,4,124,5,95,6,124,5, + 83,0,41,2,78,114,137,0,0,0,41,7,114,128,0,0, + 0,114,137,0,0,0,114,206,0,0,0,114,134,0,0,0, + 114,201,0,0,0,114,183,0,0,0,114,178,0,0,0,41, + 6,114,193,0,0,0,114,139,0,0,0,114,50,1,0,0, + 114,140,0,0,0,114,141,0,0,0,114,187,0,0,0,114, + 3,0,0,0,114,3,0,0,0,114,6,0,0,0,218,16, + 95,108,101,103,97,99,121,95,103,101,116,95,115,112,101,99, + 254,4,0,0,115,18,0,0,0,0,4,10,1,16,2,10, + 1,4,1,8,1,12,1,12,1,6,1,122,27,80,97,116, + 104,70,105,110,100,101,114,46,95,108,101,103,97,99,121,95, + 103,101,116,95,115,112,101,99,78,99,4,0,0,0,0,0, 0,0,0,0,0,0,9,0,0,0,5,0,0,0,67,0, 0,0,115,166,0,0,0,103,0,125,4,124,2,68,0,93, 134,125,5,116,0,124,5,116,1,116,2,102,2,131,2,115, @@ -2151,84 +2178,85 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 101,95,112,97,116,104,90,5,101,110,116,114,121,114,50,1, 0,0,114,187,0,0,0,114,141,0,0,0,114,3,0,0, 0,114,3,0,0,0,114,6,0,0,0,218,9,95,103,101, - 116,95,115,112,101,99,12,5,0,0,115,40,0,0,0,0, + 116,95,115,112,101,99,13,5,0,0,115,40,0,0,0,0, 5,4,1,8,1,14,1,2,1,10,1,8,1,10,1,14, 2,12,1,8,1,2,1,10,1,8,1,6,1,8,1,8, 5,12,2,12,1,6,1,122,20,80,97,116,104,70,105,110, 100,101,114,46,95,103,101,116,95,115,112,101,99,99,4,0, - 0,0,0,0,0,0,6,0,0,0,5,0,0,0,67,0, - 0,0,115,100,0,0,0,124,2,100,1,107,8,114,14,116, - 0,106,1,125,2,124,0,160,2,124,1,124,2,124,3,161, - 3,125,4,124,4,100,1,107,8,114,40,100,1,83,0,124, - 4,106,3,100,1,107,8,114,92,124,4,106,4,125,5,124, - 5,114,86,100,1,124,4,95,5,116,6,124,1,124,5,124, - 0,106,2,131,3,124,4,95,4,124,4,83,0,100,1,83, - 0,110,4,124,4,83,0,100,1,83,0,41,2,122,141,84, - 114,121,32,116,111,32,102,105,110,100,32,97,32,115,112,101, - 99,32,102,111,114,32,39,102,117,108,108,110,97,109,101,39, - 32,111,110,32,115,121,115,46,112,97,116,104,32,111,114,32, - 39,112,97,116,104,39,46,10,10,32,32,32,32,32,32,32, - 32,84,104,101,32,115,101,97,114,99,104,32,105,115,32,98, - 97,115,101,100,32,111,110,32,115,121,115,46,112,97,116,104, - 95,104,111,111,107,115,32,97,110,100,32,115,121,115,46,112, - 97,116,104,95,105,109,112,111,114,116,101,114,95,99,97,99, - 104,101,46,10,32,32,32,32,32,32,32,32,78,41,7,114, - 8,0,0,0,114,44,0,0,0,114,58,1,0,0,114,140, - 0,0,0,114,178,0,0,0,114,181,0,0,0,114,22,1, - 0,0,41,6,114,193,0,0,0,114,139,0,0,0,114,44, - 0,0,0,114,202,0,0,0,114,187,0,0,0,114,57,1, + 0,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0, + 0,0,67,0,0,0,115,100,0,0,0,124,2,100,1,107, + 8,114,14,116,0,106,1,125,2,124,0,160,2,124,1,124, + 2,124,3,161,3,125,4,124,4,100,1,107,8,114,40,100, + 1,83,0,124,4,106,3,100,1,107,8,114,92,124,4,106, + 4,125,5,124,5,114,86,100,1,124,4,95,5,116,6,124, + 1,124,5,124,0,106,2,131,3,124,4,95,4,124,4,83, + 0,100,1,83,0,110,4,124,4,83,0,100,1,83,0,41, + 2,122,141,84,114,121,32,116,111,32,102,105,110,100,32,97, + 32,115,112,101,99,32,102,111,114,32,39,102,117,108,108,110, + 97,109,101,39,32,111,110,32,115,121,115,46,112,97,116,104, + 32,111,114,32,39,112,97,116,104,39,46,10,10,32,32,32, + 32,32,32,32,32,84,104,101,32,115,101,97,114,99,104,32, + 105,115,32,98,97,115,101,100,32,111,110,32,115,121,115,46, + 112,97,116,104,95,104,111,111,107,115,32,97,110,100,32,115, + 121,115,46,112,97,116,104,95,105,109,112,111,114,116,101,114, + 95,99,97,99,104,101,46,10,32,32,32,32,32,32,32,32, + 78,41,7,114,8,0,0,0,114,44,0,0,0,114,58,1, + 0,0,114,140,0,0,0,114,178,0,0,0,114,181,0,0, + 0,114,22,1,0,0,41,6,114,193,0,0,0,114,139,0, + 0,0,114,44,0,0,0,114,202,0,0,0,114,187,0,0, + 0,114,57,1,0,0,114,3,0,0,0,114,3,0,0,0, + 114,6,0,0,0,114,203,0,0,0,45,5,0,0,115,26, + 0,0,0,0,6,8,1,6,1,14,1,8,1,4,1,10, + 1,6,1,4,3,6,1,16,1,4,2,6,2,122,20,80, + 97,116,104,70,105,110,100,101,114,46,102,105,110,100,95,115, + 112,101,99,99,3,0,0,0,0,0,0,0,0,0,0,0, + 4,0,0,0,4,0,0,0,67,0,0,0,115,30,0,0, + 0,124,0,160,0,124,1,124,2,161,2,125,3,124,3,100, + 1,107,8,114,24,100,1,83,0,124,3,106,1,83,0,41, + 2,122,170,102,105,110,100,32,116,104,101,32,109,111,100,117, + 108,101,32,111,110,32,115,121,115,46,112,97,116,104,32,111, + 114,32,39,112,97,116,104,39,32,98,97,115,101,100,32,111, + 110,32,115,121,115,46,112,97,116,104,95,104,111,111,107,115, + 32,97,110,100,10,32,32,32,32,32,32,32,32,115,121,115, + 46,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, + 97,99,104,101,46,10,10,32,32,32,32,32,32,32,32,84, + 104,105,115,32,109,101,116,104,111,100,32,105,115,32,100,101, + 112,114,101,99,97,116,101,100,46,32,32,85,115,101,32,102, + 105,110,100,95,115,112,101,99,40,41,32,105,110,115,116,101, + 97,100,46,10,10,32,32,32,32,32,32,32,32,78,114,204, + 0,0,0,114,205,0,0,0,114,3,0,0,0,114,3,0, + 0,0,114,6,0,0,0,114,206,0,0,0,69,5,0,0, + 115,8,0,0,0,0,8,12,1,8,1,4,1,122,22,80, + 97,116,104,70,105,110,100,101,114,46,102,105,110,100,95,109, + 111,100,117,108,101,41,1,78,41,2,78,78,41,1,78,41, + 12,114,125,0,0,0,114,124,0,0,0,114,126,0,0,0, + 114,127,0,0,0,114,207,0,0,0,114,46,1,0,0,114, + 52,1,0,0,114,54,1,0,0,114,55,1,0,0,114,58, + 1,0,0,114,203,0,0,0,114,206,0,0,0,114,3,0, 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,114,203,0,0,0,44,5,0,0,115,26,0,0,0,0, - 6,8,1,6,1,14,1,8,1,4,1,10,1,6,1,4, - 3,6,1,16,1,4,2,6,2,122,20,80,97,116,104,70, - 105,110,100,101,114,46,102,105,110,100,95,115,112,101,99,99, - 3,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, - 67,0,0,0,115,30,0,0,0,124,0,160,0,124,1,124, - 2,161,2,125,3,124,3,100,1,107,8,114,24,100,1,83, - 0,124,3,106,1,83,0,41,2,122,170,102,105,110,100,32, - 116,104,101,32,109,111,100,117,108,101,32,111,110,32,115,121, - 115,46,112,97,116,104,32,111,114,32,39,112,97,116,104,39, - 32,98,97,115,101,100,32,111,110,32,115,121,115,46,112,97, - 116,104,95,104,111,111,107,115,32,97,110,100,10,32,32,32, - 32,32,32,32,32,115,121,115,46,112,97,116,104,95,105,109, - 112,111,114,116,101,114,95,99,97,99,104,101,46,10,10,32, - 32,32,32,32,32,32,32,84,104,105,115,32,109,101,116,104, - 111,100,32,105,115,32,100,101,112,114,101,99,97,116,101,100, - 46,32,32,85,115,101,32,102,105,110,100,95,115,112,101,99, - 40,41,32,105,110,115,116,101,97,100,46,10,10,32,32,32, - 32,32,32,32,32,78,114,204,0,0,0,114,205,0,0,0, - 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, - 206,0,0,0,68,5,0,0,115,8,0,0,0,0,8,12, - 1,8,1,4,1,122,22,80,97,116,104,70,105,110,100,101, - 114,46,102,105,110,100,95,109,111,100,117,108,101,41,1,78, - 41,2,78,78,41,1,78,41,12,114,125,0,0,0,114,124, - 0,0,0,114,126,0,0,0,114,127,0,0,0,114,207,0, - 0,0,114,46,1,0,0,114,52,1,0,0,114,54,1,0, - 0,114,55,1,0,0,114,58,1,0,0,114,203,0,0,0, - 114,206,0,0,0,114,3,0,0,0,114,3,0,0,0,114, - 3,0,0,0,114,6,0,0,0,114,45,1,0,0,204,4, - 0,0,115,30,0,0,0,8,2,4,2,2,1,10,9,2, - 1,10,12,2,1,10,21,2,1,10,14,2,1,12,31,2, - 1,12,23,2,1,114,45,1,0,0,99,0,0,0,0,0, - 0,0,0,0,0,0,0,3,0,0,0,64,0,0,0,115, - 90,0,0,0,101,0,90,1,100,0,90,2,100,1,90,3, - 100,2,100,3,132,0,90,4,100,4,100,5,132,0,90,5, - 101,6,90,7,100,6,100,7,132,0,90,8,100,8,100,9, - 132,0,90,9,100,19,100,11,100,12,132,1,90,10,100,13, - 100,14,132,0,90,11,101,12,100,15,100,16,132,0,131,1, - 90,13,100,17,100,18,132,0,90,14,100,10,83,0,41,20, - 218,10,70,105,108,101,70,105,110,100,101,114,122,172,70,105, - 108,101,45,98,97,115,101,100,32,102,105,110,100,101,114,46, - 10,10,32,32,32,32,73,110,116,101,114,97,99,116,105,111, - 110,115,32,119,105,116,104,32,116,104,101,32,102,105,108,101, - 32,115,121,115,116,101,109,32,97,114,101,32,99,97,99,104, - 101,100,32,102,111,114,32,112,101,114,102,111,114,109,97,110, - 99,101,44,32,98,101,105,110,103,10,32,32,32,32,114,101, - 102,114,101,115,104,101,100,32,119,104,101,110,32,116,104,101, - 32,100,105,114,101,99,116,111,114,121,32,116,104,101,32,102, - 105,110,100,101,114,32,105,115,32,104,97,110,100,108,105,110, - 103,32,104,97,115,32,98,101,101,110,32,109,111,100,105,102, - 105,101,100,46,10,10,32,32,32,32,99,2,0,0,0,0, + 0,114,45,1,0,0,205,4,0,0,115,30,0,0,0,8, + 2,4,2,2,1,10,9,2,1,10,12,2,1,10,21,2, + 1,10,14,2,1,12,31,2,1,12,23,2,1,114,45,1, + 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,3,0,0,0,64,0,0,0,115,90,0,0,0, + 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, + 132,0,90,4,100,4,100,5,132,0,90,5,101,6,90,7, + 100,6,100,7,132,0,90,8,100,8,100,9,132,0,90,9, + 100,19,100,11,100,12,132,1,90,10,100,13,100,14,132,0, + 90,11,101,12,100,15,100,16,132,0,131,1,90,13,100,17, + 100,18,132,0,90,14,100,10,83,0,41,20,218,10,70,105, + 108,101,70,105,110,100,101,114,122,172,70,105,108,101,45,98, + 97,115,101,100,32,102,105,110,100,101,114,46,10,10,32,32, + 32,32,73,110,116,101,114,97,99,116,105,111,110,115,32,119, + 105,116,104,32,116,104,101,32,102,105,108,101,32,115,121,115, + 116,101,109,32,97,114,101,32,99,97,99,104,101,100,32,102, + 111,114,32,112,101,114,102,111,114,109,97,110,99,101,44,32, + 98,101,105,110,103,10,32,32,32,32,114,101,102,114,101,115, + 104,101,100,32,119,104,101,110,32,116,104,101,32,100,105,114, + 101,99,116,111,114,121,32,116,104,101,32,102,105,110,100,101, + 114,32,105,115,32,104,97,110,100,108,105,110,103,32,104,97, + 115,32,98,101,101,110,32,109,111,100,105,102,105,101,100,46, + 10,10,32,32,32,32,99,2,0,0,0,0,0,0,0,0, 0,0,0,5,0,0,0,6,0,0,0,7,0,0,0,115, 84,0,0,0,103,0,125,3,124,2,68,0,93,32,92,2, 137,0,125,4,124,3,160,0,135,0,102,1,100,1,100,2, @@ -2245,60 +2273,61 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,32,97,110,100,32,116,104,101,32,102,105,108,101,32,115, 117,102,102,105,120,101,115,32,116,104,101,32,108,111,97,100, 101,114,10,32,32,32,32,32,32,32,32,114,101,99,111,103, - 110,105,122,101,115,46,99,1,0,0,0,0,0,0,0,2, - 0,0,0,3,0,0,0,51,0,0,0,115,22,0,0,0, - 124,0,93,14,125,1,124,1,136,0,102,2,86,0,1,0, - 113,2,100,0,83,0,114,110,0,0,0,114,3,0,0,0, - 114,16,1,0,0,169,1,114,140,0,0,0,114,3,0,0, - 0,114,6,0,0,0,114,19,1,0,0,97,5,0,0,115, - 4,0,0,0,4,0,2,0,122,38,70,105,108,101,70,105, - 110,100,101,114,46,95,95,105,110,105,116,95,95,46,60,108, - 111,99,97,108,115,62,46,60,103,101,110,101,120,112,114,62, - 114,71,0,0,0,114,105,0,0,0,78,41,7,114,167,0, - 0,0,218,8,95,108,111,97,100,101,114,115,114,44,0,0, - 0,218,11,95,112,97,116,104,95,109,116,105,109,101,218,3, - 115,101,116,218,11,95,112,97,116,104,95,99,97,99,104,101, - 218,19,95,114,101,108,97,120,101,100,95,112,97,116,104,95, - 99,97,99,104,101,41,5,114,119,0,0,0,114,44,0,0, - 0,218,14,108,111,97,100,101,114,95,100,101,116,97,105,108, - 115,90,7,108,111,97,100,101,114,115,114,189,0,0,0,114, - 3,0,0,0,114,60,1,0,0,114,6,0,0,0,114,209, - 0,0,0,91,5,0,0,115,16,0,0,0,0,4,4,1, - 12,1,26,1,6,2,10,1,6,1,8,1,122,19,70,105, + 110,105,122,101,115,46,99,1,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,51,0,0,0,115, + 22,0,0,0,124,0,93,14,125,1,124,1,136,0,102,2, + 86,0,1,0,113,2,100,0,83,0,114,110,0,0,0,114, + 3,0,0,0,114,16,1,0,0,169,1,114,140,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,19,1,0,0,98, + 5,0,0,115,4,0,0,0,4,0,2,0,122,38,70,105, 108,101,70,105,110,100,101,114,46,95,95,105,110,105,116,95, - 95,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, - 0,0,67,0,0,0,115,10,0,0,0,100,1,124,0,95, - 0,100,2,83,0,41,3,122,31,73,110,118,97,108,105,100, - 97,116,101,32,116,104,101,32,100,105,114,101,99,116,111,114, - 121,32,109,116,105,109,101,46,114,105,0,0,0,78,41,1, - 114,62,1,0,0,114,246,0,0,0,114,3,0,0,0,114, - 3,0,0,0,114,6,0,0,0,114,46,1,0,0,105,5, - 0,0,115,2,0,0,0,0,2,122,28,70,105,108,101,70, - 105,110,100,101,114,46,105,110,118,97,108,105,100,97,116,101, - 95,99,97,99,104,101,115,99,2,0,0,0,0,0,0,0, - 3,0,0,0,3,0,0,0,67,0,0,0,115,42,0,0, - 0,124,0,160,0,124,1,161,1,125,2,124,2,100,1,107, - 8,114,26,100,1,103,0,102,2,83,0,124,2,106,1,124, - 2,106,2,112,38,103,0,102,2,83,0,41,2,122,197,84, - 114,121,32,116,111,32,102,105,110,100,32,97,32,108,111,97, - 100,101,114,32,102,111,114,32,116,104,101,32,115,112,101,99, - 105,102,105,101,100,32,109,111,100,117,108,101,44,32,111,114, - 32,116,104,101,32,110,97,109,101,115,112,97,99,101,10,32, - 32,32,32,32,32,32,32,112,97,99,107,97,103,101,32,112, - 111,114,116,105,111,110,115,46,32,82,101,116,117,114,110,115, - 32,40,108,111,97,100,101,114,44,32,108,105,115,116,45,111, - 102,45,112,111,114,116,105,111,110,115,41,46,10,10,32,32, - 32,32,32,32,32,32,84,104,105,115,32,109,101,116,104,111, - 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, - 32,32,85,115,101,32,102,105,110,100,95,115,112,101,99,40, - 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, - 32,32,32,32,78,41,3,114,203,0,0,0,114,140,0,0, - 0,114,178,0,0,0,41,3,114,119,0,0,0,114,139,0, - 0,0,114,187,0,0,0,114,3,0,0,0,114,3,0,0, - 0,114,6,0,0,0,114,137,0,0,0,111,5,0,0,115, - 8,0,0,0,0,7,10,1,8,1,8,1,122,22,70,105, - 108,101,70,105,110,100,101,114,46,102,105,110,100,95,108,111, - 97,100,101,114,99,6,0,0,0,0,0,0,0,7,0,0, + 95,46,60,108,111,99,97,108,115,62,46,60,103,101,110,101, + 120,112,114,62,114,71,0,0,0,114,105,0,0,0,78,41, + 7,114,167,0,0,0,218,8,95,108,111,97,100,101,114,115, + 114,44,0,0,0,218,11,95,112,97,116,104,95,109,116,105, + 109,101,218,3,115,101,116,218,11,95,112,97,116,104,95,99, + 97,99,104,101,218,19,95,114,101,108,97,120,101,100,95,112, + 97,116,104,95,99,97,99,104,101,41,5,114,119,0,0,0, + 114,44,0,0,0,218,14,108,111,97,100,101,114,95,100,101, + 116,97,105,108,115,90,7,108,111,97,100,101,114,115,114,189, + 0,0,0,114,3,0,0,0,114,60,1,0,0,114,6,0, + 0,0,114,209,0,0,0,92,5,0,0,115,16,0,0,0, + 0,4,4,1,12,1,26,1,6,2,10,1,6,1,8,1, + 122,19,70,105,108,101,70,105,110,100,101,114,46,95,95,105, + 110,105,116,95,95,99,1,0,0,0,0,0,0,0,0,0, + 0,0,1,0,0,0,2,0,0,0,67,0,0,0,115,10, + 0,0,0,100,1,124,0,95,0,100,2,83,0,41,3,122, + 31,73,110,118,97,108,105,100,97,116,101,32,116,104,101,32, + 100,105,114,101,99,116,111,114,121,32,109,116,105,109,101,46, + 114,105,0,0,0,78,41,1,114,62,1,0,0,114,246,0, + 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, + 0,114,46,1,0,0,106,5,0,0,115,2,0,0,0,0, + 2,122,28,70,105,108,101,70,105,110,100,101,114,46,105,110, + 118,97,108,105,100,97,116,101,95,99,97,99,104,101,115,99, + 2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, + 3,0,0,0,67,0,0,0,115,42,0,0,0,124,0,160, + 0,124,1,161,1,125,2,124,2,100,1,107,8,114,26,100, + 1,103,0,102,2,83,0,124,2,106,1,124,2,106,2,112, + 38,103,0,102,2,83,0,41,2,122,197,84,114,121,32,116, + 111,32,102,105,110,100,32,97,32,108,111,97,100,101,114,32, + 102,111,114,32,116,104,101,32,115,112,101,99,105,102,105,101, + 100,32,109,111,100,117,108,101,44,32,111,114,32,116,104,101, + 32,110,97,109,101,115,112,97,99,101,10,32,32,32,32,32, + 32,32,32,112,97,99,107,97,103,101,32,112,111,114,116,105, + 111,110,115,46,32,82,101,116,117,114,110,115,32,40,108,111, + 97,100,101,114,44,32,108,105,115,116,45,111,102,45,112,111, + 114,116,105,111,110,115,41,46,10,10,32,32,32,32,32,32, + 32,32,84,104,105,115,32,109,101,116,104,111,100,32,105,115, + 32,100,101,112,114,101,99,97,116,101,100,46,32,32,85,115, + 101,32,102,105,110,100,95,115,112,101,99,40,41,32,105,110, + 115,116,101,97,100,46,10,10,32,32,32,32,32,32,32,32, + 78,41,3,114,203,0,0,0,114,140,0,0,0,114,178,0, + 0,0,41,3,114,119,0,0,0,114,139,0,0,0,114,187, + 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, + 0,0,114,137,0,0,0,112,5,0,0,115,8,0,0,0, + 0,7,10,1,8,1,8,1,122,22,70,105,108,101,70,105, + 110,100,101,114,46,102,105,110,100,95,108,111,97,100,101,114, + 99,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0, 0,6,0,0,0,67,0,0,0,115,26,0,0,0,124,1, 124,2,124,3,131,2,125,6,116,0,124,2,124,3,124,6, 124,4,100,1,141,4,83,0,41,2,78,114,177,0,0,0, @@ -2306,114 +2335,115 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,114,139,0,0,0,114,44,0,0,0,90,4,115, 109,115,108,114,202,0,0,0,114,140,0,0,0,114,3,0, 0,0,114,3,0,0,0,114,6,0,0,0,114,58,1,0, - 0,123,5,0,0,115,8,0,0,0,0,1,10,1,8,1, + 0,124,5,0,0,115,8,0,0,0,0,1,10,1,8,1, 2,255,122,20,70,105,108,101,70,105,110,100,101,114,46,95, 103,101,116,95,115,112,101,99,78,99,3,0,0,0,0,0, - 0,0,14,0,0,0,8,0,0,0,67,0,0,0,115,102, - 1,0,0,100,1,125,3,124,1,160,0,100,2,161,1,100, - 3,25,0,125,4,122,24,116,1,124,0,106,2,112,34,116, - 3,160,4,161,0,131,1,106,5,125,5,87,0,110,24,4, - 0,116,6,107,10,114,66,1,0,1,0,1,0,100,4,125, - 5,89,0,110,2,88,0,124,5,124,0,106,7,107,3,114, - 92,124,0,160,8,161,0,1,0,124,5,124,0,95,7,116, - 9,131,0,114,114,124,0,106,10,125,6,124,4,160,11,161, - 0,125,7,110,10,124,0,106,12,125,6,124,4,125,7,124, - 7,124,6,107,6,114,218,116,13,124,0,106,2,124,4,131, - 2,125,8,124,0,106,14,68,0,93,58,92,2,125,9,125, - 10,100,5,124,9,23,0,125,11,116,13,124,8,124,11,131, - 2,125,12,116,15,124,12,131,1,114,208,124,0,160,16,124, - 10,124,1,124,12,124,8,103,1,124,2,161,5,2,0,1, - 0,83,0,113,150,116,17,124,8,131,1,125,3,124,0,106, - 14,68,0,93,86,92,2,125,9,125,10,116,13,124,0,106, - 2,124,4,124,9,23,0,131,2,125,12,116,18,106,19,100, - 6,124,12,100,3,100,7,141,3,1,0,124,7,124,9,23, - 0,124,6,107,6,144,1,114,54,116,15,124,12,131,1,144, - 1,114,54,124,0,160,16,124,10,124,1,124,12,100,8,124, - 2,161,5,2,0,1,0,83,0,113,224,124,3,144,1,114, - 98,116,18,160,19,100,9,124,8,161,2,1,0,116,18,160, - 20,124,1,100,8,161,2,125,13,124,8,103,1,124,13,95, - 21,124,13,83,0,100,8,83,0,41,10,122,111,84,114,121, - 32,116,111,32,102,105,110,100,32,97,32,115,112,101,99,32, - 102,111,114,32,116,104,101,32,115,112,101,99,105,102,105,101, - 100,32,109,111,100,117,108,101,46,10,10,32,32,32,32,32, - 32,32,32,82,101,116,117,114,110,115,32,116,104,101,32,109, - 97,116,99,104,105,110,103,32,115,112,101,99,44,32,111,114, - 32,78,111,110,101,32,105,102,32,110,111,116,32,102,111,117, - 110,100,46,10,32,32,32,32,32,32,32,32,70,114,71,0, - 0,0,114,28,0,0,0,114,105,0,0,0,114,209,0,0, - 0,122,9,116,114,121,105,110,103,32,123,125,41,1,90,9, - 118,101,114,98,111,115,105,116,121,78,122,25,112,111,115,115, - 105,98,108,101,32,110,97,109,101,115,112,97,99,101,32,102, - 111,114,32,123,125,41,22,114,41,0,0,0,114,49,0,0, - 0,114,44,0,0,0,114,2,0,0,0,114,55,0,0,0, - 114,9,1,0,0,114,50,0,0,0,114,62,1,0,0,218, - 11,95,102,105,108,108,95,99,97,99,104,101,114,7,0,0, - 0,114,65,1,0,0,114,106,0,0,0,114,64,1,0,0, - 114,38,0,0,0,114,61,1,0,0,114,54,0,0,0,114, - 58,1,0,0,114,56,0,0,0,114,134,0,0,0,114,149, - 0,0,0,114,183,0,0,0,114,178,0,0,0,41,14,114, - 119,0,0,0,114,139,0,0,0,114,202,0,0,0,90,12, - 105,115,95,110,97,109,101,115,112,97,99,101,90,11,116,97, - 105,108,95,109,111,100,117,108,101,114,169,0,0,0,90,5, - 99,97,99,104,101,90,12,99,97,99,104,101,95,109,111,100, - 117,108,101,90,9,98,97,115,101,95,112,97,116,104,114,17, - 1,0,0,114,188,0,0,0,90,13,105,110,105,116,95,102, - 105,108,101,110,97,109,101,90,9,102,117,108,108,95,112,97, - 116,104,114,187,0,0,0,114,3,0,0,0,114,3,0,0, - 0,114,6,0,0,0,114,203,0,0,0,128,5,0,0,115, - 74,0,0,0,0,5,4,1,14,1,2,1,24,1,14,1, - 10,1,10,1,8,1,6,2,6,1,6,1,10,2,6,1, - 4,2,8,1,12,1,14,1,8,1,10,1,8,1,26,4, - 8,2,14,1,16,1,16,1,14,1,10,1,10,1,2,0, - 2,255,10,2,6,1,12,1,12,1,8,1,4,1,122,20, - 70,105,108,101,70,105,110,100,101,114,46,102,105,110,100,95, - 115,112,101,99,99,1,0,0,0,0,0,0,0,9,0,0, - 0,10,0,0,0,67,0,0,0,115,190,0,0,0,124,0, - 106,0,125,1,122,22,116,1,160,2,124,1,112,22,116,1, - 160,3,161,0,161,1,125,2,87,0,110,30,4,0,116,4, - 116,5,116,6,102,3,107,10,114,58,1,0,1,0,1,0, - 103,0,125,2,89,0,110,2,88,0,116,7,106,8,160,9, - 100,1,161,1,115,84,116,10,124,2,131,1,124,0,95,11, - 110,74,116,10,131,0,125,3,124,2,68,0,93,56,125,4, - 124,4,160,12,100,2,161,1,92,3,125,5,125,6,125,7, - 124,6,114,136,100,3,160,13,124,5,124,7,160,14,161,0, - 161,2,125,8,110,4,124,5,125,8,124,3,160,15,124,8, - 161,1,1,0,113,94,124,3,124,0,95,11,116,7,106,8, - 160,9,116,16,161,1,114,186,100,4,100,5,132,0,124,2, - 68,0,131,1,124,0,95,17,100,6,83,0,41,7,122,68, - 70,105,108,108,32,116,104,101,32,99,97,99,104,101,32,111, - 102,32,112,111,116,101,110,116,105,97,108,32,109,111,100,117, - 108,101,115,32,97,110,100,32,112,97,99,107,97,103,101,115, - 32,102,111,114,32,116,104,105,115,32,100,105,114,101,99,116, - 111,114,121,46,114,0,0,0,0,114,71,0,0,0,114,61, - 0,0,0,99,1,0,0,0,0,0,0,0,2,0,0,0, - 4,0,0,0,83,0,0,0,115,20,0,0,0,104,0,124, - 0,93,12,125,1,124,1,160,0,161,0,146,2,113,4,83, - 0,114,3,0,0,0,41,1,114,106,0,0,0,41,2,114, - 32,0,0,0,90,2,102,110,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,218,9,60,115,101,116,99,111,109, - 112,62,205,5,0,0,115,4,0,0,0,6,0,2,0,122, - 41,70,105,108,101,70,105,110,100,101,114,46,95,102,105,108, - 108,95,99,97,99,104,101,46,60,108,111,99,97,108,115,62, - 46,60,115,101,116,99,111,109,112,62,78,41,18,114,44,0, - 0,0,114,2,0,0,0,114,6,1,0,0,114,55,0,0, - 0,114,2,1,0,0,218,15,80,101,114,109,105,115,115,105, - 111,110,69,114,114,111,114,218,18,78,111,116,65,68,105,114, - 101,99,116,111,114,121,69,114,114,111,114,114,8,0,0,0, - 114,9,0,0,0,114,10,0,0,0,114,63,1,0,0,114, - 64,1,0,0,114,101,0,0,0,114,62,0,0,0,114,106, - 0,0,0,218,3,97,100,100,114,11,0,0,0,114,65,1, - 0,0,41,9,114,119,0,0,0,114,44,0,0,0,114,7, - 1,0,0,90,21,108,111,119,101,114,95,115,117,102,102,105, - 120,95,99,111,110,116,101,110,116,115,114,41,1,0,0,114, - 117,0,0,0,114,29,1,0,0,114,17,1,0,0,90,8, - 110,101,119,95,110,97,109,101,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,114,67,1,0,0,176,5,0,0, - 115,34,0,0,0,0,2,6,1,2,1,22,1,20,3,10, - 3,12,1,12,7,6,1,8,1,16,1,4,1,18,2,4, - 1,12,1,6,1,12,1,122,22,70,105,108,101,70,105,110, - 100,101,114,46,95,102,105,108,108,95,99,97,99,104,101,99, - 1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, + 0,0,0,0,0,0,14,0,0,0,8,0,0,0,67,0, + 0,0,115,102,1,0,0,100,1,125,3,124,1,160,0,100, + 2,161,1,100,3,25,0,125,4,122,24,116,1,124,0,106, + 2,112,34,116,3,160,4,161,0,131,1,106,5,125,5,87, + 0,110,24,4,0,116,6,107,10,114,66,1,0,1,0,1, + 0,100,4,125,5,89,0,110,2,88,0,124,5,124,0,106, + 7,107,3,114,92,124,0,160,8,161,0,1,0,124,5,124, + 0,95,7,116,9,131,0,114,114,124,0,106,10,125,6,124, + 4,160,11,161,0,125,7,110,10,124,0,106,12,125,6,124, + 4,125,7,124,7,124,6,107,6,114,218,116,13,124,0,106, + 2,124,4,131,2,125,8,124,0,106,14,68,0,93,58,92, + 2,125,9,125,10,100,5,124,9,23,0,125,11,116,13,124, + 8,124,11,131,2,125,12,116,15,124,12,131,1,114,208,124, + 0,160,16,124,10,124,1,124,12,124,8,103,1,124,2,161, + 5,2,0,1,0,83,0,113,150,116,17,124,8,131,1,125, + 3,124,0,106,14,68,0,93,86,92,2,125,9,125,10,116, + 13,124,0,106,2,124,4,124,9,23,0,131,2,125,12,116, + 18,106,19,100,6,124,12,100,3,100,7,141,3,1,0,124, + 7,124,9,23,0,124,6,107,6,144,1,114,54,116,15,124, + 12,131,1,144,1,114,54,124,0,160,16,124,10,124,1,124, + 12,100,8,124,2,161,5,2,0,1,0,83,0,113,224,124, + 3,144,1,114,98,116,18,160,19,100,9,124,8,161,2,1, + 0,116,18,160,20,124,1,100,8,161,2,125,13,124,8,103, + 1,124,13,95,21,124,13,83,0,100,8,83,0,41,10,122, + 111,84,114,121,32,116,111,32,102,105,110,100,32,97,32,115, + 112,101,99,32,102,111,114,32,116,104,101,32,115,112,101,99, + 105,102,105,101,100,32,109,111,100,117,108,101,46,10,10,32, + 32,32,32,32,32,32,32,82,101,116,117,114,110,115,32,116, + 104,101,32,109,97,116,99,104,105,110,103,32,115,112,101,99, + 44,32,111,114,32,78,111,110,101,32,105,102,32,110,111,116, + 32,102,111,117,110,100,46,10,32,32,32,32,32,32,32,32, + 70,114,71,0,0,0,114,28,0,0,0,114,105,0,0,0, + 114,209,0,0,0,122,9,116,114,121,105,110,103,32,123,125, + 41,1,90,9,118,101,114,98,111,115,105,116,121,78,122,25, + 112,111,115,115,105,98,108,101,32,110,97,109,101,115,112,97, + 99,101,32,102,111,114,32,123,125,41,22,114,41,0,0,0, + 114,49,0,0,0,114,44,0,0,0,114,2,0,0,0,114, + 55,0,0,0,114,9,1,0,0,114,50,0,0,0,114,62, + 1,0,0,218,11,95,102,105,108,108,95,99,97,99,104,101, + 114,7,0,0,0,114,65,1,0,0,114,106,0,0,0,114, + 64,1,0,0,114,38,0,0,0,114,61,1,0,0,114,54, + 0,0,0,114,58,1,0,0,114,56,0,0,0,114,134,0, + 0,0,114,149,0,0,0,114,183,0,0,0,114,178,0,0, + 0,41,14,114,119,0,0,0,114,139,0,0,0,114,202,0, + 0,0,90,12,105,115,95,110,97,109,101,115,112,97,99,101, + 90,11,116,97,105,108,95,109,111,100,117,108,101,114,169,0, + 0,0,90,5,99,97,99,104,101,90,12,99,97,99,104,101, + 95,109,111,100,117,108,101,90,9,98,97,115,101,95,112,97, + 116,104,114,17,1,0,0,114,188,0,0,0,90,13,105,110, + 105,116,95,102,105,108,101,110,97,109,101,90,9,102,117,108, + 108,95,112,97,116,104,114,187,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,203,0,0,0,129, + 5,0,0,115,74,0,0,0,0,5,4,1,14,1,2,1, + 24,1,14,1,10,1,10,1,8,1,6,2,6,1,6,1, + 10,2,6,1,4,2,8,1,12,1,14,1,8,1,10,1, + 8,1,26,4,8,2,14,1,16,1,16,1,14,1,10,1, + 10,1,2,0,2,255,10,2,6,1,12,1,12,1,8,1, + 4,1,122,20,70,105,108,101,70,105,110,100,101,114,46,102, + 105,110,100,95,115,112,101,99,99,1,0,0,0,0,0,0, + 0,0,0,0,0,9,0,0,0,10,0,0,0,67,0,0, + 0,115,190,0,0,0,124,0,106,0,125,1,122,22,116,1, + 160,2,124,1,112,22,116,1,160,3,161,0,161,1,125,2, + 87,0,110,30,4,0,116,4,116,5,116,6,102,3,107,10, + 114,58,1,0,1,0,1,0,103,0,125,2,89,0,110,2, + 88,0,116,7,106,8,160,9,100,1,161,1,115,84,116,10, + 124,2,131,1,124,0,95,11,110,74,116,10,131,0,125,3, + 124,2,68,0,93,56,125,4,124,4,160,12,100,2,161,1, + 92,3,125,5,125,6,125,7,124,6,114,136,100,3,160,13, + 124,5,124,7,160,14,161,0,161,2,125,8,110,4,124,5, + 125,8,124,3,160,15,124,8,161,1,1,0,113,94,124,3, + 124,0,95,11,116,7,106,8,160,9,116,16,161,1,114,186, + 100,4,100,5,132,0,124,2,68,0,131,1,124,0,95,17, + 100,6,83,0,41,7,122,68,70,105,108,108,32,116,104,101, + 32,99,97,99,104,101,32,111,102,32,112,111,116,101,110,116, + 105,97,108,32,109,111,100,117,108,101,115,32,97,110,100,32, + 112,97,99,107,97,103,101,115,32,102,111,114,32,116,104,105, + 115,32,100,105,114,101,99,116,111,114,121,46,114,0,0,0, + 0,114,71,0,0,0,114,61,0,0,0,99,1,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, + 83,0,0,0,115,20,0,0,0,104,0,124,0,93,12,125, + 1,124,1,160,0,161,0,146,2,113,4,83,0,114,3,0, + 0,0,41,1,114,106,0,0,0,41,2,114,32,0,0,0, + 90,2,102,110,114,3,0,0,0,114,3,0,0,0,114,6, + 0,0,0,218,9,60,115,101,116,99,111,109,112,62,206,5, + 0,0,115,4,0,0,0,6,0,2,0,122,41,70,105,108, + 101,70,105,110,100,101,114,46,95,102,105,108,108,95,99,97, + 99,104,101,46,60,108,111,99,97,108,115,62,46,60,115,101, + 116,99,111,109,112,62,78,41,18,114,44,0,0,0,114,2, + 0,0,0,114,6,1,0,0,114,55,0,0,0,114,2,1, + 0,0,218,15,80,101,114,109,105,115,115,105,111,110,69,114, + 114,111,114,218,18,78,111,116,65,68,105,114,101,99,116,111, + 114,121,69,114,114,111,114,114,8,0,0,0,114,9,0,0, + 0,114,10,0,0,0,114,63,1,0,0,114,64,1,0,0, + 114,101,0,0,0,114,62,0,0,0,114,106,0,0,0,218, + 3,97,100,100,114,11,0,0,0,114,65,1,0,0,41,9, + 114,119,0,0,0,114,44,0,0,0,114,7,1,0,0,90, + 21,108,111,119,101,114,95,115,117,102,102,105,120,95,99,111, + 110,116,101,110,116,115,114,41,1,0,0,114,117,0,0,0, + 114,29,1,0,0,114,17,1,0,0,90,8,110,101,119,95, + 110,97,109,101,114,3,0,0,0,114,3,0,0,0,114,6, + 0,0,0,114,67,1,0,0,177,5,0,0,115,34,0,0, + 0,0,2,6,1,2,1,22,1,20,3,10,3,12,1,12, + 7,6,1,8,1,16,1,4,1,18,2,4,1,12,1,6, + 1,12,1,122,22,70,105,108,101,70,105,110,100,101,114,46, + 95,102,105,108,108,95,99,97,99,104,101,99,1,0,0,0, + 0,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, 7,0,0,0,115,18,0,0,0,135,0,135,1,102,2,100, 1,100,2,132,8,125,2,124,2,83,0,41,3,97,20,1, 0,0,65,32,99,108,97,115,115,32,109,101,116,104,111,100, @@ -2433,70 +2463,71 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 32,97,32,100,105,114,101,99,116,111,114,121,44,32,73,109, 112,111,114,116,69,114,114,111,114,32,105,115,10,32,32,32, 32,32,32,32,32,114,97,105,115,101,100,46,10,10,32,32, - 32,32,32,32,32,32,99,1,0,0,0,0,0,0,0,1, - 0,0,0,4,0,0,0,19,0,0,0,115,34,0,0,0, - 116,0,124,0,131,1,115,20,116,1,100,1,124,0,100,2, - 141,2,130,1,136,0,124,0,102,1,136,1,158,2,142,0, - 83,0,41,3,122,45,80,97,116,104,32,104,111,111,107,32, - 102,111,114,32,105,109,112,111,114,116,108,105,98,46,109,97, - 99,104,105,110,101,114,121,46,70,105,108,101,70,105,110,100, - 101,114,46,122,30,111,110,108,121,32,100,105,114,101,99,116, - 111,114,105,101,115,32,97,114,101,32,115,117,112,112,111,114, - 116,101,100,114,48,0,0,0,41,2,114,56,0,0,0,114, - 118,0,0,0,114,48,0,0,0,169,2,114,193,0,0,0, - 114,66,1,0,0,114,3,0,0,0,114,6,0,0,0,218, - 24,112,97,116,104,95,104,111,111,107,95,102,111,114,95,70, - 105,108,101,70,105,110,100,101,114,217,5,0,0,115,6,0, - 0,0,0,2,8,1,12,1,122,54,70,105,108,101,70,105, - 110,100,101,114,46,112,97,116,104,95,104,111,111,107,46,60, - 108,111,99,97,108,115,62,46,112,97,116,104,95,104,111,111, - 107,95,102,111,114,95,70,105,108,101,70,105,110,100,101,114, - 114,3,0,0,0,41,3,114,193,0,0,0,114,66,1,0, - 0,114,73,1,0,0,114,3,0,0,0,114,72,1,0,0, - 114,6,0,0,0,218,9,112,97,116,104,95,104,111,111,107, - 207,5,0,0,115,4,0,0,0,0,10,14,6,122,20,70, - 105,108,101,70,105,110,100,101,114,46,112,97,116,104,95,104, - 111,111,107,99,1,0,0,0,0,0,0,0,1,0,0,0, - 3,0,0,0,67,0,0,0,115,12,0,0,0,100,1,160, - 0,124,0,106,1,161,1,83,0,41,2,78,122,16,70,105, - 108,101,70,105,110,100,101,114,40,123,33,114,125,41,41,2, - 114,62,0,0,0,114,44,0,0,0,114,246,0,0,0,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,114,39, - 1,0,0,225,5,0,0,115,2,0,0,0,0,1,122,19, - 70,105,108,101,70,105,110,100,101,114,46,95,95,114,101,112, - 114,95,95,41,1,78,41,15,114,125,0,0,0,114,124,0, - 0,0,114,126,0,0,0,114,127,0,0,0,114,209,0,0, - 0,114,46,1,0,0,114,143,0,0,0,114,206,0,0,0, - 114,137,0,0,0,114,58,1,0,0,114,203,0,0,0,114, - 67,1,0,0,114,207,0,0,0,114,74,1,0,0,114,39, - 1,0,0,114,3,0,0,0,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,114,59,1,0,0,82,5,0,0, - 115,22,0,0,0,8,2,4,7,8,14,8,4,4,2,8, - 12,8,5,10,48,8,31,2,1,10,17,114,59,1,0,0, - 99,4,0,0,0,0,0,0,0,6,0,0,0,8,0,0, - 0,67,0,0,0,115,146,0,0,0,124,0,160,0,100,1, - 161,1,125,4,124,0,160,0,100,2,161,1,125,5,124,4, - 115,66,124,5,114,36,124,5,106,1,125,4,110,30,124,2, - 124,3,107,2,114,56,116,2,124,1,124,2,131,2,125,4, - 110,10,116,3,124,1,124,2,131,2,125,4,124,5,115,84, - 116,4,124,1,124,2,124,4,100,3,141,3,125,5,122,36, - 124,5,124,0,100,2,60,0,124,4,124,0,100,1,60,0, - 124,2,124,0,100,4,60,0,124,3,124,0,100,5,60,0, - 87,0,110,20,4,0,116,5,107,10,114,140,1,0,1,0, - 1,0,89,0,110,2,88,0,100,0,83,0,41,6,78,218, - 10,95,95,108,111,97,100,101,114,95,95,218,8,95,95,115, - 112,101,99,95,95,114,60,1,0,0,90,8,95,95,102,105, - 108,101,95,95,90,10,95,95,99,97,99,104,101,100,95,95, - 41,6,218,3,103,101,116,114,140,0,0,0,114,14,1,0, - 0,114,8,1,0,0,114,190,0,0,0,218,9,69,120,99, - 101,112,116,105,111,110,41,6,90,2,110,115,114,117,0,0, - 0,90,8,112,97,116,104,110,97,109,101,90,9,99,112,97, - 116,104,110,97,109,101,114,140,0,0,0,114,187,0,0,0, - 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,218, - 14,95,102,105,120,95,117,112,95,109,111,100,117,108,101,231, - 5,0,0,115,34,0,0,0,0,2,10,1,10,1,4,1, - 4,1,8,1,8,1,12,2,10,1,4,1,14,1,2,1, - 8,1,8,1,8,1,12,1,14,2,114,79,1,0,0,99, + 32,32,32,32,32,32,99,1,0,0,0,0,0,0,0,0, + 0,0,0,1,0,0,0,4,0,0,0,19,0,0,0,115, + 34,0,0,0,116,0,124,0,131,1,115,20,116,1,100,1, + 124,0,100,2,141,2,130,1,136,0,124,0,102,1,136,1, + 158,2,142,0,83,0,41,3,122,45,80,97,116,104,32,104, + 111,111,107,32,102,111,114,32,105,109,112,111,114,116,108,105, + 98,46,109,97,99,104,105,110,101,114,121,46,70,105,108,101, + 70,105,110,100,101,114,46,122,30,111,110,108,121,32,100,105, + 114,101,99,116,111,114,105,101,115,32,97,114,101,32,115,117, + 112,112,111,114,116,101,100,114,48,0,0,0,41,2,114,56, + 0,0,0,114,118,0,0,0,114,48,0,0,0,169,2,114, + 193,0,0,0,114,66,1,0,0,114,3,0,0,0,114,6, + 0,0,0,218,24,112,97,116,104,95,104,111,111,107,95,102, + 111,114,95,70,105,108,101,70,105,110,100,101,114,218,5,0, + 0,115,6,0,0,0,0,2,8,1,12,1,122,54,70,105, + 108,101,70,105,110,100,101,114,46,112,97,116,104,95,104,111, + 111,107,46,60,108,111,99,97,108,115,62,46,112,97,116,104, + 95,104,111,111,107,95,102,111,114,95,70,105,108,101,70,105, + 110,100,101,114,114,3,0,0,0,41,3,114,193,0,0,0, + 114,66,1,0,0,114,73,1,0,0,114,3,0,0,0,114, + 72,1,0,0,114,6,0,0,0,218,9,112,97,116,104,95, + 104,111,111,107,208,5,0,0,115,4,0,0,0,0,10,14, + 6,122,20,70,105,108,101,70,105,110,100,101,114,46,112,97, + 116,104,95,104,111,111,107,99,1,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, + 115,12,0,0,0,100,1,160,0,124,0,106,1,161,1,83, + 0,41,2,78,122,16,70,105,108,101,70,105,110,100,101,114, + 40,123,33,114,125,41,41,2,114,62,0,0,0,114,44,0, + 0,0,114,246,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,114,39,1,0,0,226,5,0,0,115, + 2,0,0,0,0,1,122,19,70,105,108,101,70,105,110,100, + 101,114,46,95,95,114,101,112,114,95,95,41,1,78,41,15, + 114,125,0,0,0,114,124,0,0,0,114,126,0,0,0,114, + 127,0,0,0,114,209,0,0,0,114,46,1,0,0,114,143, + 0,0,0,114,206,0,0,0,114,137,0,0,0,114,58,1, + 0,0,114,203,0,0,0,114,67,1,0,0,114,207,0,0, + 0,114,74,1,0,0,114,39,1,0,0,114,3,0,0,0, + 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, + 59,1,0,0,83,5,0,0,115,22,0,0,0,8,2,4, + 7,8,14,8,4,4,2,8,12,8,5,10,48,8,31,2, + 1,10,17,114,59,1,0,0,99,4,0,0,0,0,0,0, + 0,0,0,0,0,6,0,0,0,8,0,0,0,67,0,0, + 0,115,146,0,0,0,124,0,160,0,100,1,161,1,125,4, + 124,0,160,0,100,2,161,1,125,5,124,4,115,66,124,5, + 114,36,124,5,106,1,125,4,110,30,124,2,124,3,107,2, + 114,56,116,2,124,1,124,2,131,2,125,4,110,10,116,3, + 124,1,124,2,131,2,125,4,124,5,115,84,116,4,124,1, + 124,2,124,4,100,3,141,3,125,5,122,36,124,5,124,0, + 100,2,60,0,124,4,124,0,100,1,60,0,124,2,124,0, + 100,4,60,0,124,3,124,0,100,5,60,0,87,0,110,20, + 4,0,116,5,107,10,114,140,1,0,1,0,1,0,89,0, + 110,2,88,0,100,0,83,0,41,6,78,218,10,95,95,108, + 111,97,100,101,114,95,95,218,8,95,95,115,112,101,99,95, + 95,114,60,1,0,0,90,8,95,95,102,105,108,101,95,95, + 90,10,95,95,99,97,99,104,101,100,95,95,41,6,218,3, + 103,101,116,114,140,0,0,0,114,14,1,0,0,114,8,1, + 0,0,114,190,0,0,0,218,9,69,120,99,101,112,116,105, + 111,110,41,6,90,2,110,115,114,117,0,0,0,90,8,112, + 97,116,104,110,97,109,101,90,9,99,112,97,116,104,110,97, + 109,101,114,140,0,0,0,114,187,0,0,0,114,3,0,0, + 0,114,3,0,0,0,114,6,0,0,0,218,14,95,102,105, + 120,95,117,112,95,109,111,100,117,108,101,232,5,0,0,115, + 34,0,0,0,0,2,10,1,10,1,4,1,4,1,8,1, + 8,1,12,2,10,1,4,1,14,1,2,1,8,1,8,1, + 8,1,12,1,14,2,114,79,1,0,0,99,0,0,0,0, 0,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, 67,0,0,0,115,38,0,0,0,116,0,116,1,160,2,161, 0,102,2,125,0,116,3,116,4,102,2,125,1,116,5,116, @@ -2513,101 +2544,102 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,114,89,0,0,0,41,3,90,10,101,120,116,101,110,115, 105,111,110,115,90,6,115,111,117,114,99,101,90,8,98,121, 116,101,99,111,100,101,114,3,0,0,0,114,3,0,0,0, - 114,6,0,0,0,114,184,0,0,0,254,5,0,0,115,8, + 114,6,0,0,0,114,184,0,0,0,255,5,0,0,115,8, 0,0,0,0,5,12,1,8,1,8,1,114,184,0,0,0, - 99,1,0,0,0,0,0,0,0,12,0,0,0,9,0,0, - 0,67,0,0,0,115,178,1,0,0,124,0,97,0,116,0, - 106,1,97,1,116,0,106,2,97,2,116,1,106,3,116,4, - 25,0,125,1,100,1,68,0,93,48,125,2,124,2,116,1, - 106,3,107,7,114,56,116,0,160,5,124,2,161,1,125,3, - 110,10,116,1,106,3,124,2,25,0,125,3,116,6,124,1, - 124,2,124,3,131,3,1,0,113,30,100,2,100,3,103,1, - 102,2,100,4,100,5,100,3,103,2,102,2,102,2,125,4, - 124,4,68,0,93,110,92,2,125,5,125,6,116,7,100,6, - 100,7,132,0,124,6,68,0,131,1,131,1,115,136,116,8, - 130,1,124,6,100,8,25,0,125,7,124,5,116,1,106,3, - 107,6,114,170,116,1,106,3,124,5,25,0,125,8,1,0, - 113,226,113,106,122,20,116,0,160,5,124,5,161,1,125,8, - 87,0,1,0,113,226,87,0,113,106,4,0,116,9,107,10, - 114,214,1,0,1,0,1,0,89,0,113,106,89,0,113,106, - 88,0,113,106,116,9,100,9,131,1,130,1,116,6,124,1, - 100,10,124,8,131,3,1,0,116,6,124,1,100,11,124,7, - 131,3,1,0,116,6,124,1,100,12,100,13,160,10,124,6, - 161,1,131,3,1,0,116,6,124,1,100,14,100,15,100,16, - 132,0,124,6,68,0,131,1,131,3,1,0,116,0,160,5, - 100,17,161,1,125,9,116,6,124,1,100,17,124,9,131,3, - 1,0,116,0,160,5,100,18,161,1,125,10,116,6,124,1, - 100,18,124,10,131,3,1,0,124,5,100,4,107,2,144,1, - 114,110,116,0,160,5,100,19,161,1,125,11,116,6,124,1, - 100,20,124,11,131,3,1,0,116,6,124,1,100,21,116,11, - 131,0,131,3,1,0,116,12,160,13,116,2,160,14,161,0, - 161,1,1,0,124,5,100,4,107,2,144,1,114,174,116,15, - 160,16,100,22,161,1,1,0,100,23,116,12,107,6,144,1, - 114,174,100,24,116,17,95,18,100,25,83,0,41,26,122,205, - 83,101,116,117,112,32,116,104,101,32,112,97,116,104,45,98, - 97,115,101,100,32,105,109,112,111,114,116,101,114,115,32,102, - 111,114,32,105,109,112,111,114,116,108,105,98,32,98,121,32, - 105,109,112,111,114,116,105,110,103,32,110,101,101,100,101,100, - 10,32,32,32,32,98,117,105,108,116,45,105,110,32,109,111, - 100,117,108,101,115,32,97,110,100,32,105,110,106,101,99,116, - 105,110,103,32,116,104,101,109,32,105,110,116,111,32,116,104, - 101,32,103,108,111,98,97,108,32,110,97,109,101,115,112,97, - 99,101,46,10,10,32,32,32,32,79,116,104,101,114,32,99, - 111,109,112,111,110,101,110,116,115,32,97,114,101,32,101,120, - 116,114,97,99,116,101,100,32,102,114,111,109,32,116,104,101, - 32,99,111,114,101,32,98,111,111,116,115,116,114,97,112,32, - 109,111,100,117,108,101,46,10,10,32,32,32,32,41,4,114, - 64,0,0,0,114,75,0,0,0,218,8,98,117,105,108,116, - 105,110,115,114,160,0,0,0,90,5,112,111,115,105,120,250, - 1,47,90,2,110,116,250,1,92,99,1,0,0,0,0,0, - 0,0,2,0,0,0,3,0,0,0,115,0,0,0,115,26, - 0,0,0,124,0,93,18,125,1,116,0,124,1,131,1,100, - 0,107,2,86,0,1,0,113,2,100,1,83,0,41,2,114, - 39,0,0,0,78,41,1,114,22,0,0,0,41,2,114,32, - 0,0,0,114,95,0,0,0,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,114,19,1,0,0,34,6,0,0, - 115,4,0,0,0,4,0,2,0,122,25,95,115,101,116,117, - 112,46,60,108,111,99,97,108,115,62,46,60,103,101,110,101, - 120,112,114,62,114,73,0,0,0,122,30,105,109,112,111,114, - 116,108,105,98,32,114,101,113,117,105,114,101,115,32,112,111, - 115,105,120,32,111,114,32,110,116,114,2,0,0,0,114,35, - 0,0,0,114,31,0,0,0,114,40,0,0,0,114,58,0, - 0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,4, - 0,0,0,83,0,0,0,115,22,0,0,0,104,0,124,0, - 93,14,125,1,100,0,124,1,155,0,157,2,146,2,113,4, - 83,0,41,1,114,74,0,0,0,114,3,0,0,0,41,2, - 114,32,0,0,0,218,1,115,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,114,68,1,0,0,50,6,0,0, - 115,4,0,0,0,6,0,2,0,122,25,95,115,101,116,117, - 112,46,60,108,111,99,97,108,115,62,46,60,115,101,116,99, - 111,109,112,62,90,7,95,116,104,114,101,97,100,90,8,95, - 119,101,97,107,114,101,102,90,6,119,105,110,114,101,103,114, - 192,0,0,0,114,7,0,0,0,122,4,46,112,121,119,122, - 6,95,100,46,112,121,100,84,78,41,19,114,134,0,0,0, - 114,8,0,0,0,114,163,0,0,0,114,31,1,0,0,114, - 125,0,0,0,90,18,95,98,117,105,108,116,105,110,95,102, - 114,111,109,95,110,97,109,101,114,129,0,0,0,218,3,97, - 108,108,114,23,0,0,0,114,118,0,0,0,114,36,0,0, - 0,114,13,0,0,0,114,21,1,0,0,114,167,0,0,0, - 114,80,1,0,0,114,102,0,0,0,114,186,0,0,0,114, - 191,0,0,0,114,195,0,0,0,41,12,218,17,95,98,111, - 111,116,115,116,114,97,112,95,109,111,100,117,108,101,90,11, - 115,101,108,102,95,109,111,100,117,108,101,90,12,98,117,105, - 108,116,105,110,95,110,97,109,101,90,14,98,117,105,108,116, - 105,110,95,109,111,100,117,108,101,90,10,111,115,95,100,101, - 116,97,105,108,115,90,10,98,117,105,108,116,105,110,95,111, - 115,114,31,0,0,0,114,35,0,0,0,90,9,111,115,95, - 109,111,100,117,108,101,90,13,116,104,114,101,97,100,95,109, - 111,100,117,108,101,90,14,119,101,97,107,114,101,102,95,109, - 111,100,117,108,101,90,13,119,105,110,114,101,103,95,109,111, - 100,117,108,101,114,3,0,0,0,114,3,0,0,0,114,6, - 0,0,0,218,6,95,115,101,116,117,112,9,6,0,0,115, - 78,0,0,0,0,8,4,1,6,1,6,3,10,1,8,1, - 10,1,12,2,10,1,14,3,22,1,12,2,22,1,8,1, - 10,1,10,1,6,2,2,1,10,1,10,1,14,1,12,2, - 8,1,12,1,12,1,18,1,22,3,10,1,12,3,10,1, - 12,3,10,1,10,1,12,3,14,1,14,1,10,1,10,1, - 10,1,114,87,1,0,0,99,1,0,0,0,0,0,0,0, + 99,1,0,0,0,0,0,0,0,0,0,0,0,12,0,0, + 0,9,0,0,0,67,0,0,0,115,178,1,0,0,124,0, + 97,0,116,0,106,1,97,1,116,0,106,2,97,2,116,1, + 106,3,116,4,25,0,125,1,100,1,68,0,93,48,125,2, + 124,2,116,1,106,3,107,7,114,56,116,0,160,5,124,2, + 161,1,125,3,110,10,116,1,106,3,124,2,25,0,125,3, + 116,6,124,1,124,2,124,3,131,3,1,0,113,30,100,2, + 100,3,103,1,102,2,100,4,100,5,100,3,103,2,102,2, + 102,2,125,4,124,4,68,0,93,110,92,2,125,5,125,6, + 116,7,100,6,100,7,132,0,124,6,68,0,131,1,131,1, + 115,136,116,8,130,1,124,6,100,8,25,0,125,7,124,5, + 116,1,106,3,107,6,114,170,116,1,106,3,124,5,25,0, + 125,8,1,0,113,226,113,106,122,20,116,0,160,5,124,5, + 161,1,125,8,87,0,1,0,113,226,87,0,113,106,4,0, + 116,9,107,10,114,214,1,0,1,0,1,0,89,0,113,106, + 89,0,113,106,88,0,113,106,116,9,100,9,131,1,130,1, + 116,6,124,1,100,10,124,8,131,3,1,0,116,6,124,1, + 100,11,124,7,131,3,1,0,116,6,124,1,100,12,100,13, + 160,10,124,6,161,1,131,3,1,0,116,6,124,1,100,14, + 100,15,100,16,132,0,124,6,68,0,131,1,131,3,1,0, + 116,0,160,5,100,17,161,1,125,9,116,6,124,1,100,17, + 124,9,131,3,1,0,116,0,160,5,100,18,161,1,125,10, + 116,6,124,1,100,18,124,10,131,3,1,0,124,5,100,4, + 107,2,144,1,114,110,116,0,160,5,100,19,161,1,125,11, + 116,6,124,1,100,20,124,11,131,3,1,0,116,6,124,1, + 100,21,116,11,131,0,131,3,1,0,116,12,160,13,116,2, + 160,14,161,0,161,1,1,0,124,5,100,4,107,2,144,1, + 114,174,116,15,160,16,100,22,161,1,1,0,100,23,116,12, + 107,6,144,1,114,174,100,24,116,17,95,18,100,25,83,0, + 41,26,122,205,83,101,116,117,112,32,116,104,101,32,112,97, + 116,104,45,98,97,115,101,100,32,105,109,112,111,114,116,101, + 114,115,32,102,111,114,32,105,109,112,111,114,116,108,105,98, + 32,98,121,32,105,109,112,111,114,116,105,110,103,32,110,101, + 101,100,101,100,10,32,32,32,32,98,117,105,108,116,45,105, + 110,32,109,111,100,117,108,101,115,32,97,110,100,32,105,110, + 106,101,99,116,105,110,103,32,116,104,101,109,32,105,110,116, + 111,32,116,104,101,32,103,108,111,98,97,108,32,110,97,109, + 101,115,112,97,99,101,46,10,10,32,32,32,32,79,116,104, + 101,114,32,99,111,109,112,111,110,101,110,116,115,32,97,114, + 101,32,101,120,116,114,97,99,116,101,100,32,102,114,111,109, + 32,116,104,101,32,99,111,114,101,32,98,111,111,116,115,116, + 114,97,112,32,109,111,100,117,108,101,46,10,10,32,32,32, + 32,41,4,114,64,0,0,0,114,75,0,0,0,218,8,98, + 117,105,108,116,105,110,115,114,160,0,0,0,90,5,112,111, + 115,105,120,250,1,47,90,2,110,116,250,1,92,99,1,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0, + 0,0,115,0,0,0,115,26,0,0,0,124,0,93,18,125, + 1,116,0,124,1,131,1,100,0,107,2,86,0,1,0,113, + 2,100,1,83,0,41,2,114,39,0,0,0,78,41,1,114, + 22,0,0,0,41,2,114,32,0,0,0,114,95,0,0,0, + 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, + 19,1,0,0,35,6,0,0,115,4,0,0,0,4,0,2, + 0,122,25,95,115,101,116,117,112,46,60,108,111,99,97,108, + 115,62,46,60,103,101,110,101,120,112,114,62,114,73,0,0, + 0,122,30,105,109,112,111,114,116,108,105,98,32,114,101,113, + 117,105,114,101,115,32,112,111,115,105,120,32,111,114,32,110, + 116,114,2,0,0,0,114,35,0,0,0,114,31,0,0,0, + 114,40,0,0,0,114,58,0,0,0,99,1,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,83, + 0,0,0,115,22,0,0,0,104,0,124,0,93,14,125,1, + 100,0,124,1,155,0,157,2,146,2,113,4,83,0,41,1, + 114,74,0,0,0,114,3,0,0,0,41,2,114,32,0,0, + 0,218,1,115,114,3,0,0,0,114,3,0,0,0,114,6, + 0,0,0,114,68,1,0,0,51,6,0,0,115,4,0,0, + 0,6,0,2,0,122,25,95,115,101,116,117,112,46,60,108, + 111,99,97,108,115,62,46,60,115,101,116,99,111,109,112,62, + 90,7,95,116,104,114,101,97,100,90,8,95,119,101,97,107, + 114,101,102,90,6,119,105,110,114,101,103,114,192,0,0,0, + 114,7,0,0,0,122,4,46,112,121,119,122,6,95,100,46, + 112,121,100,84,78,41,19,114,134,0,0,0,114,8,0,0, + 0,114,163,0,0,0,114,31,1,0,0,114,125,0,0,0, + 90,18,95,98,117,105,108,116,105,110,95,102,114,111,109,95, + 110,97,109,101,114,129,0,0,0,218,3,97,108,108,114,23, + 0,0,0,114,118,0,0,0,114,36,0,0,0,114,13,0, + 0,0,114,21,1,0,0,114,167,0,0,0,114,80,1,0, + 0,114,102,0,0,0,114,186,0,0,0,114,191,0,0,0, + 114,195,0,0,0,41,12,218,17,95,98,111,111,116,115,116, + 114,97,112,95,109,111,100,117,108,101,90,11,115,101,108,102, + 95,109,111,100,117,108,101,90,12,98,117,105,108,116,105,110, + 95,110,97,109,101,90,14,98,117,105,108,116,105,110,95,109, + 111,100,117,108,101,90,10,111,115,95,100,101,116,97,105,108, + 115,90,10,98,117,105,108,116,105,110,95,111,115,114,31,0, + 0,0,114,35,0,0,0,90,9,111,115,95,109,111,100,117, + 108,101,90,13,116,104,114,101,97,100,95,109,111,100,117,108, + 101,90,14,119,101,97,107,114,101,102,95,109,111,100,117,108, + 101,90,13,119,105,110,114,101,103,95,109,111,100,117,108,101, + 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,218, + 6,95,115,101,116,117,112,10,6,0,0,115,78,0,0,0, + 0,8,4,1,6,1,6,3,10,1,8,1,10,1,12,2, + 10,1,14,3,22,1,12,2,22,1,8,1,10,1,10,1, + 6,2,2,1,10,1,10,1,14,1,12,2,8,1,12,1, + 12,1,18,1,22,3,10,1,12,3,10,1,12,3,10,1, + 10,1,12,3,14,1,14,1,10,1,10,1,10,1,114,87, + 1,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, 2,0,0,0,4,0,0,0,67,0,0,0,115,50,0,0, 0,116,0,124,0,131,1,1,0,116,1,131,0,125,1,116, 2,106,3,160,4,116,5,106,6,124,1,142,0,103,1,161, @@ -2621,7 +2653,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 104,114,186,0,0,0,114,45,1,0,0,41,2,114,86,1, 0,0,90,17,115,117,112,112,111,114,116,101,100,95,108,111, 97,100,101,114,115,114,3,0,0,0,114,3,0,0,0,114, - 6,0,0,0,218,8,95,105,110,115,116,97,108,108,74,6, + 6,0,0,0,218,8,95,105,110,115,116,97,108,108,75,6, 0,0,115,8,0,0,0,0,2,8,1,6,1,20,1,114, 89,1,0,0,41,63,114,127,0,0,0,114,12,0,0,0, 90,37,95,67,65,83,69,95,73,78,83,69,78,83,73,84, @@ -2653,7 +2685,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 111,100,117,108,101,62,1,0,0,0,115,126,0,0,0,4, 22,4,1,4,1,2,1,2,255,4,4,8,17,8,5,8, 5,8,6,8,6,8,12,8,10,8,9,8,5,8,7,8, - 9,12,22,10,127,0,7,16,1,12,2,4,1,4,2,6, + 9,12,22,10,127,0,8,16,1,12,2,4,1,4,2,6, 2,6,2,8,2,18,71,8,40,8,19,8,12,8,12,8, 28,8,17,8,33,8,28,8,24,16,13,14,10,12,11,8, 14,6,3,6,1,2,255,12,68,14,64,14,29,16,127,0, diff --git a/Python/importlib_zipimport.h b/Python/importlib_zipimport.h index 299d1c5653b349..b7968944993556 100644 --- a/Python/importlib_zipimport.h +++ b/Python/importlib_zipimport.h @@ -1,121 +1,122 @@ /* Auto-generated by Programs/_freeze_importlib.c */ const unsigned char _Py_M__zipimport[] = { - 99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, - 0,64,0,0,0,115,82,1,0,0,100,0,90,0,100,1, - 100,2,108,1,90,2,100,1,100,3,108,1,109,3,90,3, - 109,4,90,4,1,0,100,1,100,2,108,5,90,6,100,1, - 100,2,108,7,90,7,100,1,100,2,108,8,90,8,100,1, - 100,2,108,9,90,9,100,1,100,2,108,10,90,10,100,1, - 100,2,108,11,90,11,100,4,100,5,103,2,90,12,101,2, - 106,13,90,13,101,2,106,14,100,6,100,2,133,2,25,0, - 90,15,71,0,100,7,100,4,132,0,100,4,101,16,131,3, - 90,17,105,0,90,18,101,19,101,10,131,1,90,20,100,8, - 90,21,100,9,90,22,100,10,90,23,71,0,100,11,100,5, - 132,0,100,5,131,2,90,24,101,13,100,12,23,0,100,13, - 100,13,102,3,101,13,100,14,23,0,100,15,100,13,102,3, - 100,16,100,17,102,4,90,25,100,18,100,19,132,0,90,26, - 100,20,100,21,132,0,90,27,100,22,100,23,132,0,90,28, - 100,24,100,25,132,0,90,29,100,26,90,30,100,15,97,31, - 100,27,100,28,132,0,90,32,100,29,100,30,132,0,90,33, - 100,31,100,32,132,0,90,34,100,33,100,34,132,0,90,35, - 101,19,101,35,106,36,131,1,90,37,100,35,100,36,132,0, - 90,38,100,37,100,38,132,0,90,39,100,39,100,40,132,0, - 90,40,100,41,100,42,132,0,90,41,100,43,100,44,132,0, - 90,42,100,45,100,46,132,0,90,43,71,0,100,47,100,48, - 132,0,100,48,131,2,90,44,100,2,83,0,41,49,97,80, - 2,0,0,122,105,112,105,109,112,111,114,116,32,112,114,111, - 118,105,100,101,115,32,115,117,112,112,111,114,116,32,102,111, - 114,32,105,109,112,111,114,116,105,110,103,32,80,121,116,104, - 111,110,32,109,111,100,117,108,101,115,32,102,114,111,109,32, - 90,105,112,32,97,114,99,104,105,118,101,115,46,10,10,84, - 104,105,115,32,109,111,100,117,108,101,32,101,120,112,111,114, - 116,115,32,116,104,114,101,101,32,111,98,106,101,99,116,115, - 58,10,45,32,122,105,112,105,109,112,111,114,116,101,114,58, - 32,97,32,99,108,97,115,115,59,32,105,116,115,32,99,111, - 110,115,116,114,117,99,116,111,114,32,116,97,107,101,115,32, - 97,32,112,97,116,104,32,116,111,32,97,32,90,105,112,32, - 97,114,99,104,105,118,101,46,10,45,32,90,105,112,73,109, - 112,111,114,116,69,114,114,111,114,58,32,101,120,99,101,112, - 116,105,111,110,32,114,97,105,115,101,100,32,98,121,32,122, - 105,112,105,109,112,111,114,116,101,114,32,111,98,106,101,99, - 116,115,46,32,73,116,39,115,32,97,10,32,32,115,117,98, - 99,108,97,115,115,32,111,102,32,73,109,112,111,114,116,69, - 114,114,111,114,44,32,115,111,32,105,116,32,99,97,110,32, - 98,101,32,99,97,117,103,104,116,32,97,115,32,73,109,112, - 111,114,116,69,114,114,111,114,44,32,116,111,111,46,10,45, - 32,95,122,105,112,95,100,105,114,101,99,116,111,114,121,95, - 99,97,99,104,101,58,32,97,32,100,105,99,116,44,32,109, - 97,112,112,105,110,103,32,97,114,99,104,105,118,101,32,112, - 97,116,104,115,32,116,111,32,122,105,112,32,100,105,114,101, - 99,116,111,114,121,10,32,32,105,110,102,111,32,100,105,99, - 116,115,44,32,97,115,32,117,115,101,100,32,105,110,32,122, - 105,112,105,109,112,111,114,116,101,114,46,95,102,105,108,101, - 115,46,10,10,73,116,32,105,115,32,117,115,117,97,108,108, - 121,32,110,111,116,32,110,101,101,100,101,100,32,116,111,32, - 117,115,101,32,116,104,101,32,122,105,112,105,109,112,111,114, - 116,32,109,111,100,117,108,101,32,101,120,112,108,105,99,105, - 116,108,121,59,32,105,116,32,105,115,10,117,115,101,100,32, - 98,121,32,116,104,101,32,98,117,105,108,116,105,110,32,105, - 109,112,111,114,116,32,109,101,99,104,97,110,105,115,109,32, - 102,111,114,32,115,121,115,46,112,97,116,104,32,105,116,101, - 109,115,32,116,104,97,116,32,97,114,101,32,112,97,116,104, - 115,10,116,111,32,90,105,112,32,97,114,99,104,105,118,101, - 115,46,10,233,0,0,0,0,78,41,2,218,14,95,117,110, - 112,97,99,107,95,117,105,110,116,49,54,218,14,95,117,110, - 112,97,99,107,95,117,105,110,116,51,50,218,14,90,105,112, - 73,109,112,111,114,116,69,114,114,111,114,218,11,122,105,112, - 105,109,112,111,114,116,101,114,233,1,0,0,0,99,0,0, - 0,0,0,0,0,0,0,0,0,0,1,0,0,0,64,0, - 0,0,115,12,0,0,0,101,0,90,1,100,0,90,2,100, - 1,83,0,41,2,114,3,0,0,0,78,41,3,218,8,95, - 95,110,97,109,101,95,95,218,10,95,95,109,111,100,117,108, - 101,95,95,218,12,95,95,113,117,97,108,110,97,109,101,95, - 95,169,0,114,9,0,0,0,114,9,0,0,0,250,18,60, - 102,114,111,122,101,110,32,122,105,112,105,109,112,111,114,116, - 62,114,3,0,0,0,33,0,0,0,115,2,0,0,0,8, - 1,233,22,0,0,0,115,4,0,0,0,80,75,5,6,105, - 255,255,0,0,99,0,0,0,0,0,0,0,0,0,0,0, - 0,3,0,0,0,64,0,0,0,115,108,0,0,0,101,0, - 90,1,100,0,90,2,100,1,90,3,100,2,100,3,132,0, - 90,4,100,25,100,5,100,6,132,1,90,5,100,26,100,7, - 100,8,132,1,90,6,100,9,100,10,132,0,90,7,100,11, - 100,12,132,0,90,8,100,13,100,14,132,0,90,9,100,15, - 100,16,132,0,90,10,100,17,100,18,132,0,90,11,100,19, - 100,20,132,0,90,12,100,21,100,22,132,0,90,13,100,23, - 100,24,132,0,90,14,100,4,83,0,41,27,114,4,0,0, - 0,97,255,1,0,0,122,105,112,105,109,112,111,114,116,101, - 114,40,97,114,99,104,105,118,101,112,97,116,104,41,32,45, - 62,32,122,105,112,105,109,112,111,114,116,101,114,32,111,98, - 106,101,99,116,10,10,32,32,32,32,67,114,101,97,116,101, - 32,97,32,110,101,119,32,122,105,112,105,109,112,111,114,116, - 101,114,32,105,110,115,116,97,110,99,101,46,32,39,97,114, - 99,104,105,118,101,112,97,116,104,39,32,109,117,115,116,32, - 98,101,32,97,32,112,97,116,104,32,116,111,10,32,32,32, - 32,97,32,122,105,112,102,105,108,101,44,32,111,114,32,116, - 111,32,97,32,115,112,101,99,105,102,105,99,32,112,97,116, - 104,32,105,110,115,105,100,101,32,97,32,122,105,112,102,105, - 108,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44, - 32,105,116,32,99,97,110,32,98,101,10,32,32,32,32,39, - 47,116,109,112,47,109,121,105,109,112,111,114,116,46,122,105, - 112,39,44,32,111,114,32,39,47,116,109,112,47,109,121,105, - 109,112,111,114,116,46,122,105,112,47,109,121,100,105,114,101, - 99,116,111,114,121,39,44,32,105,102,32,109,121,100,105,114, - 101,99,116,111,114,121,32,105,115,32,97,10,32,32,32,32, - 118,97,108,105,100,32,100,105,114,101,99,116,111,114,121,32, - 105,110,115,105,100,101,32,116,104,101,32,97,114,99,104,105, - 118,101,46,10,10,32,32,32,32,39,90,105,112,73,109,112, - 111,114,116,69,114,114,111,114,32,105,115,32,114,97,105,115, - 101,100,32,105,102,32,39,97,114,99,104,105,118,101,112,97, - 116,104,39,32,100,111,101,115,110,39,116,32,112,111,105,110, - 116,32,116,111,32,97,32,118,97,108,105,100,32,90,105,112, - 10,32,32,32,32,97,114,99,104,105,118,101,46,10,10,32, - 32,32,32,84,104,101,32,39,97,114,99,104,105,118,101,39, - 32,97,116,116,114,105,98,117,116,101,32,111,102,32,122,105, + 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,4,0,0,0,64,0,0,0,115,82,1,0,0,100,0, + 90,0,100,1,100,2,108,1,90,2,100,1,100,3,108,1, + 109,3,90,3,109,4,90,4,1,0,100,1,100,2,108,5, + 90,6,100,1,100,2,108,7,90,7,100,1,100,2,108,8, + 90,8,100,1,100,2,108,9,90,9,100,1,100,2,108,10, + 90,10,100,1,100,2,108,11,90,11,100,4,100,5,103,2, + 90,12,101,2,106,13,90,13,101,2,106,14,100,6,100,2, + 133,2,25,0,90,15,71,0,100,7,100,4,132,0,100,4, + 101,16,131,3,90,17,105,0,90,18,101,19,101,10,131,1, + 90,20,100,8,90,21,100,9,90,22,100,10,90,23,71,0, + 100,11,100,5,132,0,100,5,131,2,90,24,101,13,100,12, + 23,0,100,13,100,13,102,3,101,13,100,14,23,0,100,15, + 100,13,102,3,100,16,100,17,102,4,90,25,100,18,100,19, + 132,0,90,26,100,20,100,21,132,0,90,27,100,22,100,23, + 132,0,90,28,100,24,100,25,132,0,90,29,100,26,90,30, + 100,15,97,31,100,27,100,28,132,0,90,32,100,29,100,30, + 132,0,90,33,100,31,100,32,132,0,90,34,100,33,100,34, + 132,0,90,35,101,19,101,35,106,36,131,1,90,37,100,35, + 100,36,132,0,90,38,100,37,100,38,132,0,90,39,100,39, + 100,40,132,0,90,40,100,41,100,42,132,0,90,41,100,43, + 100,44,132,0,90,42,100,45,100,46,132,0,90,43,71,0, + 100,47,100,48,132,0,100,48,131,2,90,44,100,2,83,0, + 41,49,97,80,2,0,0,122,105,112,105,109,112,111,114,116, + 32,112,114,111,118,105,100,101,115,32,115,117,112,112,111,114, + 116,32,102,111,114,32,105,109,112,111,114,116,105,110,103,32, + 80,121,116,104,111,110,32,109,111,100,117,108,101,115,32,102, + 114,111,109,32,90,105,112,32,97,114,99,104,105,118,101,115, + 46,10,10,84,104,105,115,32,109,111,100,117,108,101,32,101, + 120,112,111,114,116,115,32,116,104,114,101,101,32,111,98,106, + 101,99,116,115,58,10,45,32,122,105,112,105,109,112,111,114, + 116,101,114,58,32,97,32,99,108,97,115,115,59,32,105,116, + 115,32,99,111,110,115,116,114,117,99,116,111,114,32,116,97, + 107,101,115,32,97,32,112,97,116,104,32,116,111,32,97,32, + 90,105,112,32,97,114,99,104,105,118,101,46,10,45,32,90, + 105,112,73,109,112,111,114,116,69,114,114,111,114,58,32,101, + 120,99,101,112,116,105,111,110,32,114,97,105,115,101,100,32, + 98,121,32,122,105,112,105,109,112,111,114,116,101,114,32,111, + 98,106,101,99,116,115,46,32,73,116,39,115,32,97,10,32, + 32,115,117,98,99,108,97,115,115,32,111,102,32,73,109,112, + 111,114,116,69,114,114,111,114,44,32,115,111,32,105,116,32, + 99,97,110,32,98,101,32,99,97,117,103,104,116,32,97,115, + 32,73,109,112,111,114,116,69,114,114,111,114,44,32,116,111, + 111,46,10,45,32,95,122,105,112,95,100,105,114,101,99,116, + 111,114,121,95,99,97,99,104,101,58,32,97,32,100,105,99, + 116,44,32,109,97,112,112,105,110,103,32,97,114,99,104,105, + 118,101,32,112,97,116,104,115,32,116,111,32,122,105,112,32, + 100,105,114,101,99,116,111,114,121,10,32,32,105,110,102,111, + 32,100,105,99,116,115,44,32,97,115,32,117,115,101,100,32, + 105,110,32,122,105,112,105,109,112,111,114,116,101,114,46,95, + 102,105,108,101,115,46,10,10,73,116,32,105,115,32,117,115, + 117,97,108,108,121,32,110,111,116,32,110,101,101,100,101,100, + 32,116,111,32,117,115,101,32,116,104,101,32,122,105,112,105, + 109,112,111,114,116,32,109,111,100,117,108,101,32,101,120,112, + 108,105,99,105,116,108,121,59,32,105,116,32,105,115,10,117, + 115,101,100,32,98,121,32,116,104,101,32,98,117,105,108,116, + 105,110,32,105,109,112,111,114,116,32,109,101,99,104,97,110, + 105,115,109,32,102,111,114,32,115,121,115,46,112,97,116,104, + 32,105,116,101,109,115,32,116,104,97,116,32,97,114,101,32, + 112,97,116,104,115,10,116,111,32,90,105,112,32,97,114,99, + 104,105,118,101,115,46,10,233,0,0,0,0,78,41,2,218, + 14,95,117,110,112,97,99,107,95,117,105,110,116,49,54,218, + 14,95,117,110,112,97,99,107,95,117,105,110,116,51,50,218, + 14,90,105,112,73,109,112,111,114,116,69,114,114,111,114,218, + 11,122,105,112,105,109,112,111,114,116,101,114,233,1,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,0,0,0,64,0,0,0,115,12,0,0,0,101, + 0,90,1,100,0,90,2,100,1,83,0,41,2,114,3,0, + 0,0,78,41,3,218,8,95,95,110,97,109,101,95,95,218, + 10,95,95,109,111,100,117,108,101,95,95,218,12,95,95,113, + 117,97,108,110,97,109,101,95,95,169,0,114,9,0,0,0, + 114,9,0,0,0,250,18,60,102,114,111,122,101,110,32,122, + 105,112,105,109,112,111,114,116,62,114,3,0,0,0,33,0, + 0,0,115,2,0,0,0,8,1,233,22,0,0,0,115,4, + 0,0,0,80,75,5,6,105,255,255,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,64,0,0,0,115,108,0,0,0,101,0,90,1,100,0, + 90,2,100,1,90,3,100,2,100,3,132,0,90,4,100,25, + 100,5,100,6,132,1,90,5,100,26,100,7,100,8,132,1, + 90,6,100,9,100,10,132,0,90,7,100,11,100,12,132,0, + 90,8,100,13,100,14,132,0,90,9,100,15,100,16,132,0, + 90,10,100,17,100,18,132,0,90,11,100,19,100,20,132,0, + 90,12,100,21,100,22,132,0,90,13,100,23,100,24,132,0, + 90,14,100,4,83,0,41,27,114,4,0,0,0,97,255,1, + 0,0,122,105,112,105,109,112,111,114,116,101,114,40,97,114, + 99,104,105,118,101,112,97,116,104,41,32,45,62,32,122,105, 112,105,109,112,111,114,116,101,114,32,111,98,106,101,99,116, - 115,32,99,111,110,116,97,105,110,115,32,116,104,101,32,110, - 97,109,101,32,111,102,32,116,104,101,10,32,32,32,32,122, - 105,112,102,105,108,101,32,116,97,114,103,101,116,101,100,46, - 10,32,32,32,32,99,2,0,0,0,0,0,0,0,8,0, + 10,10,32,32,32,32,67,114,101,97,116,101,32,97,32,110, + 101,119,32,122,105,112,105,109,112,111,114,116,101,114,32,105, + 110,115,116,97,110,99,101,46,32,39,97,114,99,104,105,118, + 101,112,97,116,104,39,32,109,117,115,116,32,98,101,32,97, + 32,112,97,116,104,32,116,111,10,32,32,32,32,97,32,122, + 105,112,102,105,108,101,44,32,111,114,32,116,111,32,97,32, + 115,112,101,99,105,102,105,99,32,112,97,116,104,32,105,110, + 115,105,100,101,32,97,32,122,105,112,102,105,108,101,46,32, + 70,111,114,32,101,120,97,109,112,108,101,44,32,105,116,32, + 99,97,110,32,98,101,10,32,32,32,32,39,47,116,109,112, + 47,109,121,105,109,112,111,114,116,46,122,105,112,39,44,32, + 111,114,32,39,47,116,109,112,47,109,121,105,109,112,111,114, + 116,46,122,105,112,47,109,121,100,105,114,101,99,116,111,114, + 121,39,44,32,105,102,32,109,121,100,105,114,101,99,116,111, + 114,121,32,105,115,32,97,10,32,32,32,32,118,97,108,105, + 100,32,100,105,114,101,99,116,111,114,121,32,105,110,115,105, + 100,101,32,116,104,101,32,97,114,99,104,105,118,101,46,10, + 10,32,32,32,32,39,90,105,112,73,109,112,111,114,116,69, + 114,114,111,114,32,105,115,32,114,97,105,115,101,100,32,105, + 102,32,39,97,114,99,104,105,118,101,112,97,116,104,39,32, + 100,111,101,115,110,39,116,32,112,111,105,110,116,32,116,111, + 32,97,32,118,97,108,105,100,32,90,105,112,10,32,32,32, + 32,97,114,99,104,105,118,101,46,10,10,32,32,32,32,84, + 104,101,32,39,97,114,99,104,105,118,101,39,32,97,116,116, + 114,105,98,117,116,101,32,111,102,32,122,105,112,105,109,112, + 111,114,116,101,114,32,111,98,106,101,99,116,115,32,99,111, + 110,116,97,105,110,115,32,116,104,101,32,110,97,109,101,32, + 111,102,32,116,104,101,10,32,32,32,32,122,105,112,102,105, + 108,101,32,116,97,114,103,101,116,101,100,46,10,32,32,32, + 32,99,2,0,0,0,0,0,0,0,0,0,0,0,8,0, 0,0,9,0,0,0,67,0,0,0,115,36,1,0,0,116, 0,124,1,116,1,131,2,115,28,100,1,100,0,108,2,125, 2,124,2,160,3,124,1,161,1,125,1,124,1,115,44,116, @@ -165,61 +166,17 @@ const unsigned char _Py_M__zipimport[] = { 1,16,3,14,2,12,1,4,2,2,1,12,1,14,1,8, 1,14,1,6,1,6,2,22,1,8,1,122,20,122,105,112, 105,109,112,111,114,116,101,114,46,95,95,105,110,105,116,95, - 95,78,99,3,0,0,0,0,0,0,0,5,0,0,0,4, - 0,0,0,67,0,0,0,115,78,0,0,0,116,0,124,0, - 124,1,131,2,125,3,124,3,100,1,107,9,114,26,124,0, - 103,0,102,2,83,0,116,1,124,0,124,1,131,2,125,4, - 116,2,124,0,124,4,131,2,114,70,100,1,124,0,106,3, - 155,0,116,4,155,0,124,4,155,0,157,3,103,1,102,2, - 83,0,100,1,103,0,102,2,83,0,41,2,97,239,1,0, - 0,102,105,110,100,95,108,111,97,100,101,114,40,102,117,108, - 108,110,97,109,101,44,32,112,97,116,104,61,78,111,110,101, - 41,32,45,62,32,115,101,108,102,44,32,115,116,114,32,111, - 114,32,78,111,110,101,46,10,10,32,32,32,32,32,32,32, - 32,83,101,97,114,99,104,32,102,111,114,32,97,32,109,111, - 100,117,108,101,32,115,112,101,99,105,102,105,101,100,32,98, - 121,32,39,102,117,108,108,110,97,109,101,39,46,32,39,102, - 117,108,108,110,97,109,101,39,32,109,117,115,116,32,98,101, - 32,116,104,101,10,32,32,32,32,32,32,32,32,102,117,108, - 108,121,32,113,117,97,108,105,102,105,101,100,32,40,100,111, - 116,116,101,100,41,32,109,111,100,117,108,101,32,110,97,109, - 101,46,32,73,116,32,114,101,116,117,114,110,115,32,116,104, - 101,32,122,105,112,105,109,112,111,114,116,101,114,10,32,32, - 32,32,32,32,32,32,105,110,115,116,97,110,99,101,32,105, - 116,115,101,108,102,32,105,102,32,116,104,101,32,109,111,100, - 117,108,101,32,119,97,115,32,102,111,117,110,100,44,32,97, - 32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105, - 110,103,32,116,104,101,10,32,32,32,32,32,32,32,32,102, - 117,108,108,32,112,97,116,104,32,110,97,109,101,32,105,102, - 32,105,116,39,115,32,112,111,115,115,105,98,108,121,32,97, - 32,112,111,114,116,105,111,110,32,111,102,32,97,32,110,97, - 109,101,115,112,97,99,101,32,112,97,99,107,97,103,101,44, - 10,32,32,32,32,32,32,32,32,111,114,32,78,111,110,101, - 32,111,116,104,101,114,119,105,115,101,46,32,84,104,101,32, - 111,112,116,105,111,110,97,108,32,39,112,97,116,104,39,32, - 97,114,103,117,109,101,110,116,32,105,115,32,105,103,110,111, - 114,101,100,32,45,45,32,105,116,39,115,10,32,32,32,32, - 32,32,32,32,116,104,101,114,101,32,102,111,114,32,99,111, - 109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104, - 32,116,104,101,32,105,109,112,111,114,116,101,114,32,112,114, - 111,116,111,99,111,108,46,10,32,32,32,32,32,32,32,32, - 78,41,5,218,16,95,103,101,116,95,109,111,100,117,108,101, - 95,105,110,102,111,218,16,95,103,101,116,95,109,111,100,117, - 108,101,95,112,97,116,104,218,7,95,105,115,95,100,105,114, - 114,29,0,0,0,114,20,0,0,0,41,5,114,32,0,0, - 0,218,8,102,117,108,108,110,97,109,101,114,13,0,0,0, - 218,2,109,105,218,7,109,111,100,112,97,116,104,114,9,0, - 0,0,114,9,0,0,0,114,10,0,0,0,218,11,102,105, - 110,100,95,108,111,97,100,101,114,109,0,0,0,115,14,0, - 0,0,0,10,10,1,8,2,8,7,10,1,10,4,24,2, - 122,23,122,105,112,105,109,112,111,114,116,101,114,46,102,105, - 110,100,95,108,111,97,100,101,114,99,3,0,0,0,0,0, - 0,0,3,0,0,0,4,0,0,0,67,0,0,0,115,16, - 0,0,0,124,0,160,0,124,1,124,2,161,2,100,1,25, - 0,83,0,41,2,97,139,1,0,0,102,105,110,100,95,109, - 111,100,117,108,101,40,102,117,108,108,110,97,109,101,44,32, - 112,97,116,104,61,78,111,110,101,41,32,45,62,32,115,101, - 108,102,32,111,114,32,78,111,110,101,46,10,10,32,32,32, + 95,78,99,3,0,0,0,0,0,0,0,0,0,0,0,5, + 0,0,0,4,0,0,0,67,0,0,0,115,78,0,0,0, + 116,0,124,0,124,1,131,2,125,3,124,3,100,1,107,9, + 114,26,124,0,103,0,102,2,83,0,116,1,124,0,124,1, + 131,2,125,4,116,2,124,0,124,4,131,2,114,70,100,1, + 124,0,106,3,155,0,116,4,155,0,124,4,155,0,157,3, + 103,1,102,2,83,0,100,1,103,0,102,2,83,0,41,2, + 97,239,1,0,0,102,105,110,100,95,108,111,97,100,101,114, + 40,102,117,108,108,110,97,109,101,44,32,112,97,116,104,61, + 78,111,110,101,41,32,45,62,32,115,101,108,102,44,32,115, + 116,114,32,111,114,32,78,111,110,101,46,10,10,32,32,32, 32,32,32,32,32,83,101,97,114,99,104,32,102,111,114,32, 97,32,109,111,100,117,108,101,32,115,112,101,99,105,102,105, 101,100,32,98,121,32,39,102,117,108,108,110,97,109,101,39, @@ -232,42 +189,87 @@ const unsigned char _Py_M__zipimport[] = { 114,10,32,32,32,32,32,32,32,32,105,110,115,116,97,110, 99,101,32,105,116,115,101,108,102,32,105,102,32,116,104,101, 32,109,111,100,117,108,101,32,119,97,115,32,102,111,117,110, - 100,44,32,111,114,32,78,111,110,101,32,105,102,32,105,116, - 32,119,97,115,110,39,116,46,10,32,32,32,32,32,32,32, - 32,84,104,101,32,111,112,116,105,111,110,97,108,32,39,112, - 97,116,104,39,32,97,114,103,117,109,101,110,116,32,105,115, - 32,105,103,110,111,114,101,100,32,45,45,32,105,116,39,115, - 32,116,104,101,114,101,32,102,111,114,32,99,111,109,112,97, - 116,105,98,105,108,105,116,121,10,32,32,32,32,32,32,32, - 32,119,105,116,104,32,116,104,101,32,105,109,112,111,114,116, - 101,114,32,112,114,111,116,111,99,111,108,46,10,32,32,32, - 32,32,32,32,32,114,0,0,0,0,41,1,114,41,0,0, - 0,41,3,114,32,0,0,0,114,38,0,0,0,114,13,0, - 0,0,114,9,0,0,0,114,9,0,0,0,114,10,0,0, - 0,218,11,102,105,110,100,95,109,111,100,117,108,101,141,0, - 0,0,115,2,0,0,0,0,9,122,23,122,105,112,105,109, - 112,111,114,116,101,114,46,102,105,110,100,95,109,111,100,117, - 108,101,99,2,0,0,0,0,0,0,0,5,0,0,0,3, - 0,0,0,67,0,0,0,115,20,0,0,0,116,0,124,0, - 124,1,131,2,92,3,125,2,125,3,125,4,124,2,83,0, - 41,1,122,163,103,101,116,95,99,111,100,101,40,102,117,108, - 108,110,97,109,101,41,32,45,62,32,99,111,100,101,32,111, - 98,106,101,99,116,46,10,10,32,32,32,32,32,32,32,32, - 82,101,116,117,114,110,32,116,104,101,32,99,111,100,101,32, - 111,98,106,101,99,116,32,102,111,114,32,116,104,101,32,115, - 112,101,99,105,102,105,101,100,32,109,111,100,117,108,101,46, - 32,82,97,105,115,101,32,90,105,112,73,109,112,111,114,116, - 69,114,114,111,114,10,32,32,32,32,32,32,32,32,105,102, - 32,116,104,101,32,109,111,100,117,108,101,32,99,111,117,108, - 100,110,39,116,32,98,101,32,102,111,117,110,100,46,10,32, - 32,32,32,32,32,32,32,169,1,218,16,95,103,101,116,95, - 109,111,100,117,108,101,95,99,111,100,101,169,5,114,32,0, - 0,0,114,38,0,0,0,218,4,99,111,100,101,218,9,105, - 115,112,97,99,107,97,103,101,114,40,0,0,0,114,9,0, - 0,0,114,9,0,0,0,114,10,0,0,0,218,8,103,101, - 116,95,99,111,100,101,153,0,0,0,115,4,0,0,0,0, - 6,16,1,122,20,122,105,112,105,109,112,111,114,116,101,114, - 46,103,101,116,95,99,111,100,101,99,2,0,0,0,0,0, + 100,44,32,97,32,115,116,114,105,110,103,32,99,111,110,116, + 97,105,110,105,110,103,32,116,104,101,10,32,32,32,32,32, + 32,32,32,102,117,108,108,32,112,97,116,104,32,110,97,109, + 101,32,105,102,32,105,116,39,115,32,112,111,115,115,105,98, + 108,121,32,97,32,112,111,114,116,105,111,110,32,111,102,32, + 97,32,110,97,109,101,115,112,97,99,101,32,112,97,99,107, + 97,103,101,44,10,32,32,32,32,32,32,32,32,111,114,32, + 78,111,110,101,32,111,116,104,101,114,119,105,115,101,46,32, + 84,104,101,32,111,112,116,105,111,110,97,108,32,39,112,97, + 116,104,39,32,97,114,103,117,109,101,110,116,32,105,115,32, + 105,103,110,111,114,101,100,32,45,45,32,105,116,39,115,10, + 32,32,32,32,32,32,32,32,116,104,101,114,101,32,102,111, + 114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32, + 119,105,116,104,32,116,104,101,32,105,109,112,111,114,116,101, + 114,32,112,114,111,116,111,99,111,108,46,10,32,32,32,32, + 32,32,32,32,78,41,5,218,16,95,103,101,116,95,109,111, + 100,117,108,101,95,105,110,102,111,218,16,95,103,101,116,95, + 109,111,100,117,108,101,95,112,97,116,104,218,7,95,105,115, + 95,100,105,114,114,29,0,0,0,114,20,0,0,0,41,5, + 114,32,0,0,0,218,8,102,117,108,108,110,97,109,101,114, + 13,0,0,0,218,2,109,105,218,7,109,111,100,112,97,116, + 104,114,9,0,0,0,114,9,0,0,0,114,10,0,0,0, + 218,11,102,105,110,100,95,108,111,97,100,101,114,109,0,0, + 0,115,14,0,0,0,0,10,10,1,8,2,8,7,10,1, + 10,4,24,2,122,23,122,105,112,105,109,112,111,114,116,101, + 114,46,102,105,110,100,95,108,111,97,100,101,114,99,3,0, + 0,0,0,0,0,0,0,0,0,0,3,0,0,0,4,0, + 0,0,67,0,0,0,115,16,0,0,0,124,0,160,0,124, + 1,124,2,161,2,100,1,25,0,83,0,41,2,97,139,1, + 0,0,102,105,110,100,95,109,111,100,117,108,101,40,102,117, + 108,108,110,97,109,101,44,32,112,97,116,104,61,78,111,110, + 101,41,32,45,62,32,115,101,108,102,32,111,114,32,78,111, + 110,101,46,10,10,32,32,32,32,32,32,32,32,83,101,97, + 114,99,104,32,102,111,114,32,97,32,109,111,100,117,108,101, + 32,115,112,101,99,105,102,105,101,100,32,98,121,32,39,102, + 117,108,108,110,97,109,101,39,46,32,39,102,117,108,108,110, + 97,109,101,39,32,109,117,115,116,32,98,101,32,116,104,101, + 10,32,32,32,32,32,32,32,32,102,117,108,108,121,32,113, + 117,97,108,105,102,105,101,100,32,40,100,111,116,116,101,100, + 41,32,109,111,100,117,108,101,32,110,97,109,101,46,32,73, + 116,32,114,101,116,117,114,110,115,32,116,104,101,32,122,105, + 112,105,109,112,111,114,116,101,114,10,32,32,32,32,32,32, + 32,32,105,110,115,116,97,110,99,101,32,105,116,115,101,108, + 102,32,105,102,32,116,104,101,32,109,111,100,117,108,101,32, + 119,97,115,32,102,111,117,110,100,44,32,111,114,32,78,111, + 110,101,32,105,102,32,105,116,32,119,97,115,110,39,116,46, + 10,32,32,32,32,32,32,32,32,84,104,101,32,111,112,116, + 105,111,110,97,108,32,39,112,97,116,104,39,32,97,114,103, + 117,109,101,110,116,32,105,115,32,105,103,110,111,114,101,100, + 32,45,45,32,105,116,39,115,32,116,104,101,114,101,32,102, + 111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121, + 10,32,32,32,32,32,32,32,32,119,105,116,104,32,116,104, + 101,32,105,109,112,111,114,116,101,114,32,112,114,111,116,111, + 99,111,108,46,10,32,32,32,32,32,32,32,32,114,0,0, + 0,0,41,1,114,41,0,0,0,41,3,114,32,0,0,0, + 114,38,0,0,0,114,13,0,0,0,114,9,0,0,0,114, + 9,0,0,0,114,10,0,0,0,218,11,102,105,110,100,95, + 109,111,100,117,108,101,141,0,0,0,115,2,0,0,0,0, + 9,122,23,122,105,112,105,109,112,111,114,116,101,114,46,102, + 105,110,100,95,109,111,100,117,108,101,99,2,0,0,0,0, + 0,0,0,0,0,0,0,5,0,0,0,3,0,0,0,67, + 0,0,0,115,20,0,0,0,116,0,124,0,124,1,131,2, + 92,3,125,2,125,3,125,4,124,2,83,0,41,1,122,163, + 103,101,116,95,99,111,100,101,40,102,117,108,108,110,97,109, + 101,41,32,45,62,32,99,111,100,101,32,111,98,106,101,99, + 116,46,10,10,32,32,32,32,32,32,32,32,82,101,116,117, + 114,110,32,116,104,101,32,99,111,100,101,32,111,98,106,101, + 99,116,32,102,111,114,32,116,104,101,32,115,112,101,99,105, + 102,105,101,100,32,109,111,100,117,108,101,46,32,82,97,105, + 115,101,32,90,105,112,73,109,112,111,114,116,69,114,114,111, + 114,10,32,32,32,32,32,32,32,32,105,102,32,116,104,101, + 32,109,111,100,117,108,101,32,99,111,117,108,100,110,39,116, + 32,98,101,32,102,111,117,110,100,46,10,32,32,32,32,32, + 32,32,32,169,1,218,16,95,103,101,116,95,109,111,100,117, + 108,101,95,99,111,100,101,169,5,114,32,0,0,0,114,38, + 0,0,0,218,4,99,111,100,101,218,9,105,115,112,97,99, + 107,97,103,101,114,40,0,0,0,114,9,0,0,0,114,9, + 0,0,0,114,10,0,0,0,218,8,103,101,116,95,99,111, + 100,101,153,0,0,0,115,4,0,0,0,0,6,16,1,122, + 20,122,105,112,105,109,112,111,114,116,101,114,46,103,101,116, + 95,99,111,100,101,99,2,0,0,0,0,0,0,0,0,0, 0,0,4,0,0,0,8,0,0,0,67,0,0,0,115,118, 0,0,0,116,0,114,16,124,1,160,1,116,0,116,2,161, 2,125,1,124,1,125,2,124,1,160,3,124,0,106,4,116, @@ -298,82 +300,83 @@ const unsigned char _Py_M__zipimport[] = { 0,0,0,0,6,4,1,12,2,4,1,16,1,22,2,2, 1,14,1,14,1,18,1,122,20,122,105,112,105,109,112,111, 114,116,101,114,46,103,101,116,95,100,97,116,97,99,2,0, - 0,0,0,0,0,0,5,0,0,0,3,0,0,0,67,0, - 0,0,115,20,0,0,0,116,0,124,0,124,1,131,2,92, - 3,125,2,125,3,125,4,124,4,83,0,41,1,122,106,103, - 101,116,95,102,105,108,101,110,97,109,101,40,102,117,108,108, - 110,97,109,101,41,32,45,62,32,102,105,108,101,110,97,109, - 101,32,115,116,114,105,110,103,46,10,10,32,32,32,32,32, - 32,32,32,82,101,116,117,114,110,32,116,104,101,32,102,105, - 108,101,110,97,109,101,32,102,111,114,32,116,104,101,32,115, - 112,101,99,105,102,105,101,100,32,109,111,100,117,108,101,46, - 10,32,32,32,32,32,32,32,32,114,43,0,0,0,114,45, - 0,0,0,114,9,0,0,0,114,9,0,0,0,114,10,0, - 0,0,218,12,103,101,116,95,102,105,108,101,110,97,109,101, - 184,0,0,0,115,4,0,0,0,0,7,16,1,122,24,122, - 105,112,105,109,112,111,114,116,101,114,46,103,101,116,95,102, - 105,108,101,110,97,109,101,99,2,0,0,0,0,0,0,0, - 6,0,0,0,8,0,0,0,67,0,0,0,115,128,0,0, - 0,116,0,124,0,124,1,131,2,125,2,124,2,100,1,107, - 8,114,36,116,1,100,2,124,1,155,2,157,2,124,1,100, - 3,141,2,130,1,116,2,124,0,124,1,131,2,125,3,124, - 2,114,64,116,3,160,4,124,3,100,4,161,2,125,4,110, - 10,124,3,155,0,100,5,157,2,125,4,122,14,124,0,106, - 5,124,4,25,0,125,5,87,0,110,22,4,0,116,6,107, - 10,114,110,1,0,1,0,1,0,89,0,100,1,83,0,88, - 0,116,7,124,0,106,8,124,5,131,2,160,9,161,0,83, - 0,41,6,122,253,103,101,116,95,115,111,117,114,99,101,40, - 102,117,108,108,110,97,109,101,41,32,45,62,32,115,111,117, - 114,99,101,32,115,116,114,105,110,103,46,10,10,32,32,32, - 32,32,32,32,32,82,101,116,117,114,110,32,116,104,101,32, - 115,111,117,114,99,101,32,99,111,100,101,32,102,111,114,32, - 116,104,101,32,115,112,101,99,105,102,105,101,100,32,109,111, - 100,117,108,101,46,32,82,97,105,115,101,32,90,105,112,73, - 109,112,111,114,116,69,114,114,111,114,10,32,32,32,32,32, - 32,32,32,105,102,32,116,104,101,32,109,111,100,117,108,101, - 32,99,111,117,108,100,110,39,116,32,98,101,32,102,111,117, - 110,100,44,32,114,101,116,117,114,110,32,78,111,110,101,32, - 105,102,32,116,104,101,32,97,114,99,104,105,118,101,32,100, - 111,101,115,10,32,32,32,32,32,32,32,32,99,111,110,116, - 97,105,110,32,116,104,101,32,109,111,100,117,108,101,44,32, - 98,117,116,32,104,97,115,32,110,111,32,115,111,117,114,99, - 101,32,102,111,114,32,105,116,46,10,32,32,32,32,32,32, - 32,32,78,250,18,99,97,110,39,116,32,102,105,110,100,32, - 109,111,100,117,108,101,32,169,1,218,4,110,97,109,101,250, - 11,95,95,105,110,105,116,95,95,46,112,121,250,3,46,112, - 121,41,10,114,35,0,0,0,114,3,0,0,0,114,36,0, - 0,0,114,21,0,0,0,114,30,0,0,0,114,28,0,0, - 0,114,26,0,0,0,114,52,0,0,0,114,29,0,0,0, - 218,6,100,101,99,111,100,101,41,6,114,32,0,0,0,114, - 38,0,0,0,114,39,0,0,0,114,13,0,0,0,218,8, - 102,117,108,108,112,97,116,104,114,54,0,0,0,114,9,0, - 0,0,114,9,0,0,0,114,10,0,0,0,218,10,103,101, - 116,95,115,111,117,114,99,101,195,0,0,0,115,24,0,0, - 0,0,7,10,1,8,1,18,2,10,1,4,1,14,2,10, - 2,2,1,14,1,14,2,8,1,122,22,122,105,112,105,109, - 112,111,114,116,101,114,46,103,101,116,95,115,111,117,114,99, - 101,99,2,0,0,0,0,0,0,0,3,0,0,0,4,0, - 0,0,67,0,0,0,115,40,0,0,0,116,0,124,0,124, - 1,131,2,125,2,124,2,100,1,107,8,114,36,116,1,100, - 2,124,1,155,2,157,2,124,1,100,3,141,2,130,1,124, - 2,83,0,41,4,122,171,105,115,95,112,97,99,107,97,103, - 101,40,102,117,108,108,110,97,109,101,41,32,45,62,32,98, - 111,111,108,46,10,10,32,32,32,32,32,32,32,32,82,101, - 116,117,114,110,32,84,114,117,101,32,105,102,32,116,104,101, - 32,109,111,100,117,108,101,32,115,112,101,99,105,102,105,101, - 100,32,98,121,32,102,117,108,108,110,97,109,101,32,105,115, - 32,97,32,112,97,99,107,97,103,101,46,10,32,32,32,32, - 32,32,32,32,82,97,105,115,101,32,90,105,112,73,109,112, - 111,114,116,69,114,114,111,114,32,105,102,32,116,104,101,32, - 109,111,100,117,108,101,32,99,111,117,108,100,110,39,116,32, - 98,101,32,102,111,117,110,100,46,10,32,32,32,32,32,32, - 32,32,78,114,57,0,0,0,114,58,0,0,0,41,2,114, - 35,0,0,0,114,3,0,0,0,41,3,114,32,0,0,0, - 114,38,0,0,0,114,39,0,0,0,114,9,0,0,0,114, - 9,0,0,0,114,10,0,0,0,218,10,105,115,95,112,97, - 99,107,97,103,101,221,0,0,0,115,8,0,0,0,0,6, - 10,1,8,1,18,1,122,22,122,105,112,105,109,112,111,114, - 116,101,114,46,105,115,95,112,97,99,107,97,103,101,99,2, + 0,0,0,0,0,0,0,0,0,0,5,0,0,0,3,0, + 0,0,67,0,0,0,115,20,0,0,0,116,0,124,0,124, + 1,131,2,92,3,125,2,125,3,125,4,124,4,83,0,41, + 1,122,106,103,101,116,95,102,105,108,101,110,97,109,101,40, + 102,117,108,108,110,97,109,101,41,32,45,62,32,102,105,108, + 101,110,97,109,101,32,115,116,114,105,110,103,46,10,10,32, + 32,32,32,32,32,32,32,82,101,116,117,114,110,32,116,104, + 101,32,102,105,108,101,110,97,109,101,32,102,111,114,32,116, + 104,101,32,115,112,101,99,105,102,105,101,100,32,109,111,100, + 117,108,101,46,10,32,32,32,32,32,32,32,32,114,43,0, + 0,0,114,45,0,0,0,114,9,0,0,0,114,9,0,0, + 0,114,10,0,0,0,218,12,103,101,116,95,102,105,108,101, + 110,97,109,101,184,0,0,0,115,4,0,0,0,0,7,16, + 1,122,24,122,105,112,105,109,112,111,114,116,101,114,46,103, + 101,116,95,102,105,108,101,110,97,109,101,99,2,0,0,0, + 0,0,0,0,0,0,0,0,6,0,0,0,8,0,0,0, + 67,0,0,0,115,128,0,0,0,116,0,124,0,124,1,131, + 2,125,2,124,2,100,1,107,8,114,36,116,1,100,2,124, + 1,155,2,157,2,124,1,100,3,141,2,130,1,116,2,124, + 0,124,1,131,2,125,3,124,2,114,64,116,3,160,4,124, + 3,100,4,161,2,125,4,110,10,124,3,155,0,100,5,157, + 2,125,4,122,14,124,0,106,5,124,4,25,0,125,5,87, + 0,110,22,4,0,116,6,107,10,114,110,1,0,1,0,1, + 0,89,0,100,1,83,0,88,0,116,7,124,0,106,8,124, + 5,131,2,160,9,161,0,83,0,41,6,122,253,103,101,116, + 95,115,111,117,114,99,101,40,102,117,108,108,110,97,109,101, + 41,32,45,62,32,115,111,117,114,99,101,32,115,116,114,105, + 110,103,46,10,10,32,32,32,32,32,32,32,32,82,101,116, + 117,114,110,32,116,104,101,32,115,111,117,114,99,101,32,99, + 111,100,101,32,102,111,114,32,116,104,101,32,115,112,101,99, + 105,102,105,101,100,32,109,111,100,117,108,101,46,32,82,97, + 105,115,101,32,90,105,112,73,109,112,111,114,116,69,114,114, + 111,114,10,32,32,32,32,32,32,32,32,105,102,32,116,104, + 101,32,109,111,100,117,108,101,32,99,111,117,108,100,110,39, + 116,32,98,101,32,102,111,117,110,100,44,32,114,101,116,117, + 114,110,32,78,111,110,101,32,105,102,32,116,104,101,32,97, + 114,99,104,105,118,101,32,100,111,101,115,10,32,32,32,32, + 32,32,32,32,99,111,110,116,97,105,110,32,116,104,101,32, + 109,111,100,117,108,101,44,32,98,117,116,32,104,97,115,32, + 110,111,32,115,111,117,114,99,101,32,102,111,114,32,105,116, + 46,10,32,32,32,32,32,32,32,32,78,250,18,99,97,110, + 39,116,32,102,105,110,100,32,109,111,100,117,108,101,32,169, + 1,218,4,110,97,109,101,250,11,95,95,105,110,105,116,95, + 95,46,112,121,250,3,46,112,121,41,10,114,35,0,0,0, + 114,3,0,0,0,114,36,0,0,0,114,21,0,0,0,114, + 30,0,0,0,114,28,0,0,0,114,26,0,0,0,114,52, + 0,0,0,114,29,0,0,0,218,6,100,101,99,111,100,101, + 41,6,114,32,0,0,0,114,38,0,0,0,114,39,0,0, + 0,114,13,0,0,0,218,8,102,117,108,108,112,97,116,104, + 114,54,0,0,0,114,9,0,0,0,114,9,0,0,0,114, + 10,0,0,0,218,10,103,101,116,95,115,111,117,114,99,101, + 195,0,0,0,115,24,0,0,0,0,7,10,1,8,1,18, + 2,10,1,4,1,14,2,10,2,2,1,14,1,14,2,8, + 1,122,22,122,105,112,105,109,112,111,114,116,101,114,46,103, + 101,116,95,115,111,117,114,99,101,99,2,0,0,0,0,0, + 0,0,0,0,0,0,3,0,0,0,4,0,0,0,67,0, + 0,0,115,40,0,0,0,116,0,124,0,124,1,131,2,125, + 2,124,2,100,1,107,8,114,36,116,1,100,2,124,1,155, + 2,157,2,124,1,100,3,141,2,130,1,124,2,83,0,41, + 4,122,171,105,115,95,112,97,99,107,97,103,101,40,102,117, + 108,108,110,97,109,101,41,32,45,62,32,98,111,111,108,46, + 10,10,32,32,32,32,32,32,32,32,82,101,116,117,114,110, + 32,84,114,117,101,32,105,102,32,116,104,101,32,109,111,100, + 117,108,101,32,115,112,101,99,105,102,105,101,100,32,98,121, + 32,102,117,108,108,110,97,109,101,32,105,115,32,97,32,112, + 97,99,107,97,103,101,46,10,32,32,32,32,32,32,32,32, + 82,97,105,115,101,32,90,105,112,73,109,112,111,114,116,69, + 114,114,111,114,32,105,102,32,116,104,101,32,109,111,100,117, + 108,101,32,99,111,117,108,100,110,39,116,32,98,101,32,102, + 111,117,110,100,46,10,32,32,32,32,32,32,32,32,78,114, + 57,0,0,0,114,58,0,0,0,41,2,114,35,0,0,0, + 114,3,0,0,0,41,3,114,32,0,0,0,114,38,0,0, + 0,114,39,0,0,0,114,9,0,0,0,114,9,0,0,0, + 114,10,0,0,0,218,10,105,115,95,112,97,99,107,97,103, + 101,221,0,0,0,115,8,0,0,0,0,6,10,1,8,1, + 18,1,122,22,122,105,112,105,109,112,111,114,116,101,114,46, + 105,115,95,112,97,99,107,97,103,101,99,2,0,0,0,0, 0,0,0,0,0,0,0,8,0,0,0,8,0,0,0,67, 0,0,0,115,248,0,0,0,116,0,124,0,124,1,131,2, 92,3,125,2,125,3,125,4,116,1,106,2,160,3,124,1, @@ -433,70 +436,71 @@ const unsigned char _Py_M__zipimport[] = { 1,6,1,16,1,16,1,6,1,8,1,8,2,2,1,14, 1,14,1,22,1,14,1,122,23,122,105,112,105,109,112,111, 114,116,101,114,46,108,111,97,100,95,109,111,100,117,108,101, - 99,2,0,0,0,0,0,0,0,3,0,0,0,8,0,0, - 0,67,0,0,0,115,88,0,0,0,122,20,124,0,160,0, - 124,1,161,1,115,18,87,0,100,1,83,0,87,0,110,22, - 4,0,116,1,107,10,114,42,1,0,1,0,1,0,89,0, - 100,1,83,0,88,0,116,2,106,3,115,78,100,2,100,3, - 108,4,109,5,125,2,1,0,124,2,160,6,116,2,161,1, - 1,0,100,4,116,2,95,3,116,2,124,0,124,1,131,2, - 83,0,41,5,122,204,82,101,116,117,114,110,32,116,104,101, - 32,82,101,115,111,117,114,99,101,82,101,97,100,101,114,32, - 102,111,114,32,97,32,112,97,99,107,97,103,101,32,105,110, - 32,97,32,122,105,112,32,102,105,108,101,46,10,10,32,32, - 32,32,32,32,32,32,73,102,32,39,102,117,108,108,110,97, - 109,101,39,32,105,115,32,97,32,112,97,99,107,97,103,101, - 32,119,105,116,104,105,110,32,116,104,101,32,122,105,112,32, - 102,105,108,101,44,32,114,101,116,117,114,110,32,116,104,101, - 10,32,32,32,32,32,32,32,32,39,82,101,115,111,117,114, - 99,101,82,101,97,100,101,114,39,32,111,98,106,101,99,116, - 32,102,111,114,32,116,104,101,32,112,97,99,107,97,103,101, - 46,32,32,79,116,104,101,114,119,105,115,101,32,114,101,116, - 117,114,110,32,78,111,110,101,46,10,32,32,32,32,32,32, - 32,32,78,114,0,0,0,0,41,1,218,14,82,101,115,111, - 117,114,99,101,82,101,97,100,101,114,84,41,7,114,65,0, - 0,0,114,3,0,0,0,218,24,95,90,105,112,73,109,112, - 111,114,116,82,101,115,111,117,114,99,101,82,101,97,100,101, - 114,218,11,95,114,101,103,105,115,116,101,114,101,100,90,13, - 105,109,112,111,114,116,108,105,98,46,97,98,99,114,79,0, - 0,0,90,8,114,101,103,105,115,116,101,114,41,3,114,32, - 0,0,0,114,38,0,0,0,114,79,0,0,0,114,9,0, - 0,0,114,9,0,0,0,114,10,0,0,0,218,19,103,101, - 116,95,114,101,115,111,117,114,99,101,95,114,101,97,100,101, - 114,16,1,0,0,115,20,0,0,0,0,6,2,1,10,1, - 10,1,14,1,8,1,6,1,12,1,10,1,6,1,122,31, - 122,105,112,105,109,112,111,114,116,101,114,46,103,101,116,95, - 114,101,115,111,117,114,99,101,95,114,101,97,100,101,114,99, - 1,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0, - 67,0,0,0,115,24,0,0,0,100,1,124,0,106,0,155, - 0,116,1,155,0,124,0,106,2,155,0,100,2,157,5,83, - 0,41,3,78,122,21,60,122,105,112,105,109,112,111,114,116, - 101,114,32,111,98,106,101,99,116,32,34,122,2,34,62,41, - 3,114,29,0,0,0,114,20,0,0,0,114,31,0,0,0, - 41,1,114,32,0,0,0,114,9,0,0,0,114,9,0,0, - 0,114,10,0,0,0,218,8,95,95,114,101,112,114,95,95, - 34,1,0,0,115,2,0,0,0,0,1,122,20,122,105,112, - 105,109,112,111,114,116,101,114,46,95,95,114,101,112,114,95, - 95,41,1,78,41,1,78,41,15,114,6,0,0,0,114,7, - 0,0,0,114,8,0,0,0,218,7,95,95,100,111,99,95, - 95,114,34,0,0,0,114,41,0,0,0,114,42,0,0,0, - 114,48,0,0,0,114,55,0,0,0,114,56,0,0,0,114, - 64,0,0,0,114,65,0,0,0,114,78,0,0,0,114,82, - 0,0,0,114,83,0,0,0,114,9,0,0,0,114,9,0, - 0,0,114,9,0,0,0,114,10,0,0,0,114,4,0,0, - 0,45,0,0,0,115,24,0,0,0,8,1,4,17,8,46, - 10,32,10,12,8,10,8,21,8,11,8,26,8,13,8,38, - 8,18,122,12,95,95,105,110,105,116,95,95,46,112,121,99, - 84,114,60,0,0,0,70,41,3,122,4,46,112,121,99,84, - 70,41,3,114,61,0,0,0,70,70,99,2,0,0,0,0, - 0,0,0,2,0,0,0,4,0,0,0,67,0,0,0,115, - 20,0,0,0,124,0,106,0,124,1,160,1,100,1,161,1, - 100,2,25,0,23,0,83,0,41,3,78,218,1,46,233,2, - 0,0,0,41,2,114,31,0,0,0,218,10,114,112,97,114, - 116,105,116,105,111,110,41,2,114,32,0,0,0,114,38,0, - 0,0,114,9,0,0,0,114,9,0,0,0,114,10,0,0, - 0,114,36,0,0,0,52,1,0,0,115,2,0,0,0,0, - 1,114,36,0,0,0,99,2,0,0,0,0,0,0,0,3, + 99,2,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,8,0,0,0,67,0,0,0,115,88,0,0,0,122,20, + 124,0,160,0,124,1,161,1,115,18,87,0,100,1,83,0, + 87,0,110,22,4,0,116,1,107,10,114,42,1,0,1,0, + 1,0,89,0,100,1,83,0,88,0,116,2,106,3,115,78, + 100,2,100,3,108,4,109,5,125,2,1,0,124,2,160,6, + 116,2,161,1,1,0,100,4,116,2,95,3,116,2,124,0, + 124,1,131,2,83,0,41,5,122,204,82,101,116,117,114,110, + 32,116,104,101,32,82,101,115,111,117,114,99,101,82,101,97, + 100,101,114,32,102,111,114,32,97,32,112,97,99,107,97,103, + 101,32,105,110,32,97,32,122,105,112,32,102,105,108,101,46, + 10,10,32,32,32,32,32,32,32,32,73,102,32,39,102,117, + 108,108,110,97,109,101,39,32,105,115,32,97,32,112,97,99, + 107,97,103,101,32,119,105,116,104,105,110,32,116,104,101,32, + 122,105,112,32,102,105,108,101,44,32,114,101,116,117,114,110, + 32,116,104,101,10,32,32,32,32,32,32,32,32,39,82,101, + 115,111,117,114,99,101,82,101,97,100,101,114,39,32,111,98, + 106,101,99,116,32,102,111,114,32,116,104,101,32,112,97,99, + 107,97,103,101,46,32,32,79,116,104,101,114,119,105,115,101, + 32,114,101,116,117,114,110,32,78,111,110,101,46,10,32,32, + 32,32,32,32,32,32,78,114,0,0,0,0,41,1,218,14, + 82,101,115,111,117,114,99,101,82,101,97,100,101,114,84,41, + 7,114,65,0,0,0,114,3,0,0,0,218,24,95,90,105, + 112,73,109,112,111,114,116,82,101,115,111,117,114,99,101,82, + 101,97,100,101,114,218,11,95,114,101,103,105,115,116,101,114, + 101,100,90,13,105,109,112,111,114,116,108,105,98,46,97,98, + 99,114,79,0,0,0,90,8,114,101,103,105,115,116,101,114, + 41,3,114,32,0,0,0,114,38,0,0,0,114,79,0,0, + 0,114,9,0,0,0,114,9,0,0,0,114,10,0,0,0, + 218,19,103,101,116,95,114,101,115,111,117,114,99,101,95,114, + 101,97,100,101,114,16,1,0,0,115,20,0,0,0,0,6, + 2,1,10,1,10,1,14,1,8,1,6,1,12,1,10,1, + 6,1,122,31,122,105,112,105,109,112,111,114,116,101,114,46, + 103,101,116,95,114,101,115,111,117,114,99,101,95,114,101,97, + 100,101,114,99,1,0,0,0,0,0,0,0,0,0,0,0, + 1,0,0,0,5,0,0,0,67,0,0,0,115,24,0,0, + 0,100,1,124,0,106,0,155,0,116,1,155,0,124,0,106, + 2,155,0,100,2,157,5,83,0,41,3,78,122,21,60,122, + 105,112,105,109,112,111,114,116,101,114,32,111,98,106,101,99, + 116,32,34,122,2,34,62,41,3,114,29,0,0,0,114,20, + 0,0,0,114,31,0,0,0,41,1,114,32,0,0,0,114, + 9,0,0,0,114,9,0,0,0,114,10,0,0,0,218,8, + 95,95,114,101,112,114,95,95,34,1,0,0,115,2,0,0, + 0,0,1,122,20,122,105,112,105,109,112,111,114,116,101,114, + 46,95,95,114,101,112,114,95,95,41,1,78,41,1,78,41, + 15,114,6,0,0,0,114,7,0,0,0,114,8,0,0,0, + 218,7,95,95,100,111,99,95,95,114,34,0,0,0,114,41, + 0,0,0,114,42,0,0,0,114,48,0,0,0,114,55,0, + 0,0,114,56,0,0,0,114,64,0,0,0,114,65,0,0, + 0,114,78,0,0,0,114,82,0,0,0,114,83,0,0,0, + 114,9,0,0,0,114,9,0,0,0,114,9,0,0,0,114, + 10,0,0,0,114,4,0,0,0,45,0,0,0,115,24,0, + 0,0,8,1,4,17,8,46,10,32,10,12,8,10,8,21, + 8,11,8,26,8,13,8,38,8,18,122,12,95,95,105,110, + 105,116,95,95,46,112,121,99,84,114,60,0,0,0,70,41, + 3,122,4,46,112,121,99,84,70,41,3,114,61,0,0,0, + 70,70,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,4,0,0,0,67,0,0,0,115,20,0,0,0, + 124,0,106,0,124,1,160,1,100,1,161,1,100,2,25,0, + 23,0,83,0,41,3,78,218,1,46,233,2,0,0,0,41, + 2,114,31,0,0,0,218,10,114,112,97,114,116,105,116,105, + 111,110,41,2,114,32,0,0,0,114,38,0,0,0,114,9, + 0,0,0,114,9,0,0,0,114,10,0,0,0,114,36,0, + 0,0,52,1,0,0,115,2,0,0,0,0,1,114,36,0, + 0,0,99,2,0,0,0,0,0,0,0,0,0,0,0,3, 0,0,0,2,0,0,0,67,0,0,0,115,18,0,0,0, 124,1,116,0,23,0,125,2,124,2,124,0,106,1,107,6, 83,0,169,1,78,41,2,114,20,0,0,0,114,28,0,0, @@ -504,223 +508,224 @@ const unsigned char _Py_M__zipimport[] = { 105,114,112,97,116,104,114,9,0,0,0,114,9,0,0,0, 114,10,0,0,0,114,37,0,0,0,56,1,0,0,115,4, 0,0,0,0,4,8,2,114,37,0,0,0,99,2,0,0, - 0,0,0,0,0,7,0,0,0,4,0,0,0,67,0,0, - 0,115,56,0,0,0,116,0,124,0,124,1,131,2,125,2, - 116,1,68,0,93,36,92,3,125,3,125,4,125,5,124,2, - 124,3,23,0,125,6,124,6,124,0,106,2,107,6,114,14, - 124,5,2,0,1,0,83,0,113,14,100,0,83,0,114,88, - 0,0,0,41,3,114,36,0,0,0,218,16,95,122,105,112, - 95,115,101,97,114,99,104,111,114,100,101,114,114,28,0,0, - 0,41,7,114,32,0,0,0,114,38,0,0,0,114,13,0, - 0,0,218,6,115,117,102,102,105,120,218,10,105,115,98,121, - 116,101,99,111,100,101,114,47,0,0,0,114,63,0,0,0, - 114,9,0,0,0,114,9,0,0,0,114,10,0,0,0,114, - 35,0,0,0,65,1,0,0,115,12,0,0,0,0,1,10, - 1,14,1,8,1,10,1,10,1,114,35,0,0,0,99,1, - 0,0,0,0,0,0,0,26,0,0,0,9,0,0,0,67, - 0,0,0,115,254,4,0,0,122,16,116,0,160,1,124,0, - 100,1,161,2,125,1,87,0,110,38,4,0,116,2,107,10, - 114,54,1,0,1,0,1,0,116,3,100,2,124,0,155,2, - 157,2,124,0,100,3,141,2,130,1,89,0,110,2,88,0, - 124,1,144,4,143,168,1,0,122,36,124,1,160,4,116,5, - 11,0,100,4,161,2,1,0,124,1,160,6,161,0,125,2, - 124,1,160,7,116,5,161,1,125,3,87,0,110,38,4,0, - 116,2,107,10,114,138,1,0,1,0,1,0,116,3,100,5, - 124,0,155,2,157,2,124,0,100,3,141,2,130,1,89,0, - 110,2,88,0,116,8,124,3,131,1,116,5,107,3,114,170, + 0,0,0,0,0,0,0,0,0,7,0,0,0,4,0,0, + 0,67,0,0,0,115,56,0,0,0,116,0,124,0,124,1, + 131,2,125,2,116,1,68,0,93,36,92,3,125,3,125,4, + 125,5,124,2,124,3,23,0,125,6,124,6,124,0,106,2, + 107,6,114,14,124,5,2,0,1,0,83,0,113,14,100,0, + 83,0,114,88,0,0,0,41,3,114,36,0,0,0,218,16, + 95,122,105,112,95,115,101,97,114,99,104,111,114,100,101,114, + 114,28,0,0,0,41,7,114,32,0,0,0,114,38,0,0, + 0,114,13,0,0,0,218,6,115,117,102,102,105,120,218,10, + 105,115,98,121,116,101,99,111,100,101,114,47,0,0,0,114, + 63,0,0,0,114,9,0,0,0,114,9,0,0,0,114,10, + 0,0,0,114,35,0,0,0,65,1,0,0,115,12,0,0, + 0,0,1,10,1,14,1,8,1,10,1,10,1,114,35,0, + 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,26, + 0,0,0,9,0,0,0,67,0,0,0,115,254,4,0,0, + 122,16,116,0,160,1,124,0,100,1,161,2,125,1,87,0, + 110,38,4,0,116,2,107,10,114,54,1,0,1,0,1,0, + 116,3,100,2,124,0,155,2,157,2,124,0,100,3,141,2, + 130,1,89,0,110,2,88,0,124,1,144,4,143,168,1,0, + 122,36,124,1,160,4,116,5,11,0,100,4,161,2,1,0, + 124,1,160,6,161,0,125,2,124,1,160,7,116,5,161,1, + 125,3,87,0,110,38,4,0,116,2,107,10,114,138,1,0, + 1,0,1,0,116,3,100,5,124,0,155,2,157,2,124,0, + 100,3,141,2,130,1,89,0,110,2,88,0,116,8,124,3, + 131,1,116,5,107,3,114,170,116,3,100,5,124,0,155,2, + 157,2,124,0,100,3,141,2,130,1,124,3,100,0,100,6, + 133,2,25,0,116,9,107,3,144,1,114,180,122,24,124,1, + 160,4,100,7,100,4,161,2,1,0,124,1,160,6,161,0, + 125,4,87,0,110,38,4,0,116,2,107,10,114,250,1,0, + 1,0,1,0,116,3,100,5,124,0,155,2,157,2,124,0, + 100,3,141,2,130,1,89,0,110,2,88,0,116,10,124,4, + 116,11,24,0,116,5,24,0,100,7,131,2,125,5,122,22, + 124,1,160,4,124,5,161,1,1,0,124,1,160,7,161,0, + 125,6,87,0,110,40,4,0,116,2,107,10,144,1,114,76, + 1,0,1,0,1,0,116,3,100,5,124,0,155,2,157,2, + 124,0,100,3,141,2,130,1,89,0,110,2,88,0,124,6, + 160,12,116,9,161,1,125,7,124,7,100,7,107,0,144,1, + 114,116,116,3,100,8,124,0,155,2,157,2,124,0,100,3, + 141,2,130,1,124,6,124,7,124,7,116,5,23,0,133,2, + 25,0,125,3,116,8,124,3,131,1,116,5,107,3,144,1, + 114,164,116,3,100,9,124,0,155,2,157,2,124,0,100,3, + 141,2,130,1,124,4,116,8,124,6,131,1,24,0,124,7, + 23,0,125,2,116,13,124,3,100,10,100,11,133,2,25,0, + 131,1,125,8,116,13,124,3,100,11,100,12,133,2,25,0, + 131,1,125,9,124,2,124,8,107,0,144,1,114,240,116,3, + 100,13,124,0,155,2,157,2,124,0,100,3,141,2,130,1, + 124,2,124,9,107,0,144,2,114,12,116,3,100,14,124,0, + 155,2,157,2,124,0,100,3,141,2,130,1,124,2,124,8, + 56,0,125,2,124,2,124,9,24,0,125,10,124,10,100,7, + 107,0,144,2,114,56,116,3,100,15,124,0,155,2,157,2, + 124,0,100,3,141,2,130,1,105,0,125,11,100,7,125,12, + 122,14,124,1,160,4,124,2,161,1,1,0,87,0,110,40, + 4,0,116,2,107,10,144,2,114,118,1,0,1,0,1,0, + 116,3,100,5,124,0,155,2,157,2,124,0,100,3,141,2, + 130,1,89,0,110,2,88,0,124,1,160,7,100,16,161,1, + 125,3,116,8,124,3,131,1,100,6,107,0,144,2,114,152, + 116,14,100,17,131,1,130,1,124,3,100,0,100,6,133,2, + 25,0,100,18,107,3,144,2,114,174,144,4,113,226,116,8, + 124,3,131,1,100,16,107,3,144,2,114,196,116,14,100,17, + 131,1,130,1,116,15,124,3,100,19,100,20,133,2,25,0, + 131,1,125,13,116,15,124,3,100,20,100,10,133,2,25,0, + 131,1,125,14,116,15,124,3,100,10,100,21,133,2,25,0, + 131,1,125,15,116,15,124,3,100,21,100,11,133,2,25,0, + 131,1,125,16,116,13,124,3,100,11,100,12,133,2,25,0, + 131,1,125,17,116,13,124,3,100,12,100,22,133,2,25,0, + 131,1,125,18,116,13,124,3,100,22,100,23,133,2,25,0, + 131,1,125,4,116,15,124,3,100,23,100,24,133,2,25,0, + 131,1,125,19,116,15,124,3,100,24,100,25,133,2,25,0, + 131,1,125,20,116,15,124,3,100,25,100,26,133,2,25,0, + 131,1,125,21,116,13,124,3,100,27,100,16,133,2,25,0, + 131,1,125,22,124,19,124,20,23,0,124,21,23,0,125,8, + 124,22,124,9,107,4,144,3,114,156,116,3,100,28,124,0, + 155,2,157,2,124,0,100,3,141,2,130,1,124,22,124,10, + 55,0,125,22,122,14,124,1,160,7,124,19,161,1,125,23, + 87,0,110,40,4,0,116,2,107,10,144,3,114,218,1,0, + 1,0,1,0,116,3,100,5,124,0,155,2,157,2,124,0, + 100,3,141,2,130,1,89,0,110,2,88,0,116,8,124,23, + 131,1,124,19,107,3,144,3,114,252,116,3,100,5,124,0, + 155,2,157,2,124,0,100,3,141,2,130,1,122,50,116,8, + 124,1,160,7,124,8,124,19,24,0,161,1,131,1,124,8, + 124,19,24,0,107,3,144,4,114,44,116,3,100,5,124,0, + 155,2,157,2,124,0,100,3,141,2,130,1,87,0,110,40, + 4,0,116,2,107,10,144,4,114,86,1,0,1,0,1,0, 116,3,100,5,124,0,155,2,157,2,124,0,100,3,141,2, - 130,1,124,3,100,0,100,6,133,2,25,0,116,9,107,3, - 144,1,114,180,122,24,124,1,160,4,100,7,100,4,161,2, - 1,0,124,1,160,6,161,0,125,4,87,0,110,38,4,0, - 116,2,107,10,114,250,1,0,1,0,1,0,116,3,100,5, - 124,0,155,2,157,2,124,0,100,3,141,2,130,1,89,0, - 110,2,88,0,116,10,124,4,116,11,24,0,116,5,24,0, - 100,7,131,2,125,5,122,22,124,1,160,4,124,5,161,1, - 1,0,124,1,160,7,161,0,125,6,87,0,110,40,4,0, - 116,2,107,10,144,1,114,76,1,0,1,0,1,0,116,3, - 100,5,124,0,155,2,157,2,124,0,100,3,141,2,130,1, - 89,0,110,2,88,0,124,6,160,12,116,9,161,1,125,7, - 124,7,100,7,107,0,144,1,114,116,116,3,100,8,124,0, - 155,2,157,2,124,0,100,3,141,2,130,1,124,6,124,7, - 124,7,116,5,23,0,133,2,25,0,125,3,116,8,124,3, - 131,1,116,5,107,3,144,1,114,164,116,3,100,9,124,0, - 155,2,157,2,124,0,100,3,141,2,130,1,124,4,116,8, - 124,6,131,1,24,0,124,7,23,0,125,2,116,13,124,3, - 100,10,100,11,133,2,25,0,131,1,125,8,116,13,124,3, - 100,11,100,12,133,2,25,0,131,1,125,9,124,2,124,8, - 107,0,144,1,114,240,116,3,100,13,124,0,155,2,157,2, - 124,0,100,3,141,2,130,1,124,2,124,9,107,0,144,2, - 114,12,116,3,100,14,124,0,155,2,157,2,124,0,100,3, - 141,2,130,1,124,2,124,8,56,0,125,2,124,2,124,9, - 24,0,125,10,124,10,100,7,107,0,144,2,114,56,116,3, - 100,15,124,0,155,2,157,2,124,0,100,3,141,2,130,1, - 105,0,125,11,100,7,125,12,122,14,124,1,160,4,124,2, - 161,1,1,0,87,0,110,40,4,0,116,2,107,10,144,2, - 114,118,1,0,1,0,1,0,116,3,100,5,124,0,155,2, - 157,2,124,0,100,3,141,2,130,1,89,0,110,2,88,0, - 124,1,160,7,100,16,161,1,125,3,116,8,124,3,131,1, - 100,6,107,0,144,2,114,152,116,14,100,17,131,1,130,1, - 124,3,100,0,100,6,133,2,25,0,100,18,107,3,144,2, - 114,174,144,4,113,226,116,8,124,3,131,1,100,16,107,3, - 144,2,114,196,116,14,100,17,131,1,130,1,116,15,124,3, - 100,19,100,20,133,2,25,0,131,1,125,13,116,15,124,3, - 100,20,100,10,133,2,25,0,131,1,125,14,116,15,124,3, - 100,10,100,21,133,2,25,0,131,1,125,15,116,15,124,3, - 100,21,100,11,133,2,25,0,131,1,125,16,116,13,124,3, - 100,11,100,12,133,2,25,0,131,1,125,17,116,13,124,3, - 100,12,100,22,133,2,25,0,131,1,125,18,116,13,124,3, - 100,22,100,23,133,2,25,0,131,1,125,4,116,15,124,3, - 100,23,100,24,133,2,25,0,131,1,125,19,116,15,124,3, - 100,24,100,25,133,2,25,0,131,1,125,20,116,15,124,3, - 100,25,100,26,133,2,25,0,131,1,125,21,116,13,124,3, - 100,27,100,16,133,2,25,0,131,1,125,22,124,19,124,20, - 23,0,124,21,23,0,125,8,124,22,124,9,107,4,144,3, - 114,156,116,3,100,28,124,0,155,2,157,2,124,0,100,3, - 141,2,130,1,124,22,124,10,55,0,125,22,122,14,124,1, - 160,7,124,19,161,1,125,23,87,0,110,40,4,0,116,2, - 107,10,144,3,114,218,1,0,1,0,1,0,116,3,100,5, - 124,0,155,2,157,2,124,0,100,3,141,2,130,1,89,0, - 110,2,88,0,116,8,124,23,131,1,124,19,107,3,144,3, - 114,252,116,3,100,5,124,0,155,2,157,2,124,0,100,3, - 141,2,130,1,122,50,116,8,124,1,160,7,124,8,124,19, - 24,0,161,1,131,1,124,8,124,19,24,0,107,3,144,4, - 114,44,116,3,100,5,124,0,155,2,157,2,124,0,100,3, - 141,2,130,1,87,0,110,40,4,0,116,2,107,10,144,4, - 114,86,1,0,1,0,1,0,116,3,100,5,124,0,155,2, - 157,2,124,0,100,3,141,2,130,1,89,0,110,2,88,0, - 124,13,100,29,64,0,144,4,114,108,124,23,160,16,161,0, - 125,23,110,54,122,14,124,23,160,16,100,30,161,1,125,23, - 87,0,110,38,4,0,116,17,107,10,144,4,114,160,1,0, - 1,0,1,0,124,23,160,16,100,31,161,1,160,18,116,19, - 161,1,125,23,89,0,110,2,88,0,124,23,160,20,100,32, - 116,21,161,2,125,23,116,22,160,23,124,0,124,23,161,2, - 125,24,124,24,124,14,124,18,124,4,124,22,124,15,124,16, - 124,17,102,8,125,25,124,25,124,11,124,23,60,0,124,12, - 100,33,55,0,125,12,144,2,113,120,87,0,53,0,81,0, - 82,0,88,0,116,24,160,25,100,34,124,12,124,0,161,3, - 1,0,124,11,83,0,41,35,78,218,2,114,98,122,21,99, - 97,110,39,116,32,111,112,101,110,32,90,105,112,32,102,105, - 108,101,58,32,114,12,0,0,0,114,86,0,0,0,250,21, - 99,97,110,39,116,32,114,101,97,100,32,90,105,112,32,102, - 105,108,101,58,32,233,4,0,0,0,114,0,0,0,0,122, - 16,110,111,116,32,97,32,90,105,112,32,102,105,108,101,58, - 32,122,18,99,111,114,114,117,112,116,32,90,105,112,32,102, - 105,108,101,58,32,233,12,0,0,0,233,16,0,0,0,233, - 20,0,0,0,122,28,98,97,100,32,99,101,110,116,114,97, - 108,32,100,105,114,101,99,116,111,114,121,32,115,105,122,101, - 58,32,122,30,98,97,100,32,99,101,110,116,114,97,108,32, - 100,105,114,101,99,116,111,114,121,32,111,102,102,115,101,116, - 58,32,122,38,98,97,100,32,99,101,110,116,114,97,108,32, - 100,105,114,101,99,116,111,114,121,32,115,105,122,101,32,111, - 114,32,111,102,102,115,101,116,58,32,233,46,0,0,0,250, - 27,69,79,70,32,114,101,97,100,32,119,104,101,114,101,32, - 110,111,116,32,101,120,112,101,99,116,101,100,115,4,0,0, - 0,80,75,1,2,233,8,0,0,0,233,10,0,0,0,233, - 14,0,0,0,233,24,0,0,0,233,28,0,0,0,233,30, - 0,0,0,233,32,0,0,0,233,34,0,0,0,233,42,0, - 0,0,122,25,98,97,100,32,108,111,99,97,108,32,104,101, - 97,100,101,114,32,111,102,102,115,101,116,58,32,105,0,8, - 0,0,218,5,97,115,99,105,105,90,6,108,97,116,105,110, - 49,250,1,47,114,5,0,0,0,122,33,122,105,112,105,109, - 112,111,114,116,58,32,102,111,117,110,100,32,123,125,32,110, - 97,109,101,115,32,105,110,32,123,33,114,125,41,26,218,3, - 95,105,111,218,4,111,112,101,110,114,22,0,0,0,114,3, - 0,0,0,218,4,115,101,101,107,218,20,69,78,68,95,67, - 69,78,84,82,65,76,95,68,73,82,95,83,73,90,69,90, - 4,116,101,108,108,218,4,114,101,97,100,114,51,0,0,0, - 218,18,83,84,82,73,78,71,95,69,78,68,95,65,82,67, - 72,73,86,69,218,3,109,97,120,218,15,77,65,88,95,67, - 79,77,77,69,78,84,95,76,69,78,218,5,114,102,105,110, - 100,114,2,0,0,0,218,8,69,79,70,69,114,114,111,114, - 114,1,0,0,0,114,62,0,0,0,218,18,85,110,105,99, - 111,100,101,68,101,99,111,100,101,69,114,114,111,114,218,9, - 116,114,97,110,115,108,97,116,101,218,11,99,112,52,51,55, - 95,116,97,98,108,101,114,19,0,0,0,114,20,0,0,0, - 114,21,0,0,0,114,30,0,0,0,114,76,0,0,0,114, - 77,0,0,0,41,26,114,29,0,0,0,218,2,102,112,90, - 15,104,101,97,100,101,114,95,112,111,115,105,116,105,111,110, - 218,6,98,117,102,102,101,114,218,9,102,105,108,101,95,115, - 105,122,101,90,17,109,97,120,95,99,111,109,109,101,110,116, - 95,115,116,97,114,116,218,4,100,97,116,97,90,3,112,111, - 115,218,11,104,101,97,100,101,114,95,115,105,122,101,90,13, - 104,101,97,100,101,114,95,111,102,102,115,101,116,90,10,97, - 114,99,95,111,102,102,115,101,116,114,33,0,0,0,218,5, - 99,111,117,110,116,218,5,102,108,97,103,115,218,8,99,111, - 109,112,114,101,115,115,218,4,116,105,109,101,218,4,100,97, - 116,101,218,3,99,114,99,218,9,100,97,116,97,95,115,105, - 122,101,218,9,110,97,109,101,95,115,105,122,101,218,10,101, - 120,116,114,97,95,115,105,122,101,90,12,99,111,109,109,101, - 110,116,95,115,105,122,101,218,11,102,105,108,101,95,111,102, - 102,115,101,116,114,59,0,0,0,114,13,0,0,0,218,1, - 116,114,9,0,0,0,114,9,0,0,0,114,10,0,0,0, - 114,27,0,0,0,96,1,0,0,115,212,0,0,0,0,1, - 2,1,16,1,14,1,24,2,8,1,2,1,14,1,8,1, - 14,1,14,1,24,1,12,1,18,1,18,3,2,1,12,1, - 12,1,14,1,10,1,2,255,12,2,8,1,2,255,2,1, - 2,255,4,2,2,1,10,1,12,1,16,1,10,1,2,255, - 12,2,10,1,10,1,10,1,2,255,6,2,16,1,14,1, - 10,1,2,255,6,2,16,2,16,1,16,1,10,1,18,1, - 10,1,18,1,8,1,8,1,10,1,18,2,4,2,4,1, - 2,1,14,1,16,1,24,2,10,1,14,1,8,2,18,1, - 4,1,14,1,8,1,16,1,16,1,16,1,16,1,16,1, - 16,1,16,1,16,1,16,1,16,1,16,1,12,1,10,1, - 18,1,8,2,2,1,14,1,16,1,24,1,14,1,18,4, - 2,1,28,1,22,1,16,1,24,2,10,2,10,3,2,1, - 14,1,16,1,22,2,12,1,12,1,20,1,8,1,22,1, - 14,1,114,27,0,0,0,117,190,1,0,0,0,1,2,3, - 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, - 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35, - 36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51, - 52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67, - 68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83, - 84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99, - 100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115, - 116,117,118,119,120,121,122,123,124,125,126,127,195,135,195,188, - 195,169,195,162,195,164,195,160,195,165,195,167,195,170,195,171, - 195,168,195,175,195,174,195,172,195,132,195,133,195,137,195,166, - 195,134,195,180,195,182,195,178,195,187,195,185,195,191,195,150, - 195,156,194,162,194,163,194,165,226,130,167,198,146,195,161,195, - 173,195,179,195,186,195,177,195,145,194,170,194,186,194,191,226, - 140,144,194,172,194,189,194,188,194,161,194,171,194,187,226,150, - 145,226,150,146,226,150,147,226,148,130,226,148,164,226,149,161, - 226,149,162,226,149,150,226,149,149,226,149,163,226,149,145,226, - 149,151,226,149,157,226,149,156,226,149,155,226,148,144,226,148, - 148,226,148,180,226,148,172,226,148,156,226,148,128,226,148,188, - 226,149,158,226,149,159,226,149,154,226,149,148,226,149,169,226, - 149,166,226,149,160,226,149,144,226,149,172,226,149,167,226,149, - 168,226,149,164,226,149,165,226,149,153,226,149,152,226,149,146, - 226,149,147,226,149,171,226,149,170,226,148,152,226,148,140,226, - 150,136,226,150,132,226,150,140,226,150,144,226,150,128,206,177, - 195,159,206,147,207,128,206,163,207,131,194,181,207,132,206,166, - 206,152,206,169,206,180,226,136,158,207,134,206,181,226,136,169, - 226,137,161,194,177,226,137,165,226,137,164,226,140,160,226,140, - 161,195,183,226,137,136,194,176,226,136,153,194,183,226,136,154, - 226,129,191,194,178,226,150,160,194,160,99,0,0,0,0,0, - 0,0,0,1,0,0,0,8,0,0,0,67,0,0,0,115, - 108,0,0,0,116,0,114,22,116,1,160,2,100,1,161,1, - 1,0,116,3,100,2,131,1,130,1,100,3,97,0,122,60, - 122,16,100,4,100,5,108,4,109,5,125,0,1,0,87,0, - 110,38,4,0,116,6,107,10,114,82,1,0,1,0,1,0, - 116,1,160,2,100,1,161,1,1,0,116,3,100,2,131,1, - 130,1,89,0,110,2,88,0,87,0,53,0,100,6,97,0, - 88,0,116,1,160,2,100,7,161,1,1,0,124,0,83,0, - 41,8,78,122,27,122,105,112,105,109,112,111,114,116,58,32, - 122,108,105,98,32,85,78,65,86,65,73,76,65,66,76,69, - 250,41,99,97,110,39,116,32,100,101,99,111,109,112,114,101, - 115,115,32,100,97,116,97,59,32,122,108,105,98,32,110,111, - 116,32,97,118,97,105,108,97,98,108,101,84,114,0,0,0, - 0,169,1,218,10,100,101,99,111,109,112,114,101,115,115,70, - 122,25,122,105,112,105,109,112,111,114,116,58,32,122,108,105, - 98,32,97,118,97,105,108,97,98,108,101,41,7,218,15,95, - 105,109,112,111,114,116,105,110,103,95,122,108,105,98,114,76, - 0,0,0,114,77,0,0,0,114,3,0,0,0,90,4,122, - 108,105,98,114,142,0,0,0,218,9,69,120,99,101,112,116, - 105,111,110,114,141,0,0,0,114,9,0,0,0,114,9,0, - 0,0,114,10,0,0,0,218,20,95,103,101,116,95,100,101, - 99,111,109,112,114,101,115,115,95,102,117,110,99,254,1,0, - 0,115,24,0,0,0,0,2,4,3,10,1,8,2,4,1, - 4,1,16,1,14,1,10,1,18,2,6,2,10,1,114,145, - 0,0,0,99,2,0,0,0,0,0,0,0,17,0,0,0, + 130,1,89,0,110,2,88,0,124,13,100,29,64,0,144,4, + 114,108,124,23,160,16,161,0,125,23,110,54,122,14,124,23, + 160,16,100,30,161,1,125,23,87,0,110,38,4,0,116,17, + 107,10,144,4,114,160,1,0,1,0,1,0,124,23,160,16, + 100,31,161,1,160,18,116,19,161,1,125,23,89,0,110,2, + 88,0,124,23,160,20,100,32,116,21,161,2,125,23,116,22, + 160,23,124,0,124,23,161,2,125,24,124,24,124,14,124,18, + 124,4,124,22,124,15,124,16,124,17,102,8,125,25,124,25, + 124,11,124,23,60,0,124,12,100,33,55,0,125,12,144,2, + 113,120,87,0,53,0,81,0,82,0,88,0,116,24,160,25, + 100,34,124,12,124,0,161,3,1,0,124,11,83,0,41,35, + 78,218,2,114,98,122,21,99,97,110,39,116,32,111,112,101, + 110,32,90,105,112,32,102,105,108,101,58,32,114,12,0,0, + 0,114,86,0,0,0,250,21,99,97,110,39,116,32,114,101, + 97,100,32,90,105,112,32,102,105,108,101,58,32,233,4,0, + 0,0,114,0,0,0,0,122,16,110,111,116,32,97,32,90, + 105,112,32,102,105,108,101,58,32,122,18,99,111,114,114,117, + 112,116,32,90,105,112,32,102,105,108,101,58,32,233,12,0, + 0,0,233,16,0,0,0,233,20,0,0,0,122,28,98,97, + 100,32,99,101,110,116,114,97,108,32,100,105,114,101,99,116, + 111,114,121,32,115,105,122,101,58,32,122,30,98,97,100,32, + 99,101,110,116,114,97,108,32,100,105,114,101,99,116,111,114, + 121,32,111,102,102,115,101,116,58,32,122,38,98,97,100,32, + 99,101,110,116,114,97,108,32,100,105,114,101,99,116,111,114, + 121,32,115,105,122,101,32,111,114,32,111,102,102,115,101,116, + 58,32,233,46,0,0,0,250,27,69,79,70,32,114,101,97, + 100,32,119,104,101,114,101,32,110,111,116,32,101,120,112,101, + 99,116,101,100,115,4,0,0,0,80,75,1,2,233,8,0, + 0,0,233,10,0,0,0,233,14,0,0,0,233,24,0,0, + 0,233,28,0,0,0,233,30,0,0,0,233,32,0,0,0, + 233,34,0,0,0,233,42,0,0,0,122,25,98,97,100,32, + 108,111,99,97,108,32,104,101,97,100,101,114,32,111,102,102, + 115,101,116,58,32,105,0,8,0,0,218,5,97,115,99,105, + 105,90,6,108,97,116,105,110,49,250,1,47,114,5,0,0, + 0,122,33,122,105,112,105,109,112,111,114,116,58,32,102,111, + 117,110,100,32,123,125,32,110,97,109,101,115,32,105,110,32, + 123,33,114,125,41,26,218,3,95,105,111,218,4,111,112,101, + 110,114,22,0,0,0,114,3,0,0,0,218,4,115,101,101, + 107,218,20,69,78,68,95,67,69,78,84,82,65,76,95,68, + 73,82,95,83,73,90,69,90,4,116,101,108,108,218,4,114, + 101,97,100,114,51,0,0,0,218,18,83,84,82,73,78,71, + 95,69,78,68,95,65,82,67,72,73,86,69,218,3,109,97, + 120,218,15,77,65,88,95,67,79,77,77,69,78,84,95,76, + 69,78,218,5,114,102,105,110,100,114,2,0,0,0,218,8, + 69,79,70,69,114,114,111,114,114,1,0,0,0,114,62,0, + 0,0,218,18,85,110,105,99,111,100,101,68,101,99,111,100, + 101,69,114,114,111,114,218,9,116,114,97,110,115,108,97,116, + 101,218,11,99,112,52,51,55,95,116,97,98,108,101,114,19, + 0,0,0,114,20,0,0,0,114,21,0,0,0,114,30,0, + 0,0,114,76,0,0,0,114,77,0,0,0,41,26,114,29, + 0,0,0,218,2,102,112,90,15,104,101,97,100,101,114,95, + 112,111,115,105,116,105,111,110,218,6,98,117,102,102,101,114, + 218,9,102,105,108,101,95,115,105,122,101,90,17,109,97,120, + 95,99,111,109,109,101,110,116,95,115,116,97,114,116,218,4, + 100,97,116,97,90,3,112,111,115,218,11,104,101,97,100,101, + 114,95,115,105,122,101,90,13,104,101,97,100,101,114,95,111, + 102,102,115,101,116,90,10,97,114,99,95,111,102,102,115,101, + 116,114,33,0,0,0,218,5,99,111,117,110,116,218,5,102, + 108,97,103,115,218,8,99,111,109,112,114,101,115,115,218,4, + 116,105,109,101,218,4,100,97,116,101,218,3,99,114,99,218, + 9,100,97,116,97,95,115,105,122,101,218,9,110,97,109,101, + 95,115,105,122,101,218,10,101,120,116,114,97,95,115,105,122, + 101,90,12,99,111,109,109,101,110,116,95,115,105,122,101,218, + 11,102,105,108,101,95,111,102,102,115,101,116,114,59,0,0, + 0,114,13,0,0,0,218,1,116,114,9,0,0,0,114,9, + 0,0,0,114,10,0,0,0,114,27,0,0,0,96,1,0, + 0,115,212,0,0,0,0,1,2,1,16,1,14,1,24,2, + 8,1,2,1,14,1,8,1,14,1,14,1,24,1,12,1, + 18,1,18,3,2,1,12,1,12,1,14,1,10,1,2,255, + 12,2,8,1,2,255,2,1,2,255,4,2,2,1,10,1, + 12,1,16,1,10,1,2,255,12,2,10,1,10,1,10,1, + 2,255,6,2,16,1,14,1,10,1,2,255,6,2,16,2, + 16,1,16,1,10,1,18,1,10,1,18,1,8,1,8,1, + 10,1,18,2,4,2,4,1,2,1,14,1,16,1,24,2, + 10,1,14,1,8,2,18,1,4,1,14,1,8,1,16,1, + 16,1,16,1,16,1,16,1,16,1,16,1,16,1,16,1, + 16,1,16,1,12,1,10,1,18,1,8,2,2,1,14,1, + 16,1,24,1,14,1,18,4,2,1,28,1,22,1,16,1, + 24,2,10,2,10,3,2,1,14,1,16,1,22,2,12,1, + 12,1,20,1,8,1,22,1,14,1,114,27,0,0,0,117, + 190,1,0,0,0,1,2,3,4,5,6,7,8,9,10,11, + 12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27, + 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43, + 44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59, + 60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75, + 76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91, + 92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107, + 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123, + 124,125,126,127,195,135,195,188,195,169,195,162,195,164,195,160, + 195,165,195,167,195,170,195,171,195,168,195,175,195,174,195,172, + 195,132,195,133,195,137,195,166,195,134,195,180,195,182,195,178, + 195,187,195,185,195,191,195,150,195,156,194,162,194,163,194,165, + 226,130,167,198,146,195,161,195,173,195,179,195,186,195,177,195, + 145,194,170,194,186,194,191,226,140,144,194,172,194,189,194,188, + 194,161,194,171,194,187,226,150,145,226,150,146,226,150,147,226, + 148,130,226,148,164,226,149,161,226,149,162,226,149,150,226,149, + 149,226,149,163,226,149,145,226,149,151,226,149,157,226,149,156, + 226,149,155,226,148,144,226,148,148,226,148,180,226,148,172,226, + 148,156,226,148,128,226,148,188,226,149,158,226,149,159,226,149, + 154,226,149,148,226,149,169,226,149,166,226,149,160,226,149,144, + 226,149,172,226,149,167,226,149,168,226,149,164,226,149,165,226, + 149,153,226,149,152,226,149,146,226,149,147,226,149,171,226,149, + 170,226,148,152,226,148,140,226,150,136,226,150,132,226,150,140, + 226,150,144,226,150,128,206,177,195,159,206,147,207,128,206,163, + 207,131,194,181,207,132,206,166,206,152,206,169,206,180,226,136, + 158,207,134,206,181,226,136,169,226,137,161,194,177,226,137,165, + 226,137,164,226,140,160,226,140,161,195,183,226,137,136,194,176, + 226,136,153,194,183,226,136,154,226,129,191,194,178,226,150,160, + 194,160,99,0,0,0,0,0,0,0,0,0,0,0,0,1, + 0,0,0,8,0,0,0,67,0,0,0,115,108,0,0,0, + 116,0,114,22,116,1,160,2,100,1,161,1,1,0,116,3, + 100,2,131,1,130,1,100,3,97,0,122,60,122,16,100,4, + 100,5,108,4,109,5,125,0,1,0,87,0,110,38,4,0, + 116,6,107,10,114,82,1,0,1,0,1,0,116,1,160,2, + 100,1,161,1,1,0,116,3,100,2,131,1,130,1,89,0, + 110,2,88,0,87,0,53,0,100,6,97,0,88,0,116,1, + 160,2,100,7,161,1,1,0,124,0,83,0,41,8,78,122, + 27,122,105,112,105,109,112,111,114,116,58,32,122,108,105,98, + 32,85,78,65,86,65,73,76,65,66,76,69,250,41,99,97, + 110,39,116,32,100,101,99,111,109,112,114,101,115,115,32,100, + 97,116,97,59,32,122,108,105,98,32,110,111,116,32,97,118, + 97,105,108,97,98,108,101,84,114,0,0,0,0,169,1,218, + 10,100,101,99,111,109,112,114,101,115,115,70,122,25,122,105, + 112,105,109,112,111,114,116,58,32,122,108,105,98,32,97,118, + 97,105,108,97,98,108,101,41,7,218,15,95,105,109,112,111, + 114,116,105,110,103,95,122,108,105,98,114,76,0,0,0,114, + 77,0,0,0,114,3,0,0,0,90,4,122,108,105,98,114, + 142,0,0,0,218,9,69,120,99,101,112,116,105,111,110,114, + 141,0,0,0,114,9,0,0,0,114,9,0,0,0,114,10, + 0,0,0,218,20,95,103,101,116,95,100,101,99,111,109,112, + 114,101,115,115,95,102,117,110,99,254,1,0,0,115,24,0, + 0,0,0,2,4,3,10,1,8,2,4,1,4,1,16,1, + 14,1,10,1,18,2,6,2,10,1,114,145,0,0,0,99, + 2,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0, 9,0,0,0,67,0,0,0,115,130,1,0,0,124,1,92, 8,125,2,125,3,125,4,125,5,125,6,125,7,125,8,125, 9,124,4,100,1,107,0,114,36,116,0,100,2,131,1,130, @@ -770,84 +775,85 @@ const unsigned char _Py_M__zipimport[] = { 14,1,24,1,10,1,12,1,8,2,16,2,18,2,16,1, 16,1,12,1,8,1,2,1,14,1,16,1,24,1,10,1, 14,1,18,2,10,2,4,3,2,1,10,1,16,1,14,1, - 114,52,0,0,0,99,2,0,0,0,0,0,0,0,2,0, - 0,0,3,0,0,0,67,0,0,0,115,16,0,0,0,116, - 0,124,0,124,1,24,0,131,1,100,1,107,1,83,0,41, - 2,78,114,5,0,0,0,41,1,218,3,97,98,115,41,2, - 90,2,116,49,90,2,116,50,114,9,0,0,0,114,9,0, - 0,0,114,10,0,0,0,218,9,95,101,113,95,109,116,105, - 109,101,65,2,0,0,115,2,0,0,0,0,2,114,148,0, - 0,0,99,5,0,0,0,0,0,0,0,14,0,0,0,8, - 0,0,0,67,0,0,0,115,68,1,0,0,124,3,124,2, - 100,1,156,2,125,5,122,18,116,0,160,1,124,4,124,3, - 124,5,161,3,125,6,87,0,110,26,4,0,116,2,107,10, - 114,54,1,0,1,0,1,0,89,0,100,0,83,0,89,0, - 110,2,88,0,124,6,100,2,64,0,100,3,107,3,125,7, - 124,7,114,190,124,6,100,4,64,0,100,3,107,3,125,8, - 116,3,106,4,100,5,107,3,114,188,124,8,115,108,116,3, - 106,4,100,6,107,2,114,188,116,5,124,0,124,2,131,2, - 125,9,124,9,100,0,107,9,114,188,116,3,160,6,116,0, - 106,7,124,9,161,2,125,10,122,20,116,8,160,9,124,4, - 124,10,124,3,124,5,161,4,1,0,87,0,110,26,4,0, - 116,2,107,10,114,186,1,0,1,0,1,0,89,0,100,0, - 83,0,89,0,110,2,88,0,110,84,116,10,124,0,124,2, - 131,2,92,2,125,11,125,12,124,11,144,1,114,18,116,11, - 116,12,124,4,100,7,100,8,133,2,25,0,131,1,124,11, - 131,2,114,254,116,12,124,4,100,8,100,9,133,2,25,0, - 131,1,124,12,107,3,144,1,114,18,116,13,160,14,100,10, - 124,3,155,2,157,2,161,1,1,0,100,0,83,0,116,15, - 160,16,124,4,100,9,100,0,133,2,25,0,161,1,125,13, - 116,17,124,13,116,18,131,2,144,1,115,64,116,19,100,11, - 124,1,155,2,100,12,157,3,131,1,130,1,124,13,83,0, - 41,13,78,41,2,114,59,0,0,0,114,13,0,0,0,114, - 5,0,0,0,114,0,0,0,0,114,86,0,0,0,90,5, - 110,101,118,101,114,90,6,97,108,119,97,121,115,114,100,0, - 0,0,114,95,0,0,0,114,96,0,0,0,122,22,98,121, - 116,101,99,111,100,101,32,105,115,32,115,116,97,108,101,32, - 102,111,114,32,122,16,99,111,109,112,105,108,101,100,32,109, - 111,100,117,108,101,32,122,21,32,105,115,32,110,111,116,32, - 97,32,99,111,100,101,32,111,98,106,101,99,116,41,20,114, - 21,0,0,0,90,13,95,99,108,97,115,115,105,102,121,95, - 112,121,99,114,75,0,0,0,218,4,95,105,109,112,90,21, - 99,104,101,99,107,95,104,97,115,104,95,98,97,115,101,100, - 95,112,121,99,115,218,15,95,103,101,116,95,112,121,99,95, - 115,111,117,114,99,101,218,11,115,111,117,114,99,101,95,104, - 97,115,104,90,17,95,82,65,87,95,77,65,71,73,67,95, - 78,85,77,66,69,82,90,18,95,98,111,111,115,116,114,97, - 112,95,101,120,116,101,114,110,97,108,90,18,95,118,97,108, - 105,100,97,116,101,95,104,97,115,104,95,112,121,99,218,29, - 95,103,101,116,95,109,116,105,109,101,95,97,110,100,95,115, - 105,122,101,95,111,102,95,115,111,117,114,99,101,114,148,0, - 0,0,114,2,0,0,0,114,76,0,0,0,114,77,0,0, - 0,218,7,109,97,114,115,104,97,108,90,5,108,111,97,100, - 115,114,15,0,0,0,218,10,95,99,111,100,101,95,116,121, - 112,101,218,9,84,121,112,101,69,114,114,111,114,41,14,114, - 32,0,0,0,114,53,0,0,0,114,63,0,0,0,114,38, - 0,0,0,114,127,0,0,0,90,11,101,120,99,95,100,101, - 116,97,105,108,115,114,130,0,0,0,90,10,104,97,115,104, - 95,98,97,115,101,100,90,12,99,104,101,99,107,95,115,111, - 117,114,99,101,90,12,115,111,117,114,99,101,95,98,121,116, - 101,115,114,151,0,0,0,90,12,115,111,117,114,99,101,95, - 109,116,105,109,101,90,11,115,111,117,114,99,101,95,115,105, - 122,101,114,46,0,0,0,114,9,0,0,0,114,9,0,0, - 0,114,10,0,0,0,218,15,95,117,110,109,97,114,115,104, - 97,108,95,99,111,100,101,75,2,0,0,115,88,0,0,0, - 0,2,2,1,2,254,6,5,2,1,18,1,14,1,12,2, - 12,1,4,1,12,1,10,1,2,255,2,1,8,255,2,2, - 10,1,8,1,4,1,4,1,2,254,4,5,2,1,4,1, - 2,0,2,0,2,0,2,255,8,2,14,1,14,3,8,255, - 6,3,6,3,22,1,18,255,4,2,4,1,8,255,4,2, - 4,2,18,1,12,1,16,1,114,156,0,0,0,99,1,0, - 0,0,0,0,0,0,1,0,0,0,4,0,0,0,67,0, - 0,0,115,28,0,0,0,124,0,160,0,100,1,100,2,161, - 2,125,0,124,0,160,0,100,3,100,2,161,2,125,0,124, - 0,83,0,41,4,78,115,2,0,0,0,13,10,243,1,0, - 0,0,10,243,1,0,0,0,13,41,1,114,19,0,0,0, - 41,1,218,6,115,111,117,114,99,101,114,9,0,0,0,114, - 9,0,0,0,114,10,0,0,0,218,23,95,110,111,114,109, - 97,108,105,122,101,95,108,105,110,101,95,101,110,100,105,110, - 103,115,126,2,0,0,115,6,0,0,0,0,1,12,1,12, - 1,114,160,0,0,0,99,2,0,0,0,0,0,0,0,2, + 114,52,0,0,0,99,2,0,0,0,0,0,0,0,0,0, + 0,0,2,0,0,0,3,0,0,0,67,0,0,0,115,16, + 0,0,0,116,0,124,0,124,1,24,0,131,1,100,1,107, + 1,83,0,41,2,78,114,5,0,0,0,41,1,218,3,97, + 98,115,41,2,90,2,116,49,90,2,116,50,114,9,0,0, + 0,114,9,0,0,0,114,10,0,0,0,218,9,95,101,113, + 95,109,116,105,109,101,65,2,0,0,115,2,0,0,0,0, + 2,114,148,0,0,0,99,5,0,0,0,0,0,0,0,0, + 0,0,0,14,0,0,0,8,0,0,0,67,0,0,0,115, + 68,1,0,0,124,3,124,2,100,1,156,2,125,5,122,18, + 116,0,160,1,124,4,124,3,124,5,161,3,125,6,87,0, + 110,26,4,0,116,2,107,10,114,54,1,0,1,0,1,0, + 89,0,100,0,83,0,89,0,110,2,88,0,124,6,100,2, + 64,0,100,3,107,3,125,7,124,7,114,190,124,6,100,4, + 64,0,100,3,107,3,125,8,116,3,106,4,100,5,107,3, + 114,188,124,8,115,108,116,3,106,4,100,6,107,2,114,188, + 116,5,124,0,124,2,131,2,125,9,124,9,100,0,107,9, + 114,188,116,3,160,6,116,0,106,7,124,9,161,2,125,10, + 122,20,116,8,160,9,124,4,124,10,124,3,124,5,161,4, + 1,0,87,0,110,26,4,0,116,2,107,10,114,186,1,0, + 1,0,1,0,89,0,100,0,83,0,89,0,110,2,88,0, + 110,84,116,10,124,0,124,2,131,2,92,2,125,11,125,12, + 124,11,144,1,114,18,116,11,116,12,124,4,100,7,100,8, + 133,2,25,0,131,1,124,11,131,2,114,254,116,12,124,4, + 100,8,100,9,133,2,25,0,131,1,124,12,107,3,144,1, + 114,18,116,13,160,14,100,10,124,3,155,2,157,2,161,1, + 1,0,100,0,83,0,116,15,160,16,124,4,100,9,100,0, + 133,2,25,0,161,1,125,13,116,17,124,13,116,18,131,2, + 144,1,115,64,116,19,100,11,124,1,155,2,100,12,157,3, + 131,1,130,1,124,13,83,0,41,13,78,41,2,114,59,0, + 0,0,114,13,0,0,0,114,5,0,0,0,114,0,0,0, + 0,114,86,0,0,0,90,5,110,101,118,101,114,90,6,97, + 108,119,97,121,115,114,100,0,0,0,114,95,0,0,0,114, + 96,0,0,0,122,22,98,121,116,101,99,111,100,101,32,105, + 115,32,115,116,97,108,101,32,102,111,114,32,122,16,99,111, + 109,112,105,108,101,100,32,109,111,100,117,108,101,32,122,21, + 32,105,115,32,110,111,116,32,97,32,99,111,100,101,32,111, + 98,106,101,99,116,41,20,114,21,0,0,0,90,13,95,99, + 108,97,115,115,105,102,121,95,112,121,99,114,75,0,0,0, + 218,4,95,105,109,112,90,21,99,104,101,99,107,95,104,97, + 115,104,95,98,97,115,101,100,95,112,121,99,115,218,15,95, + 103,101,116,95,112,121,99,95,115,111,117,114,99,101,218,11, + 115,111,117,114,99,101,95,104,97,115,104,90,17,95,82,65, + 87,95,77,65,71,73,67,95,78,85,77,66,69,82,90,18, + 95,98,111,111,115,116,114,97,112,95,101,120,116,101,114,110, + 97,108,90,18,95,118,97,108,105,100,97,116,101,95,104,97, + 115,104,95,112,121,99,218,29,95,103,101,116,95,109,116,105, + 109,101,95,97,110,100,95,115,105,122,101,95,111,102,95,115, + 111,117,114,99,101,114,148,0,0,0,114,2,0,0,0,114, + 76,0,0,0,114,77,0,0,0,218,7,109,97,114,115,104, + 97,108,90,5,108,111,97,100,115,114,15,0,0,0,218,10, + 95,99,111,100,101,95,116,121,112,101,218,9,84,121,112,101, + 69,114,114,111,114,41,14,114,32,0,0,0,114,53,0,0, + 0,114,63,0,0,0,114,38,0,0,0,114,127,0,0,0, + 90,11,101,120,99,95,100,101,116,97,105,108,115,114,130,0, + 0,0,90,10,104,97,115,104,95,98,97,115,101,100,90,12, + 99,104,101,99,107,95,115,111,117,114,99,101,90,12,115,111, + 117,114,99,101,95,98,121,116,101,115,114,151,0,0,0,90, + 12,115,111,117,114,99,101,95,109,116,105,109,101,90,11,115, + 111,117,114,99,101,95,115,105,122,101,114,46,0,0,0,114, + 9,0,0,0,114,9,0,0,0,114,10,0,0,0,218,15, + 95,117,110,109,97,114,115,104,97,108,95,99,111,100,101,75, + 2,0,0,115,88,0,0,0,0,2,2,1,2,254,6,5, + 2,1,18,1,14,1,12,2,12,1,4,1,12,1,10,1, + 2,255,2,1,8,255,2,2,10,1,8,1,4,1,4,1, + 2,254,4,5,2,1,4,1,2,0,2,0,2,0,2,255, + 8,2,14,1,14,3,8,255,6,3,6,3,22,1,18,255, + 4,2,4,1,8,255,4,2,4,2,18,1,12,1,16,1, + 114,156,0,0,0,99,1,0,0,0,0,0,0,0,0,0, + 0,0,1,0,0,0,4,0,0,0,67,0,0,0,115,28, + 0,0,0,124,0,160,0,100,1,100,2,161,2,125,0,124, + 0,160,0,100,3,100,2,161,2,125,0,124,0,83,0,41, + 4,78,115,2,0,0,0,13,10,243,1,0,0,0,10,243, + 1,0,0,0,13,41,1,114,19,0,0,0,41,1,218,6, + 115,111,117,114,99,101,114,9,0,0,0,114,9,0,0,0, + 114,10,0,0,0,218,23,95,110,111,114,109,97,108,105,122, + 101,95,108,105,110,101,95,101,110,100,105,110,103,115,126,2, + 0,0,115,6,0,0,0,0,1,12,1,12,1,114,160,0, + 0,0,99,2,0,0,0,0,0,0,0,0,0,0,0,2, 0,0,0,6,0,0,0,67,0,0,0,115,24,0,0,0, 116,0,124,1,131,1,125,1,116,1,124,1,124,0,100,1, 100,2,100,3,141,4,83,0,41,4,78,114,74,0,0,0, @@ -857,56 +863,57 @@ const unsigned char _Py_M__zipimport[] = { 0,0,114,9,0,0,0,114,10,0,0,0,218,15,95,99, 111,109,112,105,108,101,95,115,111,117,114,99,101,133,2,0, 0,115,4,0,0,0,0,1,8,1,114,162,0,0,0,99, - 2,0,0,0,0,0,0,0,2,0,0,0,11,0,0,0, - 67,0,0,0,115,68,0,0,0,116,0,160,1,124,0,100, - 1,63,0,100,2,23,0,124,0,100,3,63,0,100,4,64, - 0,124,0,100,5,64,0,124,1,100,6,63,0,124,1,100, - 3,63,0,100,7,64,0,124,1,100,5,64,0,100,8,20, - 0,100,9,100,9,100,9,102,9,161,1,83,0,41,10,78, - 233,9,0,0,0,105,188,7,0,0,233,5,0,0,0,233, - 15,0,0,0,233,31,0,0,0,233,11,0,0,0,233,63, - 0,0,0,114,86,0,0,0,114,14,0,0,0,41,2,114, - 132,0,0,0,90,6,109,107,116,105,109,101,41,2,218,1, - 100,114,139,0,0,0,114,9,0,0,0,114,9,0,0,0, - 114,10,0,0,0,218,14,95,112,97,114,115,101,95,100,111, - 115,116,105,109,101,139,2,0,0,115,22,0,0,0,0,1, - 4,1,10,1,10,1,6,1,6,1,10,1,10,1,2,0, - 2,0,2,249,114,170,0,0,0,99,2,0,0,0,0,0, - 0,0,6,0,0,0,10,0,0,0,67,0,0,0,115,116, - 0,0,0,122,82,124,1,100,1,100,0,133,2,25,0,100, - 2,107,6,115,22,116,0,130,1,124,1,100,0,100,1,133, - 2,25,0,125,1,124,0,106,1,124,1,25,0,125,2,124, - 2,100,3,25,0,125,3,124,2,100,4,25,0,125,4,124, - 2,100,5,25,0,125,5,116,2,124,4,124,3,131,2,124, - 5,102,2,87,0,83,0,4,0,116,3,116,4,116,5,102, - 3,107,10,114,110,1,0,1,0,1,0,89,0,100,6,83, - 0,88,0,100,0,83,0,41,7,78,114,14,0,0,0,169, - 2,218,1,99,218,1,111,114,164,0,0,0,233,6,0,0, - 0,233,3,0,0,0,41,2,114,0,0,0,0,114,0,0, - 0,0,41,6,218,14,65,115,115,101,114,116,105,111,110,69, - 114,114,111,114,114,28,0,0,0,114,170,0,0,0,114,26, - 0,0,0,218,10,73,110,100,101,120,69,114,114,111,114,114, - 155,0,0,0,41,6,114,32,0,0,0,114,13,0,0,0, - 114,54,0,0,0,114,132,0,0,0,114,133,0,0,0,90, - 17,117,110,99,111,109,112,114,101,115,115,101,100,95,115,105, - 122,101,114,9,0,0,0,114,9,0,0,0,114,10,0,0, - 0,114,152,0,0,0,152,2,0,0,115,20,0,0,0,0, - 1,2,2,20,1,12,1,10,3,8,1,8,1,8,1,16, - 1,20,1,114,152,0,0,0,99,2,0,0,0,0,0,0, - 0,3,0,0,0,8,0,0,0,67,0,0,0,115,86,0, - 0,0,124,1,100,1,100,0,133,2,25,0,100,2,107,6, - 115,20,116,0,130,1,124,1,100,0,100,1,133,2,25,0, - 125,1,122,14,124,0,106,1,124,1,25,0,125,2,87,0, - 110,22,4,0,116,2,107,10,114,68,1,0,1,0,1,0, - 89,0,100,0,83,0,88,0,116,3,124,0,106,4,124,2, - 131,2,83,0,100,0,83,0,41,3,78,114,14,0,0,0, - 114,171,0,0,0,41,5,114,176,0,0,0,114,28,0,0, - 0,114,26,0,0,0,114,52,0,0,0,114,29,0,0,0, - 41,3,114,32,0,0,0,114,13,0,0,0,114,54,0,0, - 0,114,9,0,0,0,114,9,0,0,0,114,10,0,0,0, - 114,150,0,0,0,171,2,0,0,115,14,0,0,0,0,2, - 20,1,12,2,2,1,14,1,14,1,8,2,114,150,0,0, - 0,99,2,0,0,0,0,0,0,0,11,0,0,0,9,0, + 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 11,0,0,0,67,0,0,0,115,68,0,0,0,116,0,160, + 1,124,0,100,1,63,0,100,2,23,0,124,0,100,3,63, + 0,100,4,64,0,124,0,100,5,64,0,124,1,100,6,63, + 0,124,1,100,3,63,0,100,7,64,0,124,1,100,5,64, + 0,100,8,20,0,100,9,100,9,100,9,102,9,161,1,83, + 0,41,10,78,233,9,0,0,0,105,188,7,0,0,233,5, + 0,0,0,233,15,0,0,0,233,31,0,0,0,233,11,0, + 0,0,233,63,0,0,0,114,86,0,0,0,114,14,0,0, + 0,41,2,114,132,0,0,0,90,6,109,107,116,105,109,101, + 41,2,218,1,100,114,139,0,0,0,114,9,0,0,0,114, + 9,0,0,0,114,10,0,0,0,218,14,95,112,97,114,115, + 101,95,100,111,115,116,105,109,101,139,2,0,0,115,22,0, + 0,0,0,1,4,1,10,1,10,1,6,1,6,1,10,1, + 10,1,2,0,2,0,2,249,114,170,0,0,0,99,2,0, + 0,0,0,0,0,0,0,0,0,0,6,0,0,0,10,0, + 0,0,67,0,0,0,115,116,0,0,0,122,82,124,1,100, + 1,100,0,133,2,25,0,100,2,107,6,115,22,116,0,130, + 1,124,1,100,0,100,1,133,2,25,0,125,1,124,0,106, + 1,124,1,25,0,125,2,124,2,100,3,25,0,125,3,124, + 2,100,4,25,0,125,4,124,2,100,5,25,0,125,5,116, + 2,124,4,124,3,131,2,124,5,102,2,87,0,83,0,4, + 0,116,3,116,4,116,5,102,3,107,10,114,110,1,0,1, + 0,1,0,89,0,100,6,83,0,88,0,100,0,83,0,41, + 7,78,114,14,0,0,0,169,2,218,1,99,218,1,111,114, + 164,0,0,0,233,6,0,0,0,233,3,0,0,0,41,2, + 114,0,0,0,0,114,0,0,0,0,41,6,218,14,65,115, + 115,101,114,116,105,111,110,69,114,114,111,114,114,28,0,0, + 0,114,170,0,0,0,114,26,0,0,0,218,10,73,110,100, + 101,120,69,114,114,111,114,114,155,0,0,0,41,6,114,32, + 0,0,0,114,13,0,0,0,114,54,0,0,0,114,132,0, + 0,0,114,133,0,0,0,90,17,117,110,99,111,109,112,114, + 101,115,115,101,100,95,115,105,122,101,114,9,0,0,0,114, + 9,0,0,0,114,10,0,0,0,114,152,0,0,0,152,2, + 0,0,115,20,0,0,0,0,1,2,2,20,1,12,1,10, + 3,8,1,8,1,8,1,16,1,20,1,114,152,0,0,0, + 99,2,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,8,0,0,0,67,0,0,0,115,86,0,0,0,124,1, + 100,1,100,0,133,2,25,0,100,2,107,6,115,20,116,0, + 130,1,124,1,100,0,100,1,133,2,25,0,125,1,122,14, + 124,0,106,1,124,1,25,0,125,2,87,0,110,22,4,0, + 116,2,107,10,114,68,1,0,1,0,1,0,89,0,100,0, + 83,0,88,0,116,3,124,0,106,4,124,2,131,2,83,0, + 100,0,83,0,41,3,78,114,14,0,0,0,114,171,0,0, + 0,41,5,114,176,0,0,0,114,28,0,0,0,114,26,0, + 0,0,114,52,0,0,0,114,29,0,0,0,41,3,114,32, + 0,0,0,114,13,0,0,0,114,54,0,0,0,114,9,0, + 0,0,114,9,0,0,0,114,10,0,0,0,114,150,0,0, + 0,171,2,0,0,115,14,0,0,0,0,2,20,1,12,2, + 2,1,14,1,14,1,8,2,114,150,0,0,0,99,2,0, + 0,0,0,0,0,0,0,0,0,0,11,0,0,0,9,0, 0,0,67,0,0,0,115,198,0,0,0,116,0,124,0,124, 1,131,2,125,2,116,1,68,0,93,160,92,3,125,3,125, 4,125,5,124,2,124,3,23,0,125,6,116,2,106,3,100, @@ -935,53 +942,54 @@ const unsigned char _Py_M__zipimport[] = { 2,0,0,115,36,0,0,0,0,1,10,1,14,1,8,1, 22,1,2,1,14,1,14,1,6,2,8,1,12,1,4,1, 18,2,10,1,8,3,2,1,8,1,16,2,114,44,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,64,0,0,0,115,60,0,0,0,101,0,90,1,100, - 0,90,2,100,1,90,3,100,2,90,4,100,3,100,4,132, - 0,90,5,100,5,100,6,132,0,90,6,100,7,100,8,132, - 0,90,7,100,9,100,10,132,0,90,8,100,11,100,12,132, - 0,90,9,100,13,83,0,41,14,114,80,0,0,0,122,165, - 80,114,105,118,97,116,101,32,99,108,97,115,115,32,117,115, - 101,100,32,116,111,32,115,117,112,112,111,114,116,32,90,105, - 112,73,109,112,111,114,116,46,103,101,116,95,114,101,115,111, - 117,114,99,101,95,114,101,97,100,101,114,40,41,46,10,10, - 32,32,32,32,84,104,105,115,32,99,108,97,115,115,32,105, - 115,32,97,108,108,111,119,101,100,32,116,111,32,114,101,102, - 101,114,101,110,99,101,32,97,108,108,32,116,104,101,32,105, - 110,110,97,114,100,115,32,97,110,100,32,112,114,105,118,97, - 116,101,32,112,97,114,116,115,32,111,102,10,32,32,32,32, - 116,104,101,32,122,105,112,105,109,112,111,114,116,101,114,46, - 10,32,32,32,32,70,99,3,0,0,0,0,0,0,0,3, - 0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,0, - 124,1,124,0,95,0,124,2,124,0,95,1,100,0,83,0, - 114,88,0,0,0,41,2,114,4,0,0,0,114,38,0,0, - 0,41,3,114,32,0,0,0,114,4,0,0,0,114,38,0, - 0,0,114,9,0,0,0,114,9,0,0,0,114,10,0,0, - 0,114,34,0,0,0,220,2,0,0,115,4,0,0,0,0, - 1,6,1,122,33,95,90,105,112,73,109,112,111,114,116,82, - 101,115,111,117,114,99,101,82,101,97,100,101,114,46,95,95, - 105,110,105,116,95,95,99,2,0,0,0,0,0,0,0,5, - 0,0,0,8,0,0,0,67,0,0,0,115,92,0,0,0, - 124,0,106,0,160,1,100,1,100,2,161,2,125,2,124,2, - 155,0,100,2,124,1,155,0,157,3,125,3,100,3,100,4, - 108,2,109,3,125,4,1,0,122,18,124,4,124,0,106,4, - 160,5,124,3,161,1,131,1,87,0,83,0,4,0,116,6, - 107,10,114,86,1,0,1,0,1,0,116,7,124,3,131,1, - 130,1,89,0,110,2,88,0,100,0,83,0,41,5,78,114, - 85,0,0,0,114,110,0,0,0,114,0,0,0,0,41,1, - 218,7,66,121,116,101,115,73,79,41,8,114,38,0,0,0, - 114,19,0,0,0,90,2,105,111,114,178,0,0,0,114,4, - 0,0,0,114,55,0,0,0,114,22,0,0,0,218,17,70, - 105,108,101,78,111,116,70,111,117,110,100,69,114,114,111,114, - 41,5,114,32,0,0,0,218,8,114,101,115,111,117,114,99, - 101,218,16,102,117,108,108,110,97,109,101,95,97,115,95,112, - 97,116,104,114,13,0,0,0,114,178,0,0,0,114,9,0, - 0,0,114,9,0,0,0,114,10,0,0,0,218,13,111,112, - 101,110,95,114,101,115,111,117,114,99,101,224,2,0,0,115, - 14,0,0,0,0,1,14,1,14,1,12,1,2,1,18,1, - 14,1,122,38,95,90,105,112,73,109,112,111,114,116,82,101, - 115,111,117,114,99,101,82,101,97,100,101,114,46,111,112,101, - 110,95,114,101,115,111,117,114,99,101,99,2,0,0,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,2,0,0,0,64,0,0,0,115,60,0,0,0,101, + 0,90,1,100,0,90,2,100,1,90,3,100,2,90,4,100, + 3,100,4,132,0,90,5,100,5,100,6,132,0,90,6,100, + 7,100,8,132,0,90,7,100,9,100,10,132,0,90,8,100, + 11,100,12,132,0,90,9,100,13,83,0,41,14,114,80,0, + 0,0,122,165,80,114,105,118,97,116,101,32,99,108,97,115, + 115,32,117,115,101,100,32,116,111,32,115,117,112,112,111,114, + 116,32,90,105,112,73,109,112,111,114,116,46,103,101,116,95, + 114,101,115,111,117,114,99,101,95,114,101,97,100,101,114,40, + 41,46,10,10,32,32,32,32,84,104,105,115,32,99,108,97, + 115,115,32,105,115,32,97,108,108,111,119,101,100,32,116,111, + 32,114,101,102,101,114,101,110,99,101,32,97,108,108,32,116, + 104,101,32,105,110,110,97,114,100,115,32,97,110,100,32,112, + 114,105,118,97,116,101,32,112,97,114,116,115,32,111,102,10, + 32,32,32,32,116,104,101,32,122,105,112,105,109,112,111,114, + 116,101,114,46,10,32,32,32,32,70,99,3,0,0,0,0, + 0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,67, + 0,0,0,115,16,0,0,0,124,1,124,0,95,0,124,2, + 124,0,95,1,100,0,83,0,114,88,0,0,0,41,2,114, + 4,0,0,0,114,38,0,0,0,41,3,114,32,0,0,0, + 114,4,0,0,0,114,38,0,0,0,114,9,0,0,0,114, + 9,0,0,0,114,10,0,0,0,114,34,0,0,0,220,2, + 0,0,115,4,0,0,0,0,1,6,1,122,33,95,90,105, + 112,73,109,112,111,114,116,82,101,115,111,117,114,99,101,82, + 101,97,100,101,114,46,95,95,105,110,105,116,95,95,99,2, + 0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,8, + 0,0,0,67,0,0,0,115,92,0,0,0,124,0,106,0, + 160,1,100,1,100,2,161,2,125,2,124,2,155,0,100,2, + 124,1,155,0,157,3,125,3,100,3,100,4,108,2,109,3, + 125,4,1,0,122,18,124,4,124,0,106,4,160,5,124,3, + 161,1,131,1,87,0,83,0,4,0,116,6,107,10,114,86, + 1,0,1,0,1,0,116,7,124,3,131,1,130,1,89,0, + 110,2,88,0,100,0,83,0,41,5,78,114,85,0,0,0, + 114,110,0,0,0,114,0,0,0,0,41,1,218,7,66,121, + 116,101,115,73,79,41,8,114,38,0,0,0,114,19,0,0, + 0,90,2,105,111,114,178,0,0,0,114,4,0,0,0,114, + 55,0,0,0,114,22,0,0,0,218,17,70,105,108,101,78, + 111,116,70,111,117,110,100,69,114,114,111,114,41,5,114,32, + 0,0,0,218,8,114,101,115,111,117,114,99,101,218,16,102, + 117,108,108,110,97,109,101,95,97,115,95,112,97,116,104,114, + 13,0,0,0,114,178,0,0,0,114,9,0,0,0,114,9, + 0,0,0,114,10,0,0,0,218,13,111,112,101,110,95,114, + 101,115,111,117,114,99,101,224,2,0,0,115,14,0,0,0, + 0,1,14,1,14,1,12,1,2,1,18,1,14,1,122,38, + 95,90,105,112,73,109,112,111,114,116,82,101,115,111,117,114, + 99,101,82,101,97,100,101,114,46,111,112,101,110,95,114,101, + 115,111,117,114,99,101,99,2,0,0,0,0,0,0,0,0, 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, 8,0,0,0,116,0,130,1,100,0,83,0,114,88,0,0, 0,41,1,114,179,0,0,0,41,2,114,32,0,0,0,114, @@ -990,86 +998,87 @@ const unsigned char _Py_M__zipimport[] = { 116,104,233,2,0,0,115,2,0,0,0,0,4,122,38,95, 90,105,112,73,109,112,111,114,116,82,101,115,111,117,114,99, 101,82,101,97,100,101,114,46,114,101,115,111,117,114,99,101, - 95,112,97,116,104,99,2,0,0,0,0,0,0,0,4,0, - 0,0,8,0,0,0,67,0,0,0,115,72,0,0,0,124, - 0,106,0,160,1,100,1,100,2,161,2,125,2,124,2,155, - 0,100,2,124,1,155,0,157,3,125,3,122,16,124,0,106, - 2,160,3,124,3,161,1,1,0,87,0,110,22,4,0,116, - 4,107,10,114,66,1,0,1,0,1,0,89,0,100,3,83, - 0,88,0,100,4,83,0,41,5,78,114,85,0,0,0,114, - 110,0,0,0,70,84,41,5,114,38,0,0,0,114,19,0, - 0,0,114,4,0,0,0,114,55,0,0,0,114,22,0,0, - 0,41,4,114,32,0,0,0,114,59,0,0,0,114,181,0, - 0,0,114,13,0,0,0,114,9,0,0,0,114,9,0,0, - 0,114,10,0,0,0,218,11,105,115,95,114,101,115,111,117, - 114,99,101,239,2,0,0,115,14,0,0,0,0,3,14,1, - 14,1,2,1,16,1,14,1,8,1,122,36,95,90,105,112, - 73,109,112,111,114,116,82,101,115,111,117,114,99,101,82,101, - 97,100,101,114,46,105,115,95,114,101,115,111,117,114,99,101, - 99,1,0,0,0,0,0,0,0,9,0,0,0,9,0,0, - 0,99,0,0,0,115,186,0,0,0,100,1,100,2,108,0, - 109,1,125,1,1,0,124,1,124,0,106,2,160,3,124,0, - 106,4,161,1,131,1,125,2,124,2,160,5,124,0,106,2, - 106,6,161,1,125,3,124,3,106,7,100,3,107,2,115,58, - 116,8,130,1,124,3,106,9,125,4,116,10,131,0,125,5, - 124,0,106,2,106,11,68,0,93,102,125,6,122,18,124,1, - 124,6,131,1,160,5,124,4,161,1,125,7,87,0,110,24, - 4,0,116,12,107,10,114,124,1,0,1,0,1,0,89,0, - 113,78,89,0,110,2,88,0,124,7,106,9,106,7,125,8, - 116,13,124,8,131,1,100,1,107,2,114,156,124,7,106,7, - 86,0,1,0,113,78,124,8,124,5,107,7,114,78,124,5, - 160,14,124,8,161,1,1,0,124,8,86,0,1,0,113,78, - 100,0,83,0,41,4,78,114,0,0,0,0,41,1,218,4, - 80,97,116,104,114,60,0,0,0,41,15,90,7,112,97,116, - 104,108,105,98,114,185,0,0,0,114,4,0,0,0,114,56, - 0,0,0,114,38,0,0,0,90,11,114,101,108,97,116,105, - 118,101,95,116,111,114,29,0,0,0,114,59,0,0,0,114, - 176,0,0,0,90,6,112,97,114,101,110,116,218,3,115,101, - 116,114,28,0,0,0,114,23,0,0,0,114,51,0,0,0, - 218,3,97,100,100,41,9,114,32,0,0,0,114,185,0,0, - 0,90,13,102,117,108,108,110,97,109,101,95,112,97,116,104, - 90,13,114,101,108,97,116,105,118,101,95,112,97,116,104,90, - 12,112,97,99,107,97,103,101,95,112,97,116,104,90,12,115, - 117,98,100,105,114,115,95,115,101,101,110,218,8,102,105,108, - 101,110,97,109,101,90,8,114,101,108,97,116,105,118,101,90, - 11,112,97,114,101,110,116,95,110,97,109,101,114,9,0,0, - 0,114,9,0,0,0,114,10,0,0,0,218,8,99,111,110, - 116,101,110,116,115,250,2,0,0,115,34,0,0,0,0,8, - 12,1,18,1,14,3,14,1,6,1,6,1,12,1,2,1, - 18,1,14,1,10,5,8,1,12,1,10,1,8,1,10,1, - 122,33,95,90,105,112,73,109,112,111,114,116,82,101,115,111, - 117,114,99,101,82,101,97,100,101,114,46,99,111,110,116,101, - 110,116,115,78,41,10,114,6,0,0,0,114,7,0,0,0, - 114,8,0,0,0,114,84,0,0,0,114,81,0,0,0,114, - 34,0,0,0,114,182,0,0,0,114,183,0,0,0,114,184, - 0,0,0,114,189,0,0,0,114,9,0,0,0,114,9,0, - 0,0,114,9,0,0,0,114,10,0,0,0,114,80,0,0, - 0,212,2,0,0,115,14,0,0,0,8,1,4,5,4,2, - 8,4,8,9,8,6,8,11,114,80,0,0,0,41,45,114, - 84,0,0,0,90,26,95,102,114,111,122,101,110,95,105,109, - 112,111,114,116,108,105,98,95,101,120,116,101,114,110,97,108, - 114,21,0,0,0,114,1,0,0,0,114,2,0,0,0,90, - 17,95,102,114,111,122,101,110,95,105,109,112,111,114,116,108, - 105,98,114,76,0,0,0,114,149,0,0,0,114,111,0,0, - 0,114,153,0,0,0,114,67,0,0,0,114,132,0,0,0, - 90,7,95,95,97,108,108,95,95,114,20,0,0,0,90,15, - 112,97,116,104,95,115,101,112,97,114,97,116,111,114,115,114, - 18,0,0,0,114,75,0,0,0,114,3,0,0,0,114,25, - 0,0,0,218,4,116,121,112,101,114,70,0,0,0,114,114, - 0,0,0,114,116,0,0,0,114,118,0,0,0,114,4,0, - 0,0,114,89,0,0,0,114,36,0,0,0,114,37,0,0, - 0,114,35,0,0,0,114,27,0,0,0,114,123,0,0,0, - 114,143,0,0,0,114,145,0,0,0,114,52,0,0,0,114, - 148,0,0,0,114,156,0,0,0,218,8,95,95,99,111,100, - 101,95,95,114,154,0,0,0,114,160,0,0,0,114,162,0, - 0,0,114,170,0,0,0,114,152,0,0,0,114,150,0,0, - 0,114,44,0,0,0,114,80,0,0,0,114,9,0,0,0, - 114,9,0,0,0,114,9,0,0,0,114,10,0,0,0,218, - 8,60,109,111,100,117,108,101,62,1,0,0,0,115,88,0, - 0,0,4,16,8,1,16,1,8,1,8,1,8,1,8,1, - 8,1,8,2,8,3,6,1,14,3,16,4,4,2,8,2, - 4,1,4,1,4,2,14,127,0,127,0,1,12,1,12,1, - 2,1,2,252,4,9,8,4,8,9,8,31,8,126,2,254, - 2,29,4,5,8,21,8,46,8,10,8,46,10,5,8,7, - 8,6,8,13,8,19,8,15,8,26, + 95,112,97,116,104,99,2,0,0,0,0,0,0,0,0,0, + 0,0,4,0,0,0,8,0,0,0,67,0,0,0,115,72, + 0,0,0,124,0,106,0,160,1,100,1,100,2,161,2,125, + 2,124,2,155,0,100,2,124,1,155,0,157,3,125,3,122, + 16,124,0,106,2,160,3,124,3,161,1,1,0,87,0,110, + 22,4,0,116,4,107,10,114,66,1,0,1,0,1,0,89, + 0,100,3,83,0,88,0,100,4,83,0,41,5,78,114,85, + 0,0,0,114,110,0,0,0,70,84,41,5,114,38,0,0, + 0,114,19,0,0,0,114,4,0,0,0,114,55,0,0,0, + 114,22,0,0,0,41,4,114,32,0,0,0,114,59,0,0, + 0,114,181,0,0,0,114,13,0,0,0,114,9,0,0,0, + 114,9,0,0,0,114,10,0,0,0,218,11,105,115,95,114, + 101,115,111,117,114,99,101,239,2,0,0,115,14,0,0,0, + 0,3,14,1,14,1,2,1,16,1,14,1,8,1,122,36, + 95,90,105,112,73,109,112,111,114,116,82,101,115,111,117,114, + 99,101,82,101,97,100,101,114,46,105,115,95,114,101,115,111, + 117,114,99,101,99,1,0,0,0,0,0,0,0,0,0,0, + 0,9,0,0,0,9,0,0,0,99,0,0,0,115,186,0, + 0,0,100,1,100,2,108,0,109,1,125,1,1,0,124,1, + 124,0,106,2,160,3,124,0,106,4,161,1,131,1,125,2, + 124,2,160,5,124,0,106,2,106,6,161,1,125,3,124,3, + 106,7,100,3,107,2,115,58,116,8,130,1,124,3,106,9, + 125,4,116,10,131,0,125,5,124,0,106,2,106,11,68,0, + 93,102,125,6,122,18,124,1,124,6,131,1,160,5,124,4, + 161,1,125,7,87,0,110,24,4,0,116,12,107,10,114,124, + 1,0,1,0,1,0,89,0,113,78,89,0,110,2,88,0, + 124,7,106,9,106,7,125,8,116,13,124,8,131,1,100,1, + 107,2,114,156,124,7,106,7,86,0,1,0,113,78,124,8, + 124,5,107,7,114,78,124,5,160,14,124,8,161,1,1,0, + 124,8,86,0,1,0,113,78,100,0,83,0,41,4,78,114, + 0,0,0,0,41,1,218,4,80,97,116,104,114,60,0,0, + 0,41,15,90,7,112,97,116,104,108,105,98,114,185,0,0, + 0,114,4,0,0,0,114,56,0,0,0,114,38,0,0,0, + 90,11,114,101,108,97,116,105,118,101,95,116,111,114,29,0, + 0,0,114,59,0,0,0,114,176,0,0,0,90,6,112,97, + 114,101,110,116,218,3,115,101,116,114,28,0,0,0,114,23, + 0,0,0,114,51,0,0,0,218,3,97,100,100,41,9,114, + 32,0,0,0,114,185,0,0,0,90,13,102,117,108,108,110, + 97,109,101,95,112,97,116,104,90,13,114,101,108,97,116,105, + 118,101,95,112,97,116,104,90,12,112,97,99,107,97,103,101, + 95,112,97,116,104,90,12,115,117,98,100,105,114,115,95,115, + 101,101,110,218,8,102,105,108,101,110,97,109,101,90,8,114, + 101,108,97,116,105,118,101,90,11,112,97,114,101,110,116,95, + 110,97,109,101,114,9,0,0,0,114,9,0,0,0,114,10, + 0,0,0,218,8,99,111,110,116,101,110,116,115,250,2,0, + 0,115,34,0,0,0,0,8,12,1,18,1,14,3,14,1, + 6,1,6,1,12,1,2,1,18,1,14,1,10,5,8,1, + 12,1,10,1,8,1,10,1,122,33,95,90,105,112,73,109, + 112,111,114,116,82,101,115,111,117,114,99,101,82,101,97,100, + 101,114,46,99,111,110,116,101,110,116,115,78,41,10,114,6, + 0,0,0,114,7,0,0,0,114,8,0,0,0,114,84,0, + 0,0,114,81,0,0,0,114,34,0,0,0,114,182,0,0, + 0,114,183,0,0,0,114,184,0,0,0,114,189,0,0,0, + 114,9,0,0,0,114,9,0,0,0,114,9,0,0,0,114, + 10,0,0,0,114,80,0,0,0,212,2,0,0,115,14,0, + 0,0,8,1,4,5,4,2,8,4,8,9,8,6,8,11, + 114,80,0,0,0,41,45,114,84,0,0,0,90,26,95,102, + 114,111,122,101,110,95,105,109,112,111,114,116,108,105,98,95, + 101,120,116,101,114,110,97,108,114,21,0,0,0,114,1,0, + 0,0,114,2,0,0,0,90,17,95,102,114,111,122,101,110, + 95,105,109,112,111,114,116,108,105,98,114,76,0,0,0,114, + 149,0,0,0,114,111,0,0,0,114,153,0,0,0,114,67, + 0,0,0,114,132,0,0,0,90,7,95,95,97,108,108,95, + 95,114,20,0,0,0,90,15,112,97,116,104,95,115,101,112, + 97,114,97,116,111,114,115,114,18,0,0,0,114,75,0,0, + 0,114,3,0,0,0,114,25,0,0,0,218,4,116,121,112, + 101,114,70,0,0,0,114,114,0,0,0,114,116,0,0,0, + 114,118,0,0,0,114,4,0,0,0,114,89,0,0,0,114, + 36,0,0,0,114,37,0,0,0,114,35,0,0,0,114,27, + 0,0,0,114,123,0,0,0,114,143,0,0,0,114,145,0, + 0,0,114,52,0,0,0,114,148,0,0,0,114,156,0,0, + 0,218,8,95,95,99,111,100,101,95,95,114,154,0,0,0, + 114,160,0,0,0,114,162,0,0,0,114,170,0,0,0,114, + 152,0,0,0,114,150,0,0,0,114,44,0,0,0,114,80, + 0,0,0,114,9,0,0,0,114,9,0,0,0,114,9,0, + 0,0,114,10,0,0,0,218,8,60,109,111,100,117,108,101, + 62,1,0,0,0,115,88,0,0,0,4,16,8,1,16,1, + 8,1,8,1,8,1,8,1,8,1,8,2,8,3,6,1, + 14,3,16,4,4,2,8,2,4,1,4,1,4,2,14,127, + 0,127,0,1,12,1,12,1,2,1,2,252,4,9,8,4, + 8,9,8,31,8,126,2,254,2,29,4,5,8,21,8,46, + 8,10,8,46,10,5,8,7,8,6,8,13,8,19,8,15, + 8,26, }; diff --git a/Python/marshal.c b/Python/marshal.c index 52932af225a48f..caaddfe9e44e49 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -530,6 +530,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p) PyCodeObject *co = (PyCodeObject *)v; W_TYPE(TYPE_CODE, p); w_long(co->co_argcount, p); + w_long(co->co_posonlyargcount, p); w_long(co->co_kwonlyargcount, p); w_long(co->co_nlocals, p); w_long(co->co_stacksize, p); @@ -1322,6 +1323,7 @@ r_object(RFILE *p) case TYPE_CODE: { int argcount; + int posonlyargcount; int kwonlyargcount; int nlocals; int stacksize; @@ -1347,6 +1349,10 @@ r_object(RFILE *p) argcount = (int)r_long(p); if (PyErr_Occurred()) goto code_error; + posonlyargcount = (int)r_long(p); + if (PyErr_Occurred()) { + goto code_error; + } kwonlyargcount = (int)r_long(p); if (PyErr_Occurred()) goto code_error; @@ -1391,7 +1397,7 @@ r_object(RFILE *p) goto code_error; v = (PyObject *) PyCode_New( - argcount, kwonlyargcount, + argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize, flags, code, consts, names, varnames, freevars, cellvars, filename, name, diff --git a/Python/symtable.c b/Python/symtable.c index 1d68a7d939fa54..fe6bc9aca4d08f 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1653,6 +1653,8 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a) /* skip default arguments inside function block XXX should ast be different? */ + if (a->posonlyargs && !symtable_visit_params(st, a->posonlyargs)) + return 0; if (a->args && !symtable_visit_params(st, a->args)) return 0; if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs)) diff --git a/Tools/parser/unparse.py b/Tools/parser/unparse.py index 70b47a17405312..385902ef4bc5e7 100644 --- a/Tools/parser/unparse.py +++ b/Tools/parser/unparse.py @@ -592,14 +592,18 @@ def _arg(self, t): def _arguments(self, t): first = True # normal arguments - defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults - for a, d in zip(t.args, defaults): + all_args = t.posonlyargs + t.args + defaults = [None] * (len(all_args) - len(t.defaults)) + t.defaults + for index, elements in enumerate(zip(all_args, defaults), 1): + a, d = elements if first:first = False else: self.write(", ") self.dispatch(a) if d: self.write("=") self.dispatch(d) + if index == len(t.posonlyargs): + self.write(", /") # varargs, or bare '*' if no varargs but keyword-only arguments present if t.vararg or t.kwonlyargs: From 843bf42aa65aaa25b356e7b3d8733a117b8f01a4 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 29 Apr 2019 05:49:30 -0700 Subject: [PATCH 113/212] Add initial 'whatsnew' section for PEP 570 (GH-12942) --- Doc/whatsnew/3.8.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 90ff72f67ff434..225faf8c0b7a67 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -83,6 +83,31 @@ See :pep:`572` for a full description. .. TODO: Emily will sprint on docs at PyCon US 2019. +Positional-only parameters +-------------------------- + +There is new syntax (``/``) to indicate that some function parameters +must be specified positionally (i.e., cannot be used as keyword +arguments). This is the same notation as shown by ``help()`` for +functions implemented in C (produced by Larry Hastings' "Argument +Clinic" tool). Example:: + + def pow(x, y, z=None, /): + r = x**y + if z is not None: + r %= z + return r + +Now ``pow(2, 10)`` and ``pow(2, 10, 17)`` are valid calls, but +``pow(x=2, y=10)`` and ``pow(2, 10, z=17)`` are invalid. + +See :pep:`570` for a full description. + +(Contributed by Pablo Galindo in :issue:`36540`.) + +.. TODO: Pablo will sprint on docs at PyCon US 2019. + + Parallel filesystem cache for compiled bytecode files ----------------------------------------------------- From a86e06433a010f873dfd7957e0f87a39539876ee Mon Sep 17 00:00:00 2001 From: xdegaye Date: Mon, 29 Apr 2019 14:53:30 +0200 Subject: [PATCH 114/212] bpo-35952: Fix test.pythoninfo when the compiler is missing (GH-13007) --- Lib/test/pythoninfo.py | 15 +++++++++++---- .../2019-04-29-11-47-06.bpo-35952.3uNuyo.rst | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-29-11-47-06.bpo-35952.3uNuyo.rst diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 19f274a6b6294b..580956633f4d40 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -571,10 +571,17 @@ def collect_cc(info_add): except ImportError: args = CC.split() args.append('--version') - proc = subprocess.Popen(args, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True) + try: + proc = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True) + except OSError: + # Cannot run the compiler, for example when Python has been + # cross-compiled and installed on the target platform where the + # compiler is missing. + return + stdout = proc.communicate()[0] if proc.returncode: # CC --version failed: ignore error diff --git a/Misc/NEWS.d/next/Library/2019-04-29-11-47-06.bpo-35952.3uNuyo.rst b/Misc/NEWS.d/next/Library/2019-04-29-11-47-06.bpo-35952.3uNuyo.rst new file mode 100644 index 00000000000000..9aeea90d8162b1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-29-11-47-06.bpo-35952.3uNuyo.rst @@ -0,0 +1 @@ +Fix pythoninfo when the compiler is missing. From 88c093705615c50c47fdd9ab976803f73de7e308 Mon Sep 17 00:00:00 2001 From: Paul Ganssle Date: Mon, 29 Apr 2019 09:22:03 -0400 Subject: [PATCH 115/212] bpo-36004: Add date.fromisocalendar (GH-11888) This commit implements the first version of date.fromisocalendar, the inverse function for date.isocalendar. --- Doc/library/datetime.rst | 17 +++++ Doc/whatsnew/3.8.rst | 10 +++ Lib/datetime.py | 35 +++++++++ Lib/test/datetimetester.py | 76 +++++++++++++++++++ .../2019-02-17-12-55-51.bpo-36004.hCt_KK.rst | 4 + Modules/_datetimemodule.c | 67 ++++++++++++++++ 6 files changed, 209 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2019-02-17-12-55-51.bpo-36004.hCt_KK.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 1ee23c2175a27d..abdc977354803e 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -458,6 +458,13 @@ Other constructors, all class methods: .. versionadded:: 3.7 +.. classmethod:: date.fromisocalendar(year, week, day) + + Return a :class:`date` corresponding to the ISO calendar date specified by + year, week and day. This is the inverse of the function :meth:`date.isocalendar`. + + .. versionadded:: 3.8 + Class attributes: @@ -854,6 +861,16 @@ Other constructors, all class methods: .. versionadded:: 3.7 + +.. classmethod:: datetime.fromisocalendar(year, week, day) + + Return a :class:`datetime` corresponding to the ISO calendar date specified + by year, week and day. The non-date components of the datetime are populated + with their normal default values. This is the inverse of the function + :meth:`datetime.isocalendar`. + + .. versionadded:: 3.8 + .. classmethod:: datetime.strptime(date_string, format) Return a :class:`.datetime` corresponding to *date_string*, parsed according to diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 225faf8c0b7a67..ac57335221c49b 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -244,6 +244,16 @@ where the DLL is stored (if a full or partial path is used to load the initial DLL) and paths added by :func:`~os.add_dll_directory`. +datetime +-------- + +Added new alternate constructors :meth:`datetime.date.fromisocalendar` and +:meth:`datetime.datetime.fromisocalendar`, which construct :class:`date` and +:class:`datetime` objects respectively from ISO year, week number and weekday; +these are the inverse of each class's ``isocalendar`` method. +(Contributed by Paul Ganssle in :issue:`36004`.) + + gettext ------- diff --git a/Lib/datetime.py b/Lib/datetime.py index 85bfa48e05dea4..0e64815944dbd7 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -884,6 +884,40 @@ def fromisoformat(cls, date_string): except Exception: raise ValueError(f'Invalid isoformat string: {date_string!r}') + @classmethod + def fromisocalendar(cls, year, week, day): + """Construct a date from the ISO year, week number and weekday. + + This is the inverse of the date.isocalendar() function""" + # Year is bounded this way because 9999-12-31 is (9999, 52, 5) + if not MINYEAR <= year <= MAXYEAR: + raise ValueError(f"Year is out of range: {year}") + + if not 0 < week < 53: + out_of_range = True + + if week == 53: + # ISO years have 53 weeks in them on years starting with a + # Thursday and leap years starting on a Wednesday + first_weekday = _ymd2ord(year, 1, 1) % 7 + if (first_weekday == 4 or (first_weekday == 3 and + _is_leap(year))): + out_of_range = False + + if out_of_range: + raise ValueError(f"Invalid week: {week}") + + if not 0 < day < 8: + raise ValueError(f"Invalid weekday: {day} (range is [1, 7])") + + # Now compute the offset from (Y, 1, 1) in days: + day_offset = (week - 1) * 7 + (day - 1) + + # Calculate the ordinal day for monday, week 1 + day_1 = _isoweek1monday(year) + ord_day = day_1 + day_offset + + return cls(*_ord2ymd(ord_day)) # Conversions to string @@ -2141,6 +2175,7 @@ def _isoweek1monday(year): week1monday += 7 return week1monday + class timezone(tzinfo): __slots__ = '_offset', '_name' diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 617bf9a25587dc..9fe32ebc5b395f 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1795,6 +1795,82 @@ def test_fromisoformat_fails_typeerror(self): with self.assertRaises(TypeError): self.theclass.fromisoformat(bad_type) + def test_fromisocalendar(self): + # For each test case, assert that fromisocalendar is the + # inverse of the isocalendar function + dates = [ + (2016, 4, 3), + (2005, 1, 2), # (2004, 53, 7) + (2008, 12, 30), # (2009, 1, 2) + (2010, 1, 2), # (2009, 53, 6) + (2009, 12, 31), # (2009, 53, 4) + (1900, 1, 1), # Unusual non-leap year (year % 100 == 0) + (1900, 12, 31), + (2000, 1, 1), # Unusual leap year (year % 400 == 0) + (2000, 12, 31), + (2004, 1, 1), # Leap year + (2004, 12, 31), + (1, 1, 1), + (9999, 12, 31), + (MINYEAR, 1, 1), + (MAXYEAR, 12, 31), + ] + + for datecomps in dates: + with self.subTest(datecomps=datecomps): + dobj = self.theclass(*datecomps) + isocal = dobj.isocalendar() + + d_roundtrip = self.theclass.fromisocalendar(*isocal) + + self.assertEqual(dobj, d_roundtrip) + + def test_fromisocalendar_value_errors(self): + isocals = [ + (2019, 0, 1), + (2019, -1, 1), + (2019, 54, 1), + (2019, 1, 0), + (2019, 1, -1), + (2019, 1, 8), + (2019, 53, 1), + (10000, 1, 1), + (0, 1, 1), + (9999999, 1, 1), + (2<<32, 1, 1), + (2019, 2<<32, 1), + (2019, 1, 2<<32), + ] + + for isocal in isocals: + with self.subTest(isocal=isocal): + with self.assertRaises(ValueError): + self.theclass.fromisocalendar(*isocal) + + def test_fromisocalendar_type_errors(self): + err_txformers = [ + str, + float, + lambda x: None, + ] + + # Take a valid base tuple and transform it to contain one argument + # with the wrong type. Repeat this for each argument, e.g. + # [("2019", 1, 1), (2019, "1", 1), (2019, 1, "1"), ...] + isocals = [] + base = (2019, 1, 1) + for i in range(3): + for txformer in err_txformers: + err_val = list(base) + err_val[i] = txformer(err_val[i]) + isocals.append(tuple(err_val)) + + for isocal in isocals: + with self.subTest(isocal=isocal): + with self.assertRaises(TypeError): + self.theclass.fromisocalendar(*isocal) + + ############################################################################# # datetime tests diff --git a/Misc/NEWS.d/next/Library/2019-02-17-12-55-51.bpo-36004.hCt_KK.rst b/Misc/NEWS.d/next/Library/2019-02-17-12-55-51.bpo-36004.hCt_KK.rst new file mode 100644 index 00000000000000..d2162be82f706c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-02-17-12-55-51.bpo-36004.hCt_KK.rst @@ -0,0 +1,4 @@ +Added new alternate constructors :meth:`datetime.date.fromisocalendar` and +:meth:`datetime.datetime.fromisocalendar`, which construct date objects from +ISO year, week number and weekday; these are the inverse of each class's +``isocalendar`` method. Patch by Paul Ganssle. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index b3954c98ee7df3..83e43a24395b45 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3003,6 +3003,67 @@ date_fromisoformat(PyObject *cls, PyObject *dtstr) return NULL; } + +static PyObject * +date_fromisocalendar(PyObject *cls, PyObject *args, PyObject *kw) +{ + static char *keywords[] = { + "year", "week", "day", NULL + }; + + int year, week, day; + if (PyArg_ParseTupleAndKeywords(args, kw, "iii:fromisocalendar", + keywords, + &year, &week, &day) == 0) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + PyErr_Format(PyExc_ValueError, + "ISO calendar component out of range"); + + } + return NULL; + } + + // Year is bounded to 0 < year < 10000 because 9999-12-31 is (9999, 52, 5) + if (year < MINYEAR || year > MAXYEAR) { + PyErr_Format(PyExc_ValueError, "Year is out of range: %d", year); + return NULL; + } + + if (week <= 0 || week >= 53) { + int out_of_range = 1; + if (week == 53) { + // ISO years have 53 weeks in it on years starting with a Thursday + // and on leap years starting on Wednesday + int first_weekday = weekday(year, 1, 1); + if (first_weekday == 3 || (first_weekday == 2 && is_leap(year))) { + out_of_range = 0; + } + } + + if (out_of_range) { + PyErr_Format(PyExc_ValueError, "Invalid week: %d", week); + return NULL; + } + } + + if (day <= 0 || day >= 8) { + PyErr_Format(PyExc_ValueError, "Invalid day: %d (range is [1, 7])", + day); + return NULL; + } + + // Convert (Y, W, D) to (Y, M, D) in-place + int day_1 = iso_week1_monday(year); + + int month = week; + int day_offset = (month - 1)*7 + day - 1; + + ord_to_ymd(day_1 + day_offset, &year, &month, &day); + + return new_date_subclass_ex(year, month, day, cls); +} + + /* * Date arithmetic. */ @@ -3296,6 +3357,12 @@ static PyMethodDef date_methods[] = { METH_CLASS, PyDoc_STR("str -> Construct a date from the output of date.isoformat()")}, + {"fromisocalendar", (PyCFunction)(void(*)(void))date_fromisocalendar, + METH_VARARGS | METH_KEYWORDS | METH_CLASS, + PyDoc_STR("int, int, int -> Construct a date from the ISO year, week " + "number and weekday.\n\n" + "This is the inverse of the date.isocalendar() function")}, + {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS, PyDoc_STR("Current date or datetime: same as " "self.__class__.fromtimestamp(time.time()).")}, From be6dbfb43b89989ccc83fbc4c5234f50f44c47ad Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Mon, 29 Apr 2019 17:55:39 +0300 Subject: [PATCH 116/212] bpo-1613500: Don't hardcode output file mode in fileinput.FileInput (GH-12986) --- Lib/fileinput.py | 5 +++-- Lib/test/test_fileinput.py | 10 ++++++++++ .../Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst diff --git a/Lib/fileinput.py b/Lib/fileinput.py index 4a71cc5ff31872..0764aa5e4d2480 100644 --- a/Lib/fileinput.py +++ b/Lib/fileinput.py @@ -222,6 +222,7 @@ def __init__(self, files=None, inplace=False, backup="", bufsize=0, warnings.warn("'U' mode is deprecated", DeprecationWarning, 2) self._mode = mode + self._write_mode = mode.replace('r', 'w') if 'U' not in mode else 'w' if openhook: if inplace: raise ValueError("FileInput cannot use an opening hook in inplace mode") @@ -348,14 +349,14 @@ def _readline(self): try: perm = os.fstat(self._file.fileno()).st_mode except OSError: - self._output = open(self._filename, "w") + self._output = open(self._filename, self._write_mode) else: mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC if hasattr(os, 'O_BINARY'): mode |= os.O_BINARY fd = os.open(self._filename, mode, perm) - self._output = os.fdopen(fd, "w") + self._output = os.fdopen(fd, self._write_mode) try: os.chmod(self._filename, perm) except OSError: diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py index 3857401ca60fa6..8b7577b0205cde 100644 --- a/Lib/test/test_fileinput.py +++ b/Lib/test/test_fileinput.py @@ -329,6 +329,16 @@ def test_readline_binary_mode(self): self.assertEqual(fi.readline(), b'') self.assertEqual(fi.readline(), b'') + def test_inplace_binary_write_mode(self): + temp_file = self.writeTmp(b'Initial text.', mode='wb') + with FileInput(temp_file, mode='rb', inplace=True) as fobj: + line = fobj.readline() + self.assertEqual(line, b'Initial text.') + # print() cannot be used with files opened in binary mode. + sys.stdout.write(b'New line.') + with open(temp_file, 'rb') as f: + self.assertEqual(f.read(), b'New line.') + def test_context_manager(self): t1 = self.writeTmp("A\nB\nC") t2 = self.writeTmp("D\nE\nF") diff --git a/Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst b/Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst new file mode 100644 index 00000000000000..4501819ac360e6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst @@ -0,0 +1,3 @@ +:class:`fileinput.FileInput` now uses the input file mode to correctly set +the output file mode (previously it was hardcoded to ``'w'``) when +``inplace=True`` is passed to its constructor. From 883dfc668f9730b00928730035b5dbd24b9da2a0 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Mon, 29 Apr 2019 15:07:39 -0400 Subject: [PATCH 117/212] bpo-34602: Avoid failures setting macOS stack resource limit (GH-13011) Under some conditions the earlier fix for bpo-18075, "Infinite recursion tests triggering a segfault on Mac OS X", now causes failures on macOS when attempting to change stack limit with resource.setrlimit resource.RLIMIT_STACK, like regrtest does when running the test suite. The reverted change had specified a non-default stack size when linking the python executable on macOS. As of macOS 10.14.4, the previous code causes a hard failure when running tests, although similar failures had been seen under some conditions under some earlier systems. For now, revert the original change and resume using the default stack size when linking the interpreter. --- .../next/macOS/2019-04-29-10-54-14.bpo-34602.Lrl2zU.rst | 3 +++ configure | 6 ------ configure.ac | 6 ------ 3 files changed, 3 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/macOS/2019-04-29-10-54-14.bpo-34602.Lrl2zU.rst diff --git a/Misc/NEWS.d/next/macOS/2019-04-29-10-54-14.bpo-34602.Lrl2zU.rst b/Misc/NEWS.d/next/macOS/2019-04-29-10-54-14.bpo-34602.Lrl2zU.rst new file mode 100644 index 00000000000000..6f7ac881c82e2e --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2019-04-29-10-54-14.bpo-34602.Lrl2zU.rst @@ -0,0 +1,3 @@ +Avoid failures setting macOS stack resource limit with resource.setrlimit. +This reverts an earlier fix for bpo-18075 which forced a non-default stack +size when building the interpreter executable on macOS. diff --git a/configure b/configure index 8d9c73d1c386bd..e6e4007351591a 100755 --- a/configure +++ b/configure @@ -9542,12 +9542,6 @@ then # -u libsys_s pulls in all symbols in libsys Darwin/*) LINKFORSHARED="$extra_undefs -framework CoreFoundation" - - # Issue #18075: the default maximum stack size (8MBytes) is too - # small for the default recursion limit. Increase the stack size - # to ensure that tests don't crash - LINKFORSHARED="-Wl,-stack_size,1000000 $LINKFORSHARED" - if test "$enable_framework" then LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' diff --git a/configure.ac b/configure.ac index 7d2eff0d94c34f..a02597da2db5ea 100644 --- a/configure.ac +++ b/configure.ac @@ -2701,12 +2701,6 @@ then # -u libsys_s pulls in all symbols in libsys Darwin/*) LINKFORSHARED="$extra_undefs -framework CoreFoundation" - - # Issue #18075: the default maximum stack size (8MBytes) is too - # small for the default recursion limit. Increase the stack size - # to ensure that tests don't crash - LINKFORSHARED="-Wl,-stack_size,1000000 $LINKFORSHARED" - if test "$enable_framework" then LINKFORSHARED="$LINKFORSHARED "'$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' From 9bdd6d1c2a61e0a27dba063e9eccf70e295f73a4 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Mon, 29 Apr 2019 15:11:53 -0400 Subject: [PATCH 118/212] Prevent macOS installer build failure if ABIFLAGS is empty. (GH-13012) --- Mac/BuildScript/build-installer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 2e3a61ec71d183..fb43da5478f728 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -1207,7 +1207,8 @@ def buildPython(): if ln.startswith('VERSION='): VERSION=ln.split()[1] if ln.startswith('ABIFLAGS='): - ABIFLAGS=ln.split()[1] + ABIFLAGS=ln.split() + ABIFLAGS=ABIFLAGS[1] if len(ABIFLAGS) > 1 else '' if ln.startswith('LDVERSION='): LDVERSION=ln.split()[1] fp.close() @@ -1258,7 +1259,8 @@ def buildPython(): import pprint if getVersionMajorMinor() >= (3, 6): # XXX this is extra-fragile - path = os.path.join(path_to_lib, '_sysconfigdata_m_darwin_darwin.py') + path = os.path.join(path_to_lib, + '_sysconfigdata_%s_darwin_darwin.py' % (ABIFLAGS,)) else: path = os.path.join(path_to_lib, '_sysconfigdata.py') fp = open(path, 'r') From 81c5a905951aaf46f292eb459c32649c0b74ef61 Mon Sep 17 00:00:00 2001 From: Marco Rougeth Date: Tue, 30 Apr 2019 00:23:28 +0100 Subject: [PATCH 119/212] bpo-36232: Improve error message on dbm.open() when the db doesn't exist (GH-12060) --- Lib/dbm/__init__.py | 3 ++- .../next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst | 2 +- .../next/Library/2019-04-06-20-25-25.bpo-36232.SClmhb.rst | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-06-20-25-25.bpo-36232.SClmhb.rst diff --git a/Lib/dbm/__init__.py b/Lib/dbm/__init__.py index 6831a844073740..f65da521af4da8 100644 --- a/Lib/dbm/__init__.py +++ b/Lib/dbm/__init__.py @@ -82,7 +82,8 @@ def open(file, flag='r', mode=0o666): # file doesn't exist and the new flag was used so use default type mod = _defaultmod else: - raise error[0]("need 'c' or 'n' flag to open new db") + raise error[0]("db file doesn't exist; " + "use 'c' or 'n' flag to create a new db") elif result == "": # db type cannot be determined raise error[0]("db type could not be determined") diff --git a/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst b/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst index a43504839c6fff..8d1f9d940cc61c 100644 --- a/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst +++ b/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst @@ -1,4 +1,4 @@ Calling ``stop()`` on an unstarted or stopped :func:`unittest.mock.patch` object will now return `None` instead of raising :exc:`RuntimeError`, making the method idempotent. -Patch byKarthikeyan Singaravelan. +Patch by Karthikeyan Singaravelan. diff --git a/Misc/NEWS.d/next/Library/2019-04-06-20-25-25.bpo-36232.SClmhb.rst b/Misc/NEWS.d/next/Library/2019-04-06-20-25-25.bpo-36232.SClmhb.rst new file mode 100644 index 00000000000000..25290be7c9c5ac --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-06-20-25-25.bpo-36232.SClmhb.rst @@ -0,0 +1,2 @@ +Improve error message when trying to open existing DBM database that +actually doesn't exist. Patch by Marco Rougeth. From d5d2b4546939b98244708e5bb0cfccd55b99d244 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Tue, 30 Apr 2019 02:01:14 +0100 Subject: [PATCH 120/212] bpo-36751: Deprecate getfullargspec and report positional-only args as regular args (GH-13016) * bpo-36751: Deprecate getfullargspec and report positional-only args as regular args * Use inspect.signature in testhelpers --- Doc/library/inspect.rst | 5 ++ Doc/whatsnew/3.8.rst | 4 + Lib/inspect.py | 43 +++++------ Lib/test/test_inspect.py | 76 ++++++++++--------- Lib/unittest/test/testmock/testhelpers.py | 4 +- .../2019-04-29-23-30-21.bpo-36751.3NCRbm.rst | 3 + 6 files changed, 74 insertions(+), 61 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-29-23-30-21.bpo-36751.3NCRbm.rst diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 81824ddc1e54db..d12f122a57b599 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -948,6 +948,11 @@ Classes and functions APIs. This function is retained primarily for use in code that needs to maintain compatibility with the Python 2 ``inspect`` module API. + .. deprecated:: 3.8 + Use :func:`signature` and + :ref:`Signature Object `, which provide a + better introspecting API for callables. + .. versionchanged:: 3.4 This function is now based on :func:`signature`, but still ignores ``__wrapped__`` attributes and includes the already bound first diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index ac57335221c49b..bbc55ddd63418d 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -726,6 +726,10 @@ Deprecated `. (Contributed by Serhiy Storchaka in :issue:`36492`.) +* The function :func:`~inspect.getfullargspec` in the :mod:`inspect` + module is deprecated in favor of the :func:`inspect.signature` + API. (Contributed by Pablo Galindo in :issue:`36751`.) + API and Feature Removals ======================== diff --git a/Lib/inspect.py b/Lib/inspect.py index 3201e794fb37f7..fffca22357a928 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1081,16 +1081,15 @@ def getargspec(func): warnings.warn("inspect.getargspec() is deprecated since Python 3.0, " "use inspect.signature() or inspect.getfullargspec()", DeprecationWarning, stacklevel=2) - args, varargs, varkw, defaults, posonlyargs, kwonlyargs, \ - kwonlydefaults, ann = getfullargspec(func) - if posonlyargs or kwonlyargs or ann: - raise ValueError("Function has positional-only, keyword-only parameters" - " or annotations, use getfullargspec() API which can" - " support them") + args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ + getfullargspec(func) + if kwonlyargs or ann: + raise ValueError("Function has keyword-only parameters or annotations" + ", use inspect.signature() API which can support them") return ArgSpec(args, varargs, varkw, defaults) FullArgSpec = namedtuple('FullArgSpec', - 'args, varargs, varkw, defaults, posonlyargs, kwonlyargs, kwonlydefaults, annotations') + 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations') def getfullargspec(func): """Get the names and default values of a callable object's parameters. @@ -1104,11 +1103,16 @@ def getfullargspec(func): 'kwonlydefaults' is a dictionary mapping names from kwonlyargs to defaults. 'annotations' is a dictionary mapping parameter names to annotations. + .. deprecated:: 3.8 + Use inspect.signature() instead of inspect.getfullargspec(). + Notable differences from inspect.signature(): - the "self" parameter is always reported, even for bound methods - wrapper chains defined by __wrapped__ *not* unwrapped automatically """ + warnings.warn("Use inspect.signature() instead of inspect.getfullargspec()", + DeprecationWarning) try: # Re: `skip_bound_arg=False` # @@ -1182,8 +1186,8 @@ def getfullargspec(func): # compatibility with 'func.__defaults__' defaults = None - return FullArgSpec(args, varargs, varkw, defaults, - posonlyargs, kwonlyargs, kwdefaults, annotations) + return FullArgSpec(posonlyargs + args, varargs, varkw, defaults, + kwonlyargs, kwdefaults, annotations) ArgInfo = namedtuple('ArgInfo', 'args varargs keywords locals') @@ -1214,8 +1218,7 @@ def _formatannotation(annotation): return _formatannotation def formatargspec(args, varargs=None, varkw=None, defaults=None, - posonlyargs=(), kwonlyargs=(), kwonlydefaults={}, - annotations={}, + kwonlyargs=(), kwonlydefaults={}, annotations={}, formatarg=str, formatvarargs=lambda name: '*' + name, formatvarkw=lambda name: '**' + name, @@ -1248,17 +1251,12 @@ def formatargandannotation(arg): return result specs = [] if defaults: - firstdefault = len(posonlyargs) + len(args) - len(defaults) - posonly_left = len(posonlyargs) - for i, arg in enumerate([*posonlyargs, *args]): + firstdefault = len(args) - len(defaults) + for i, arg in enumerate(args): spec = formatargandannotation(arg) if defaults and i >= firstdefault: spec = spec + formatvalue(defaults[i - firstdefault]) specs.append(spec) - posonly_left -= 1 - if posonlyargs and posonly_left == 0: - specs.append('/') - if varargs is not None: specs.append(formatvarargs(formatargandannotation(varargs))) else: @@ -1346,8 +1344,7 @@ def getcallargs(*func_and_positional, **named): func = func_and_positional[0] positional = func_and_positional[1:] spec = getfullargspec(func) - (args, varargs, varkw, defaults, posonlyargs, - kwonlyargs, kwonlydefaults, ann) = spec + args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = spec f_name = func.__name__ arg2value = {} @@ -1356,16 +1353,12 @@ def getcallargs(*func_and_positional, **named): # implicit 'self' (or 'cls' for classmethods) argument positional = (func.__self__,) + positional num_pos = len(positional) - num_posonlyargs = len(posonlyargs) num_args = len(args) num_defaults = len(defaults) if defaults else 0 - n = min(num_pos, num_posonlyargs) - for i in range(num_posonlyargs): - arg2value[posonlyargs[i]] = positional[i] n = min(num_pos, num_args) for i in range(n): - arg2value[args[i]] = positional[num_posonlyargs+i] + arg2value[args[i]] = positional[i] if varargs: arg2value[varargs] = tuple(positional[n:]) possible_kwargs = set(args + kwonlyargs) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 06f8d69a579f0e..3c825b00e5e4a7 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -766,28 +766,29 @@ def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None, posonlyargs_e=[], kwonlyargs_e=[], kwonlydefaults_e=None, ann_e={}, formatted=None): - args, varargs, varkw, defaults, posonlyargs, kwonlyargs, kwonlydefaults, ann = \ - inspect.getfullargspec(routine) + with self.assertWarns(DeprecationWarning): + args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ + inspect.getfullargspec(routine) self.assertEqual(args, args_e) self.assertEqual(varargs, varargs_e) self.assertEqual(varkw, varkw_e) self.assertEqual(defaults, defaults_e) - self.assertEqual(posonlyargs, posonlyargs_e) self.assertEqual(kwonlyargs, kwonlyargs_e) self.assertEqual(kwonlydefaults, kwonlydefaults_e) self.assertEqual(ann, ann_e) if formatted is not None: with self.assertWarns(DeprecationWarning): self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults, - posonlyargs, kwonlyargs, - kwonlydefaults, ann), + kwonlyargs, kwonlydefaults, ann), formatted) def test_getargspec(self): self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)') - self.assertRaises(ValueError, self.assertArgSpecEquals, - mod.spam, []) + self.assertArgSpecEquals(mod.spam, + ['a', 'b', 'c', 'd', 'e', 'f'], + 'g', 'h', (3, 4, 5), + '(a, b, c, d=3, e=4, f=5, *g, **h)') self.assertRaises(ValueError, self.assertArgSpecEquals, mod2.keyworded, []) @@ -811,25 +812,22 @@ def test_getfullargspec(self): kwonlyargs_e=['arg'], formatted='(*, arg)') - self.assertFullArgSpecEquals(mod2.all_markers, ['c', 'd'], - posonlyargs_e=['a', 'b'], + self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'], kwonlyargs_e=['e', 'f'], - formatted='(a, b, /, c, d, *, e, f)') + formatted='(a, b, c, d, *, e, f)') self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs, - ['c', 'd'], - posonlyargs_e=['a', 'b'], + ['a', 'b', 'c', 'd'], varargs_e='args', varkw_e='kwargs', kwonlyargs_e=['e', 'f'], - formatted='(a, b, /, c, d, *args, e, f, **kwargs)') + formatted='(a, b, c, d, *args, e, f, **kwargs)') - self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['c', 'd'], + self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'], defaults_e=(1,2,3), - posonlyargs_e=['a', 'b'], kwonlyargs_e=['e', 'f'], kwonlydefaults_e={'e': 4, 'f': 5}, - formatted='(a, b=1, /, c=2, d=3, *, e=4, f=5)') + formatted='(a, b=1, c=2, d=3, *, e=4, f=5)') def test_argspec_api_ignores_wrapped(self): # Issue 20684: low level introspection API must ignore __wrapped__ @@ -877,25 +875,27 @@ def test(): spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY) test.__signature__ = inspect.Signature(parameters=(spam_param,)) - self.assertFullArgSpecEquals(test, [], posonlyargs_e=['spam'], formatted='(spam, /)') + self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)') def test_getfullargspec_signature_annos(self): def test(a:'spam') -> 'ham': pass - spec = inspect.getfullargspec(test) + with self.assertWarns(DeprecationWarning): + spec = inspect.getfullargspec(test) self.assertEqual(test.__annotations__, spec.annotations) def test(): pass - spec = inspect.getfullargspec(test) + with self.assertWarns(DeprecationWarning): + spec = inspect.getfullargspec(test) self.assertEqual(test.__annotations__, spec.annotations) @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") def test_getfullargspec_builtin_methods(self): - self.assertFullArgSpecEquals(_pickle.Pickler.dump, [], - posonlyargs_e=['self', 'obj'], formatted='(self, obj, /)') + self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'], + formatted='(self, obj)') - self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, [], - posonlyargs_e=['self', 'obj'], formatted='(self, obj, /)') + self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'], + formatted='(self, obj)') self.assertFullArgSpecEquals( os.stat, @@ -910,7 +910,8 @@ def test_getfullargspec_builtin_methods(self): def test_getfullargspec_builtin_func(self): import _testcapi builtin = _testcapi.docstring_with_signature_with_defaults - spec = inspect.getfullargspec(builtin) + with self.assertWarns(DeprecationWarning): + spec = inspect.getfullargspec(builtin) self.assertEqual(spec.defaults[0], 'avocado') @cpython_only @@ -919,17 +920,20 @@ def test_getfullargspec_builtin_func(self): def test_getfullargspec_builtin_func_no_signature(self): import _testcapi builtin = _testcapi.docstring_no_signature - with self.assertRaises(TypeError): - inspect.getfullargspec(builtin) + with self.assertWarns(DeprecationWarning): + with self.assertRaises(TypeError): + inspect.getfullargspec(builtin) def test_getfullargspec_definition_order_preserved_on_kwonly(self): for fn in signatures_with_lexicographic_keyword_only_parameters(): - signature = inspect.getfullargspec(fn) + with self.assertWarns(DeprecationWarning): + signature = inspect.getfullargspec(fn) l = list(signature.kwonlyargs) sorted_l = sorted(l) self.assertTrue(l) self.assertEqual(l, sorted_l) - signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn) + with self.assertWarns(DeprecationWarning): + signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn) l = list(signature.kwonlyargs) self.assertEqual(l, unsorted_keyword_only_parameters) @@ -1386,8 +1390,9 @@ class TestGetcallargsFunctions(unittest.TestCase): def assertEqualCallArgs(self, func, call_params_string, locs=None): locs = dict(locs or {}, func=func) r1 = eval('func(%s)' % call_params_string, None, locs) - r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None, - locs) + with self.assertWarns(DeprecationWarning): + r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None, + locs) self.assertEqual(r1, r2) def assertEqualException(self, func, call_param_string, locs=None): @@ -1399,8 +1404,9 @@ def assertEqualException(self, func, call_param_string, locs=None): else: self.fail('Exception not raised') try: - eval('inspect.getcallargs(func, %s)' % call_param_string, None, - locs) + with self.assertWarns(DeprecationWarning): + eval('inspect.getcallargs(func, %s)' % call_param_string, None, + locs) except Exception as e: ex2 = e else: @@ -1558,14 +1564,16 @@ def test_errors(self): def f5(*, a): pass with self.assertRaisesRegex(TypeError, 'missing 1 required keyword-only'): - inspect.getcallargs(f5) + with self.assertWarns(DeprecationWarning): + inspect.getcallargs(f5) # issue20817: def f6(a, b, c): pass with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"): - inspect.getcallargs(f6) + with self.assertWarns(DeprecationWarning): + inspect.getcallargs(f6) # bpo-33197 with self.assertRaisesRegex(ValueError, diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py index 0d03108aca5570..e321976aeb9f1a 100644 --- a/Lib/unittest/test/testmock/testhelpers.py +++ b/Lib/unittest/test/testmock/testhelpers.py @@ -920,7 +920,7 @@ def myfunc(x, y): mock(1, 2) mock(x=1, y=2) - self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(myfunc)) + self.assertEqual(inspect.signature(mock), inspect.signature(myfunc)) self.assertEqual(mock.mock_calls, [call(1, 2), call(x=1, y=2)]) self.assertRaises(TypeError, mock, 1) @@ -934,7 +934,7 @@ def foo(a: int, b: int=10, *, c:int) -> int: mock(1, 2, c=3) mock(1, c=3) - self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(foo)) + self.assertEqual(inspect.signature(mock), inspect.signature(foo)) self.assertEqual(mock.mock_calls, [call(1, 2, c=3), call(1, c=3)]) self.assertRaises(TypeError, mock, 1) self.assertRaises(TypeError, mock, 1, 2, 3, c=4) diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-29-23-30-21.bpo-36751.3NCRbm.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-29-23-30-21.bpo-36751.3NCRbm.rst new file mode 100644 index 00000000000000..5b16aaa0b0c30e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-04-29-23-30-21.bpo-36751.3NCRbm.rst @@ -0,0 +1,3 @@ +The :func:`~inspect.getfullargspec` function in the :mod:`inspect` module is +deprecated in favor of the :func:`inspect.signature` API. Contributed by +Pablo Galindo. From ee0309f3d83ab9ffa02542bcf45ece84f4fb265e Mon Sep 17 00:00:00 2001 From: Utkarsh Gupta Date: Tue, 30 Apr 2019 02:20:06 +0000 Subject: [PATCH 121/212] closes bpo-35329: Change 'Package' to 'package' in accordance with PEP8. (GH-13008) --- Doc/tutorial/modules.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/tutorial/modules.rst b/Doc/tutorial/modules.rst index fd594fd97af4d4..d0a68faa2ee250 100644 --- a/Doc/tutorial/modules.rst +++ b/Doc/tutorial/modules.rst @@ -523,7 +523,7 @@ Although certain modules are designed to export only names that follow certain patterns when you use ``import *``, it is still considered bad practice in production code. -Remember, there is nothing wrong with using ``from Package import +Remember, there is nothing wrong with using ``from package import specific_submodule``! In fact, this is the recommended notation unless the importing module needs to use submodules with the same name from different packages. From b0a2c0fa83f9b79616ccf451687096542de1e6f8 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 29 Apr 2019 23:47:33 -0700 Subject: [PATCH 122/212] bpo-36018: Test idempotence. Test two methods against one-another. (GH-13021) --- Lib/test/test_statistics.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 0a967055f0fe6c..903ee8f343cb1c 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -2158,6 +2158,20 @@ def test_specific_cases(self): result = quantiles(map(datatype, data), n=n) self.assertTrue(all(type(x) == datatype) for x in result) self.assertEqual(result, list(map(datatype, expected))) + # Quantiles should be idempotent + if len(expected) >= 2: + self.assertEqual(quantiles(expected, n=n), expected) + # Cross-check against other methods + if len(data) >= n: + # After end caps are added, method='inclusive' should + # give the same result as method='exclusive' whenever + # there are more data points than desired cut points. + padded_data = [min(data) - 1000] + data + [max(data) + 1000] + self.assertEqual( + quantiles(data, n=n), + quantiles(padded_data, n=n, method='inclusive'), + (n, data), + ) # Invariant under tranlation and scaling def f(x): return 3.5 * x - 1234.675 @@ -2219,6 +2233,15 @@ def f(x): actual = quantiles(statistics.NormalDist(), n=n, method="inclusive") self.assertTrue(all(math.isclose(e, a, abs_tol=0.0001) for e, a in zip(expected, actual))) + # Whenever n is smaller than the number of data points, running + # method='inclusive' should give the same result as method='exclusive' + # after the two included extreme points are removed. + data = [random.randrange(10_000) for i in range(501)] + actual = quantiles(data, n=32, method='inclusive') + data.remove(min(data)) + data.remove(max(data)) + expected = quantiles(data, n=32) + self.assertEqual(expected, actual) def test_equal_inputs(self): quantiles = statistics.quantiles From 3bbcc92577f8e616bc94c679040043bacd00ebf1 Mon Sep 17 00:00:00 2001 From: gescheit Date: Tue, 30 Apr 2019 10:54:30 +0300 Subject: [PATCH 123/212] bpo-25430: improve performance of IPNetwork.__contains__ (GH-1785) make a compare in bit-operation manner. --- Lib/ipaddress.py | 3 +-- .../next/Library/2019-04-15-12-22-09.bpo-25430.7_8kqc.rst | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-15-12-22-09.bpo-25430.7_8kqc.rst diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 909a55de4f197d..662d7373890761 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -697,8 +697,7 @@ def __contains__(self, other): # dealing with another address else: # address - return (int(self.network_address) <= int(other._ip) <= - int(self.broadcast_address)) + return other._ip & self.netmask._ip == self.network_address._ip def overlaps(self, other): """Tell if self is partly contained in other.""" diff --git a/Misc/NEWS.d/next/Library/2019-04-15-12-22-09.bpo-25430.7_8kqc.rst b/Misc/NEWS.d/next/Library/2019-04-15-12-22-09.bpo-25430.7_8kqc.rst new file mode 100644 index 00000000000000..922bdef56ec31e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-15-12-22-09.bpo-25430.7_8kqc.rst @@ -0,0 +1 @@ +improve performance of ``IPNetwork.__contains__()`` \ No newline at end of file From b84cb70880a0acfcbbaca7bcda405af08f94d269 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 30 Apr 2019 12:19:34 +0200 Subject: [PATCH 124/212] bpo-36734: Fix compilation of faulthandler.c on HP-UX (GH-12970) Initialize "stack_t current_stack" to zero using memset(). --- .../next/Library/2019-04-26-17-14-20.bpo-36734.p2MaiN.rst | 2 ++ Modules/faulthandler.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-26-17-14-20.bpo-36734.p2MaiN.rst diff --git a/Misc/NEWS.d/next/Library/2019-04-26-17-14-20.bpo-36734.p2MaiN.rst b/Misc/NEWS.d/next/Library/2019-04-26-17-14-20.bpo-36734.p2MaiN.rst new file mode 100644 index 00000000000000..09341990a63d17 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-26-17-14-20.bpo-36734.p2MaiN.rst @@ -0,0 +1,2 @@ +Fix compilation of ``faulthandler.c`` on HP-UX. Initialize ``stack_t +current_stack`` to zero using ``memset()``. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 30fe18695fec82..d45b8660ee65f7 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1370,7 +1370,8 @@ void _PyFaulthandler_Fini(void) #ifdef HAVE_SIGALTSTACK if (stack.ss_sp != NULL) { /* Fetch the current alt stack */ - stack_t current_stack = {}; + stack_t current_stack; + memset(¤t_stack, 0, sizeof(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. From d537ab0ff9767ef024f26246899728f0116b1ec3 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Tue, 30 Apr 2019 12:03:02 +0000 Subject: [PATCH 125/212] bpo-36742: Fixes handling of pre-normalization characters in urlsplit() (GH-13017) --- Lib/test/test_urlparse.py | 6 ++++++ Lib/urllib/parse.py | 11 +++++++---- .../Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index 0faf2bbb645924..d0365ecab72ccb 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -1011,6 +1011,12 @@ def test_urlsplit_normalization(self): self.assertIn('\u2100', denorm_chars) self.assertIn('\uFF03', denorm_chars) + # bpo-36742: Verify port separators are ignored when they + # existed prior to decomposition + urllib.parse.urlsplit('http://\u30d5\u309a:80') + with self.assertRaises(ValueError): + urllib.parse.urlsplit('http://\u30d5\u309a\ufe1380') + for scheme in ["http", "https", "ftp"]: for c in denorm_chars: url = "{}://netloc{}false.netloc/path".format(scheme, c) diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index fb518a97749ccb..dfba704144e9b4 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -402,13 +402,16 @@ def _checknetloc(netloc): # looking for characters like \u2100 that expand to 'a/c' # IDNA uses NFKC equivalence, so normalize for this check import unicodedata - netloc2 = unicodedata.normalize('NFKC', netloc) - if netloc == netloc2: + n = netloc.rpartition('@')[2] # ignore anything to the left of '@' + n = n.replace(':', '') # ignore characters already included + n = n.replace('#', '') # but not the surrounding text + n = n.replace('?', '') + netloc2 = unicodedata.normalize('NFKC', n) + if n == netloc2: return - _, _, netloc = netloc.rpartition('@') # anything to the left of '@' is okay for c in '/?#@:': if c in netloc2: - raise ValueError("netloc '" + netloc2 + "' contains invalid " + + raise ValueError("netloc '" + netloc + "' contains invalid " + "characters under NFKC normalization") def urlsplit(url, scheme='', allow_fragments=True): diff --git a/Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst b/Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst new file mode 100644 index 00000000000000..d729ed2f3cd507 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst @@ -0,0 +1 @@ +Fixes mishandling of pre-normalization characters in urlsplit(). From 0df635c7f8aa69e56a092bd4f142f0f164741ab2 Mon Sep 17 00:00:00 2001 From: Mario Corchero Date: Tue, 30 Apr 2019 19:56:36 +0100 Subject: [PATCH 126/212] Don't report deleted attributes in __dir__ (GH#10148) When an attribute is deleted from a Mock, a sentinel is added rather than just deleting the attribute. This commit checks for such sentinels when returning the child mocks in the __dir__ method as users won't expect deleted attributes to appear when performing dir(mock). --- Lib/unittest/mock.py | 6 ++++-- Lib/unittest/test/testmock/testmock.py | 9 +++++++++ .../Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 1636073ff00935..997af717256646 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -684,12 +684,14 @@ def __dir__(self): extras = self._mock_methods or [] from_type = dir(type(self)) from_dict = list(self.__dict__) + from_child_mocks = [ + m_name for m_name, m_value in self._mock_children.items() + if m_value is not _deleted] from_type = [e for e in from_type if not e.startswith('_')] from_dict = [e for e in from_dict if not e.startswith('_') or _is_magic(e)] - return sorted(set(extras + from_type + from_dict + - list(self._mock_children))) + return sorted(set(extras + from_type + from_dict + from_child_mocks)) def __setattr__(self, name, value): diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index bdaebbe66b74db..0e7e4a1d8c93fd 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -885,6 +885,15 @@ def test_filter_dir(self): patcher.stop() + def test_dir_does_not_include_deleted_attributes(self): + mock = Mock() + mock.child.return_value = 1 + + self.assertIn('child', dir(mock)) + del mock.child + self.assertNotIn('child', dir(mock)) + + def test_configure_mock(self): mock = Mock(foo='bar') self.assertEqual(mock.foo, 'bar') diff --git a/Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst b/Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst new file mode 100644 index 00000000000000..45a0729506e392 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst @@ -0,0 +1,2 @@ +Don't return deleted attributes when calling dir on a +:class:`unittest.mock.Mock`. From 463b82a3efe8a6a9f3924a5b37482e961dffe3b8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 1 May 2019 01:36:13 +0200 Subject: [PATCH 127/212] bpo-36763: Fix Py_SetStandardStreamEncoding() (GH-13028) Fix memory leak in Py_SetStandardStreamEncoding(): release memory if the function is called twice. --- .../next/C API/2019-05-01-00-42-08.bpo-36763.vghb86.rst | 2 ++ Python/coreconfig.c | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2019-05-01-00-42-08.bpo-36763.vghb86.rst diff --git a/Misc/NEWS.d/next/C API/2019-05-01-00-42-08.bpo-36763.vghb86.rst b/Misc/NEWS.d/next/C API/2019-05-01-00-42-08.bpo-36763.vghb86.rst new file mode 100644 index 00000000000000..1c34920827fc62 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-05-01-00-42-08.bpo-36763.vghb86.rst @@ -0,0 +1,2 @@ +Fix memory leak in :c:func:`Py_SetStandardStreamEncoding`: release memory if +the function is called twice. diff --git a/Python/coreconfig.c b/Python/coreconfig.c index d05beef2aa5526..471d5126f8038d 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -375,6 +375,7 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) * Py_Initialize hasn't been called yet. */ if (encoding) { + PyMem_RawFree(_Py_StandardStreamEncoding); _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding); if (!_Py_StandardStreamEncoding) { res = -2; @@ -382,11 +383,11 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) } } if (errors) { + PyMem_RawFree(_Py_StandardStreamErrors); _Py_StandardStreamErrors = _PyMem_RawStrdup(errors); if (!_Py_StandardStreamErrors) { - if (_Py_StandardStreamEncoding) { - PyMem_RawFree(_Py_StandardStreamEncoding); - } + PyMem_RawFree(_Py_StandardStreamEncoding); + _Py_StandardStreamEncoding = NULL; res = -3; goto done; } From 5f38b8407b071acd96da2c8cde411d0e26967735 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 1 May 2019 02:30:12 +0200 Subject: [PATCH 128/212] bpo-36763: Add _PyCoreConfig_SetArgv() (GH-13030) * Add 2 new config methods: * _PyCoreConfig_SetArgv() * _PyCoreConfig_SetWideArgv() * Add also an internal _PyCoreConfig_SetPyArgv() method. * Remove 'args' parameter from _PyCoreConfig_Read(). --- Include/internal/pycore_coreconfig.h | 14 +++++++-- Lib/test/pythoninfo.py | 3 +- Python/coreconfig.c | 45 +++++++++++++++++++++------- Python/pathconfig.c | 2 +- Python/pylifecycle.c | 11 ++++++- 5 files changed, 58 insertions(+), 17 deletions(-) diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index ac98e00159ce3b..b1d02eef4513d3 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -108,11 +108,21 @@ PyAPI_FUNC(int) _PyCoreConfig_Copy( PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPathConfig(_PyCoreConfig *config); PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPathConfig( const _PyCoreConfig *config); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config, - const _PyArgv *args); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config); PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config, _PyRuntimeState *runtime); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPyArgv( + _PyCoreConfig *config, + const _PyArgv *args); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetArgv( + _PyCoreConfig *config, + int argc, + char **argv); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideArgv(_PyCoreConfig *config, + int argc, + wchar_t **argv); + /* --- Function used for testing ---------------------------------- */ diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 580956633f4d40..e9edf675b9105a 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -602,8 +602,7 @@ def collect_gdbm(info_add): def collect_get_config(info_add): - # Dump global configuration variables, _PyCoreConfig - # and _PyMainInterpreterConfig + # Get global configuration variables, _PyPreConfig and _PyCoreConfig try: from _testinternalcapi import get_configs except ImportError: diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 471d5126f8038d..750676a4731c45 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -2003,8 +2003,7 @@ config_init_argv(_PyCoreConfig *config, const _PyPreCmdline *cmdline) static _PyInitError -core_read_precmdline(_PyCoreConfig *config, const _PyArgv *args, - _PyPreCmdline *precmdline) +core_read_precmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline) { _PyInitError err; @@ -2072,23 +2071,47 @@ config_read_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline) } +_PyInitError +_PyCoreConfig_SetPyArgv(_PyCoreConfig *config, const _PyArgv *args) +{ + return _PyArgv_AsWstrList(args, &config->argv); +} + + +_PyInitError +_PyCoreConfig_SetArgv(_PyCoreConfig *config, int argc, char **argv) +{ + _PyArgv args = { + .argc = argc, + .use_bytes_argv = 1, + .bytes_argv = argv, + .wchar_argv = NULL}; + return _PyCoreConfig_SetPyArgv(config, &args); +} + + +_PyInitError +_PyCoreConfig_SetWideArgv(_PyCoreConfig *config, int argc, wchar_t **argv) +{ + _PyArgv args = { + .argc = argc, + .use_bytes_argv = 0, + .bytes_argv = NULL, + .wchar_argv = argv}; + return _PyCoreConfig_SetPyArgv(config, &args); +} + + /* Read the configuration into _PyCoreConfig from: * Command line arguments * Environment variables * Py_xxx global configuration variables */ _PyInitError -_PyCoreConfig_Read(_PyCoreConfig *config, const _PyArgv *args) +_PyCoreConfig_Read(_PyCoreConfig *config) { _PyInitError err; - if (args) { - err = _PyArgv_AsWstrList(args, &config->argv); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - err = _Py_PreInitializeFromCoreConfig(config); if (_Py_INIT_FAILED(err)) { return err; @@ -2097,7 +2120,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyArgv *args) _PyCoreConfig_GetGlobalConfig(config); _PyPreCmdline precmdline = _PyPreCmdline_INIT; - err = core_read_precmdline(config, args, &precmdline); + err = core_read_precmdline(config, &precmdline); if (_Py_INIT_FAILED(err)) { goto done; } diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 10e141a47de02b..7fea7c3667865c 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -394,7 +394,7 @@ pathconfig_global_init(void) _PyInitError err; _PyCoreConfig config = _PyCoreConfig_INIT; - err = _PyCoreConfig_Read(&config, NULL); + err = _PyCoreConfig_Read(&config); if (_Py_INIT_FAILED(err)) { goto error; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index d93fe065558aa3..185d4066e50b1c 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -801,13 +801,22 @@ pyinit_coreconfig(_PyRuntimeState *runtime, const _PyArgv *args, PyInterpreterState **interp_p) { + _PyInitError err; + if (src_config) { if (_PyCoreConfig_Copy(config, src_config) < 0) { return _Py_INIT_NO_MEMORY(); } } - _PyInitError err = _PyCoreConfig_Read(config, args); + if (args) { + err = _PyCoreConfig_SetPyArgv(config, args); + if (_Py_INIT_FAILED(err)) { + return err; + } + } + + err = _PyCoreConfig_Read(config); if (_Py_INIT_FAILED(err)) { return err; } From c4e671eec20dfcb29b18596a89ef075f826c9f96 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Tue, 30 Apr 2019 19:12:21 -0700 Subject: [PATCH 129/212] bpo-30458: Disallow control chars in http URLs. (GH-12755) Disallow control chars in http URLs in urllib.urlopen. This addresses a potential security problem for applications that do not sanity check their URLs where http request headers could be injected. --- Lib/http/client.py | 14 ++++++ Lib/test/test_urllib.py | 49 +++++++++++++++++++ Lib/test/test_xmlrpc.py | 9 +++- .../2019-04-10-08-53-30.bpo-36276.51E-DA.rst | 1 + 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-36276.51E-DA.rst diff --git a/Lib/http/client.py b/Lib/http/client.py index 5a2225276b1acd..99d6a68cf42823 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -137,6 +137,16 @@ _is_legal_header_name = re.compile(rb'[^:\s][^:\r\n]*').fullmatch _is_illegal_header_value = re.compile(rb'\n(?![ \t])|\r(?![ \t\n])').search +# These characters are not allowed within HTTP URL paths. +# See https://tools.ietf.org/html/rfc3986#section-3.3 and the +# https://tools.ietf.org/html/rfc3986#appendix-A pchar definition. +# Prevents CVE-2019-9740. Includes control characters such as \r\n. +# We don't restrict chars above \x7f as putrequest() limits us to ASCII. +_contains_disallowed_url_pchar_re = re.compile('[\x00-\x20\x7f]') +# Arguably only these _should_ allowed: +# _is_allowed_url_pchars_re = re.compile(r"^[/!$&'()*+,;=:@%a-zA-Z0-9._~-]+$") +# We are more lenient for assumed real world compatibility purposes. + # We always set the Content-Length header for these methods because some # servers will otherwise respond with a 411 _METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'} @@ -1079,6 +1089,10 @@ def putrequest(self, method, url, skip_host=False, self._method = method if not url: url = '/' + # Prevent CVE-2019-9740. + if match := _contains_disallowed_url_pchar_re.search(url): + raise ValueError(f"URL can't contain control characters. {url!r} " + f"(found at least {match.group()!r})") request = '%s %s %s' % (method, url, self._http_vsn_str) # Non-ASCII characters should have been eliminated earlier diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index 2ac73b58d83206..e87c85b92876ab 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -329,6 +329,55 @@ def test_willclose(self): finally: self.unfakehttp() + def test_url_with_control_char_rejected(self): + for char_no in list(range(0, 0x21)) + [0x7f]: + char = chr(char_no) + schemeless_url = f"//localhost:7777/test{char}/" + self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello.") + try: + # We explicitly test urllib.request.urlopen() instead of the top + # level 'def urlopen()' function defined in this... (quite ugly) + # test suite. They use different url opening codepaths. Plain + # urlopen uses FancyURLOpener which goes via a codepath that + # calls urllib.parse.quote() on the URL which makes all of the + # above attempts at injection within the url _path_ safe. + escaped_char_repr = repr(char).replace('\\', r'\\') + with self.assertRaisesRegex( + ValueError, f"contain control.*{escaped_char_repr}"): + urllib.request.urlopen(f"http:{schemeless_url}") + with self.assertRaisesRegex( + ValueError, f"contain control.*{escaped_char_repr}"): + urllib.request.urlopen(f"https:{schemeless_url}") + # This code path quotes the URL so there is no injection. + resp = urlopen(f"http:{schemeless_url}") + self.assertNotIn(char, resp.geturl()) + finally: + self.unfakehttp() + + def test_url_with_newline_header_injection_rejected(self): + self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello.") + host = "localhost:7777?a=1 HTTP/1.1\r\nX-injected: header\r\nTEST: 123" + schemeless_url = "//" + host + ":8080/test/?test=a" + try: + # We explicitly test urllib.request.urlopen() instead of the top + # level 'def urlopen()' function defined in this... (quite ugly) + # test suite. They use different url opening codepaths. Plain + # urlopen uses FancyURLOpener which goes via a codepath that + # calls urllib.parse.quote() on the URL which makes all of the + # above attempts at injection within the url _path_ safe. + with self.assertRaisesRegex( + ValueError, r"contain control.*\\r.*(found at least . .)"): + urllib.request.urlopen(f"http:{schemeless_url}") + with self.assertRaisesRegex(ValueError, r"contain control.*\\n"): + urllib.request.urlopen(f"https:{schemeless_url}") + # This code path quotes the URL so there is no injection. + resp = urlopen(f"http:{schemeless_url}") + self.assertNotIn(' ', resp.geturl()) + self.assertNotIn('\r', resp.geturl()) + self.assertNotIn('\n', resp.geturl()) + finally: + self.unfakehttp() + def test_read_0_9(self): # "0.9" response accepted (but not "simple responses" without # a status line) diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index 9c8b6958c620ce..52bacc1eafa789 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -943,8 +943,13 @@ def test_unicode_host(self): def test_partial_post(self): # Check that a partial POST doesn't make the server loop: issue #14001. - with contextlib.closing(http.client.HTTPConnection(ADDR, PORT)) as conn: - conn.request('POST', '/RPC2 HTTP/1.0\r\nContent-Length: 100\r\n\r\nbye') + with contextlib.closing(socket.create_connection((ADDR, PORT))) as conn: + conn.send('POST /RPC2 HTTP/1.0\r\n' + 'Content-Length: 100\r\n\r\n' + 'bye HTTP/1.1\r\n' + f'Host: {ADDR}:{PORT}\r\n' + 'Accept-Encoding: identity\r\n' + 'Content-Length: 0\r\n\r\n'.encode('ascii')) def test_context_manager(self): with xmlrpclib.ServerProxy(URL) as server: diff --git a/Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-36276.51E-DA.rst b/Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-36276.51E-DA.rst new file mode 100644 index 00000000000000..4fed4d545040e9 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-36276.51E-DA.rst @@ -0,0 +1 @@ +Address CVE-2019-9740 by disallowing URL paths with embedded whitespace or control characters through into the underlying http client request. Such potentially malicious header injection URLs now cause a ValueError to be raised. \ No newline at end of file From db7197543112954b0912e3d46e39fefcb1c3b950 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 1 May 2019 05:35:33 +0200 Subject: [PATCH 130/212] bpo-36763: Rework _PyInitError API (GH-13031) * Remove _PyInitError.user_err field and _Py_INIT_USER_ERR() macro: use _Py_INIT_ERR() instead. _Py_ExitInitError() now longer calls abort() on error: exit with exit code 1 instead. * Add _PyInitError._type private field. * exitcode field type is now unsigned int on Windows. * Rename prefix field to _func. * Rename msg field to err_msg. --- Include/cpython/coreconfig.h | 43 +++++++++++++++++++++++------------- Modules/getpath.c | 4 ++-- Modules/main.c | 2 +- Python/bootstrap_hash.c | 4 ++-- Python/coreconfig.c | 17 +++++++------- Python/frozenmain.c | 4 +--- Python/preconfig.c | 10 ++++----- Python/pylifecycle.c | 18 ++++++++------- 8 files changed, 57 insertions(+), 45 deletions(-) diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index ed2f09f933b23a..5743bf5d0fa4ac 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -8,10 +8,18 @@ extern "C" { /* --- _PyInitError ----------------------------------------------- */ typedef struct { - const char *prefix; - const char *msg; - int user_err; + enum { + _Py_INIT_ERR_TYPE_OK=0, + _Py_INIT_ERR_TYPE_ERROR=1, + _Py_INIT_ERR_TYPE_EXIT=2 + } _type; + const char *_func; + const char *err_msg; +#ifdef MS_WINDOWS + unsigned int exitcode; +#else int exitcode; +#endif } _PyInitError; /* Almost all errors causing Python initialization to fail */ @@ -23,20 +31,25 @@ typedef struct { #endif #define _Py_INIT_OK() \ - (_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0, .exitcode = -1} -#define _Py_INIT_ERR(MSG) \ - (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 0, .exitcode = -1} -/* Error that can be fixed by the user like invalid input parameter. - Don't abort() the process on such error. */ -#define _Py_INIT_USER_ERR(MSG) \ - (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 1, .exitcode = -1} -#define _Py_INIT_NO_MEMORY() _Py_INIT_USER_ERR("memory allocation failed") + (_PyInitError){._type = _Py_INIT_ERR_TYPE_OK,} + /* other fields are set to 0 */ +#define _Py_INIT_ERR(ERR_MSG) \ + (_PyInitError){ \ + ._type = _Py_INIT_ERR_TYPE_ERROR, \ + ._func = _Py_INIT_GET_FUNC(), \ + .err_msg = (ERR_MSG)} + /* other fields are set to 0 */ +#define _Py_INIT_NO_MEMORY() _Py_INIT_ERR("memory allocation failed") #define _Py_INIT_EXIT(EXITCODE) \ - (_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0, .exitcode = (EXITCODE)} -#define _Py_INIT_HAS_EXITCODE(err) \ - (err.exitcode != -1) + (_PyInitError){ \ + ._type = _Py_INIT_ERR_TYPE_EXIT, \ + .exitcode = (EXITCODE)} +#define _Py_INIT_IS_ERROR(err) \ + (err._type == _Py_INIT_ERR_TYPE_ERROR) +#define _Py_INIT_IS_EXIT(err) \ + (err._type == _Py_INIT_ERR_TYPE_EXIT) #define _Py_INIT_FAILED(err) \ - (err.msg != NULL || _Py_INIT_HAS_EXITCODE(err)) + (err._type != _Py_INIT_ERR_TYPE_OK) /* --- _PyWstrList ------------------------------------------------ */ diff --git a/Modules/getpath.c b/Modules/getpath.c index dd188c612893a9..3991ad719c1ed4 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -114,10 +114,10 @@ extern "C" { #define DECODE_LOCALE_ERR(NAME, LEN) \ ((LEN) == (size_t)-2) \ - ? _Py_INIT_USER_ERR("cannot decode " NAME) \ + ? _Py_INIT_ERR("cannot decode " NAME) \ : _Py_INIT_NO_MEMORY() -#define PATHLEN_ERR() _Py_INIT_USER_ERR("path configuration: path too long") +#define PATHLEN_ERR() _Py_INIT_ERR("path configuration: path too long") typedef struct { wchar_t *path_env; /* PATH environment variable */ diff --git a/Modules/main.c b/Modules/main.c index 68f0b99c9fbbf4..575683cd7f889f 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -570,7 +570,7 @@ exit_sigint(void) static void _Py_NO_RETURN pymain_exit_error(_PyInitError err) { - if (_Py_INIT_HAS_EXITCODE(err)) { + if (_Py_INIT_IS_EXIT(err)) { /* If it's an error rather than a regular exit, leave Python runtime alive: _Py_ExitInitError() uses the current exception and use sys.stdout in this case. */ diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index 35d9b7f24a912f..dd752b86094d4b 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -578,8 +578,8 @@ _Py_HashRandomization_Init(const _PyCoreConfig *config) pyurandom() is non-blocking mode (blocking=0): see the PEP 524. */ res = pyurandom(secret, secret_size, 0, 0); if (res < 0) { - return _Py_INIT_USER_ERR("failed to get random numbers " - "to initialize Python"); + return _Py_INIT_ERR("failed to get random numbers " + "to initialize Python"); } } return _Py_INIT_OK(); diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 750676a4731c45..4bfe745ce449d0 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -475,7 +475,7 @@ Py_GetArgcArgv(int *argc, wchar_t ***argv) #define DECODE_LOCALE_ERR(NAME, LEN) \ (((LEN) == -2) \ - ? _Py_INIT_USER_ERR("cannot decode " NAME) \ + ? _Py_INIT_ERR("cannot decode " NAME) \ : _Py_INIT_NO_MEMORY()) /* Free memory allocated in config, but don't clear all attributes */ @@ -1018,8 +1018,8 @@ config_init_hash_seed(_PyCoreConfig *config) || seed > 4294967295UL || (errno == ERANGE && seed == ULONG_MAX)) { - return _Py_INIT_USER_ERR("PYTHONHASHSEED must be \"random\" " - "or an integer in range [0; 4294967295]"); + return _Py_INIT_ERR("PYTHONHASHSEED must be \"random\" " + "or an integer in range [0; 4294967295]"); } /* Use a specific hash */ config->use_hash_seed = 1; @@ -1129,8 +1129,7 @@ config_init_tracemalloc(_PyCoreConfig *config) valid = 0; } if (!valid) { - return _Py_INIT_USER_ERR("PYTHONTRACEMALLOC: invalid number " - "of frames"); + return _Py_INIT_ERR("PYTHONTRACEMALLOC: invalid number of frames"); } config->tracemalloc = nframe; } @@ -1146,8 +1145,8 @@ config_init_tracemalloc(_PyCoreConfig *config) valid = 0; } if (!valid) { - return _Py_INIT_USER_ERR("-X tracemalloc=NFRAME: " - "invalid number of frames"); + return _Py_INIT_ERR("-X tracemalloc=NFRAME: " + "invalid number of frames"); } } else { @@ -1267,8 +1266,8 @@ config_get_locale_encoding(char **locale_encoding) #else const char *encoding = nl_langinfo(CODESET); if (!encoding || encoding[0] == '\0') { - return _Py_INIT_USER_ERR("failed to get the locale encoding: " - "nl_langinfo(CODESET) failed"); + return _Py_INIT_ERR("failed to get the locale encoding: " + "nl_langinfo(CODESET) failed"); } #endif *locale_encoding = _PyMem_RawStrdup(encoding); diff --git a/Python/frozenmain.c b/Python/frozenmain.c index 6554aa75b038f8..a777576ad78c8c 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -18,9 +18,7 @@ Py_FrozenMain(int argc, char **argv) { _PyInitError err = _PyRuntime_Initialize(); if (_Py_INIT_FAILED(err)) { - fprintf(stderr, "Fatal Python error: %s\n", err.msg); - fflush(stderr); - exit(1); + _Py_ExitInitError(err); } const char *p; diff --git a/Python/preconfig.c b/Python/preconfig.c index 78377cf6e3a26a..108cbc66606176 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -7,7 +7,7 @@ #define DECODE_LOCALE_ERR(NAME, LEN) \ (((LEN) == -2) \ - ? _Py_INIT_USER_ERR("cannot decode " NAME) \ + ? _Py_INIT_ERR("cannot decode " NAME) \ : _Py_INIT_NO_MEMORY()) @@ -526,7 +526,7 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline) config->utf8_mode = 0; } else { - return _Py_INIT_USER_ERR("invalid -X utf8 option value"); + return _Py_INIT_ERR("invalid -X utf8 option value"); } } else { @@ -544,8 +544,8 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline) config->utf8_mode = 0; } else { - return _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment " - "variable value"); + return _Py_INIT_ERR("invalid PYTHONUTF8 environment " + "variable value"); } return _Py_INIT_OK(); } @@ -831,7 +831,7 @@ _PyPreConfig_SetAllocator(_PyPreConfig *config) PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); if (_PyMem_SetupAllocators(config->allocator) < 0) { - return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator"); + return _Py_INIT_ERR("Unknown PYTHONMALLOC allocator"); } /* Copy the pre-configuration with the new allocator */ diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 185d4066e50b1c..c874a509aa559e 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1685,7 +1685,7 @@ initsite(void) PyObject *m; m = PyImport_ImportModule("site"); if (m == NULL) { - return _Py_INIT_USER_ERR("Failed to import the site module"); + return _Py_INIT_ERR("Failed to import the site module"); } Py_DECREF(m); return _Py_INIT_OK(); @@ -1872,8 +1872,7 @@ init_sys_streams(PyInterpreterState *interp) struct _Py_stat_struct sb; if (_Py_fstat_noraise(fileno(stdin), &sb) == 0 && S_ISDIR(sb.st_mode)) { - return _Py_INIT_USER_ERR(" is a directory, " - "cannot continue"); + return _Py_INIT_ERR(" is a directory, cannot continue"); } #endif @@ -2181,14 +2180,17 @@ Py_FatalError(const char *msg) void _Py_NO_RETURN _Py_ExitInitError(_PyInitError err) { - if (_Py_INIT_HAS_EXITCODE(err)) { + assert(_Py_INIT_FAILED(err)); + if (_Py_INIT_IS_EXIT(err)) { +#ifdef MS_WINDOWS + ExitProcess(err.exitcode); +#else exit(err.exitcode); +#endif } else { - /* On "user" error: exit with status 1. - For all other errors, call abort(). */ - int status = err.user_err ? 1 : -1; - fatal_error(err.prefix, err.msg, status); + assert(_Py_INIT_IS_ERROR(err)); + fatal_error(err._func, err.err_msg, 1); } } From 49e27f0afb02ce7b98ed5a4387238850117f4c7e Mon Sep 17 00:00:00 2001 From: Chris Withers Date: Wed, 1 May 2019 08:48:44 +0100 Subject: [PATCH 131/212] remove jython support from unittest.mock (GH#13033) --- Lib/unittest/mock.py | 11 ++--------- Lib/unittest/test/testmock/testmock.py | 15 --------------- Lib/unittest/test/testmock/testpatch.py | 1 - 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 997af717256646..721e91f8cbcbae 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -36,13 +36,6 @@ _builtins = {name for name in dir(builtins) if not name.startswith('_')} -BaseExceptions = (BaseException,) -if 'java' in sys.platform: - # jython - import java - BaseExceptions = (BaseException, java.lang.Throwable) - - FILTER_DIR = True # Workaround for issue #12370 @@ -57,8 +50,8 @@ def _is_instance_mock(obj): def _is_exception(obj): return ( - isinstance(obj, BaseExceptions) or - isinstance(obj, type) and issubclass(obj, BaseExceptions) + isinstance(obj, BaseException) or + isinstance(obj, type) and issubclass(obj, BaseException) ) diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index 0e7e4a1d8c93fd..9bef51abd87f51 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -184,21 +184,6 @@ def f(): mock.side_effect = ValueError('Bazinga!') self.assertRaisesRegex(ValueError, 'Bazinga!', mock) - @unittest.skipUnless('java' in sys.platform, - 'This test only applies to Jython') - def test_java_exception_side_effect(self): - import java - mock = Mock(side_effect=java.lang.RuntimeException("Boom!")) - - # can't use assertRaises with java exceptions - try: - mock(1, 2, fish=3) - except java.lang.RuntimeException: - pass - else: - self.fail('java exception not raised') - mock.assert_called_with(1,2, fish=3) - def test_reset_mock(self): parent = Mock() diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index 51c66fec67fc45..e5abd9bda489fc 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -1312,7 +1312,6 @@ def test(f, foo): def test_patch_multiple_create_mocks_different_order(self): - # bug revealed by Jython! original_f = Foo.f original_g = Foo.g From 2fc936ed24cf04ed32f6015a8aa78c8ea40da66b Mon Sep 17 00:00:00 2001 From: Xtreak Date: Wed, 1 May 2019 17:29:49 +0530 Subject: [PATCH 132/212] bpo-30458: Disable https related urllib tests on a build without ssl (GH-13032) These tests require an SSL enabled build. Skip these tests when python is built without SSL to fix test failures. https://bugs.python.org/issue30458 --- Lib/test/test_urllib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index e87c85b92876ab..c5b23f935b275b 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -329,6 +329,7 @@ def test_willclose(self): finally: self.unfakehttp() + @unittest.skipUnless(ssl, "ssl module required") def test_url_with_control_char_rejected(self): for char_no in list(range(0, 0x21)) + [0x7f]: char = chr(char_no) @@ -354,6 +355,7 @@ def test_url_with_control_char_rejected(self): finally: self.unfakehttp() + @unittest.skipUnless(ssl, "ssl module required") def test_url_with_newline_header_injection_rejected(self): self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello.") host = "localhost:7777?a=1 HTTP/1.1\r\nX-injected: header\r\nTEST: 123" From 1a9f0d8efded4bf37c864ed572beff28c43c7c77 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 1 May 2019 15:22:52 +0200 Subject: [PATCH 133/212] bpo-36763: Add _PyCoreConfig_SetString() (GH-13035) Add 3 new config methods: * _PyCoreConfig_SetString() * _PyCoreConfig_SetWideString() * _PyCoreConfig_SetWideStringFromString() Changes: * _PyCoreConfig_Copy() returns _PyInitError. * Add CONFIG_GET_ENV_DUP(). --- Include/internal/pycore_coreconfig.h | 12 +- Python/coreconfig.c | 384 ++++++++++++++++----------- Python/pylifecycle.c | 23 +- 3 files changed, 251 insertions(+), 168 deletions(-) diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index b1d02eef4513d3..8af310d2b0ceaf 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -102,16 +102,24 @@ PyAPI_FUNC(_PyInitError) _PyPreConfig_Write(_PyPreConfig *config); /* --- _PyCoreConfig ---------------------------------------------- */ PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *); -PyAPI_FUNC(int) _PyCoreConfig_Copy( +PyAPI_FUNC(_PyInitError) _PyCoreConfig_Copy( _PyCoreConfig *config, const _PyCoreConfig *config2); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetString( + char **config_str, + const char *str); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideString( + wchar_t **config_str, + const wchar_t *str); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideStringFromString( + wchar_t **config_str, + const char *str); PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPathConfig(_PyCoreConfig *config); PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPathConfig( const _PyCoreConfig *config); PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config); PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config, _PyRuntimeState *runtime); - PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPyArgv( _PyCoreConfig *config, const _PyArgv *args); diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 4bfe745ce449d0..7f388cbcdd0e06 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -520,34 +520,111 @@ _PyCoreConfig_Clear(_PyCoreConfig *config) } -int +/* Copy str into *config_str (duplicate the string) */ +_PyInitError +_PyCoreConfig_SetString(char **config_str, const char *str) +{ + char *str2; + if (str != NULL) { + str2 = _PyMem_RawStrdup(str); + if (str2 == NULL) { + return _Py_INIT_NO_MEMORY(); + } + } + else { + str2 = NULL; + } + PyMem_RawFree(*config_str); + *config_str = str2; + return _Py_INIT_OK(); +} + + +/* Copy str into *config_str (duplicate the string) */ +_PyInitError +_PyCoreConfig_SetWideString(wchar_t **config_str, const wchar_t *str) +{ + wchar_t *str2; + if (str != NULL) { + str2 = _PyMem_RawWcsdup(str); + if (str2 == NULL) { + return _Py_INIT_NO_MEMORY(); + } + } + else { + str2 = NULL; + } + PyMem_RawFree(*config_str); + *config_str = str2; + return _Py_INIT_OK(); +} + + +/* Decode str using Py_DecodeLocale() and set the result into *config_str */ +static _PyInitError +_PyCoreConfig_SetWideStringFromStringErr(wchar_t **config_str, const char *str, + const char *decode_err_msg) +{ + wchar_t *str2; + if (str != NULL) { + size_t len; + str2 = Py_DecodeLocale(str, &len); + if (str2 == NULL) { + if (len == (size_t)-2) { + return _Py_INIT_ERR(decode_err_msg); + } + else { + return _Py_INIT_NO_MEMORY(); + } + } + } + else { + str2 = NULL; + } + PyMem_RawFree(*config_str); + *config_str = str2; + return _Py_INIT_OK(); +} + + +_PyInitError +_PyCoreConfig_SetWideStringFromString(wchar_t **config_str, const char *str) +{ + return _PyCoreConfig_SetWideStringFromStringErr( + config_str, str, "cannot decode string"); +} + + +#define CONFIG_DECODE_LOCALE(config_str, str, NAME) \ + _PyCoreConfig_SetWideStringFromStringErr(config_str, str, \ + "cannot decode " NAME) + + +_PyInitError _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) { + _PyInitError err; _PyCoreConfig_Clear(config); #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR #define COPY_STR_ATTR(ATTR) \ do { \ - if (config2->ATTR != NULL) { \ - config->ATTR = _PyMem_RawStrdup(config2->ATTR); \ - if (config->ATTR == NULL) { \ - return -1; \ - } \ + err = _PyCoreConfig_SetString(&config->ATTR, config2->ATTR); \ + if (_Py_INIT_FAILED(err)) { \ + return err; \ } \ } while (0) #define COPY_WSTR_ATTR(ATTR) \ do { \ - if (config2->ATTR != NULL) { \ - config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \ - if (config->ATTR == NULL) { \ - return -1; \ - } \ + err = _PyCoreConfig_SetWideString(&config->ATTR, config2->ATTR); \ + if (_Py_INIT_FAILED(err)) { \ + return err; \ } \ } while (0) #define COPY_WSTRLIST(LIST) \ do { \ if (_PyWstrList_Copy(&config->LIST, &config2->LIST) < 0 ) { \ - return -1; \ + return _Py_INIT_NO_MEMORY(); \ } \ } while (0) @@ -617,7 +694,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) #undef COPY_STR_ATTR #undef COPY_WSTR_ATTR #undef COPY_WSTRLIST - return 0; + return _Py_INIT_OK(); } @@ -746,54 +823,44 @@ _PyCoreConfig_GetEnv(const _PyCoreConfig *config, const char *name) /* Get a copy of the environment variable as wchar_t*. Return 0 on success, but *dest can be NULL. Return -1 on memory allocation failure. Return -2 on decoding error. */ -static int +static _PyInitError _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, wchar_t **dest, - wchar_t *wname, char *name) + wchar_t *wname, char *name, + const char *decode_err_msg) { + assert(*dest == NULL); assert(config->use_environment >= 0); if (!config->use_environment) { *dest = NULL; - return 0; + return _Py_INIT_OK(); } #ifdef MS_WINDOWS const wchar_t *var = _wgetenv(wname); if (!var || var[0] == '\0') { *dest = NULL; - return 0; - } - - wchar_t *copy = _PyMem_RawWcsdup(var); - if (copy == NULL) { - return -1; + return _Py_INIT_OK(); } - *dest = copy; + return _PyCoreConfig_SetWideString(dest, var); #else const char *var = getenv(name); if (!var || var[0] == '\0') { *dest = NULL; - return 0; + return _Py_INIT_OK(); } - size_t len; - wchar_t *wvar = Py_DecodeLocale(var, &len); - if (!wvar) { - if (len == (size_t)-2) { - return -2; - } - else { - return -1; - } - } - *dest = wvar; + return _PyCoreConfig_SetWideStringFromStringErr(dest, var, decode_err_msg); #endif - return 0; } +#define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \ + _PyCoreConfig_GetEnvDup(CONFIG, DEST, WNAME, NAME, "cannot decode " NAME) + + static void _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config) { @@ -876,6 +943,7 @@ _PyCoreConfig_SetGlobalConfig(const _PyCoreConfig *config) static _PyInitError config_init_program_name(_PyCoreConfig *config) { + _PyInitError err; assert(config->program_name == NULL); /* If Py_SetProgramName() was called, use its value */ @@ -900,13 +968,11 @@ config_init_program_name(_PyCoreConfig *config) script. */ const char *p = _PyCoreConfig_GetEnv(config, "PYTHONEXECUTABLE"); if (p != NULL) { - size_t len; - wchar_t* program_name = Py_DecodeLocale(p, &len); - if (program_name == NULL) { - return DECODE_LOCALE_ERR("PYTHONEXECUTABLE environment " - "variable", (Py_ssize_t)len); + err = CONFIG_DECODE_LOCALE(&config->program_name, p, + "PYTHONEXECUTABLE environment variable"); + if (_Py_INIT_FAILED(err)) { + return err; } - config->program_name = program_name; return _Py_INIT_OK(); } #ifdef WITH_NEXT_FRAMEWORK @@ -916,13 +982,11 @@ config_init_program_name(_PyCoreConfig *config) /* Used by Mac/Tools/pythonw.c to forward * the argv0 of the stub executable */ - size_t len; - wchar_t* program_name = Py_DecodeLocale(pyvenv_launcher, &len); - if (program_name == NULL) { - return DECODE_LOCALE_ERR("__PYVENV_LAUNCHER__ environment " - "variable", (Py_ssize_t)len); + err = CONFIG_DECODE_LOCALE(&config->program_name, pyvenv_launcher, + "__PYVENV_LAUNCHER__ environment variable"); + if (_Py_INIT_FAILED(err)) { + return err; } - config->program_name = program_name; return _Py_INIT_OK(); } } @@ -931,9 +995,10 @@ config_init_program_name(_PyCoreConfig *config) /* Use argv[0] by default, if available */ if (config->program != NULL) { - config->program_name = _PyMem_RawWcsdup(config->program); - if (config->program_name == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetWideString(&config->program_name, + config->program); + if (_Py_INIT_FAILED(err)) { + return err; } return _Py_INIT_OK(); } @@ -944,9 +1009,9 @@ config_init_program_name(_PyCoreConfig *config) #else const wchar_t *default_program_name = L"python3"; #endif - config->program_name = _PyMem_RawWcsdup(default_program_name); - if (config->program_name == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetWideString(&config->program_name, default_program_name); + if (_Py_INIT_FAILED(err)) { + return err; } return _Py_INIT_OK(); } @@ -959,13 +1024,13 @@ config_init_executable(_PyCoreConfig *config) /* If Py_SetProgramFullPath() was called, use its value */ const wchar_t *program_full_path = _Py_path_config.program_full_path; if (program_full_path != NULL) { - config->executable = _PyMem_RawWcsdup(program_full_path); - if (config->executable == NULL) { - return _Py_INIT_NO_MEMORY(); + _PyInitError err = _PyCoreConfig_SetWideString(&config->executable, + program_full_path); + if (_Py_INIT_FAILED(err)) { + return err; } return _Py_INIT_OK(); } - return _Py_INIT_OK(); } @@ -985,20 +1050,15 @@ config_init_home(_PyCoreConfig *config) /* If Py_SetPythonHome() was called, use its value */ wchar_t *home = _Py_path_config.home; if (home) { - config->home = _PyMem_RawWcsdup(home); - if (config->home == NULL) { - return _Py_INIT_NO_MEMORY(); + _PyInitError err = _PyCoreConfig_SetWideString(&config->home, home); + if (_Py_INIT_FAILED(err)) { + return err; } return _Py_INIT_OK(); } - int res = _PyCoreConfig_GetEnvDup(config, &home, - L"PYTHONHOME", "PYTHONHOME"); - if (res < 0) { - return DECODE_LOCALE_ERR("PYTHONHOME", res); - } - config->home = home; - return _Py_INIT_OK(); + return CONFIG_GET_ENV_DUP(config, &config->home, + L"PYTHONHOME", "PYTHONHOME"); } @@ -1055,6 +1115,7 @@ config_wstr_to_int(const wchar_t *wstr, int *result) static _PyInitError config_read_env_vars(_PyCoreConfig *config) { + _PyInitError err; int use_env = config->use_environment; /* Get environment variables */ @@ -1094,17 +1155,15 @@ config_read_env_vars(_PyCoreConfig *config) } if (config->module_search_path_env == NULL) { - wchar_t *path; - int res = _PyCoreConfig_GetEnvDup(config, &path, - L"PYTHONPATH", "PYTHONPATH"); - if (res < 0) { - return DECODE_LOCALE_ERR("PYTHONPATH", res); + err = CONFIG_GET_ENV_DUP(config, &config->module_search_path_env, + L"PYTHONPATH", "PYTHONPATH"); + if (_Py_INIT_FAILED(err)) { + return err; } - config->module_search_path_env = path; } if (config->use_hash_seed < 0) { - _PyInitError err = config_init_hash_seed(config); + err = config_init_hash_seed(config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1174,24 +1233,16 @@ config_init_pycache_prefix(_PyCoreConfig *config) } } else { - // -X pycache_prefix= can cancel the env var + // PYTHONPYCACHEPREFIX env var ignored + // if "-X pycache_prefix=" option is used config->pycache_prefix = NULL; } + return _Py_INIT_OK(); } - else { - wchar_t *env; - int res = _PyCoreConfig_GetEnvDup(config, &env, - L"PYTHONPYCACHEPREFIX", - "PYTHONPYCACHEPREFIX"); - if (res < 0) { - return DECODE_LOCALE_ERR("PYTHONPYCACHEPREFIX", res); - } - if (env) { - config->pycache_prefix = env; - } - } - return _Py_INIT_OK(); + return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix, + L"PYTHONPYCACHEPREFIX", + "PYTHONPYCACHEPREFIX"); } @@ -1270,11 +1321,9 @@ config_get_locale_encoding(char **locale_encoding) "nl_langinfo(CODESET) failed"); } #endif - *locale_encoding = _PyMem_RawStrdup(encoding); - if (*locale_encoding == NULL) { - return _Py_INIT_NO_MEMORY(); - } - return _Py_INIT_OK(); + + assert(*locale_encoding == NULL); + return _PyCoreConfig_SetString(locale_encoding, encoding); } @@ -1282,19 +1331,23 @@ static _PyInitError config_init_stdio_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) { + _PyInitError err; + /* If Py_SetStandardStreamEncoding() have been called, use these parameters. */ if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) { - config->stdio_encoding = _PyMem_RawStrdup(_Py_StandardStreamEncoding); - if (config->stdio_encoding == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetString(&config->stdio_encoding, + _Py_StandardStreamEncoding); + if (_Py_INIT_FAILED(err)) { + return err; } } if (config->stdio_errors == NULL && _Py_StandardStreamErrors != NULL) { - config->stdio_errors = _PyMem_RawStrdup(_Py_StandardStreamErrors); - if (config->stdio_errors == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetString(&config->stdio_errors, + _Py_StandardStreamErrors); + if (_Py_INIT_FAILED(err)) { + return err; } } @@ -1305,27 +1358,30 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* PYTHONIOENCODING environment variable */ const char *opt = _PyCoreConfig_GetEnv(config, "PYTHONIOENCODING"); if (opt) { - char *pythonioencoding = _PyMem_RawStrdup(opt); - if (pythonioencoding == NULL) { - return _Py_INIT_NO_MEMORY(); + /* _PyCoreConfig_SetString() requires dest to be initialized to NULL */ + char *pythonioencoding = NULL; + err = _PyCoreConfig_SetString(&pythonioencoding, opt); + if (_Py_INIT_FAILED(err)) { + return err; } - char *err = strchr(pythonioencoding, ':'); - if (err) { - *err = '\0'; - err++; - if (!err[0]) { - err = NULL; + char *errors = strchr(pythonioencoding, ':'); + if (errors) { + *errors = '\0'; + errors++; + if (!errors[0]) { + errors = NULL; } } /* Does PYTHONIOENCODING contain an encoding? */ if (pythonioencoding[0]) { if (config->stdio_encoding == NULL) { - config->stdio_encoding = _PyMem_RawStrdup(pythonioencoding); - if (config->stdio_encoding == NULL) { + err = _PyCoreConfig_SetString(&config->stdio_encoding, + pythonioencoding); + if (_Py_INIT_FAILED(err)) { PyMem_RawFree(pythonioencoding); - return _Py_INIT_NO_MEMORY(); + return err; } } @@ -1333,16 +1389,16 @@ config_init_stdio_encoding(_PyCoreConfig *config, use "strict" error handler by default. PYTHONIOENCODING=latin1 behaves as PYTHONIOENCODING=latin1:strict. */ - if (!err) { - err = "strict"; + if (!errors) { + errors = "strict"; } } - if (config->stdio_errors == NULL && err != NULL) { - config->stdio_errors = _PyMem_RawStrdup(err); - if (config->stdio_errors == NULL) { + if (config->stdio_errors == NULL && errors != NULL) { + err = _PyCoreConfig_SetString(&config->stdio_errors, errors); + if (_Py_INIT_FAILED(err)) { PyMem_RawFree(pythonioencoding); - return _Py_INIT_NO_MEMORY(); + return err; } } @@ -1352,31 +1408,35 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* UTF-8 Mode uses UTF-8/surrogateescape */ if (preconfig->utf8_mode) { if (config->stdio_encoding == NULL) { - config->stdio_encoding = _PyMem_RawStrdup("utf-8"); - if (config->stdio_encoding == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetString(&config->stdio_encoding, + "utf-8"); + if (_Py_INIT_FAILED(err)) { + return err; } } if (config->stdio_errors == NULL) { - config->stdio_errors = _PyMem_RawStrdup("surrogateescape"); - if (config->stdio_errors == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetString(&config->stdio_errors, + "surrogateescape"); + if (_Py_INIT_FAILED(err)) { + return err; } } } /* Choose the default error handler based on the current locale. */ if (config->stdio_encoding == NULL) { - _PyInitError err = config_get_locale_encoding(&config->stdio_encoding); + err = config_get_locale_encoding(&config->stdio_encoding); if (_Py_INIT_FAILED(err)) { return err; } } if (config->stdio_errors == NULL) { const char *errors = config_get_stdio_errors(config); - config->stdio_errors = _PyMem_RawStrdup(errors); - if (config->stdio_errors == NULL) { - return _Py_INIT_NO_MEMORY(); + assert(errors != NULL); + + err = _PyCoreConfig_SetString(&config->stdio_errors, errors); + if (_Py_INIT_FAILED(err)) { + return err; } } @@ -1387,19 +1447,23 @@ config_init_stdio_encoding(_PyCoreConfig *config, static _PyInitError config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) { + _PyInitError err; + #ifdef MS_WINDOWS if (preconfig->legacy_windows_fs_encoding) { /* Legacy Windows filesystem encoding: mbcs/replace */ if (config->filesystem_encoding == NULL) { - config->filesystem_encoding = _PyMem_RawStrdup("mbcs"); - if (config->filesystem_encoding == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetString(&config->filesystem_encoding, + "mbcs"); + if (_Py_INIT_FAILED(err)) { + return err; } } if (config->filesystem_errors == NULL) { - config->filesystem_errors = _PyMem_RawStrdup("replace"); - if (config->filesystem_errors == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetString(&config->filesystem_errors, + "replace"); + if (_Py_INIT_FAILED(err)) { + return err; } } } @@ -1409,51 +1473,54 @@ config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) Note: UTF-8 Mode takes the same code path and the Legacy Windows FS encoding has the priortiy over UTF-8 Mode. */ if (config->filesystem_encoding == NULL) { - config->filesystem_encoding = _PyMem_RawStrdup("utf-8"); - if (config->filesystem_encoding == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetString(&config->filesystem_encoding, + "utf-8"); + if (_Py_INIT_FAILED(err)) { + return err; } } if (config->filesystem_errors == NULL) { - config->filesystem_errors = _PyMem_RawStrdup("surrogatepass"); - if (config->filesystem_errors == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetString(&config->filesystem_errors, + "surrogatepass"); + if (_Py_INIT_FAILED(err)) { + return err; } } #else if (config->filesystem_encoding == NULL) { if (preconfig->utf8_mode) { /* UTF-8 Mode use: utf-8/surrogateescape */ - config->filesystem_encoding = _PyMem_RawStrdup("utf-8"); + err = _PyCoreConfig_SetString(&config->filesystem_encoding, + "utf-8"); /* errors defaults to surrogateescape above */ } else if (_Py_GetForceASCII()) { - config->filesystem_encoding = _PyMem_RawStrdup("ascii"); + err = _PyCoreConfig_SetString(&config->filesystem_encoding, + "ascii"); } else { /* macOS and Android use UTF-8, other platforms use the locale encoding. */ #if defined(__APPLE__) || defined(__ANDROID__) - config->filesystem_encoding = _PyMem_RawStrdup("utf-8"); + err = _PyCoreConfig_SetString(&config->filesystem_encoding, + "utf-8"); #else - _PyInitError err = config_get_locale_encoding(&config->filesystem_encoding); - if (_Py_INIT_FAILED(err)) { - return err; - } + err = config_get_locale_encoding(&config->filesystem_encoding); #endif } - if (config->filesystem_encoding == NULL) { - return _Py_INIT_NO_MEMORY(); + if (_Py_INIT_FAILED(err)) { + return err; } } if (config->filesystem_errors == NULL) { /* by default, use the "surrogateescape" error handler */ - config->filesystem_errors = _PyMem_RawStrdup("surrogateescape"); - if (config->filesystem_errors == NULL) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_SetString(&config->filesystem_errors, + "surrogateescape"); + if (_Py_INIT_FAILED(err)) { + return err; } } #endif @@ -1828,13 +1895,16 @@ config_parse_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline, static _PyInitError config_init_env_warnoptions(const _PyCoreConfig *config, _PyWstrList *warnoptions) { - wchar_t *env; - int res = _PyCoreConfig_GetEnvDup(config, &env, - L"PYTHONWARNINGS", "PYTHONWARNINGS"); - if (res < 0) { - return DECODE_LOCALE_ERR("PYTHONWARNINGS", res); + _PyInitError err; + /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */ + wchar_t *env = NULL; + err = CONFIG_GET_ENV_DUP(config, &env, + L"PYTHONWARNINGS", "PYTHONWARNINGS"); + if (_Py_INIT_FAILED(err)) { + return err; } + /* env var is not set or is empty */ if (env == NULL) { return _Py_INIT_OK(); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index c874a509aa559e..afa683b7e84199 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -472,6 +472,7 @@ _Py_Initialize_ReconfigureCore(_PyRuntimeState *runtime, PyInterpreterState **interp_p, const _PyCoreConfig *core_config) { + _PyInitError err; PyThreadState *tstate = _PyThreadState_GET(); if (!tstate) { return _Py_INIT_ERR("failed to read thread state"); @@ -485,13 +486,14 @@ _Py_Initialize_ReconfigureCore(_PyRuntimeState *runtime, _PyCoreConfig_Write(core_config, runtime); - if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_Copy(&interp->core_config, core_config); + if (_Py_INIT_FAILED(err)) { + return err; } core_config = &interp->core_config; if (core_config->_install_importlib) { - _PyInitError err = _PyCoreConfig_SetPathConfig(core_config); + err = _PyCoreConfig_SetPathConfig(core_config); if (_Py_INIT_FAILED(err)) { return err; } @@ -545,8 +547,9 @@ pycore_create_interpreter(_PyRuntimeState *runtime, } *interp_p = interp; - if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) { - return _Py_INIT_NO_MEMORY(); + _PyInitError err = _PyCoreConfig_Copy(&interp->core_config, core_config); + if (_Py_INIT_FAILED(err)) { + return err; } core_config = &interp->core_config; @@ -804,8 +807,9 @@ pyinit_coreconfig(_PyRuntimeState *runtime, _PyInitError err; if (src_config) { - if (_PyCoreConfig_Copy(config, src_config) < 0) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_Copy(config, src_config); + if (_Py_INIT_FAILED(err)) { + return err; } } @@ -1433,8 +1437,9 @@ new_interpreter(PyThreadState **tstate_p) core_config = &main_interp->core_config; } - if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) { - return _Py_INIT_NO_MEMORY(); + err = _PyCoreConfig_Copy(&interp->core_config, core_config); + if (_Py_INIT_FAILED(err)) { + return err; } core_config = &interp->core_config; From 18029d80bde1743da6900600633f0fa54d7c1044 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Wed, 1 May 2019 11:12:35 -0400 Subject: [PATCH 134/212] MNT: set stacklevel in the getfullargspec deprecation warning to 2 (GH-13029) This is consistent with the rest of the `warnings.warn` usage in the inspect.py module and aids identifying code that needs to be fixed. This warning came in via d5d2b4546939b98244708e5bb0cfccd55b99d244 --- Lib/inspect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/inspect.py b/Lib/inspect.py index fffca22357a928..c460309bb5a1b6 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1112,7 +1112,7 @@ def getfullargspec(func): """ warnings.warn("Use inspect.signature() instead of inspect.getfullargspec()", - DeprecationWarning) + DeprecationWarning, stacklevel=2) try: # Re: `skip_bound_arg=False` # From 3d37ea25dc97e4cb024045581979570835deb13c Mon Sep 17 00:00:00 2001 From: Petter Strandmark Date: Wed, 1 May 2019 19:32:15 +0200 Subject: [PATCH 135/212] bpo-27682: Handle client connection terminations in wsgiref (GH-9713) --- Lib/test/test_wsgiref.py | 18 ++++++++++++++++++ Lib/wsgiref/handlers.py | 4 ++++ .../2018-10-05-16-01-00.bpo-34547.abbaa.rst | 2 ++ 3 files changed, 24 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2018-10-05-16-01-00.bpo-34547.abbaa.rst diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py index 737dfed3a51e57..46f88a94434bcd 100644 --- a/Lib/test/test_wsgiref.py +++ b/Lib/test/test_wsgiref.py @@ -788,6 +788,24 @@ def flush(self): b"Hello, world!", written) + def testClientConnectionTerminations(self): + environ = {"SERVER_PROTOCOL": "HTTP/1.0"} + for exception in ( + ConnectionAbortedError, + BrokenPipeError, + ConnectionResetError, + ): + with self.subTest(exception=exception): + class AbortingWriter: + def write(self, b): + raise exception + + stderr = StringIO() + h = SimpleHandler(BytesIO(), AbortingWriter(), stderr, environ) + h.run(hello_app) + + self.assertFalse(stderr.getvalue()) + if __name__ == "__main__": unittest.main() diff --git a/Lib/wsgiref/handlers.py b/Lib/wsgiref/handlers.py index 28ed9b7a6d0353..834073d50091e0 100644 --- a/Lib/wsgiref/handlers.py +++ b/Lib/wsgiref/handlers.py @@ -136,6 +136,10 @@ def run(self, application): self.setup_environ() self.result = application(self.environ, self.start_response) self.finish_response() + except (ConnectionAbortedError, BrokenPipeError, ConnectionResetError): + # We expect the client to close the connection abruptly from time + # to time. + return except: try: self.handle_error() diff --git a/Misc/NEWS.d/next/Library/2018-10-05-16-01-00.bpo-34547.abbaa.rst b/Misc/NEWS.d/next/Library/2018-10-05-16-01-00.bpo-34547.abbaa.rst new file mode 100644 index 00000000000000..7b63c05ed2bed0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-10-05-16-01-00.bpo-34547.abbaa.rst @@ -0,0 +1,2 @@ +:class:`wsgiref.handlers.BaseHandler` now handles abrupt client connection +terminations gracefully. Patch by Petter Strandmark. From 43851a202cabce1e6be699e7177735c778b6697e Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Wed, 1 May 2019 21:20:38 +0200 Subject: [PATCH 136/212] bpo-36673: Implement comment/PI parsing support for the TreeBuilder in ElementTree. (#12883) * bpo-36673: Implement comment/PI parsing support for the TreeBuilder in ElementTree. * bpo-36673: Rewrite the comment/PI factory handling for the TreeBuilder in "_elementtree" to make it use the same factories as the ElementTree module, and to make it explicit when the comments/PIs are inserted into the tree and when they are not (which is the default). --- Doc/library/xml.etree.elementtree.rst | 65 +++- Lib/test/test_xml_etree.py | 90 ++++- Lib/xml/etree/ElementTree.py | 67 +++- .../2019-04-20-09-50-32.bpo-36673.XF4Egb.rst | 3 + Modules/_elementtree.c | 331 ++++++++++++++++-- Modules/clinic/_elementtree.c.h | 128 ++++++- 6 files changed, 630 insertions(+), 54 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-20-09-50-32.bpo-36673.XF4Egb.rst diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 9e2c295867ca3a..c9e04c2fc8fcc2 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -523,8 +523,9 @@ Functions Parses an XML section into an element tree incrementally, and reports what's going on to the user. *source* is a filename or :term:`file object` containing XML data. *events* is a sequence of events to report back. The - supported events are the strings ``"start"``, ``"end"``, ``"start-ns"`` and - ``"end-ns"`` (the "ns" events are used to get detailed namespace + supported events are the strings ``"start"``, ``"end"``, ``"comment"``, + ``"pi"``, ``"start-ns"`` and ``"end-ns"`` + (the "ns" events are used to get detailed namespace information). If *events* is omitted, only ``"end"`` events are reported. *parser* is an optional parser instance. If not given, the standard :class:`XMLParser` parser is used. *parser* must be a subclass of @@ -549,6 +550,10 @@ Functions .. deprecated:: 3.4 The *parser* argument. + .. versionchanged:: 3.8 + The ``comment`` and ``pi`` events were added. + + .. function:: parse(source, parser=None) Parses an XML section into an element tree. *source* is a filename or file @@ -1021,14 +1026,24 @@ TreeBuilder Objects ^^^^^^^^^^^^^^^^^^^ -.. class:: TreeBuilder(element_factory=None) +.. class:: TreeBuilder(element_factory=None, *, comment_factory=None, \ + pi_factory=None, insert_comments=False, insert_pis=False) Generic element structure builder. This builder converts a sequence of - start, data, and end method calls to a well-formed element structure. You - can use this class to build an element structure using a custom XML parser, - or a parser for some other XML-like format. *element_factory*, when given, - must be a callable accepting two positional arguments: a tag and - a dict of attributes. It is expected to return a new element instance. + start, data, end, comment and pi method calls to a well-formed element + structure. You can use this class to build an element structure using + a custom XML parser, or a parser for some other XML-like format. + + *element_factory*, when given, must be a callable accepting two positional + arguments: a tag and a dict of attributes. It is expected to return a new + element instance. + + The *comment_factory* and *pi_factory* functions, when given, should behave + like the :func:`Comment` and :func:`ProcessingInstruction` functions to + create comments and processing instructions. When not given, the default + factories will be used. When *insert_comments* and/or *insert_pis* is true, + comments/pis will be inserted into the tree if they appear within the root + element (but not outside of it). .. method:: close() @@ -1054,6 +1069,22 @@ TreeBuilder Objects containing element attributes. Returns the opened element. + .. method:: comment(text) + + Creates a comment with the given *text*. If ``insert_comments`` is true, + this will also add it to the tree. + + .. versionadded:: 3.8 + + + .. method:: pi(target, text) + + Creates a comment with the given *target* name and *text*. If + ``insert_pis`` is true, this will also add it to the tree. + + .. versionadded:: 3.8 + + In addition, a custom :class:`TreeBuilder` object can provide the following method: @@ -1150,9 +1181,9 @@ XMLPullParser Objects callback target, :class:`XMLPullParser` collects an internal list of parsing events and lets the user read from it. *events* is a sequence of events to report back. The supported events are the strings ``"start"``, ``"end"``, - ``"start-ns"`` and ``"end-ns"`` (the "ns" events are used to get detailed - namespace information). If *events* is omitted, only ``"end"`` events are - reported. + ``"comment"``, ``"pi"``, ``"start-ns"`` and ``"end-ns"`` (the "ns" events + are used to get detailed namespace information). If *events* is omitted, + only ``"end"`` events are reported. .. method:: feed(data) @@ -1171,7 +1202,13 @@ XMLPullParser Objects data fed to the parser. The iterator yields ``(event, elem)`` pairs, where *event* is a string representing the type of event (e.g. ``"end"``) and *elem* is the - encountered :class:`Element` object. + encountered :class:`Element` object, or other context value as follows. + + * ``start``, ``end``: the current Element. + * ``comment``, ``pi``: the current comment / processing instruction + * ``start-ns``: a tuple ``(prefix, uri)`` naming the declared namespace + mapping. + * ``end-ns``: :const:`None` (this may change in a future version) Events provided in a previous call to :meth:`read_events` will not be yielded again. Events are consumed from the internal queue only when @@ -1191,6 +1228,10 @@ XMLPullParser Objects .. versionadded:: 3.4 + .. versionchanged:: 3.8 + The ``comment`` and ``pi`` events were added. + + Exceptions ^^^^^^^^^^ diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index e0d2cb7b995231..8a228b8ccd6257 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -1194,6 +1194,12 @@ def _feed(self, parser, data, chunk_size=None): for i in range(0, len(data), chunk_size): parser.feed(data[i:i+chunk_size]) + def assert_events(self, parser, expected): + self.assertEqual( + [(event, (elem.tag, elem.text)) + for event, elem in parser.read_events()], + expected) + def assert_event_tags(self, parser, expected): events = parser.read_events() self.assertEqual([(action, elem.tag) for action, elem in events], @@ -1276,8 +1282,10 @@ def test_events(self): self.assert_event_tags(parser, []) parser = ET.XMLPullParser(events=('start', 'end')) - self._feed(parser, "\n") - self.assert_event_tags(parser, []) + self._feed(parser, "\n") + self.assert_events(parser, []) + + parser = ET.XMLPullParser(events=('start', 'end')) self._feed(parser, "\n") self.assert_event_tags(parser, [('start', 'root')]) self._feed(parser, "text") self.assertIsNone(parser.close()) + def test_events_comment(self): + parser = ET.XMLPullParser(events=('start', 'comment', 'end')) + self._feed(parser, "\n") + self.assert_events(parser, [('comment', (ET.Comment, ' text here '))]) + self._feed(parser, "\n") + self.assert_events(parser, [('comment', (ET.Comment, ' more text here '))]) + self._feed(parser, "text") + self.assert_event_tags(parser, [('start', 'root-tag')]) + self._feed(parser, "\n") + self.assert_events(parser, [('comment', (ET.Comment, ' inner comment'))]) + self._feed(parser, "\n") + self.assert_event_tags(parser, [('end', 'root-tag')]) + self._feed(parser, "\n") + self.assert_events(parser, [('comment', (ET.Comment, ' outer comment '))]) + + parser = ET.XMLPullParser(events=('comment',)) + self._feed(parser, "\n") + self.assert_events(parser, [('comment', (ET.Comment, ' text here '))]) + + def test_events_pi(self): + parser = ET.XMLPullParser(events=('start', 'pi', 'end')) + self._feed(parser, "\n") + self.assert_events(parser, [('pi', (ET.PI, 'pitarget'))]) + parser = ET.XMLPullParser(events=('pi',)) + self._feed(parser, "\n") + self.assert_events(parser, [('pi', (ET.PI, 'pitarget some text '))]) + def test_events_sequence(self): # Test that events can be some sequence that's not just a tuple or list eventset = {'end', 'start'} @@ -1333,7 +1368,6 @@ def __next__(self): self._feed(parser, "bar") self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')]) - def test_unknown_event(self): with self.assertRaises(ValueError): ET.XMLPullParser(events=('start', 'end', 'bogus')) @@ -2741,6 +2775,33 @@ class DummyBuilder(BaseDummyBuilder): parser.feed(self.sample1) self.assertIsNone(parser.close()) + def test_treebuilder_comment(self): + b = ET.TreeBuilder() + self.assertEqual(b.comment('ctext').tag, ET.Comment) + self.assertEqual(b.comment('ctext').text, 'ctext') + + b = ET.TreeBuilder(comment_factory=ET.Comment) + self.assertEqual(b.comment('ctext').tag, ET.Comment) + self.assertEqual(b.comment('ctext').text, 'ctext') + + b = ET.TreeBuilder(comment_factory=len) + self.assertEqual(b.comment('ctext'), len('ctext')) + + def test_treebuilder_pi(self): + b = ET.TreeBuilder() + self.assertEqual(b.pi('target', None).tag, ET.PI) + self.assertEqual(b.pi('target', None).text, 'target') + + b = ET.TreeBuilder(pi_factory=ET.PI) + self.assertEqual(b.pi('target').tag, ET.PI) + self.assertEqual(b.pi('target').text, "target") + self.assertEqual(b.pi('pitarget', ' text ').tag, ET.PI) + self.assertEqual(b.pi('pitarget', ' text ').text, "pitarget text ") + + b = ET.TreeBuilder(pi_factory=lambda target, text: (len(target), text)) + self.assertEqual(b.pi('target'), (len('target'), None)) + self.assertEqual(b.pi('pitarget', ' text '), (len('pitarget'), ' text ')) + def test_treebuilder_elementfactory_none(self): parser = ET.XMLParser(target=ET.TreeBuilder(element_factory=None)) parser.feed(self.sample1) @@ -2761,6 +2822,21 @@ def foobar(self, x): e = parser.close() self._check_sample1_element(e) + def test_subclass_comment_pi(self): + class MyTreeBuilder(ET.TreeBuilder): + def foobar(self, x): + return x * 2 + + tb = MyTreeBuilder(comment_factory=ET.Comment, pi_factory=ET.PI) + self.assertEqual(tb.foobar(10), 20) + + parser = ET.XMLParser(target=tb) + parser.feed(self.sample1) + parser.feed('') + + e = parser.close() + self._check_sample1_element(e) + def test_element_factory(self): lst = [] def myfactory(tag, attrib): @@ -3418,6 +3494,12 @@ def test_main(module=None): # Copy the path cache (should be empty) path_cache = ElementPath._cache ElementPath._cache = path_cache.copy() + # Align the Comment/PI factories. + if hasattr(ET, '_set_factories'): + old_factories = ET._set_factories(ET.Comment, ET.PI) + else: + old_factories = None + try: support.run_unittest(*test_classes) finally: @@ -3426,6 +3508,8 @@ def test_main(module=None): nsmap.clear() nsmap.update(nsmap_copy) ElementPath._cache = path_cache + if old_factories is not None: + ET._set_factories(*old_factories) # don't interfere with subsequent tests ET = pyET = None diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index c9e2f36835021e..c6400480f5b4b4 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -1374,12 +1374,30 @@ class TreeBuilder: *element_factory* is an optional element factory which is called to create new Element instances, as necessary. + *comment_factory* is a factory to create comments to be used instead of + the standard factory. If *insert_comments* is false (the default), + comments will not be inserted into the tree. + + *pi_factory* is a factory to create processing instructions to be used + instead of the standard factory. If *insert_pis* is false (the default), + processing instructions will not be inserted into the tree. """ - def __init__(self, element_factory=None): + def __init__(self, element_factory=None, *, + comment_factory=None, pi_factory=None, + insert_comments=False, insert_pis=False): self._data = [] # data collector self._elem = [] # element stack self._last = None # last element + self._root = None # root element self._tail = None # true if we're after an end tag + if comment_factory is None: + comment_factory = Comment + self._comment_factory = comment_factory + self.insert_comments = insert_comments + if pi_factory is None: + pi_factory = ProcessingInstruction + self._pi_factory = pi_factory + self.insert_pis = insert_pis if element_factory is None: element_factory = Element self._factory = element_factory @@ -1387,8 +1405,8 @@ def __init__(self, element_factory=None): def close(self): """Flush builder buffers and return toplevel document Element.""" assert len(self._elem) == 0, "missing end tags" - assert self._last is not None, "missing toplevel element" - return self._last + assert self._root is not None, "missing toplevel element" + return self._root def _flush(self): if self._data: @@ -1417,6 +1435,8 @@ def start(self, tag, attrs): self._last = elem = self._factory(tag, attrs) if self._elem: self._elem[-1].append(elem) + elif self._root is None: + self._root = elem self._elem.append(elem) self._tail = 0 return elem @@ -1435,6 +1455,33 @@ def end(self, tag): self._tail = 1 return self._last + def comment(self, text): + """Create a comment using the comment_factory. + + *text* is the text of the comment. + """ + return self._handle_single( + self._comment_factory, self.insert_comments, text) + + def pi(self, target, text=None): + """Create a processing instruction using the pi_factory. + + *target* is the target name of the processing instruction. + *text* is the data of the processing instruction, or ''. + """ + return self._handle_single( + self._pi_factory, self.insert_pis, target, text) + + def _handle_single(self, factory, insert, *args): + elem = factory(*args) + if insert: + self._flush() + self._last = elem + if self._elem: + self._elem[-1].append(elem) + self._tail = 1 + return elem + # also see ElementTree and TreeBuilder class XMLParser: @@ -1519,6 +1566,15 @@ def handler(prefix, uri, event=event_name, append=append): def handler(prefix, event=event_name, append=append): append((event, None)) parser.EndNamespaceDeclHandler = handler + elif event_name == 'comment': + def handler(text, event=event_name, append=append, self=self): + append((event, self.target.comment(text))) + parser.CommentHandler = handler + elif event_name == 'pi': + def handler(pi_target, data, event=event_name, append=append, + self=self): + append((event, self.target.pi(pi_target, data))) + parser.ProcessingInstructionHandler = handler else: raise ValueError("unknown event %r" % event_name) @@ -1640,7 +1696,10 @@ def close(self): # (see tests) _Element_Py = Element - # Element, SubElement, ParseError, TreeBuilder, XMLParser + # Element, SubElement, ParseError, TreeBuilder, XMLParser, _set_factories from _elementtree import * + from _elementtree import _set_factories except ImportError: pass +else: + _set_factories(Comment, ProcessingInstruction) diff --git a/Misc/NEWS.d/next/Library/2019-04-20-09-50-32.bpo-36673.XF4Egb.rst b/Misc/NEWS.d/next/Library/2019-04-20-09-50-32.bpo-36673.XF4Egb.rst new file mode 100644 index 00000000000000..76bf914e22b196 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-20-09-50-32.bpo-36673.XF4Egb.rst @@ -0,0 +1,3 @@ +The TreeBuilder and XMLPullParser in xml.etree.ElementTree gained support +for parsing comments and processing instructions. +Patch by Stefan Behnel. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 1e58cd05b51237..5481c61678712b 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -92,6 +92,8 @@ typedef struct { PyObject *parseerror_obj; PyObject *deepcopy_obj; PyObject *elementpath_obj; + PyObject *comment_factory; + PyObject *pi_factory; } elementtreestate; static struct PyModuleDef elementtreemodule; @@ -114,6 +116,8 @@ elementtree_clear(PyObject *m) Py_CLEAR(st->parseerror_obj); Py_CLEAR(st->deepcopy_obj); Py_CLEAR(st->elementpath_obj); + Py_CLEAR(st->comment_factory); + Py_CLEAR(st->pi_factory); return 0; } @@ -124,6 +128,8 @@ elementtree_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(st->parseerror_obj); Py_VISIT(st->deepcopy_obj); Py_VISIT(st->elementpath_obj); + Py_VISIT(st->comment_factory); + Py_VISIT(st->pi_factory); return 0; } @@ -2385,6 +2391,8 @@ typedef struct { Py_ssize_t index; /* current stack size (0 means empty) */ PyObject *element_factory; + PyObject *comment_factory; + PyObject *pi_factory; /* element tracing */ PyObject *events_append; /* the append method of the list of events, or NULL */ @@ -2392,6 +2400,11 @@ typedef struct { PyObject *end_event_obj; PyObject *start_ns_event_obj; PyObject *end_ns_event_obj; + PyObject *comment_event_obj; + PyObject *pi_event_obj; + + char insert_comments; + char insert_pis; } TreeBuilderObject; #define TreeBuilder_CheckExact(op) (Py_TYPE(op) == &TreeBuilder_Type) @@ -2413,6 +2426,8 @@ treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) t->data = NULL; t->element_factory = NULL; + t->comment_factory = NULL; + t->pi_factory = NULL; t->stack = PyList_New(20); if (!t->stack) { Py_DECREF(t->this); @@ -2425,6 +2440,8 @@ treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) t->events_append = NULL; t->start_event_obj = t->end_event_obj = NULL; t->start_ns_event_obj = t->end_ns_event_obj = NULL; + t->comment_event_obj = t->pi_event_obj = NULL; + t->insert_comments = t->insert_pis = 0; } return (PyObject *)t; } @@ -2433,17 +2450,53 @@ treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) _elementtree.TreeBuilder.__init__ element_factory: object = NULL + * + comment_factory: object = NULL + pi_factory: object = NULL + insert_comments: bool = False + insert_pis: bool = False [clinic start generated code]*/ static int _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self, - PyObject *element_factory) -/*[clinic end generated code: output=91cfa7558970ee96 input=1b424eeefc35249c]*/ + PyObject *element_factory, + PyObject *comment_factory, + PyObject *pi_factory, + int insert_comments, int insert_pis) +/*[clinic end generated code: output=8571d4dcadfdf952 input=1f967b5c245e0a71]*/ { - if (element_factory) { + if (element_factory && element_factory != Py_None) { Py_INCREF(element_factory); Py_XSETREF(self->element_factory, element_factory); + } else { + Py_CLEAR(self->element_factory); + } + + if (!comment_factory || comment_factory == Py_None) { + elementtreestate *st = ET_STATE_GLOBAL; + comment_factory = st->comment_factory; + } + if (comment_factory) { + Py_INCREF(comment_factory); + Py_XSETREF(self->comment_factory, comment_factory); + self->insert_comments = insert_comments; + } else { + Py_CLEAR(self->comment_factory); + self->insert_comments = 0; + } + + if (!pi_factory || pi_factory == Py_None) { + elementtreestate *st = ET_STATE_GLOBAL; + pi_factory = st->pi_factory; + } + if (pi_factory) { + Py_INCREF(pi_factory); + Py_XSETREF(self->pi_factory, pi_factory); + self->insert_pis = insert_pis; + } else { + Py_CLEAR(self->pi_factory); + self->insert_pis = 0; } return 0; @@ -2452,6 +2505,8 @@ _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self, static int treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg) { + Py_VISIT(self->pi_event_obj); + Py_VISIT(self->comment_event_obj); Py_VISIT(self->end_ns_event_obj); Py_VISIT(self->start_ns_event_obj); Py_VISIT(self->end_event_obj); @@ -2462,6 +2517,8 @@ treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg) Py_VISIT(self->last); Py_VISIT(self->data); Py_VISIT(self->stack); + Py_VISIT(self->pi_factory); + Py_VISIT(self->comment_factory); Py_VISIT(self->element_factory); return 0; } @@ -2469,6 +2526,8 @@ treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg) static int treebuilder_gc_clear(TreeBuilderObject *self) { + Py_CLEAR(self->pi_event_obj); + Py_CLEAR(self->comment_event_obj); Py_CLEAR(self->end_ns_event_obj); Py_CLEAR(self->start_ns_event_obj); Py_CLEAR(self->end_event_obj); @@ -2478,6 +2537,8 @@ treebuilder_gc_clear(TreeBuilderObject *self) Py_CLEAR(self->data); Py_CLEAR(self->last); Py_CLEAR(self->this); + Py_CLEAR(self->pi_factory); + Py_CLEAR(self->comment_factory); Py_CLEAR(self->element_factory); Py_CLEAR(self->root); return 0; @@ -2494,6 +2555,57 @@ treebuilder_dealloc(TreeBuilderObject *self) /* -------------------------------------------------------------------- */ /* helpers for handling of arbitrary element-like objects */ +/*[clinic input] +_elementtree._set_factories + + comment_factory: object + pi_factory: object + / + +Change the factories used to create comments and processing instructions. + +For internal use only. +[clinic start generated code]*/ + +static PyObject * +_elementtree__set_factories_impl(PyObject *module, PyObject *comment_factory, + PyObject *pi_factory) +/*[clinic end generated code: output=813b408adee26535 input=99d17627aea7fb3b]*/ +{ + elementtreestate *st = ET_STATE_GLOBAL; + PyObject *old; + + if (!PyCallable_Check(comment_factory) && comment_factory != Py_None) { + PyErr_Format(PyExc_TypeError, "Comment factory must be callable, not %.100s", + Py_TYPE(comment_factory)->tp_name); + return NULL; + } + if (!PyCallable_Check(pi_factory) && pi_factory != Py_None) { + PyErr_Format(PyExc_TypeError, "PI factory must be callable, not %.100s", + Py_TYPE(pi_factory)->tp_name); + return NULL; + } + + old = PyTuple_Pack(2, + st->comment_factory ? st->comment_factory : Py_None, + st->pi_factory ? st->pi_factory : Py_None); + + if (comment_factory == Py_None) { + Py_CLEAR(st->comment_factory); + } else { + Py_INCREF(comment_factory); + Py_XSETREF(st->comment_factory, comment_factory); + } + if (pi_factory == Py_None) { + Py_CLEAR(st->pi_factory); + } else { + Py_INCREF(pi_factory); + Py_XSETREF(st->pi_factory, pi_factory); + } + + return old; +} + static int treebuilder_set_element_text_or_tail(PyObject *element, PyObject **data, PyObject **dest, _Py_Identifier *name) @@ -2569,7 +2681,7 @@ treebuilder_append_event(TreeBuilderObject *self, PyObject *action, PyObject *event = PyTuple_Pack(2, action, node); if (event == NULL) return -1; - res = PyObject_CallFunctionObjArgs(self->events_append, event, NULL); + res = _PyObject_FastCall(self->events_append, &event, 1); Py_DECREF(event); if (res == NULL) return -1; @@ -2593,7 +2705,7 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag, return NULL; } - if (!self->element_factory || self->element_factory == Py_None) { + if (!self->element_factory) { node = create_new_element(tag, attrib); } else if (attrib == Py_None) { attrib = PyDict_New(); @@ -2721,6 +2833,84 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag) return (PyObject*) self->last; } +LOCAL(PyObject*) +treebuilder_handle_comment(TreeBuilderObject* self, PyObject* text) +{ + PyObject* comment = NULL; + PyObject* this; + + if (treebuilder_flush_data(self) < 0) { + return NULL; + } + + if (self->comment_factory) { + comment = _PyObject_FastCall(self->comment_factory, &text, 1); + if (!comment) + return NULL; + + this = self->this; + if (self->insert_comments && this != Py_None) { + if (treebuilder_add_subelement(this, comment) < 0) + goto error; + } + } else { + Py_INCREF(text); + comment = text; + } + + if (self->events_append && self->comment_event_obj) { + if (treebuilder_append_event(self, self->comment_event_obj, comment) < 0) + goto error; + } + + return comment; + + error: + Py_DECREF(comment); + return NULL; +} + +LOCAL(PyObject*) +treebuilder_handle_pi(TreeBuilderObject* self, PyObject* target, PyObject* text) +{ + PyObject* pi = NULL; + PyObject* this; + PyObject* stack[2] = {target, text}; + + if (treebuilder_flush_data(self) < 0) { + return NULL; + } + + if (self->pi_factory) { + pi = _PyObject_FastCall(self->pi_factory, stack, 2); + if (!pi) { + return NULL; + } + + this = self->this; + if (self->insert_pis && this != Py_None) { + if (treebuilder_add_subelement(this, pi) < 0) + goto error; + } + } else { + pi = PyTuple_Pack(2, target, text); + if (!pi) { + return NULL; + } + } + + if (self->events_append && self->pi_event_obj) { + if (treebuilder_append_event(self, self->pi_event_obj, pi) < 0) + goto error; + } + + return pi; + + error: + Py_DECREF(pi); + return NULL; +} + /* -------------------------------------------------------------------- */ /* methods (in alphabetical order) */ @@ -2754,6 +2944,38 @@ _elementtree_TreeBuilder_end(TreeBuilderObject *self, PyObject *tag) return treebuilder_handle_end(self, tag); } +/*[clinic input] +_elementtree.TreeBuilder.comment + + text: object + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_TreeBuilder_comment(TreeBuilderObject *self, PyObject *text) +/*[clinic end generated code: output=22835be41deeaa27 input=47e7ebc48ed01dfa]*/ +{ + return treebuilder_handle_comment(self, text); +} + +/*[clinic input] +_elementtree.TreeBuilder.pi + + target: object + text: object = None + / + +[clinic start generated code]*/ + +static PyObject * +_elementtree_TreeBuilder_pi_impl(TreeBuilderObject *self, PyObject *target, + PyObject *text) +/*[clinic end generated code: output=21eb95ec9d04d1d9 input=349342bd79c35570]*/ +{ + return treebuilder_handle_pi(self, target, text); +} + LOCAL(PyObject*) treebuilder_done(TreeBuilderObject* self) { @@ -2925,7 +3147,7 @@ expat_set_error(enum XML_Error error_code, Py_ssize_t line, Py_ssize_t column, if (errmsg == NULL) return; - error = PyObject_CallFunctionObjArgs(st->parseerror_obj, errmsg, NULL); + error = _PyObject_FastCall(st->parseerror_obj, &errmsg, 1); Py_DECREF(errmsg); if (!error) return; @@ -2988,7 +3210,7 @@ expat_default_handler(XMLParserObject* self, const XML_Char* data_in, (TreeBuilderObject*) self->target, value ); else if (self->handle_data) - res = PyObject_CallFunctionObjArgs(self->handle_data, value, NULL); + res = _PyObject_FastCall(self->handle_data, &value, 1); else res = NULL; Py_XDECREF(res); @@ -3099,7 +3321,7 @@ expat_data_handler(XMLParserObject* self, const XML_Char* data_in, /* shortcut */ res = treebuilder_handle_data((TreeBuilderObject*) self->target, data); else if (self->handle_data) - res = PyObject_CallFunctionObjArgs(self->handle_data, data, NULL); + res = _PyObject_FastCall(self->handle_data, &data, 1); else res = NULL; @@ -3126,7 +3348,7 @@ expat_end_handler(XMLParserObject* self, const XML_Char* tag_in) else if (self->handle_end) { tag = makeuniversal(self, tag_in); if (tag) { - res = PyObject_CallFunctionObjArgs(self->handle_end, tag, NULL); + res = _PyObject_FastCall(self->handle_end, &tag, 1); Py_DECREF(tag); } } @@ -3176,21 +3398,31 @@ expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in) static void expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in) { - PyObject* comment; - PyObject* res; + PyObject* comment = NULL; + PyObject* res = NULL; if (PyErr_Occurred()) return; - if (self->handle_comment) { + if (TreeBuilder_CheckExact(self->target)) { + /* shortcut */ + TreeBuilderObject *target = (TreeBuilderObject*) self->target; + comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict"); - if (comment) { - res = PyObject_CallFunctionObjArgs(self->handle_comment, - comment, NULL); - Py_XDECREF(res); - Py_DECREF(comment); - } + if (!comment) + return; /* parser will look for errors */ + + res = treebuilder_handle_comment(target, comment); + } else if (self->handle_comment) { + comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict"); + if (!comment) + return; + + res = _PyObject_FastCall(self->handle_comment, &comment, 1); } + + Py_XDECREF(res); + Py_DECREF(comment); } static void @@ -3258,27 +3490,51 @@ static void expat_pi_handler(XMLParserObject* self, const XML_Char* target_in, const XML_Char* data_in) { - PyObject* target; + PyObject* pi_target = NULL; PyObject* data; PyObject* res; + PyObject* stack[2]; if (PyErr_Occurred()) return; - if (self->handle_pi) { - target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict"); - data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict"); - if (target && data) { - res = PyObject_CallFunctionObjArgs(self->handle_pi, - target, data, NULL); + if (TreeBuilder_CheckExact(self->target)) { + /* shortcut */ + TreeBuilderObject *target = (TreeBuilderObject*) self->target; + + if (target->events_append && target->pi_event_obj) { + pi_target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict"); + if (!pi_target) + goto error; + data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict"); + if (!data) + goto error; + res = treebuilder_handle_pi(target, pi_target, data); Py_XDECREF(res); Py_DECREF(data); - Py_DECREF(target); - } else { - Py_XDECREF(data); - Py_XDECREF(target); + Py_DECREF(pi_target); } + } else if (self->handle_pi) { + pi_target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict"); + if (!pi_target) + goto error; + data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict"); + if (!data) + goto error; + + stack[0] = pi_target; + stack[1] = data; + res = _PyObject_FastCall(self->handle_pi, stack, 2); + Py_XDECREF(res); + Py_DECREF(data); + Py_DECREF(pi_target); } + + return; + + error: + Py_XDECREF(pi_target); + return; } /* -------------------------------------------------------------------- */ @@ -3695,6 +3951,8 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self, Py_CLEAR(target->end_event_obj); Py_CLEAR(target->start_ns_event_obj); Py_CLEAR(target->end_ns_event_obj); + Py_CLEAR(target->comment_event_obj); + Py_CLEAR(target->pi_event_obj); if (events_to_report == Py_None) { /* default is "end" only */ @@ -3740,6 +3998,18 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self, (XML_StartNamespaceDeclHandler) expat_start_ns_handler, (XML_EndNamespaceDeclHandler) expat_end_ns_handler ); + } else if (strcmp(event_name, "comment") == 0) { + Py_XSETREF(target->comment_event_obj, event_name_obj); + EXPAT(SetCommentHandler)( + self->parser, + (XML_CommentHandler) expat_comment_handler + ); + } else if (strcmp(event_name, "pi") == 0) { + Py_XSETREF(target->pi_event_obj, event_name_obj); + EXPAT(SetProcessingInstructionHandler)( + self->parser, + (XML_ProcessingInstructionHandler) expat_pi_handler + ); } else { Py_DECREF(event_name_obj); Py_DECREF(events_seq); @@ -3882,6 +4152,8 @@ static PyMethodDef treebuilder_methods[] = { _ELEMENTTREE_TREEBUILDER_DATA_METHODDEF _ELEMENTTREE_TREEBUILDER_START_METHODDEF _ELEMENTTREE_TREEBUILDER_END_METHODDEF + _ELEMENTTREE_TREEBUILDER_COMMENT_METHODDEF + _ELEMENTTREE_TREEBUILDER_PI_METHODDEF _ELEMENTTREE_TREEBUILDER_CLOSE_METHODDEF {NULL, NULL} }; @@ -3983,6 +4255,7 @@ static PyTypeObject XMLParser_Type = { static PyMethodDef _functions[] = { {"SubElement", (PyCFunction)(void(*)(void)) subelement, METH_VARARGS | METH_KEYWORDS}, + _ELEMENTTREE__SET_FACTORIES_METHODDEF {NULL, NULL} }; diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h index d239c802583c6c..0f55480140b315 100644 --- a/Modules/clinic/_elementtree.c.h +++ b/Modules/clinic/_elementtree.c.h @@ -635,19 +635,26 @@ _elementtree_Element_set(ElementObject *self, PyObject *const *args, Py_ssize_t static int _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self, - PyObject *element_factory); + PyObject *element_factory, + PyObject *comment_factory, + PyObject *pi_factory, + int insert_comments, int insert_pis); static int _elementtree_TreeBuilder___init__(PyObject *self, PyObject *args, PyObject *kwargs) { int return_value = -1; - static const char * const _keywords[] = {"element_factory", NULL}; + static const char * const _keywords[] = {"element_factory", "comment_factory", "pi_factory", "insert_comments", "insert_pis", NULL}; static _PyArg_Parser _parser = {NULL, _keywords, "TreeBuilder", 0}; - PyObject *argsbuf[1]; + PyObject *argsbuf[5]; PyObject * const *fastargs; Py_ssize_t nargs = PyTuple_GET_SIZE(args); Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; PyObject *element_factory = NULL; + PyObject *comment_factory = NULL; + PyObject *pi_factory = NULL; + int insert_comments = 0; + int insert_pis = 0; fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 1, 0, argsbuf); if (!fastargs) { @@ -656,9 +663,76 @@ _elementtree_TreeBuilder___init__(PyObject *self, PyObject *args, PyObject *kwar if (!noptargs) { goto skip_optional_pos; } - element_factory = fastargs[0]; + if (fastargs[0]) { + element_factory = fastargs[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } skip_optional_pos: - return_value = _elementtree_TreeBuilder___init___impl((TreeBuilderObject *)self, element_factory); + if (!noptargs) { + goto skip_optional_kwonly; + } + if (fastargs[1]) { + comment_factory = fastargs[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[2]) { + pi_factory = fastargs[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[3]) { + insert_comments = PyObject_IsTrue(fastargs[3]); + if (insert_comments < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + insert_pis = PyObject_IsTrue(fastargs[4]); + if (insert_pis < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _elementtree_TreeBuilder___init___impl((TreeBuilderObject *)self, element_factory, comment_factory, pi_factory, insert_comments, insert_pis); + +exit: + return return_value; +} + +PyDoc_STRVAR(_elementtree__set_factories__doc__, +"_set_factories($module, comment_factory, pi_factory, /)\n" +"--\n" +"\n" +"Change the factories used to create comments and processing instructions.\n" +"\n" +"For internal use only."); + +#define _ELEMENTTREE__SET_FACTORIES_METHODDEF \ + {"_set_factories", (PyCFunction)(void(*)(void))_elementtree__set_factories, METH_FASTCALL, _elementtree__set_factories__doc__}, + +static PyObject * +_elementtree__set_factories_impl(PyObject *module, PyObject *comment_factory, + PyObject *pi_factory); + +static PyObject * +_elementtree__set_factories(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *comment_factory; + PyObject *pi_factory; + + if (!_PyArg_CheckPositional("_set_factories", nargs, 2, 2)) { + goto exit; + } + comment_factory = args[0]; + pi_factory = args[1]; + return_value = _elementtree__set_factories_impl(module, comment_factory, pi_factory); exit: return return_value; @@ -680,6 +754,48 @@ PyDoc_STRVAR(_elementtree_TreeBuilder_end__doc__, #define _ELEMENTTREE_TREEBUILDER_END_METHODDEF \ {"end", (PyCFunction)_elementtree_TreeBuilder_end, METH_O, _elementtree_TreeBuilder_end__doc__}, +PyDoc_STRVAR(_elementtree_TreeBuilder_comment__doc__, +"comment($self, text, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_TREEBUILDER_COMMENT_METHODDEF \ + {"comment", (PyCFunction)_elementtree_TreeBuilder_comment, METH_O, _elementtree_TreeBuilder_comment__doc__}, + +PyDoc_STRVAR(_elementtree_TreeBuilder_pi__doc__, +"pi($self, target, text=None, /)\n" +"--\n" +"\n"); + +#define _ELEMENTTREE_TREEBUILDER_PI_METHODDEF \ + {"pi", (PyCFunction)(void(*)(void))_elementtree_TreeBuilder_pi, METH_FASTCALL, _elementtree_TreeBuilder_pi__doc__}, + +static PyObject * +_elementtree_TreeBuilder_pi_impl(TreeBuilderObject *self, PyObject *target, + PyObject *text); + +static PyObject * +_elementtree_TreeBuilder_pi(TreeBuilderObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *target; + PyObject *text = Py_None; + + if (!_PyArg_CheckPositional("pi", nargs, 1, 2)) { + goto exit; + } + target = args[0]; + if (nargs < 2) { + goto skip_optional; + } + text = args[1]; +skip_optional: + return_value = _elementtree_TreeBuilder_pi_impl(self, target, text); + +exit: + return return_value; +} + PyDoc_STRVAR(_elementtree_TreeBuilder_close__doc__, "close($self, /)\n" "--\n" @@ -853,4 +969,4 @@ _elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=440b5d90a4b86590 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=386a68425d072b5c input=a9049054013a1b77]*/ From dde3eebdaa8d2c51971ca704d53af7cbcda8bb34 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Wed, 1 May 2019 21:49:58 +0200 Subject: [PATCH 137/212] bpo-36676: Namespace prefix aware parsing support for the ET.XMLParser target (GH-12885) * bpo-36676: Implement namespace prefix aware parsing support for the XMLParser target in ElementTree. --- Doc/library/xml.etree.elementtree.rst | 22 ++- Lib/test/test_xml_etree.py | 93 +++++++++++- Lib/xml/etree/ElementTree.py | 30 +++- .../2019-04-20-13-10-34.bpo-36676.XF4Egb.rst | 3 + Modules/_elementtree.c | 140 +++++++++++++++--- 5 files changed, 258 insertions(+), 30 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-20-13-10-34.bpo-36676.XF4Egb.rst diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index c9e04c2fc8fcc2..66090af00fa16e 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -1086,7 +1086,7 @@ TreeBuilder Objects In addition, a custom :class:`TreeBuilder` object can provide the - following method: + following methods: .. method:: doctype(name, pubid, system) @@ -1096,6 +1096,23 @@ TreeBuilder Objects .. versionadded:: 3.2 + .. method:: start_ns(prefix, uri) + + Is called whenever the parser encounters a new namespace declaration, + before the ``start()`` callback for the opening element that defines it. + *prefix* is ``''`` for the default namespace and the declared + namespace prefix name otherwise. *uri* is the namespace URI. + + .. versionadded:: 3.8 + + .. method:: end_ns(prefix) + + Is called after the ``end()`` callback of an element that declared + a namespace prefix mapping, with the name of the *prefix* that went + out of scope. + + .. versionadded:: 3.8 + .. _elementtree-xmlparser-objects: @@ -1131,7 +1148,8 @@ XMLParser Objects :meth:`XMLParser.feed` calls *target*\'s ``start(tag, attrs_dict)`` method for each opening tag, its ``end(tag)`` method for each closing tag, and data - is processed by method ``data(data)``. :meth:`XMLParser.close` calls + is processed by method ``data(data)``. For further supported callback + methods, see the :class:`TreeBuilder` class. :meth:`XMLParser.close` calls *target*\'s method ``close()``. :class:`XMLParser` can be used not only for building a tree structure. This is an example of counting the maximum depth of an XML file:: diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 8a228b8ccd6257..0abc42a173d930 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -14,12 +14,13 @@ import operator import pickle import sys +import textwrap import types import unittest import warnings import weakref -from itertools import product +from itertools import product, islice from test import support from test.support import TESTFN, findfile, import_fresh_module, gc_collect, swap_attr @@ -694,12 +695,17 @@ def pi(self, target, data): self.append(("pi", target, data)) def comment(self, data): self.append(("comment", data)) + def start_ns(self, prefix, uri): + self.append(("start-ns", prefix, uri)) + def end_ns(self, prefix): + self.append(("end-ns", prefix)) builder = Builder() parser = ET.XMLParser(target=builder) parser.feed(data) self.assertEqual(builder, [ ('pi', 'pi', 'data'), ('comment', ' comment '), + ('start-ns', '', 'namespace'), ('start', '{namespace}root'), ('start', '{namespace}element'), ('end', '{namespace}element'), @@ -708,8 +714,30 @@ def comment(self, data): ('start', '{namespace}empty-element'), ('end', '{namespace}empty-element'), ('end', '{namespace}root'), + ('end-ns', ''), ]) + def test_custom_builder_only_end_ns(self): + class Builder(list): + def end_ns(self, prefix): + self.append(("end-ns", prefix)) + + builder = Builder() + parser = ET.XMLParser(target=builder) + parser.feed(textwrap.dedent("""\ + + + + text + texttail + + + """)) + self.assertEqual(builder, [ + ('end-ns', 'a'), + ('end-ns', 'p'), + ('end-ns', ''), + ]) # Element.getchildren() and ElementTree.getiterator() are deprecated. @checkwarnings(("This method will be removed in future versions. " @@ -1194,14 +1222,19 @@ def _feed(self, parser, data, chunk_size=None): for i in range(0, len(data), chunk_size): parser.feed(data[i:i+chunk_size]) - def assert_events(self, parser, expected): + def assert_events(self, parser, expected, max_events=None): self.assertEqual( [(event, (elem.tag, elem.text)) - for event, elem in parser.read_events()], + for event, elem in islice(parser.read_events(), max_events)], expected) - def assert_event_tags(self, parser, expected): - events = parser.read_events() + def assert_event_tuples(self, parser, expected, max_events=None): + self.assertEqual( + list(islice(parser.read_events(), max_events)), + expected) + + def assert_event_tags(self, parser, expected, max_events=None): + events = islice(parser.read_events(), max_events) self.assertEqual([(action, elem.tag) for action, elem in events], expected) @@ -1276,6 +1309,56 @@ def test_ns_events(self): self.assertEqual(list(parser.read_events()), [('end-ns', None)]) self.assertIsNone(parser.close()) + def test_ns_events_start(self): + parser = ET.XMLPullParser(events=('start-ns', 'start', 'end')) + self._feed(parser, "\n") + self.assert_event_tuples(parser, [ + ('start-ns', ('', 'abc')), + ('start-ns', ('p', 'xyz')), + ], max_events=2) + self.assert_event_tags(parser, [ + ('start', '{abc}tag'), + ], max_events=1) + + self._feed(parser, "\n") + self.assert_event_tags(parser, [ + ('start', '{abc}child'), + ('end', '{abc}child'), + ]) + + self._feed(parser, "\n") + parser.close() + self.assert_event_tags(parser, [ + ('end', '{abc}tag'), + ]) + + def test_ns_events_start_end(self): + parser = ET.XMLPullParser(events=('start-ns', 'start', 'end', 'end-ns')) + self._feed(parser, "\n") + self.assert_event_tuples(parser, [ + ('start-ns', ('', 'abc')), + ('start-ns', ('p', 'xyz')), + ], max_events=2) + self.assert_event_tags(parser, [ + ('start', '{abc}tag'), + ], max_events=1) + + self._feed(parser, "\n") + self.assert_event_tags(parser, [ + ('start', '{abc}child'), + ('end', '{abc}child'), + ]) + + self._feed(parser, "\n") + parser.close() + self.assert_event_tags(parser, [ + ('end', '{abc}tag'), + ], max_events=1) + self.assert_event_tuples(parser, [ + ('end-ns', None), + ('end-ns', None), + ]) + def test_events(self): parser = ET.XMLPullParser(events=()) self._feed(parser, "\n") diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index c6400480f5b4b4..5b26ac72fd1aae 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -1518,6 +1518,10 @@ def __init__(self, *, target=None, encoding=None): parser.StartElementHandler = self._start if hasattr(target, 'end'): parser.EndElementHandler = self._end + if hasattr(target, 'start_ns'): + parser.StartNamespaceDeclHandler = self._start_ns + if hasattr(target, 'end_ns'): + parser.EndNamespaceDeclHandler = self._end_ns if hasattr(target, 'data'): parser.CharacterDataHandler = target.data # miscellaneous callbacks @@ -1559,12 +1563,24 @@ def handler(tag, event=event_name, append=append, append((event, end(tag))) parser.EndElementHandler = handler elif event_name == "start-ns": - def handler(prefix, uri, event=event_name, append=append): - append((event, (prefix or "", uri or ""))) + # TreeBuilder does not implement .start_ns() + if hasattr(self.target, "start_ns"): + def handler(prefix, uri, event=event_name, append=append, + start_ns=self._start_ns): + append((event, start_ns(prefix, uri))) + else: + def handler(prefix, uri, event=event_name, append=append): + append((event, (prefix or '', uri or ''))) parser.StartNamespaceDeclHandler = handler elif event_name == "end-ns": - def handler(prefix, event=event_name, append=append): - append((event, None)) + # TreeBuilder does not implement .end_ns() + if hasattr(self.target, "end_ns"): + def handler(prefix, event=event_name, append=append, + end_ns=self._end_ns): + append((event, end_ns(prefix))) + else: + def handler(prefix, event=event_name, append=append): + append((event, None)) parser.EndNamespaceDeclHandler = handler elif event_name == 'comment': def handler(text, event=event_name, append=append, self=self): @@ -1595,6 +1611,12 @@ def _fixname(self, key): self._names[key] = name return name + def _start_ns(self, prefix, uri): + return self.target.start_ns(prefix or '', uri or '') + + def _end_ns(self, prefix): + return self.target.end_ns(prefix or '') + def _start(self, tag, attr_list): # Handler for expat's StartElementHandler. Since ordered_attributes # is set, the attributes are reported as a list of alternating diff --git a/Misc/NEWS.d/next/Library/2019-04-20-13-10-34.bpo-36676.XF4Egb.rst b/Misc/NEWS.d/next/Library/2019-04-20-13-10-34.bpo-36676.XF4Egb.rst new file mode 100644 index 00000000000000..e0bede81eec108 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-20-13-10-34.bpo-36676.XF4Egb.rst @@ -0,0 +1,3 @@ +The XMLParser() in xml.etree.ElementTree provides namespace prefix context to the +parser target if it defines the callback methods "start_ns()" and/or "end_ns()". +Patch by Stefan Behnel. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 5481c61678712b..b69e3a45fe308f 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2911,6 +2911,39 @@ treebuilder_handle_pi(TreeBuilderObject* self, PyObject* target, PyObject* text) return NULL; } +LOCAL(PyObject*) +treebuilder_handle_start_ns(TreeBuilderObject* self, PyObject* prefix, PyObject* uri) +{ + PyObject* parcel; + + if (self->events_append && self->start_ns_event_obj) { + parcel = PyTuple_Pack(2, prefix, uri); + if (!parcel) { + return NULL; + } + + if (treebuilder_append_event(self, self->start_ns_event_obj, parcel) < 0) { + Py_DECREF(parcel); + return NULL; + } + Py_DECREF(parcel); + } + + Py_RETURN_NONE; +} + +LOCAL(PyObject*) +treebuilder_handle_end_ns(TreeBuilderObject* self, PyObject* prefix) +{ + if (self->events_append && self->end_ns_event_obj) { + if (treebuilder_append_event(self, self->end_ns_event_obj, prefix) < 0) { + return NULL; + } + } + + Py_RETURN_NONE; +} + /* -------------------------------------------------------------------- */ /* methods (in alphabetical order) */ @@ -3046,6 +3079,8 @@ typedef struct { PyObject *names; + PyObject *handle_start_ns; + PyObject *handle_end_ns; PyObject *handle_start; PyObject *handle_data; PyObject *handle_end; @@ -3357,42 +3392,89 @@ expat_end_handler(XMLParserObject* self, const XML_Char* tag_in) } static void -expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix, - const XML_Char *uri) +expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix_in, + const XML_Char *uri_in) { - TreeBuilderObject *target = (TreeBuilderObject*) self->target; - PyObject *parcel; + PyObject* res = NULL; + PyObject* uri; + PyObject* prefix; + PyObject* stack[2]; if (PyErr_Occurred()) return; - if (!target->events_append || !target->start_ns_event_obj) - return; + if (!uri_in) + uri_in = ""; + if (!prefix_in) + prefix_in = ""; - if (!uri) - uri = ""; - if (!prefix) - prefix = ""; + if (TreeBuilder_CheckExact(self->target)) { + /* shortcut - TreeBuilder does not actually implement .start_ns() */ + TreeBuilderObject *target = (TreeBuilderObject*) self->target; - parcel = Py_BuildValue("ss", prefix, uri); - if (!parcel) - return; - treebuilder_append_event(target, target->start_ns_event_obj, parcel); - Py_DECREF(parcel); + if (target->events_append && target->start_ns_event_obj) { + prefix = PyUnicode_DecodeUTF8(prefix_in, strlen(prefix_in), "strict"); + if (!prefix) + return; + uri = PyUnicode_DecodeUTF8(uri_in, strlen(uri_in), "strict"); + if (!uri) { + Py_DECREF(prefix); + return; + } + + res = treebuilder_handle_start_ns(target, prefix, uri); + Py_DECREF(uri); + Py_DECREF(prefix); + } + } else if (self->handle_start_ns) { + prefix = PyUnicode_DecodeUTF8(prefix_in, strlen(prefix_in), "strict"); + if (!prefix) + return; + uri = PyUnicode_DecodeUTF8(uri_in, strlen(uri_in), "strict"); + if (!uri) { + Py_DECREF(prefix); + return; + } + + stack[0] = prefix; + stack[1] = uri; + res = _PyObject_FastCall(self->handle_start_ns, stack, 2); + Py_DECREF(uri); + Py_DECREF(prefix); + } + + Py_XDECREF(res); } static void expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in) { - TreeBuilderObject *target = (TreeBuilderObject*) self->target; + PyObject *res = NULL; + PyObject* prefix; if (PyErr_Occurred()) return; - if (!target->events_append) - return; + if (!prefix_in) + prefix_in = ""; + + if (TreeBuilder_CheckExact(self->target)) { + /* shortcut - TreeBuilder does not actually implement .end_ns() */ + TreeBuilderObject *target = (TreeBuilderObject*) self->target; + + if (target->events_append && target->end_ns_event_obj) { + res = treebuilder_handle_end_ns(target, Py_None); + } + } else if (self->handle_end_ns) { + prefix = PyUnicode_DecodeUTF8(prefix_in, strlen(prefix_in), "strict"); + if (!prefix) + return; + + res = _PyObject_FastCall(self->handle_end_ns, &prefix, 1); + Py_DECREF(prefix); + } - treebuilder_append_event(target, target->end_ns_event_obj, Py_None); + Py_XDECREF(res); } static void @@ -3546,6 +3628,7 @@ xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (self) { self->parser = NULL; self->target = self->entity = self->names = NULL; + self->handle_start_ns = self->handle_end_ns = NULL; self->handle_start = self->handle_data = self->handle_end = NULL; self->handle_comment = self->handle_pi = self->handle_close = NULL; self->handle_doctype = NULL; @@ -3614,6 +3697,14 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, } self->target = target; + self->handle_start_ns = PyObject_GetAttrString(target, "start_ns"); + if (ignore_attribute_error(self->handle_start_ns)) { + return -1; + } + self->handle_end_ns = PyObject_GetAttrString(target, "end_ns"); + if (ignore_attribute_error(self->handle_end_ns)) { + return -1; + } self->handle_start = PyObject_GetAttrString(target, "start"); if (ignore_attribute_error(self->handle_start)) { return -1; @@ -3645,6 +3736,12 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, /* configure parser */ EXPAT(SetUserData)(self->parser, self); + if (self->handle_start_ns || self->handle_end_ns) + EXPAT(SetNamespaceDeclHandler)( + self->parser, + (XML_StartNamespaceDeclHandler) expat_start_ns_handler, + (XML_EndNamespaceDeclHandler) expat_end_ns_handler + ); EXPAT(SetElementHandler)( self->parser, (XML_StartElementHandler) expat_start_handler, @@ -3689,6 +3786,9 @@ xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg) Py_VISIT(self->handle_end); Py_VISIT(self->handle_data); Py_VISIT(self->handle_start); + Py_VISIT(self->handle_start_ns); + Py_VISIT(self->handle_end_ns); + Py_VISIT(self->handle_doctype); Py_VISIT(self->target); Py_VISIT(self->entity); @@ -3712,6 +3812,8 @@ xmlparser_gc_clear(XMLParserObject *self) Py_CLEAR(self->handle_end); Py_CLEAR(self->handle_data); Py_CLEAR(self->handle_start); + Py_CLEAR(self->handle_start_ns); + Py_CLEAR(self->handle_end_ns); Py_CLEAR(self->handle_doctype); Py_CLEAR(self->target); From ee88af3f4f7493df4ecf52faf429e63351bbcd5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Ogam?= Date: Wed, 1 May 2019 22:08:17 +0200 Subject: [PATCH 138/212] Namespace packages _bootstrap.ModuleSpec.loader attributes are no longer None (#10376) Namespace packages _bootstrap.ModuleSpec.loader attributes are no longer `None` _after_ calling the importlib._bootstrap._init_module_attrs function. See: * https://stackoverflow.com/questions/52869541/namespace-package-spec-loader-and-loader-attributes-not-set-to-none * https://bugs.python.org/issue35181 --- Doc/reference/import.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst index 88290c88bb35d9..0228bfb7e984c5 100644 --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -345,12 +345,11 @@ of what happens during the loading portion of import:: _init_module_attrs(spec, module) if spec.loader is None: - if spec.submodule_search_locations is not None: - # namespace package - sys.modules[spec.name] = module - else: - # unsupported - raise ImportError + # unsupported + raise ImportError + if spec.origin is None and spec.submodule_search_locations is not None: + # namespace package + sys.modules[spec.name] = module elif not hasattr(spec.loader, 'exec_module'): module = spec.loader.load_module(spec.name) # Set __loader__ and __package__ if missing. From e1d5dd645d5f59867cb0ad63179110f310cbca89 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Wed, 1 May 2019 22:34:13 +0200 Subject: [PATCH 139/212] bpo-13611: C14N 2.0 implementation for ElementTree (GH-12966) * Implement C14N 2.0 as a new canonicalize() function in ElementTree. Missing features: - prefix renaming in XPath expressions (tag and attribute text is supported) - preservation of original prefixes given redundant namespace declarations --- Doc/library/xml.etree.elementtree.rst | 60 ++++ Doc/whatsnew/3.8.rst | 4 + Lib/test/test_xml_etree.py | 229 ++++++++++++ Lib/test/xmltestdata/c14n-20/c14nComment.xml | 4 + Lib/test/xmltestdata/c14n-20/c14nDefault.xml | 3 + Lib/test/xmltestdata/c14n-20/c14nPrefix.xml | 4 + .../xmltestdata/c14n-20/c14nPrefixQname.xml | 7 + .../c14n-20/c14nPrefixQnameXpathElem.xml | 8 + Lib/test/xmltestdata/c14n-20/c14nQname.xml | 6 + .../xmltestdata/c14n-20/c14nQnameElem.xml | 6 + .../c14n-20/c14nQnameXpathElem.xml | 7 + Lib/test/xmltestdata/c14n-20/c14nTrim.xml | 4 + Lib/test/xmltestdata/c14n-20/doc.dtd | 6 + Lib/test/xmltestdata/c14n-20/doc.xsl | 5 + Lib/test/xmltestdata/c14n-20/inC14N1.xml | 14 + Lib/test/xmltestdata/c14n-20/inC14N2.xml | 11 + Lib/test/xmltestdata/c14n-20/inC14N3.xml | 18 + Lib/test/xmltestdata/c14n-20/inC14N4.xml | 13 + Lib/test/xmltestdata/c14n-20/inC14N5.xml | 12 + Lib/test/xmltestdata/c14n-20/inC14N6.xml | 2 + Lib/test/xmltestdata/c14n-20/inNsContent.xml | 4 + Lib/test/xmltestdata/c14n-20/inNsDefault.xml | 3 + Lib/test/xmltestdata/c14n-20/inNsPushdown.xml | 6 + Lib/test/xmltestdata/c14n-20/inNsRedecl.xml | 3 + Lib/test/xmltestdata/c14n-20/inNsSort.xml | 4 + .../xmltestdata/c14n-20/inNsSuperfluous.xml | 4 + Lib/test/xmltestdata/c14n-20/inNsXml.xml | 3 + .../c14n-20/out_inC14N1_c14nComment.xml | 6 + .../c14n-20/out_inC14N1_c14nDefault.xml | 4 + .../c14n-20/out_inC14N2_c14nDefault.xml | 11 + .../c14n-20/out_inC14N2_c14nTrim.xml | 1 + .../c14n-20/out_inC14N3_c14nDefault.xml | 14 + .../c14n-20/out_inC14N3_c14nPrefix.xml | 14 + .../c14n-20/out_inC14N3_c14nTrim.xml | 1 + .../c14n-20/out_inC14N4_c14nDefault.xml | 10 + .../c14n-20/out_inC14N4_c14nTrim.xml | 2 + .../c14n-20/out_inC14N5_c14nDefault.xml | 3 + .../c14n-20/out_inC14N5_c14nTrim.xml | 1 + .../c14n-20/out_inC14N6_c14nDefault.xml | 1 + .../c14n-20/out_inNsContent_c14nDefault.xml | 4 + ...t_inNsContent_c14nPrefixQnameXpathElem.xml | 4 + .../c14n-20/out_inNsContent_c14nQnameElem.xml | 4 + .../out_inNsContent_c14nQnameXpathElem.xml | 4 + .../c14n-20/out_inNsDefault_c14nDefault.xml | 3 + .../c14n-20/out_inNsDefault_c14nPrefix.xml | 3 + .../c14n-20/out_inNsPushdown_c14nDefault.xml | 6 + .../c14n-20/out_inNsPushdown_c14nPrefix.xml | 6 + .../c14n-20/out_inNsRedecl_c14nDefault.xml | 3 + .../c14n-20/out_inNsRedecl_c14nPrefix.xml | 3 + .../c14n-20/out_inNsSort_c14nDefault.xml | 4 + .../c14n-20/out_inNsSort_c14nPrefix.xml | 4 + .../out_inNsSuperfluous_c14nDefault.xml | 4 + .../out_inNsSuperfluous_c14nPrefix.xml | 4 + .../c14n-20/out_inNsXml_c14nDefault.xml | 3 + .../c14n-20/out_inNsXml_c14nPrefix.xml | 3 + .../c14n-20/out_inNsXml_c14nPrefixQname.xml | 3 + .../c14n-20/out_inNsXml_c14nQname.xml | 3 + Lib/test/xmltestdata/c14n-20/world.txt | 1 + Lib/xml/etree/ElementTree.py | 331 ++++++++++++++++++ .../2019-04-26-10-10-34.bpo-13611.XEF4bg.rst | 2 + 60 files changed, 920 insertions(+) create mode 100644 Lib/test/xmltestdata/c14n-20/c14nComment.xml create mode 100644 Lib/test/xmltestdata/c14n-20/c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/c14nPrefix.xml create mode 100644 Lib/test/xmltestdata/c14n-20/c14nPrefixQname.xml create mode 100644 Lib/test/xmltestdata/c14n-20/c14nPrefixQnameXpathElem.xml create mode 100644 Lib/test/xmltestdata/c14n-20/c14nQname.xml create mode 100644 Lib/test/xmltestdata/c14n-20/c14nQnameElem.xml create mode 100644 Lib/test/xmltestdata/c14n-20/c14nQnameXpathElem.xml create mode 100644 Lib/test/xmltestdata/c14n-20/c14nTrim.xml create mode 100644 Lib/test/xmltestdata/c14n-20/doc.dtd create mode 100644 Lib/test/xmltestdata/c14n-20/doc.xsl create mode 100644 Lib/test/xmltestdata/c14n-20/inC14N1.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inC14N2.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inC14N3.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inC14N4.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inC14N5.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inC14N6.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inNsContent.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inNsDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inNsPushdown.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inNsRedecl.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inNsSort.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inNsSuperfluous.xml create mode 100644 Lib/test/xmltestdata/c14n-20/inNsXml.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N1_c14nComment.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N1_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N2_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N2_c14nTrim.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nPrefix.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nTrim.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N4_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N4_c14nTrim.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N5_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N5_c14nTrim.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inC14N6_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nPrefixQnameXpathElem.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nQnameElem.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nQnameXpathElem.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsDefault_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsDefault_c14nPrefix.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsPushdown_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsPushdown_c14nPrefix.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsRedecl_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsRedecl_c14nPrefix.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsSort_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsSort_c14nPrefix.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsSuperfluous_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsSuperfluous_c14nPrefix.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nDefault.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nPrefix.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nPrefixQname.xml create mode 100644 Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nQname.xml create mode 100644 Lib/test/xmltestdata/c14n-20/world.txt create mode 100644 Misc/NEWS.d/next/Library/2019-04-26-10-10-34.bpo-13611.XEF4bg.rst diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 66090af00fa16e..ef74d0c852cd75 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -465,6 +465,53 @@ Reference Functions ^^^^^^^^^ +.. function:: canonicalize(xml_data=None, *, out=None, from_file=None, **options) + + `C14N 2.0 `_ transformation function. + + Canonicalization is a way to normalise XML output in a way that allows + byte-by-byte comparisons and digital signatures. It reduced the freedom + that XML serializers have and instead generates a more constrained XML + representation. The main restrictions regard the placement of namespace + declarations, the ordering of attributes, and ignorable whitespace. + + This function takes an XML data string (*xml_data*) or a file path or + file-like object (*from_file*) as input, converts it to the canonical + form, and writes it out using the *out* file(-like) object, if provided, + or returns it as a text string if not. The output file receives text, + not bytes. It should therefore be opened in text mode with ``utf-8`` + encoding. + + Typical uses:: + + xml_data = "..." + print(canonicalize(xml_data)) + + with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file: + canonicalize(xml_data, out=out_file) + + with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file: + canonicalize(from_file="inputfile.xml", out=out_file) + + The configuration *options* are as follows: + + - *with_comments*: set to true to include comments (default: false) + - *strip_text*: set to true to strip whitespace before and after text content + (default: false) + - *rewrite_prefixes*: set to true to replace namespace prefixes by "n{number}" + (default: false) + - *qname_aware_tags*: a set of qname aware tag names in which prefixes + should be replaced in text content (default: empty) + - *qname_aware_attrs*: a set of qname aware attribute names in which prefixes + should be replaced in text content (default: empty) + - *exclude_attrs*: a set of attribute names that should not be serialised + - *exclude_tags*: a set of tag names that should not be serialised + + In the option list above, "a set" refers to any collection or iterable of + strings, no ordering is expected. + + .. versionadded:: 3.8 + .. function:: Comment(text=None) @@ -1114,6 +1161,19 @@ TreeBuilder Objects .. versionadded:: 3.8 +.. class:: C14NWriterTarget(write, *, \ + with_comments=False, strip_text=False, rewrite_prefixes=False, \ + qname_aware_tags=None, qname_aware_attrs=None, \ + exclude_attrs=None, exclude_tags=None) + + A `C14N 2.0 `_ writer. Arguments are the + same as for the :func:`canonicalize` function. This class does not build a + tree but translates the callback events directly into a serialised form + using the *write* function. + + .. versionadded:: 3.8 + + .. _elementtree-xmlparser-objects: XMLParser Objects diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index bbc55ddd63418d..37570bcad52608 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -525,6 +525,10 @@ xml external entities by default. (Contributed by Christian Heimes in :issue:`17239`.) +* The :mod:`xml.etree.ElementTree` module provides a new function + :func:`–xml.etree.ElementTree.canonicalize()` that implements C14N 2.0. + (Contributed by Stefan Behnel in :issue:`13611`.) + Optimizations ============= diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 0abc42a173d930..a59a11f025da31 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -12,6 +12,7 @@ import itertools import locale import operator +import os import pickle import sys import textwrap @@ -20,6 +21,7 @@ import warnings import weakref +from functools import partial from itertools import product, islice from test import support from test.support import TESTFN, findfile, import_fresh_module, gc_collect, swap_attr @@ -3527,6 +3529,231 @@ def test_correct_import_pyET(self): self.assertIsInstance(pyET.Element.__init__, types.FunctionType) self.assertIsInstance(pyET.XMLParser.__init__, types.FunctionType) + +# -------------------------------------------------------------------- + +def c14n_roundtrip(xml, **options): + return pyET.canonicalize(xml, **options) + + +class C14NTest(unittest.TestCase): + maxDiff = None + + # + # simple roundtrip tests (from c14n.py) + + def test_simple_roundtrip(self): + # Basics + self.assertEqual(c14n_roundtrip(""), '') + self.assertEqual(c14n_roundtrip(""), # FIXME + '') + self.assertEqual(c14n_roundtrip(""), + '') + self.assertEqual(c14n_roundtrip(""), + '') + self.assertEqual(c14n_roundtrip(""), + '') + + # C14N spec + self.assertEqual(c14n_roundtrip("Hello, world!"), + 'Hello, world!') + self.assertEqual(c14n_roundtrip("2"), + '2') + self.assertEqual(c14n_roundtrip('"0" && value<"10" ?"valid":"error"]]>'), + 'value>"0" && value<"10" ?"valid":"error"') + self.assertEqual(c14n_roundtrip('''valid'''), + 'valid') + self.assertEqual(c14n_roundtrip(""), + '') + self.assertEqual(c14n_roundtrip(""), + '') + self.assertEqual(c14n_roundtrip(""), + '') + + # fragments from PJ's tests + #self.assertEqual(c14n_roundtrip(""), + #'') + + def test_c14n_exclusion(self): + xml = textwrap.dedent("""\ + + + abtext + + btext + + dtext + + + """) + self.assertEqual( + c14n_roundtrip(xml, strip_text=True), + '' + 'abtext' + 'btext' + 'dtext' + '') + self.assertEqual( + c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr']), + '' + 'abtext' + 'btext' + 'dtext' + '') + self.assertEqual( + c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d']), + '' + 'abtext' + 'btext' + '' + '') + self.assertEqual( + c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr'], + exclude_tags=['{http://example.com/x}d']), + '' + 'abtext' + 'btext' + '' + '') + self.assertEqual( + c14n_roundtrip(xml, strip_text=True, exclude_tags=['a', 'b']), + '' + 'dtext' + '') + self.assertEqual( + c14n_roundtrip(xml, exclude_tags=['a', 'b']), + '\n' + ' \n' + ' \n' + ' \n' + ' dtext\n' + ' \n' + '') + self.assertEqual( + c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d', 'b']), + '' + '' + '' + '') + self.assertEqual( + c14n_roundtrip(xml, exclude_tags=['{http://example.com/x}d', 'b']), + '\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + '') + + # + # basic method=c14n tests from the c14n 2.0 specification. uses + # test files under xmltestdata/c14n-20. + + # note that this uses generated C14N versions of the standard ET.write + # output, not roundtripped C14N (see above). + + def test_xml_c14n2(self): + datadir = findfile("c14n-20", subdir="xmltestdata") + full_path = partial(os.path.join, datadir) + + files = [filename[:-4] for filename in sorted(os.listdir(datadir)) + if filename.endswith('.xml')] + input_files = [ + filename for filename in files + if filename.startswith('in') + ] + configs = { + filename: { + # sequential + option.tag.split('}')[-1]: ((option.text or '').strip(), option) + for option in ET.parse(full_path(filename) + ".xml").getroot() + } + for filename in files + if filename.startswith('c14n') + } + + tests = { + input_file: [ + (filename, configs[filename.rsplit('_', 1)[-1]]) + for filename in files + if filename.startswith(f'out_{input_file}_') + and filename.rsplit('_', 1)[-1] in configs + ] + for input_file in input_files + } + + # Make sure we found all test cases. + self.assertEqual(30, len([ + output_file for output_files in tests.values() + for output_file in output_files])) + + def get_option(config, option_name, default=None): + return config.get(option_name, (default, ()))[0] + + for input_file, output_files in tests.items(): + for output_file, config in output_files: + keep_comments = get_option( + config, 'IgnoreComments') == 'true' # no, it's right :) + strip_text = get_option( + config, 'TrimTextNodes') == 'true' + rewrite_prefixes = get_option( + config, 'PrefixRewrite') == 'sequential' + if 'QNameAware' in config: + qattrs = [ + f"{{{el.get('NS')}}}{el.get('Name')}" + for el in config['QNameAware'][1].findall( + '{http://www.w3.org/2010/xml-c14n2}QualifiedAttr') + ] + qtags = [ + f"{{{el.get('NS')}}}{el.get('Name')}" + for el in config['QNameAware'][1].findall( + '{http://www.w3.org/2010/xml-c14n2}Element') + ] + else: + qtags = qattrs = None + + # Build subtest description from config. + config_descr = ','.join( + f"{name}={value or ','.join(c.tag.split('}')[-1] for c in children)}" + for name, (value, children) in sorted(config.items()) + ) + + with self.subTest(f"{output_file}({config_descr})"): + if input_file == 'inNsRedecl' and not rewrite_prefixes: + self.skipTest( + f"Redeclared namespace handling is not supported in {output_file}") + if input_file == 'inNsSuperfluous' and not rewrite_prefixes: + self.skipTest( + f"Redeclared namespace handling is not supported in {output_file}") + if 'QNameAware' in config and config['QNameAware'][1].find( + '{http://www.w3.org/2010/xml-c14n2}XPathElement') is not None: + self.skipTest( + f"QName rewriting in XPath text is not supported in {output_file}") + + f = full_path(input_file + ".xml") + if input_file == 'inC14N5': + # Hack: avoid setting up external entity resolution in the parser. + with open(full_path('world.txt'), 'rb') as entity_file: + with open(f, 'rb') as f: + f = io.BytesIO(f.read().replace(b'&ent2;', entity_file.read())) + + text = ET.canonicalize( + from_file=f, + with_comments=keep_comments, + strip_text=strip_text, + rewrite_prefixes=rewrite_prefixes, + qname_aware_tags=qtags, qname_aware_attrs=qattrs) + + with open(full_path(output_file + ".xml"), 'r', encoding='utf8') as f: + expected = f.read() + if input_file == 'inC14N3': + # FIXME: cET resolves default attributes but ET does not! + expected = expected.replace(' attr="default"', '') + text = text.replace(' attr="default"', '') + self.assertEqual(expected, text) + # -------------------------------------------------------------------- @@ -3559,6 +3786,8 @@ def test_main(module=None): XMLParserTest, XMLPullParserTest, BugsTest, + KeywordArgsTest, + C14NTest, ] # These tests will only run for the pure-Python version that doesn't import diff --git a/Lib/test/xmltestdata/c14n-20/c14nComment.xml b/Lib/test/xmltestdata/c14n-20/c14nComment.xml new file mode 100644 index 00000000000000..e95aa302d04fdb --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/c14nComment.xml @@ -0,0 +1,4 @@ + + true + + diff --git a/Lib/test/xmltestdata/c14n-20/c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/c14nDefault.xml new file mode 100644 index 00000000000000..c1364142cc59bf --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/c14nDefault.xml @@ -0,0 +1,3 @@ + + + diff --git a/Lib/test/xmltestdata/c14n-20/c14nPrefix.xml b/Lib/test/xmltestdata/c14n-20/c14nPrefix.xml new file mode 100644 index 00000000000000..fb233b42b1334f --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/c14nPrefix.xml @@ -0,0 +1,4 @@ + + sequential + + diff --git a/Lib/test/xmltestdata/c14n-20/c14nPrefixQname.xml b/Lib/test/xmltestdata/c14n-20/c14nPrefixQname.xml new file mode 100644 index 00000000000000..23188eedbc2451 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/c14nPrefixQname.xml @@ -0,0 +1,7 @@ + + sequential + + + + + diff --git a/Lib/test/xmltestdata/c14n-20/c14nPrefixQnameXpathElem.xml b/Lib/test/xmltestdata/c14n-20/c14nPrefixQnameXpathElem.xml new file mode 100644 index 00000000000000..626fc48f410fa0 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/c14nPrefixQnameXpathElem.xml @@ -0,0 +1,8 @@ + + sequential + + + + + + diff --git a/Lib/test/xmltestdata/c14n-20/c14nQname.xml b/Lib/test/xmltestdata/c14n-20/c14nQname.xml new file mode 100644 index 00000000000000..919e5903f5ce6e --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/c14nQname.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Lib/test/xmltestdata/c14n-20/c14nQnameElem.xml b/Lib/test/xmltestdata/c14n-20/c14nQnameElem.xml new file mode 100644 index 00000000000000..0321f8061952e6 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/c14nQnameElem.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Lib/test/xmltestdata/c14n-20/c14nQnameXpathElem.xml b/Lib/test/xmltestdata/c14n-20/c14nQnameXpathElem.xml new file mode 100644 index 00000000000000..c4890bc8b01d5e --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/c14nQnameXpathElem.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Lib/test/xmltestdata/c14n-20/c14nTrim.xml b/Lib/test/xmltestdata/c14n-20/c14nTrim.xml new file mode 100644 index 00000000000000..ccb9cf65db7235 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/c14nTrim.xml @@ -0,0 +1,4 @@ + + true + + diff --git a/Lib/test/xmltestdata/c14n-20/doc.dtd b/Lib/test/xmltestdata/c14n-20/doc.dtd new file mode 100644 index 00000000000000..5c5d544a0df845 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/doc.dtd @@ -0,0 +1,6 @@ + + + + + + diff --git a/Lib/test/xmltestdata/c14n-20/doc.xsl b/Lib/test/xmltestdata/c14n-20/doc.xsl new file mode 100644 index 00000000000000..a3f2348cc2f2b3 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/doc.xsl @@ -0,0 +1,5 @@ + + + diff --git a/Lib/test/xmltestdata/c14n-20/inC14N1.xml b/Lib/test/xmltestdata/c14n-20/inC14N1.xml new file mode 100644 index 00000000000000..ed450c7341d382 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inC14N1.xml @@ -0,0 +1,14 @@ + + + + + + +Hello, world! + + + + + + diff --git a/Lib/test/xmltestdata/c14n-20/inC14N2.xml b/Lib/test/xmltestdata/c14n-20/inC14N2.xml new file mode 100644 index 00000000000000..74eeea147c3791 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inC14N2.xml @@ -0,0 +1,11 @@ + + + A B + + A + + B + A B + C + + diff --git a/Lib/test/xmltestdata/c14n-20/inC14N3.xml b/Lib/test/xmltestdata/c14n-20/inC14N3.xml new file mode 100644 index 00000000000000..fea78213f1ae69 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inC14N3.xml @@ -0,0 +1,18 @@ +]> + + + + + + + + + + + + + + diff --git a/Lib/test/xmltestdata/c14n-20/inC14N4.xml b/Lib/test/xmltestdata/c14n-20/inC14N4.xml new file mode 100644 index 00000000000000..909a847435b86c --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inC14N4.xml @@ -0,0 +1,13 @@ + + +]> + + First line Second line + 2 + "0" && value<"10" ?"valid":"error"]]> + valid + + + + diff --git a/Lib/test/xmltestdata/c14n-20/inC14N5.xml b/Lib/test/xmltestdata/c14n-20/inC14N5.xml new file mode 100644 index 00000000000000..501161bad5187f --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inC14N5.xml @@ -0,0 +1,12 @@ + + + + + +]> + + &ent1;, &ent2;! + + + diff --git a/Lib/test/xmltestdata/c14n-20/inC14N6.xml b/Lib/test/xmltestdata/c14n-20/inC14N6.xml new file mode 100644 index 00000000000000..31e2071867257c --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inC14N6.xml @@ -0,0 +1,2 @@ + +© diff --git a/Lib/test/xmltestdata/c14n-20/inNsContent.xml b/Lib/test/xmltestdata/c14n-20/inNsContent.xml new file mode 100644 index 00000000000000..b9924660ba6da3 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inNsContent.xml @@ -0,0 +1,4 @@ + + xsd:string + /soap-env:body/child::b:foo[@att1 != "c:val" and @att2 != 'xsd:string'] + diff --git a/Lib/test/xmltestdata/c14n-20/inNsDefault.xml b/Lib/test/xmltestdata/c14n-20/inNsDefault.xml new file mode 100644 index 00000000000000..3e0d323bad27c2 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inNsDefault.xml @@ -0,0 +1,3 @@ + + + diff --git a/Lib/test/xmltestdata/c14n-20/inNsPushdown.xml b/Lib/test/xmltestdata/c14n-20/inNsPushdown.xml new file mode 100644 index 00000000000000..daa67d83f15914 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inNsPushdown.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Lib/test/xmltestdata/c14n-20/inNsRedecl.xml b/Lib/test/xmltestdata/c14n-20/inNsRedecl.xml new file mode 100644 index 00000000000000..10bd97beda3baa --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inNsRedecl.xml @@ -0,0 +1,3 @@ + + + diff --git a/Lib/test/xmltestdata/c14n-20/inNsSort.xml b/Lib/test/xmltestdata/c14n-20/inNsSort.xml new file mode 100644 index 00000000000000..8e9fc01c647b24 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inNsSort.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Lib/test/xmltestdata/c14n-20/inNsSuperfluous.xml b/Lib/test/xmltestdata/c14n-20/inNsSuperfluous.xml new file mode 100644 index 00000000000000..f77720f7b0b09d --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inNsSuperfluous.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Lib/test/xmltestdata/c14n-20/inNsXml.xml b/Lib/test/xmltestdata/c14n-20/inNsXml.xml new file mode 100644 index 00000000000000..7520cf3fb9eb28 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/inNsXml.xml @@ -0,0 +1,3 @@ + + data + diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N1_c14nComment.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N1_c14nComment.xml new file mode 100644 index 00000000000000..d98d16840c6bcc --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N1_c14nComment.xml @@ -0,0 +1,6 @@ + +Hello, world! + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N1_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N1_c14nDefault.xml new file mode 100644 index 00000000000000..af9a9770578e9d --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N1_c14nDefault.xml @@ -0,0 +1,4 @@ + +Hello, world! + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N2_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N2_c14nDefault.xml new file mode 100644 index 00000000000000..2afa15ccb36382 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N2_c14nDefault.xml @@ -0,0 +1,11 @@ + + + A B + + A + + B + A B + C + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N2_c14nTrim.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N2_c14nTrim.xml new file mode 100644 index 00000000000000..7a1dc32946bce3 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N2_c14nTrim.xml @@ -0,0 +1 @@ +A BABA BC \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nDefault.xml new file mode 100644 index 00000000000000..662e108aa8a1e4 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nDefault.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nPrefix.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nPrefix.xml new file mode 100644 index 00000000000000..041e1ec8ebe59a --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nPrefix.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nTrim.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nTrim.xml new file mode 100644 index 00000000000000..4f35ad9662df3b --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N3_c14nTrim.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N4_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N4_c14nDefault.xml new file mode 100644 index 00000000000000..243d0e61f2e94f --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N4_c14nDefault.xml @@ -0,0 +1,10 @@ + + First line +Second line + 2 + value>"0" && value<"10" ?"valid":"error" + valid + + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N4_c14nTrim.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N4_c14nTrim.xml new file mode 100644 index 00000000000000..24d83ba8ab0012 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N4_c14nTrim.xml @@ -0,0 +1,2 @@ +First line +Second line2value>"0" && value<"10" ?"valid":"error"valid \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N5_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N5_c14nDefault.xml new file mode 100644 index 00000000000000..c232e740aee4a7 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N5_c14nDefault.xml @@ -0,0 +1,3 @@ + + Hello, world! + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N5_c14nTrim.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N5_c14nTrim.xml new file mode 100644 index 00000000000000..3fa84b1e986014 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N5_c14nTrim.xml @@ -0,0 +1 @@ +Hello, world! \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inC14N6_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inC14N6_c14nDefault.xml new file mode 100644 index 00000000000000..0be38f98cb1398 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inC14N6_c14nDefault.xml @@ -0,0 +1 @@ +© \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nDefault.xml new file mode 100644 index 00000000000000..62d7e004a44034 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nDefault.xml @@ -0,0 +1,4 @@ + + xsd:string + /soap-env:body/child::b:foo[@att1 != "c:val" and @att2 != 'xsd:string'] + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nPrefixQnameXpathElem.xml b/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nPrefixQnameXpathElem.xml new file mode 100644 index 00000000000000..20e1c2e9d6dfb4 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nPrefixQnameXpathElem.xml @@ -0,0 +1,4 @@ + + n1:string + /n3:body/child::n2:foo[@att1 != "c:val" and @att2 != 'xsd:string'] + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nQnameElem.xml b/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nQnameElem.xml new file mode 100644 index 00000000000000..db8680daa033d7 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nQnameElem.xml @@ -0,0 +1,4 @@ + + xsd:string + /soap-env:body/child::b:foo[@att1 != "c:val" and @att2 != 'xsd:string'] + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nQnameXpathElem.xml b/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nQnameXpathElem.xml new file mode 100644 index 00000000000000..df3b21579fac5e --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsContent_c14nQnameXpathElem.xml @@ -0,0 +1,4 @@ + + xsd:string + /soap-env:body/child::b:foo[@att1 != "c:val" and @att2 != 'xsd:string'] + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsDefault_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inNsDefault_c14nDefault.xml new file mode 100644 index 00000000000000..674b076dd6d9a6 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsDefault_c14nDefault.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsDefault_c14nPrefix.xml b/Lib/test/xmltestdata/c14n-20/out_inNsDefault_c14nPrefix.xml new file mode 100644 index 00000000000000..83edaae91e7423 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsDefault_c14nPrefix.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsPushdown_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inNsPushdown_c14nDefault.xml new file mode 100644 index 00000000000000..fa4f21b5d0af55 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsPushdown_c14nDefault.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsPushdown_c14nPrefix.xml b/Lib/test/xmltestdata/c14n-20/out_inNsPushdown_c14nPrefix.xml new file mode 100644 index 00000000000000..6d579200c9dc8c --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsPushdown_c14nPrefix.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsRedecl_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inNsRedecl_c14nDefault.xml new file mode 100644 index 00000000000000..ba37f925103c70 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsRedecl_c14nDefault.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsRedecl_c14nPrefix.xml b/Lib/test/xmltestdata/c14n-20/out_inNsRedecl_c14nPrefix.xml new file mode 100644 index 00000000000000..af3bb2d6f062cd --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsRedecl_c14nPrefix.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsSort_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inNsSort_c14nDefault.xml new file mode 100644 index 00000000000000..8a92c5c61c2c2c --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsSort_c14nDefault.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsSort_c14nPrefix.xml b/Lib/test/xmltestdata/c14n-20/out_inNsSort_c14nPrefix.xml new file mode 100644 index 00000000000000..8d44c84fe5d307 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsSort_c14nPrefix.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsSuperfluous_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inNsSuperfluous_c14nDefault.xml new file mode 100644 index 00000000000000..6bb862d763d737 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsSuperfluous_c14nDefault.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsSuperfluous_c14nPrefix.xml b/Lib/test/xmltestdata/c14n-20/out_inNsSuperfluous_c14nPrefix.xml new file mode 100644 index 00000000000000..700a16d42a7746 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsSuperfluous_c14nPrefix.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nDefault.xml b/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nDefault.xml new file mode 100644 index 00000000000000..1689f3bf423dc5 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nDefault.xml @@ -0,0 +1,3 @@ + + data + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nPrefix.xml b/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nPrefix.xml new file mode 100644 index 00000000000000..38508a47f6b904 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nPrefix.xml @@ -0,0 +1,3 @@ + + data + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nPrefixQname.xml b/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nPrefixQname.xml new file mode 100644 index 00000000000000..867980f82bfa59 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nPrefixQname.xml @@ -0,0 +1,3 @@ + + data + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nQname.xml b/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nQname.xml new file mode 100644 index 00000000000000..0300f9d562db30 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/out_inNsXml_c14nQname.xml @@ -0,0 +1,3 @@ + + data + \ No newline at end of file diff --git a/Lib/test/xmltestdata/c14n-20/world.txt b/Lib/test/xmltestdata/c14n-20/world.txt new file mode 100644 index 00000000000000..04fea06420ca60 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/world.txt @@ -0,0 +1 @@ +world \ No newline at end of file diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index 5b26ac72fd1aae..645e999a0be6ca 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -87,6 +87,7 @@ "XML", "XMLID", "XMLParser", "XMLPullParser", "register_namespace", + "canonicalize", "C14NWriterTarget", ] VERSION = "1.3.0" @@ -1711,6 +1712,336 @@ def close(self): del self.target, self._target +# -------------------------------------------------------------------- +# C14N 2.0 + +def canonicalize(xml_data=None, *, out=None, from_file=None, **options): + """Convert XML to its C14N 2.0 serialised form. + + If *out* is provided, it must be a file or file-like object that receives + the serialised canonical XML output (text, not bytes) through its ``.write()`` + method. To write to a file, open it in text mode with encoding "utf-8". + If *out* is not provided, this function returns the output as text string. + + Either *xml_data* (an XML string) or *from_file* (a file path or + file-like object) must be provided as input. + + The configuration options are the same as for the ``C14NWriterTarget``. + """ + if xml_data is None and from_file is None: + raise ValueError("Either 'xml_data' or 'from_file' must be provided as input") + sio = None + if out is None: + sio = out = io.StringIO() + + parser = XMLParser(target=C14NWriterTarget(out.write, **options)) + + if xml_data is not None: + parser.feed(xml_data) + parser.close() + elif from_file is not None: + parse(from_file, parser=parser) + + return sio.getvalue() if sio is not None else None + + +_looks_like_prefix_name = re.compile(r'^\w+:\w+$', re.UNICODE).match + + +class C14NWriterTarget: + """ + Canonicalization writer target for the XMLParser. + + Serialises parse events to XML C14N 2.0. + + The *write* function is used for writing out the resulting data stream + as text (not bytes). To write to a file, open it in text mode with encoding + "utf-8" and pass its ``.write`` method. + + Configuration options: + + - *with_comments*: set to true to include comments + - *strip_text*: set to true to strip whitespace before and after text content + - *rewrite_prefixes*: set to true to replace namespace prefixes by "n{number}" + - *qname_aware_tags*: a set of qname aware tag names in which prefixes + should be replaced in text content + - *qname_aware_attrs*: a set of qname aware attribute names in which prefixes + should be replaced in text content + - *exclude_attrs*: a set of attribute names that should not be serialised + - *exclude_tags*: a set of tag names that should not be serialised + """ + def __init__(self, write, *, + with_comments=False, strip_text=False, rewrite_prefixes=False, + qname_aware_tags=None, qname_aware_attrs=None, + exclude_attrs=None, exclude_tags=None): + self._write = write + self._data = [] + self._with_comments = with_comments + self._strip_text = strip_text + self._exclude_attrs = set(exclude_attrs) if exclude_attrs else None + self._exclude_tags = set(exclude_tags) if exclude_tags else None + + self._rewrite_prefixes = rewrite_prefixes + if qname_aware_tags: + self._qname_aware_tags = set(qname_aware_tags) + else: + self._qname_aware_tags = None + if qname_aware_attrs: + self._find_qname_aware_attrs = set(qname_aware_attrs).intersection + else: + self._find_qname_aware_attrs = None + + # Stack with globally and newly declared namespaces as (uri, prefix) pairs. + self._declared_ns_stack = [[ + ("http://www.w3.org/XML/1998/namespace", "xml"), + ]] + # Stack with user declared namespace prefixes as (uri, prefix) pairs. + self._ns_stack = [] + if not rewrite_prefixes: + self._ns_stack.append(list(_namespace_map.items())) + self._ns_stack.append([]) + self._prefix_map = {} + self._preserve_space = [False] + self._pending_start = None + self._root_seen = False + self._root_done = False + self._ignored_depth = 0 + + def _iter_namespaces(self, ns_stack, _reversed=reversed): + for namespaces in _reversed(ns_stack): + if namespaces: # almost no element declares new namespaces + yield from namespaces + + def _resolve_prefix_name(self, prefixed_name): + prefix, name = prefixed_name.split(':', 1) + for uri, p in self._iter_namespaces(self._ns_stack): + if p == prefix: + return f'{{{uri}}}{name}' + raise ValueError(f'Prefix {prefix} of QName "{prefixed_name}" is not declared in scope') + + def _qname(self, qname, uri=None): + if uri is None: + uri, tag = qname[1:].rsplit('}', 1) if qname[:1] == '{' else ('', qname) + else: + tag = qname + + prefixes_seen = set() + for u, prefix in self._iter_namespaces(self._declared_ns_stack): + if u == uri and prefix not in prefixes_seen: + return f'{prefix}:{tag}' if prefix else tag, tag, uri + prefixes_seen.add(prefix) + + # Not declared yet => add new declaration. + if self._rewrite_prefixes: + if uri in self._prefix_map: + prefix = self._prefix_map[uri] + else: + prefix = self._prefix_map[uri] = f'n{len(self._prefix_map)}' + self._declared_ns_stack[-1].append((uri, prefix)) + return f'{prefix}:{tag}', tag, uri + + if not uri and '' not in prefixes_seen: + # No default namespace declared => no prefix needed. + return tag, tag, uri + + for u, prefix in self._iter_namespaces(self._ns_stack): + if u == uri: + self._declared_ns_stack[-1].append((uri, prefix)) + return f'{prefix}:{tag}' if prefix else tag, tag, uri + + raise ValueError(f'Namespace "{uri}" is not declared in scope') + + def data(self, data): + if not self._ignored_depth: + self._data.append(data) + + def _flush(self, _join_text=''.join): + data = _join_text(self._data) + del self._data[:] + if self._strip_text and not self._preserve_space[-1]: + data = data.strip() + if self._pending_start is not None: + args, self._pending_start = self._pending_start, None + qname_text = data if data and _looks_like_prefix_name(data) else None + self._start(*args, qname_text) + if qname_text is not None: + return + if data and self._root_seen: + self._write(_escape_cdata_c14n(data)) + + def start_ns(self, prefix, uri): + if self._ignored_depth: + return + # we may have to resolve qnames in text content + if self._data: + self._flush() + self._ns_stack[-1].append((uri, prefix)) + + def start(self, tag, attrs): + if self._exclude_tags is not None and ( + self._ignored_depth or tag in self._exclude_tags): + self._ignored_depth += 1 + return + if self._data: + self._flush() + + new_namespaces = [] + self._declared_ns_stack.append(new_namespaces) + + if self._qname_aware_tags is not None and tag in self._qname_aware_tags: + # Need to parse text first to see if it requires a prefix declaration. + self._pending_start = (tag, attrs, new_namespaces) + return + self._start(tag, attrs, new_namespaces) + + def _start(self, tag, attrs, new_namespaces, qname_text=None): + if self._exclude_attrs is not None and attrs: + attrs = {k: v for k, v in attrs.items() if k not in self._exclude_attrs} + + qnames = {tag, *attrs} + resolved_names = {} + + # Resolve prefixes in attribute and tag text. + if qname_text is not None: + qname = resolved_names[qname_text] = self._resolve_prefix_name(qname_text) + qnames.add(qname) + if self._find_qname_aware_attrs is not None and attrs: + qattrs = self._find_qname_aware_attrs(attrs) + if qattrs: + for attr_name in qattrs: + value = attrs[attr_name] + if _looks_like_prefix_name(value): + qname = resolved_names[value] = self._resolve_prefix_name(value) + qnames.add(qname) + else: + qattrs = None + else: + qattrs = None + + # Assign prefixes in lexicographical order of used URIs. + parse_qname = self._qname + parsed_qnames = {n: parse_qname(n) for n in sorted( + qnames, key=lambda n: n.split('}', 1))} + + # Write namespace declarations in prefix order ... + if new_namespaces: + attr_list = [ + ('xmlns:' + prefix if prefix else 'xmlns', uri) + for uri, prefix in new_namespaces + ] + attr_list.sort() + else: + # almost always empty + attr_list = [] + + # ... followed by attributes in URI+name order + if attrs: + for k, v in sorted(attrs.items()): + if qattrs is not None and k in qattrs and v in resolved_names: + v = parsed_qnames[resolved_names[v]][0] + attr_qname, attr_name, uri = parsed_qnames[k] + # No prefix for attributes in default ('') namespace. + attr_list.append((attr_qname if uri else attr_name, v)) + + # Honour xml:space attributes. + space_behaviour = attrs.get('{http://www.w3.org/XML/1998/namespace}space') + self._preserve_space.append( + space_behaviour == 'preserve' if space_behaviour + else self._preserve_space[-1]) + + # Write the tag. + write = self._write + write('<' + parsed_qnames[tag][0]) + if attr_list: + write(''.join([f' {k}="{_escape_attrib_c14n(v)}"' for k, v in attr_list])) + write('>') + + # Write the resolved qname text content. + if qname_text is not None: + write(_escape_cdata_c14n(parsed_qnames[resolved_names[qname_text]][0])) + + self._root_seen = True + self._ns_stack.append([]) + + def end(self, tag): + if self._ignored_depth: + self._ignored_depth -= 1 + return + if self._data: + self._flush() + self._write(f'') + self._preserve_space.pop() + self._root_done = len(self._preserve_space) == 1 + self._declared_ns_stack.pop() + self._ns_stack.pop() + + def comment(self, text): + if not self._with_comments: + return + if self._ignored_depth: + return + if self._root_done: + self._write('\n') + elif self._root_seen and self._data: + self._flush() + self._write(f'') + if not self._root_seen: + self._write('\n') + + def pi(self, target, data): + if self._ignored_depth: + return + if self._root_done: + self._write('\n') + elif self._root_seen and self._data: + self._flush() + self._write( + f'' if data else f'') + if not self._root_seen: + self._write('\n') + + +def _escape_cdata_c14n(text): + # escape character data + try: + # it's worth avoiding do-nothing calls for strings that are + # shorter than 500 character, or so. assume that's, by far, + # the most common case in most applications. + if '&' in text: + text = text.replace('&', '&') + if '<' in text: + text = text.replace('<', '<') + if '>' in text: + text = text.replace('>', '>') + if '\r' in text: + text = text.replace('\r', ' ') + return text + except (TypeError, AttributeError): + _raise_serialization_error(text) + + +def _escape_attrib_c14n(text): + # escape attribute value + try: + if '&' in text: + text = text.replace('&', '&') + if '<' in text: + text = text.replace('<', '<') + if '"' in text: + text = text.replace('"', '"') + if '\t' in text: + text = text.replace('\t', ' ') + if '\n' in text: + text = text.replace('\n', ' ') + if '\r' in text: + text = text.replace('\r', ' ') + return text + except (TypeError, AttributeError): + _raise_serialization_error(text) + + +# -------------------------------------------------------------------- + # Import the C accelerators try: # Element is going to be shadowed by the C implementation. We need to keep diff --git a/Misc/NEWS.d/next/Library/2019-04-26-10-10-34.bpo-13611.XEF4bg.rst b/Misc/NEWS.d/next/Library/2019-04-26-10-10-34.bpo-13611.XEF4bg.rst new file mode 100644 index 00000000000000..d01decb9617ab5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-26-10-10-34.bpo-13611.XEF4bg.rst @@ -0,0 +1,2 @@ +The xml.etree.ElementTree packages gained support for C14N 2.0 serialisation. +Patch by Stefan Behnel. From b7378d77289c911ca6a0c0afaf513879002df7d5 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Wed, 1 May 2019 16:39:21 -0400 Subject: [PATCH 140/212] bpo-30458: Use InvalidURL instead of ValueError. (GH-13044) Use http.client.InvalidURL instead of ValueError as the new error case's exception. --- Lib/http/client.py | 2 +- Lib/test/test_urllib.py | 10 ++++++---- ...DA.rst => 2019-04-10-08-53-30.bpo-30458.51E-DA.rst} | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) rename Misc/NEWS.d/next/Security/{2019-04-10-08-53-30.bpo-36276.51E-DA.rst => 2019-04-10-08-53-30.bpo-30458.51E-DA.rst} (75%) diff --git a/Lib/http/client.py b/Lib/http/client.py index 99d6a68cf42823..f71a062d2b5783 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -1091,7 +1091,7 @@ def putrequest(self, method, url, skip_host=False, url = '/' # Prevent CVE-2019-9740. if match := _contains_disallowed_url_pchar_re.search(url): - raise ValueError(f"URL can't contain control characters. {url!r} " + raise InvalidURL(f"URL can't contain control characters. {url!r} " f"(found at least {match.group()!r})") request = '%s %s %s' % (method, url, self._http_vsn_str) diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index c5b23f935b275b..7214492eca9d88 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -343,11 +343,12 @@ def test_url_with_control_char_rejected(self): # calls urllib.parse.quote() on the URL which makes all of the # above attempts at injection within the url _path_ safe. escaped_char_repr = repr(char).replace('\\', r'\\') + InvalidURL = http.client.InvalidURL with self.assertRaisesRegex( - ValueError, f"contain control.*{escaped_char_repr}"): + InvalidURL, f"contain control.*{escaped_char_repr}"): urllib.request.urlopen(f"http:{schemeless_url}") with self.assertRaisesRegex( - ValueError, f"contain control.*{escaped_char_repr}"): + InvalidURL, f"contain control.*{escaped_char_repr}"): urllib.request.urlopen(f"https:{schemeless_url}") # This code path quotes the URL so there is no injection. resp = urlopen(f"http:{schemeless_url}") @@ -367,10 +368,11 @@ def test_url_with_newline_header_injection_rejected(self): # urlopen uses FancyURLOpener which goes via a codepath that # calls urllib.parse.quote() on the URL which makes all of the # above attempts at injection within the url _path_ safe. + InvalidURL = http.client.InvalidURL with self.assertRaisesRegex( - ValueError, r"contain control.*\\r.*(found at least . .)"): + InvalidURL, r"contain control.*\\r.*(found at least . .)"): urllib.request.urlopen(f"http:{schemeless_url}") - with self.assertRaisesRegex(ValueError, r"contain control.*\\n"): + with self.assertRaisesRegex(InvalidURL, r"contain control.*\\n"): urllib.request.urlopen(f"https:{schemeless_url}") # This code path quotes the URL so there is no injection. resp = urlopen(f"http:{schemeless_url}") diff --git a/Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-36276.51E-DA.rst b/Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-30458.51E-DA.rst similarity index 75% rename from Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-36276.51E-DA.rst rename to Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-30458.51E-DA.rst index 4fed4d545040e9..ed8027fb4d6420 100644 --- a/Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-36276.51E-DA.rst +++ b/Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-30458.51E-DA.rst @@ -1 +1 @@ -Address CVE-2019-9740 by disallowing URL paths with embedded whitespace or control characters through into the underlying http client request. Such potentially malicious header injection URLs now cause a ValueError to be raised. \ No newline at end of file +Address CVE-2019-9740 by disallowing URL paths with embedded whitespace or control characters through into the underlying http client request. Such potentially malicious header injection URLs now cause an http.client.InvalidURL exception to be raised. From adbf178e49113b2de0042e86a1228560475a65c5 Mon Sep 17 00:00:00 2001 From: Chris Withers Date: Wed, 1 May 2019 23:04:04 +0100 Subject: [PATCH 141/212] Mock 100% coverage (GH-13045) This was achieved by: * moving many pass statements in tests onto their own lines, so they pass line coverage and can match an easy ignore pattern if branch coverage is added later. * removing code that cannot be reached. * removing long-disabled tests. * removing unused code. * adding tests for uncovered code It turned out that removing `if __name__ == '__main__'` blocks that run unittest.main() at the bottom of test files was surprisingly contentious, so they remain and can be filtered out with an appropriate .coveragerc. --- Lib/unittest/mock.py | 61 +----- Lib/unittest/test/testmock/support.py | 3 +- Lib/unittest/test/testmock/testcallable.py | 3 +- Lib/unittest/test/testmock/testhelpers.py | 195 ++++++++++-------- .../test/testmock/testmagicmethods.py | 6 +- Lib/unittest/test/testmock/testmock.py | 126 ++++++----- Lib/unittest/test/testmock/testpatch.py | 164 ++++++--------- Lib/unittest/test/testmock/testsealable.py | 9 +- Lib/unittest/test/testmock/testwith.py | 13 +- 9 files changed, 263 insertions(+), 317 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 721e91f8cbcbae..351aba5d44d7f4 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -63,10 +63,7 @@ def _get_signature_object(func, as_instance, eat_self): """ if isinstance(func, type) and not as_instance: # If it's a type and should be modelled as a type, use __init__. - try: - func = func.__init__ - except AttributeError: - return None + func = func.__init__ # Skip the `self` argument in __init__ eat_self = True elif not isinstance(func, FunctionTypes): @@ -147,8 +144,6 @@ def _set_signature(mock, original, instance=False): # creates a function with signature (*args, **kwargs) that delegates to a # mock. It still does signature checking by calling a lambda with the same # signature as the original. - if not _callable(original): - return skipfirst = isinstance(original, type) result = _get_signature_object(original, instance, skipfirst) @@ -175,10 +170,6 @@ def checksig(*args, **kwargs): def _setup_func(funcopy, mock, sig): funcopy.mock = mock - # can't use isinstance with mocks - if not _is_instance_mock(mock): - return - def assert_called_with(*args, **kwargs): return mock.assert_called_with(*args, **kwargs) def assert_called(*args, **kwargs): @@ -263,12 +254,6 @@ def __reduce__(self): _deleted = sentinel.DELETED -def _copy(value): - if type(value) in (dict, list, tuple, set): - return type(value)(value) - return value - - _allowed_names = { 'return_value', '_mock_return_value', 'side_effect', '_mock_side_effect', '_mock_parent', '_mock_new_parent', @@ -351,8 +336,6 @@ def _check_and_set_parent(parent, value, name, new_name): class _MockIter(object): def __init__(self, obj): self.obj = iter(obj) - def __iter__(self): - return self def __next__(self): return next(self.obj) @@ -452,7 +435,7 @@ def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False, if isinstance(spec, type): _spec_class = spec else: - _spec_class = _get_class(spec) + _spec_class = type(spec) res = _get_signature_object(spec, _spec_as_instance, _eat_self) _spec_signature = res and res[1] @@ -624,7 +607,7 @@ def _extract_mock_name(self): dot = '.' if _name_list == ['()']: dot = '' - seen = set() + while _parent is not None: last = _parent @@ -635,11 +618,6 @@ def _extract_mock_name(self): _parent = _parent._mock_new_parent - # use ids here so as not to call __hash__ on the mocks - if id(_parent) in seen: - break - seen.add(id(_parent)) - _name_list = list(reversed(_name_list)) _first = last._mock_name or 'mock' if len(_name_list) > 1: @@ -753,8 +731,6 @@ def _format_mock_failure_message(self, args, kwargs): message = 'expected call not found.\nExpected: %s\nActual: %s' expected_string = self._format_mock_call_signature(args, kwargs) call_args = self.call_args - if len(call_args) == 3: - call_args = call_args[1:] actual_string = self._format_mock_call_signature(*call_args) return message % (expected_string, actual_string) @@ -992,8 +968,6 @@ def _mock_call(_mock_self, *args, **kwargs): self.call_args = _call self.call_args_list.append(_call) - seen = set() - # initial stuff for method_calls: do_method_calls = self._mock_parent is not None method_call_name = self._mock_name @@ -1029,13 +1003,6 @@ def _mock_call(_mock_self, *args, **kwargs): # follow the parental chain: _new_parent = _new_parent._mock_new_parent - # check we're not in an infinite loop: - # ( use ids here so as not to call __hash__ on the mocks) - _new_parent_id = id(_new_parent) - if _new_parent_id in seen: - break - seen.add(_new_parent_id) - effect = self.side_effect if effect is not None: if _is_exception(effect): @@ -1858,12 +1825,7 @@ def _set_return_value(mock, method, name): return_calulator = _calculate_return_value.get(name) if return_calulator is not None: - try: - return_value = return_calulator(mock) - except AttributeError: - # XXXX why do we return AttributeError here? - # set it as a side_effect instead? - return_value = AttributeError(name) + return_value = return_calulator(mock) method.return_value = return_value return @@ -1943,10 +1905,6 @@ def __init__(self, name, parent): self.name = name self.parent = parent - def __call__(self, *args, **kwargs): - m = self.create_mock() - return m(*args, **kwargs) - def create_mock(self): entry = self.name parent = self.parent @@ -2330,19 +2288,10 @@ def _must_skip(spec, entry, is_type): else: return False - # shouldn't get here unless function is a dynamically provided attribute - # XXXX untested behaviour + # function is a dynamically provided attribute return is_type -def _get_class(obj): - try: - return obj.__class__ - except AttributeError: - # it is possible for objects to have no __class__ - return type(obj) - - class _SpecState(object): def __init__(self, spec, spec_set=False, parent=None, diff --git a/Lib/unittest/test/testmock/support.py b/Lib/unittest/test/testmock/support.py index f146be244e9c40..49986d65dc47af 100644 --- a/Lib/unittest/test/testmock/support.py +++ b/Lib/unittest/test/testmock/support.py @@ -9,8 +9,7 @@ def is_instance(obj, klass): class SomeClass(object): class_attribute = None - def wibble(self): - pass + def wibble(self): pass class X(object): diff --git a/Lib/unittest/test/testmock/testcallable.py b/Lib/unittest/test/testmock/testcallable.py index 34474c4c816e0a..5eadc007049400 100644 --- a/Lib/unittest/test/testmock/testcallable.py +++ b/Lib/unittest/test/testmock/testcallable.py @@ -98,8 +98,7 @@ def test_patch_spec_set_instance(self): def test_patch_spec_callable_class(self): class CallableX(X): - def __call__(self): - pass + def __call__(self): pass class Sub(CallableX): pass diff --git a/Lib/unittest/test/testmock/testhelpers.py b/Lib/unittest/test/testmock/testhelpers.py index e321976aeb9f1a..301bca430c131c 100644 --- a/Lib/unittest/test/testmock/testhelpers.py +++ b/Lib/unittest/test/testmock/testhelpers.py @@ -12,12 +12,9 @@ from functools import partial class SomeClass(object): - def one(self, a, b): - pass - def two(self): - pass - def three(self, a=None): - pass + def one(self, a, b): pass + def two(self): pass + def three(self, a=None): pass @@ -48,12 +45,9 @@ def test_any_and_datetime(self): def test_any_mock_calls_comparison_order(self): mock = Mock() - d = datetime.now() class Foo(object): - def __eq__(self, other): - return False - def __ne__(self, other): - return True + def __eq__(self, other): pass + def __ne__(self, other): pass for d in datetime.now(), Foo(): mock.reset_mock() @@ -378,8 +372,7 @@ def test_basic(self): def test_create_autospec_return_value(self): - def f(): - pass + def f(): pass mock = create_autospec(f, return_value='foo') self.assertEqual(mock(), 'foo') @@ -399,8 +392,7 @@ def test_autospec_reset_mock(self): def test_mocking_unbound_methods(self): class Foo(object): - def foo(self, foo): - pass + def foo(self, foo): pass p = patch.object(Foo, 'foo') mock_foo = p.start() Foo().foo(1) @@ -408,24 +400,6 @@ def foo(self, foo): mock_foo.assert_called_with(1) - def test_create_autospec_unbound_methods(self): - # see mock issue 128 - # this is expected to fail until the issue is fixed - return - class Foo(object): - def foo(self): - pass - - klass = create_autospec(Foo) - instance = klass() - self.assertRaises(TypeError, instance.foo, 1) - - # Note: no type checking on the "self" parameter - klass.foo(1) - klass.foo.assert_called_with(1) - self.assertRaises(TypeError, klass.foo) - - def test_create_autospec_keyword_arguments(self): class Foo(object): a = 3 @@ -434,8 +408,7 @@ class Foo(object): def test_create_autospec_keyword_only_arguments(self): - def foo(a, *, b=None): - pass + def foo(a, *, b=None): pass m = create_autospec(foo) m(1) @@ -448,8 +421,7 @@ def foo(a, *, b=None): def test_function_as_instance_attribute(self): obj = SomeClass() - def f(a): - pass + def f(a): pass obj.f = f mock = create_autospec(obj) @@ -485,13 +457,57 @@ class Sub(SomeClass): self._check_someclass_mock(mock) + def test_spec_has_descriptor_returning_function(self): + + class CrazyDescriptor(object): + + def __get__(self, obj, type_): + if obj is None: + return lambda x: None + + class MyClass(object): + + some_attr = CrazyDescriptor() + + mock = create_autospec(MyClass) + mock.some_attr(1) + with self.assertRaises(TypeError): + mock.some_attr() + with self.assertRaises(TypeError): + mock.some_attr(1, 2) + + + def test_spec_has_function_not_in_bases(self): + + class CrazyClass(object): + + def __dir__(self): + return super(CrazyClass, self).__dir__()+['crazy'] + + def __getattr__(self, item): + if item == 'crazy': + return lambda x: x + raise AttributeError(item) + + inst = CrazyClass() + with self.assertRaises(AttributeError): + inst.other + self.assertEqual(inst.crazy(42), 42) + + mock = create_autospec(inst) + mock.crazy(42) + with self.assertRaises(TypeError): + mock.crazy() + with self.assertRaises(TypeError): + mock.crazy(1, 2) + + def test_builtin_functions_types(self): # we could replace builtin functions / methods with a function # with *args / **kwargs signature. Using the builtin method type # as a spec seems to work fairly well though. class BuiltinSubclass(list): - def bar(self, arg): - pass + def bar(self, arg): pass sorted = sorted attr = {} @@ -565,17 +581,13 @@ class Sub(SomeClass): def test_descriptors(self): class Foo(object): @classmethod - def f(cls, a, b): - pass + def f(cls, a, b): pass @staticmethod - def g(a, b): - pass + def g(a, b): pass - class Bar(Foo): - pass + class Bar(Foo): pass - class Baz(SomeClass, Bar): - pass + class Baz(SomeClass, Bar): pass for spec in (Foo, Foo(), Bar, Bar(), Baz, Baz()): mock = create_autospec(spec) @@ -588,8 +600,7 @@ class Baz(SomeClass, Bar): def test_recursive(self): class A(object): - def a(self): - pass + def a(self): pass foo = 'foo bar baz' bar = foo @@ -611,11 +622,9 @@ def a(self): def test_spec_inheritance_for_classes(self): class Foo(object): - def a(self, x): - pass + def a(self, x): pass class Bar(object): - def f(self, y): - pass + def f(self, y): pass class_mock = create_autospec(Foo) @@ -695,8 +704,7 @@ def test_builtins(self): def test_function(self): - def f(a, b): - pass + def f(a, b): pass mock = create_autospec(f) self.assertRaises(TypeError, mock) @@ -726,9 +734,10 @@ class RaiserClass(object): def existing(a, b): return a + b + self.assertEqual(RaiserClass.existing(1, 2), 3) s = create_autospec(RaiserClass) self.assertRaises(TypeError, lambda x: s.existing(1, 2, 3)) - s.existing(1, 2) + self.assertEqual(s.existing(1, 2), s.existing.return_value) self.assertRaises(AttributeError, lambda: s.nonexisting) # check we can fetch the raiser attribute and it has no spec @@ -738,8 +747,7 @@ def existing(a, b): def test_signature_class(self): class Foo(object): - def __init__(self, a, b=3): - pass + def __init__(self, a, b=3): pass mock = create_autospec(Foo) @@ -765,10 +773,8 @@ class Foo(object): def test_signature_callable(self): class Callable(object): - def __init__(self, x, y): - pass - def __call__(self, a): - pass + def __init__(self, x, y): pass + def __call__(self, a): pass mock = create_autospec(Callable) mock(1, 2) @@ -824,8 +830,7 @@ class Foo(object): def test_autospec_functions_with_self_in_odd_place(self): class Foo(object): - def f(a, self): - pass + def f(a, self): pass a = create_autospec(Foo) a.f(10) @@ -842,12 +847,9 @@ def __init__(self, value): self.value = value def __get__(self, obj, cls=None): - if obj is None: - return self - return self.value + return self - def __set__(self, obj, value): - pass + def __set__(self, obj, value): pass class MyProperty(property): pass @@ -856,12 +858,10 @@ class Foo(object): __slots__ = ['slot'] @property - def prop(self): - return 3 + def prop(self): pass @MyProperty - def subprop(self): - return 4 + def subprop(self): pass desc = Descriptor(42) @@ -913,8 +913,7 @@ def __getattr__(self, attribute): def test_spec_inspect_signature(self): - def myfunc(x, y): - pass + def myfunc(x, y): pass mock = create_autospec(myfunc) mock(1, 2) @@ -930,6 +929,7 @@ def test_spec_inspect_signature_annotations(self): def foo(a: int, b: int=10, *, c:int) -> int: return a + b + c + self.assertEqual(foo(1, 2 , c=3), 6) mock = create_autospec(foo) mock(1, 2, c=3) mock(1, c=3) @@ -940,6 +940,42 @@ def foo(a: int, b: int=10, *, c:int) -> int: self.assertRaises(TypeError, mock, 1, 2, 3, c=4) + def test_spec_function_no_name(self): + func = lambda: 'nope' + mock = create_autospec(func) + self.assertEqual(mock.__name__, 'funcopy') + + + def test_spec_function_assert_has_calls(self): + def f(a): pass + mock = create_autospec(f) + mock(1) + mock.assert_has_calls([call(1)]) + with self.assertRaises(AssertionError): + mock.assert_has_calls([call(2)]) + + + def test_spec_function_assert_any_call(self): + def f(a): pass + mock = create_autospec(f) + mock(1) + mock.assert_any_call(1) + with self.assertRaises(AssertionError): + mock.assert_any_call(2) + + + def test_spec_function_reset_mock(self): + def f(a): pass + rv = Mock() + mock = create_autospec(f, return_value=rv) + mock(1)(2) + self.assertEqual(mock.mock_calls, [call(1)]) + self.assertEqual(rv.mock_calls, [call(2)]) + mock.reset_mock() + self.assertEqual(mock.mock_calls, []) + self.assertEqual(rv.mock_calls, []) + + class TestCallList(unittest.TestCase): def test_args_list_contains_call_list(self): @@ -1019,16 +1055,14 @@ def test_type(self): def test_call_magic_method(self): class Callable: - def __call__(self): - pass + def __call__(self): pass instance = Callable() self.assertTrue(_callable(instance)) def test_staticmethod(self): class WithStaticMethod: @staticmethod - def staticfunc(): - pass + def staticfunc(): pass self.assertTrue(_callable(WithStaticMethod.staticfunc)) def test_non_callable_staticmethod(self): @@ -1039,8 +1073,7 @@ class BadStaticMethod: def test_classmethod(self): class WithClassMethod: @classmethod - def classfunc(cls): - pass + def classfunc(cls): pass self.assertTrue(_callable(WithClassMethod.classfunc)) def test_non_callable_classmethod(self): diff --git a/Lib/unittest/test/testmock/testmagicmethods.py b/Lib/unittest/test/testmock/testmagicmethods.py index 69dfe60f7eaed2..130a3397ba0d8c 100644 --- a/Lib/unittest/test/testmock/testmagicmethods.py +++ b/Lib/unittest/test/testmock/testmagicmethods.py @@ -305,8 +305,7 @@ def test_magic_methods_fspath(self): def test_magic_methods_and_spec(self): class Iterable(object): - def __iter__(self): - pass + def __iter__(self): pass mock = Mock(spec=Iterable) self.assertRaises(AttributeError, lambda: mock.__iter__) @@ -330,8 +329,7 @@ def set_int(): def test_magic_methods_and_spec_set(self): class Iterable(object): - def __iter__(self): - pass + def __iter__(self): pass mock = Mock(spec_set=Iterable) self.assertRaises(AttributeError, lambda: mock.__iter__) diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index 9bef51abd87f51..5f917dd20f1dde 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -28,16 +28,13 @@ def next(self): class Something(object): - def meth(self, a, b, c, d=None): - pass + def meth(self, a, b, c, d=None): pass @classmethod - def cmeth(cls, a, b, c, d=None): - pass + def cmeth(cls, a, b, c, d=None): pass @staticmethod - def smeth(a, b, c, d=None): - pass + def smeth(a, b, c, d=None): pass class MockTest(unittest.TestCase): @@ -83,6 +80,21 @@ def test_return_value_in_constructor(self): "return value in constructor not honoured") + def test_change_return_value_via_delegate(self): + def f(): pass + mock = create_autospec(f) + mock.mock.return_value = 1 + self.assertEqual(mock(), 1) + + + def test_change_side_effect_via_delegate(self): + def f(): pass + mock = create_autospec(f) + mock.mock.side_effect = TypeError() + with self.assertRaises(TypeError): + mock() + + def test_repr(self): mock = Mock(name='foo') self.assertIn('foo', repr(mock)) @@ -161,8 +173,7 @@ def test_autospec_side_effect(self): results = [1, 2, 3] def effect(): return results.pop() - def f(): - pass + def f(): pass mock = create_autospec(f) mock.side_effect = [1, 2, 3] @@ -177,8 +188,7 @@ def f(): def test_autospec_side_effect_exception(self): # Test for issue 23661 - def f(): - pass + def f(): pass mock = create_autospec(f) mock.side_effect = ValueError('Bazinga!') @@ -340,8 +350,7 @@ def test_assert_called_with_any(self): def test_assert_called_with_function_spec(self): - def f(a, b, c, d=None): - pass + def f(a, b, c, d=None): pass mock = Mock(spec=f) @@ -409,8 +418,7 @@ def test_assert_called_once_with_call_list(self): def test_assert_called_once_with_function_spec(self): - def f(a, b, c, d=None): - pass + def f(a, b, c, d=None): pass mock = Mock(spec=f) @@ -514,8 +522,7 @@ def test_from_spec(self): class Something(object): x = 3 __something__ = None - def y(self): - pass + def y(self): pass def test_attributes(mock): # should work @@ -601,8 +608,7 @@ def method(self): def test_customize_wrapped_object_with_side_effect_iterable(self): class Real(object): - def method(self): - raise NotImplementedError() + def method(self): pass real = Real() mock = Mock(wraps=real) @@ -615,8 +621,7 @@ def method(self): def test_customize_wrapped_object_with_side_effect_exception(self): class Real(object): - def method(self): - raise NotImplementedError() + def method(self): pass real = Real() mock = Mock(wraps=real) @@ -627,9 +632,7 @@ def method(self): def test_customize_wrapped_object_with_side_effect_function(self): class Real(object): - def method(self): - raise NotImplementedError() - + def method(self): pass def side_effect(): return sentinel.VALUE @@ -642,8 +645,7 @@ def side_effect(): def test_customize_wrapped_object_with_return_value(self): class Real(object): - def method(self): - raise NotImplementedError() + def method(self): pass real = Real() mock = Mock(wraps=real) @@ -655,8 +657,7 @@ def method(self): def test_customize_wrapped_object_with_return_value_and_side_effect(self): # side_effect should always take precedence over return_value. class Real(object): - def method(self): - raise NotImplementedError() + def method(self): pass real = Real() mock = Mock(wraps=real) @@ -671,8 +672,7 @@ def method(self): def test_customize_wrapped_object_with_return_value_and_side_effect2(self): # side_effect can return DEFAULT to default to return_value class Real(object): - def method(self): - raise NotImplementedError() + def method(self): pass real = Real() mock = Mock(wraps=real) @@ -684,8 +684,7 @@ def method(self): def test_customize_wrapped_object_with_return_value_and_side_effect_default(self): class Real(object): - def method(self): - raise NotImplementedError() + def method(self): pass real = Real() mock = Mock(wraps=real) @@ -764,6 +763,26 @@ class X(object): self.assertIsInstance(mock, X) + def test_spec_class_no_object_base(self): + class X: + pass + + mock = Mock(spec=X) + self.assertIsInstance(mock, X) + + mock = Mock(spec=X()) + self.assertIsInstance(mock, X) + + self.assertIs(mock.__class__, X) + self.assertEqual(Mock().__class__.__name__, 'Mock') + + mock = Mock(spec_set=X) + self.assertIsInstance(mock, X) + + mock = Mock(spec_set=X()) + self.assertIsInstance(mock, X) + + def test_setting_attribute_with_spec_set(self): class X(object): y = 3 @@ -902,15 +921,9 @@ def test_configure_mock(self): def assertRaisesWithMsg(self, exception, message, func, *args, **kwargs): # needed because assertRaisesRegex doesn't work easily with newlines - try: + with self.assertRaises(exception) as context: func(*args, **kwargs) - except: - instance = sys.exc_info()[1] - self.assertIsInstance(instance, exception) - else: - self.fail('Exception %r not raised' % (exception,)) - - msg = str(instance) + msg = str(context.exception) self.assertEqual(msg, message) @@ -1099,6 +1112,18 @@ def test_mock_call_repr(self): self.assertEqual(repr(m.mock_calls[2]), 'call.foo().bar().baz.bob()') + def test_mock_call_repr_loop(self): + m = Mock() + m.foo = m + repr(m.foo()) + self.assertRegex(repr(m.foo()), r"") + + + def test_mock_calls_contains(self): + m = Mock() + self.assertFalse([call()] in m.mock_calls) + + def test_subclassing(self): class Subclass(Mock): pass @@ -1312,8 +1337,7 @@ def test_assert_has_calls(self): def test_assert_has_calls_with_function_spec(self): - def f(a, b, c, d=None): - pass + def f(a, b, c, d=None): pass mock = Mock(spec=f) @@ -1371,8 +1395,7 @@ def test_assert_any_call(self): def test_assert_any_call_with_function_spec(self): - def f(a, b, c, d=None): - pass + def f(a, b, c, d=None): pass mock = Mock(spec=f) @@ -1391,8 +1414,7 @@ def f(a, b, c, d=None): def test_mock_calls_create_autospec(self): - def f(a, b): - pass + def f(a, b): pass obj = Iter() obj.f = f @@ -1417,12 +1439,10 @@ def test_create_autospec_with_name(self): def test_create_autospec_classmethod_and_staticmethod(self): class TestClass: @classmethod - def class_method(cls): - pass + def class_method(cls): pass @staticmethod - def static_method(): - pass + def static_method(): pass for method in ('class_method', 'static_method'): with self.subTest(method=method): mock_method = mock.create_autospec(getattr(TestClass, method)) @@ -1848,8 +1868,7 @@ def test_parent_attribute_of_call(self): def test_parent_propagation_with_create_autospec(self): - def foo(a, b): - pass + def foo(a, b): pass mock = Mock() mock.child = create_autospec(foo) @@ -1878,11 +1897,12 @@ def test_isinstance_under_settrace(self): with patch.dict('sys.modules'): del sys.modules['unittest.mock'] - def trace(frame, event, arg): + # This trace will stop coverage being measured ;-) + def trace(frame, event, arg): # pragma: no cover return trace + self.addCleanup(sys.settrace, sys.gettrace()) sys.settrace(trace) - self.addCleanup(sys.settrace, None) from unittest.mock import ( Mock, MagicMock, NonCallableMock, NonCallableMagicMock diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index e5abd9bda489fc..3295c5b2420e88 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -43,31 +43,24 @@ def __delattr__(self, name): class Foo(object): - def __init__(self, a): - pass - def f(self, a): - pass - def g(self): - pass + def __init__(self, a): pass + def f(self, a): pass + def g(self): pass foo = 'bar' @staticmethod - def static_method(): - return 24 + def static_method(): pass @classmethod - def class_method(cls): - return 42 + def class_method(cls): pass class Bar(object): - def a(self): - pass + def a(self): pass foo_name = '%s.Foo' % __name__ -def function(a, b=Foo): - pass +def function(a, b=Foo): pass class Container(object): @@ -370,31 +363,19 @@ def test(): def test_patch_wont_create_by_default(self): - try: + with self.assertRaises(AttributeError): @patch('%s.frooble' % builtin_string, sentinel.Frooble) - def test(): - self.assertEqual(frooble, sentinel.Frooble) + def test(): pass test() - except AttributeError: - pass - else: - self.fail('Patching non existent attributes should fail') - self.assertRaises(NameError, lambda: frooble) def test_patchobject_wont_create_by_default(self): - try: + with self.assertRaises(AttributeError): @patch.object(SomeClass, 'ord', sentinel.Frooble) - def test(): - self.fail('Patching non existent attributes should fail') - + def test(): pass test() - except AttributeError: - pass - else: - self.fail('Patching non existent attributes should fail') self.assertFalse(hasattr(SomeClass, 'ord')) @@ -484,6 +465,9 @@ class Something(object): attribute = sentinel.Original class Foo(object): + + test_class_attr = 'whatever' + def test_method(other_self, mock_something): self.assertEqual(PTModule.something, mock_something, "unpatched") @@ -642,8 +626,7 @@ def test_name_preserved(self): @patch('%s.SomeClass' % __name__, object(), autospec=True) @patch.object(SomeClass, object()) @patch.dict(foo) - def some_name(): - pass + def some_name(): pass self.assertEqual(some_name.__name__, 'some_name') @@ -654,12 +637,9 @@ def test_patch_with_exception(self): @patch.dict(foo, {'a': 'b'}) def test(): raise NameError('Konrad') - try: + + with self.assertRaises(NameError): test() - except NameError: - pass - else: - self.fail('NameError not raised by test') self.assertEqual(foo, {}) @@ -689,49 +669,6 @@ def test(): support.target = original - def test_patch_descriptor(self): - # would be some effort to fix this - we could special case the - # builtin descriptors: classmethod, property, staticmethod - return - class Nothing(object): - foo = None - - class Something(object): - foo = {} - - @patch.object(Nothing, 'foo', 2) - @classmethod - def klass(cls): - self.assertIs(cls, Something) - - @patch.object(Nothing, 'foo', 2) - @staticmethod - def static(arg): - return arg - - @patch.dict(foo) - @classmethod - def klass_dict(cls): - self.assertIs(cls, Something) - - @patch.dict(foo) - @staticmethod - def static_dict(arg): - return arg - - # these will raise exceptions if patching descriptors is broken - self.assertEqual(Something.static('f00'), 'f00') - Something.klass() - self.assertEqual(Something.static_dict('f00'), 'f00') - Something.klass_dict() - - something = Something() - self.assertEqual(something.static('f00'), 'f00') - something.klass() - self.assertEqual(something.static_dict('f00'), 'f00') - something.klass_dict() - - def test_patch_spec_set(self): @patch('%s.SomeClass' % __name__, spec=SomeClass, spec_set=True) def test(MockClass): @@ -931,17 +868,13 @@ def test_patch_dict_keyword_args(self): def test_autospec(self): class Boo(object): - def __init__(self, a): - pass - def f(self, a): - pass - def g(self): - pass + def __init__(self, a): pass + def f(self, a): pass + def g(self): pass foo = 'bar' class Bar(object): - def a(self): - pass + def a(self): pass def _test(mock): mock(1) @@ -1488,20 +1421,17 @@ def test_nested_patch_failure(self): @patch.object(Foo, 'g', 1) @patch.object(Foo, 'missing', 1) @patch.object(Foo, 'f', 1) - def thing1(): - pass + def thing1(): pass @patch.object(Foo, 'missing', 1) @patch.object(Foo, 'g', 1) @patch.object(Foo, 'f', 1) - def thing2(): - pass + def thing2(): pass @patch.object(Foo, 'g', 1) @patch.object(Foo, 'f', 1) @patch.object(Foo, 'missing', 1) - def thing3(): - pass + def thing3(): pass for func in thing1, thing2, thing3: self.assertRaises(AttributeError, func) @@ -1520,20 +1450,17 @@ def crasher(): @patch.object(Foo, 'g', 1) @patch.object(Foo, 'foo', new_callable=crasher) @patch.object(Foo, 'f', 1) - def thing1(): - pass + def thing1(): pass @patch.object(Foo, 'foo', new_callable=crasher) @patch.object(Foo, 'g', 1) @patch.object(Foo, 'f', 1) - def thing2(): - pass + def thing2(): pass @patch.object(Foo, 'g', 1) @patch.object(Foo, 'f', 1) @patch.object(Foo, 'foo', new_callable=crasher) - def thing3(): - pass + def thing3(): pass for func in thing1, thing2, thing3: self.assertRaises(NameError, func) @@ -1559,8 +1486,7 @@ def test_patch_multiple_failure(self): patcher.additional_patchers = additionals @patcher - def func(): - pass + def func(): pass self.assertRaises(AttributeError, func) self.assertEqual(Foo.f, original_f) @@ -1588,8 +1514,7 @@ def crasher(): patcher.additional_patchers = additionals @patcher - def func(): - pass + def func(): pass self.assertRaises(NameError, func) self.assertEqual(Foo.f, original_f) @@ -1898,5 +1823,36 @@ def foo(*a, x=0): self.assertEqual(foo(), 1) self.assertEqual(foo(), 0) + def test_dotted_but_module_not_loaded(self): + # This exercises the AttributeError branch of _dot_lookup. + + # make sure it's there + import unittest.test.testmock.support + # now make sure it's not: + with patch.dict('sys.modules'): + del sys.modules['unittest.test.testmock.support'] + del sys.modules['unittest.test.testmock'] + del sys.modules['unittest.test'] + del sys.modules['unittest'] + + # now make sure we can patch based on a dotted path: + @patch('unittest.test.testmock.support.X') + def test(mock): + pass + test() + + + def test_invalid_target(self): + with self.assertRaises(TypeError): + patch('') + + + def test_cant_set_kwargs_when_passing_a_mock(self): + @patch('unittest.test.testmock.support.X', new=object(), x=1) + def test(): pass + with self.assertRaises(TypeError): + test() + + if __name__ == '__main__': unittest.main() diff --git a/Lib/unittest/test/testmock/testsealable.py b/Lib/unittest/test/testmock/testsealable.py index 0e72b32411c646..59f52338d411e6 100644 --- a/Lib/unittest/test/testmock/testsealable.py +++ b/Lib/unittest/test/testmock/testsealable.py @@ -3,15 +3,10 @@ class SampleObject: - def __init__(self): - self.attr_sample1 = 1 - self.attr_sample2 = 1 - def method_sample1(self): - pass + def method_sample1(self): pass - def method_sample2(self): - pass + def method_sample2(self): pass class TestSealable(unittest.TestCase): diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py index ec4e540dcfd941..37100b8c1834b3 100644 --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -10,6 +10,8 @@ something_else = sentinel.SomethingElse +class SampleException(Exception): pass + class WithTest(unittest.TestCase): @@ -20,14 +22,10 @@ def test_with_statement(self): def test_with_statement_exception(self): - try: + with self.assertRaises(SampleException): with patch('%s.something' % __name__, sentinel.Something2): self.assertEqual(something, sentinel.Something2, "unpatched") - raise Exception('pow') - except Exception: - pass - else: - self.fail("patch swallowed exception") + raise SampleException() self.assertEqual(something, sentinel.Something) @@ -128,8 +126,7 @@ def test_dict_context_manager(self): def test_double_patch_instance_method(self): class C: - def f(self): - pass + def f(self): pass c = C() From 482b6b565af896cda0c78e5e266d11666c822d91 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Wed, 1 May 2019 17:48:13 -0700 Subject: [PATCH 142/212] Move dangling bullet points into named subsections (GH-13046) --- Doc/whatsnew/3.8.rst | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 37570bcad52608..30ee14c3610f23 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -216,17 +216,6 @@ New Modules Improved Modules ================ -* The :meth:`_asdict()` method for :func:`collections.namedtuple` now returns - a :class:`dict` instead of a :class:`collections.OrderedDict`. This works because - regular dicts have guaranteed ordering in since Python 3.7. If the extra - features of :class:`OrderedDict` are required, the suggested remediation is - to cast the result to the desired type: ``OrderedDict(nt._asdict())``. - (Contributed by Raymond Hettinger in :issue:`35864`.) - -* The :mod:`unicodedata` module has been upgraded to use the `Unicode 12.0.0 - `_ - release. - asyncio ------- @@ -234,6 +223,17 @@ asyncio On Windows, the default event loop is now :class:`~asyncio.ProactorEventLoop`. +collections +----------- + +The :meth:`_asdict()` method for :func:`collections.namedtuple` now returns +a :class:`dict` instead of a :class:`collections.OrderedDict`. This works because +regular dicts have guaranteed ordering in since Python 3.7. If the extra +features of :class:`OrderedDict` are required, the suggested remediation is +to cast the result to the desired type: ``OrderedDict(nt._asdict())``. +(Contributed by Raymond Hettinger in :issue:`35864`.) + + ctypes ------ @@ -490,10 +490,15 @@ Added new clock :data:`~time.CLOCK_UPTIME_RAW` for macOS 10.12. unicodedata ----------- +* The :mod:`unicodedata` module has been upgraded to use the `Unicode 12.0.0 + `_ + release. + * New function :func:`~unicodedata.is_normalized` can be used to verify a string is in a specific normal form. (Contributed by Max Belanger and David Euresti in :issue:`32285`). + unittest -------- From 671d782f8dc52942dc8c48a513bf24ff8465b112 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Wed, 1 May 2019 17:49:12 -0700 Subject: [PATCH 143/212] bpo-36018: Update example to show mean and stdev (GH-13047) --- Doc/whatsnew/3.8.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 30ee14c3610f23..c958fc36d667c0 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -424,8 +424,10 @@ and manipulating normal distributions of a random variable. :: >>> temperature_feb = NormalDist.from_samples([4, 12, -3, 2, 7, 14]) - >>> temperature_feb - NormalDist(mu=6.0, sigma=6.356099432828281) + >>> temperature_feb.mean + 6.0 + >>> temperature_feb.stdev + 6.356099432828281 >>> temperature_feb.cdf(3) # Chance of being under 3 degrees 0.3184678262814532 @@ -433,8 +435,8 @@ and manipulating normal distributions of a random variable. >>> temperature_feb.pdf(7) / temperature_feb.pdf(10) 1.2039930378537762 - >>> el_nino = NormalDist(4, 2.5) - >>> temperature_feb += el_nino # Add in a climate effect + >>> el_niño = NormalDist(4, 2.5) + >>> temperature_feb += el_niño # Add in a climate effect >>> temperature_feb NormalDist(mu=10.0, sigma=6.830080526611674) From 11e4a941e9c6225776a986b05230a1963e83f4fb Mon Sep 17 00:00:00 2001 From: Xtreak Date: Thu, 2 May 2019 08:19:50 +0530 Subject: [PATCH 144/212] Change bisect to bisect_cmd in docstring (#13040) --- Lib/test/bisect_cmd.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/bisect_cmd.py b/Lib/test/bisect_cmd.py index 968537e0f8019f..cb06480e7c91fa 100755 --- a/Lib/test/bisect_cmd.py +++ b/Lib/test/bisect_cmd.py @@ -4,17 +4,17 @@ Find the test_os test method which alters the environment: - ./python -m test.bisect --fail-env-changed test_os + ./python -m test.bisect_cmd --fail-env-changed test_os Find a reference leak in "test_os", write the list of failing tests into the "bisect" file: - ./python -m test.bisect -o bisect -R 3:3 test_os + ./python -m test.bisect_cmd -o bisect -R 3:3 test_os Load an existing list of tests from a file using -i option: ./python -m test --list-cases -m FileTests test_os > tests - ./python -m test.bisect -i tests test_os + ./python -m test.bisect_cmd -i tests test_os """ import argparse From cb9fbd35885a8921b9df99e801df4f82e3ba336b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 1 May 2019 23:51:56 -0400 Subject: [PATCH 145/212] bpo-36763: Make _PyCoreConfig.check_hash_pycs_mode public (GH-13052) _PyCoreConfig: Rename _check_hash_pycs_mode field to check_hash_pycs_mode (make it public) and change its type from "const char*" to "wchar_t*". --- Include/cpython/coreconfig.h | 7 +++---- Lib/test/test_embed.py | 4 ++-- Programs/_testembed.c | 2 +- Python/coreconfig.c | 30 +++++++++++++++++++++--------- Python/import.c | 2 +- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index 5743bf5d0fa4ac..99388e635c75b3 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -363,7 +363,7 @@ typedef struct { Needed by freeze_importlib. */ int _install_importlib; - /* Value of the --check-hash-based-pycs configure option. Valid values: + /* Value of the --check-hash-based-pycs command line option: - "default" means the 'check_source' flag in hash-based pycs determines invalidation @@ -372,11 +372,10 @@ typedef struct { - "never" causes the interpreter to always assume hash-based pycs are valid - Set by the --check-hash-based-pycs command line option. The default value is "default". See PEP 552 "Deterministic pycs" for more details. */ - const char *_check_hash_pycs_mode; + wchar_t *check_hash_pycs_mode; /* If greater than 0, suppress _PyPathConfig_Calculate() warnings. @@ -418,7 +417,7 @@ typedef struct { .user_site_directory = -1, \ .buffered_stdio = -1, \ ._install_importlib = 1, \ - ._check_hash_pycs_mode = "default", \ + .check_hash_pycs_mode = NULL, \ ._frozen = -1, \ ._init_main = 1} /* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */ diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index cd6027205a9201..fb0051957aad0c 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -346,7 +346,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'run_filename': None, '_install_importlib': 1, - '_check_hash_pycs_mode': 'default', + 'check_hash_pycs_mode': 'default', '_frozen': 0, '_init_main': 1, } @@ -577,7 +577,7 @@ def test_init_from_config(self): 'user_site_directory': 0, 'faulthandler': 1, - '_check_hash_pycs_mode': 'always', + 'check_hash_pycs_mode': 'always', '_frozen': 1, } self.check_config("init_from_config", config, preconfig) diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 3fc8e6d8c6b220..6e764e3b6cce57 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -495,7 +495,7 @@ static int test_init_from_config(void) Py_NoUserSiteDirectory = 0; config.user_site_directory = 0; - config._check_hash_pycs_mode = "always"; + config.check_hash_pycs_mode = L"always"; Py_FrozenFlag = 0; config._frozen = 1; diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 7f388cbcdd0e06..1cb4b52e600eea 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -516,6 +516,7 @@ _PyCoreConfig_Clear(_PyCoreConfig *config) CLEAR(config->run_command); CLEAR(config->run_module); CLEAR(config->run_filename); + CLEAR(config->check_hash_pycs_mode); #undef CLEAR } @@ -686,7 +687,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_WSTR_ATTR(run_command); COPY_WSTR_ATTR(run_module); COPY_WSTR_ATTR(run_filename); - COPY_ATTR(_check_hash_pycs_mode); + COPY_WSTR_ATTR(check_hash_pycs_mode); COPY_ATTR(_frozen); COPY_ATTR(_init_main); @@ -792,7 +793,7 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) SET_ITEM_WSTR(run_module); SET_ITEM_WSTR(run_filename); SET_ITEM_INT(_install_importlib); - SET_ITEM_STR(_check_hash_pycs_mode); + SET_ITEM_WSTR(check_hash_pycs_mode); SET_ITEM_INT(_frozen); SET_ITEM_INT(_init_main); @@ -1711,6 +1712,7 @@ static _PyInitError config_parse_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline, _PyWstrList *warnoptions) { + _PyInitError err; const _PyWstrList *argv = &precmdline->argv; int print_version = 0; @@ -1757,12 +1759,15 @@ config_parse_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline, case 0: // Handle long option. assert(longindex == 0); // Only one long option now. - if (!wcscmp(_PyOS_optarg, L"always")) { - config->_check_hash_pycs_mode = "always"; - } else if (!wcscmp(_PyOS_optarg, L"never")) { - config->_check_hash_pycs_mode = "never"; - } else if (!wcscmp(_PyOS_optarg, L"default")) { - config->_check_hash_pycs_mode = "default"; + if (wcscmp(_PyOS_optarg, L"always") == 0 + || wcscmp(_PyOS_optarg, L"never") == 0 + || wcscmp(_PyOS_optarg, L"default") == 0) + { + err = _PyCoreConfig_SetWideString(&config->check_hash_pycs_mode, + _PyOS_optarg); + if (_Py_INIT_FAILED(err)) { + return err; + } } else { fprintf(stderr, "--check-hash-based-pycs must be one of " "'default', 'always', or 'never'\n"); @@ -2131,6 +2136,13 @@ config_read_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline) goto done; } + if (config->check_hash_pycs_mode == NULL) { + err = _PyCoreConfig_SetWideString(&config->check_hash_pycs_mode, L"default"); + if (_Py_INIT_FAILED(err)) { + goto done; + } + } + err = _Py_INIT_OK(); done: @@ -2254,7 +2266,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config) #ifdef MS_WINDOWS assert(config->legacy_windows_stdio >= 0); #endif - assert(config->_check_hash_pycs_mode != NULL); + assert(config->check_hash_pycs_mode != NULL); assert(config->_install_importlib >= 0); assert(config->_frozen >= 0); diff --git a/Python/import.c b/Python/import.c index 3b2090b963ddc6..b03bc98773ae74 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2305,7 +2305,7 @@ PyInit__imp(void) if (d == NULL) goto failure; _PyCoreConfig *config = &_PyInterpreterState_Get()->core_config; - PyObject *pyc_mode = PyUnicode_FromString(config->_check_hash_pycs_mode); + PyObject *pyc_mode = PyUnicode_FromWideChar(config->check_hash_pycs_mode, -1); if (pyc_mode == NULL) { goto failure; } From 5f2b3b036744d8a397e9c3c32186b9fdb8cf106a Mon Sep 17 00:00:00 2001 From: Hossein Pourbozorg Date: Thu, 2 May 2019 12:47:55 +0430 Subject: [PATCH 146/212] regarding to grammar and spell check (#13020) --- README.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 65cca826dd2de5..0f0c32b7cf50d0 100644 --- a/README.rst +++ b/README.rst @@ -70,7 +70,7 @@ to find out more. On macOS and Cygwin, the executable is called ``python.exe``; elsewhere it's just ``python``. If you are running on macOS with the latest updates installed, make sure to install -openSSL or some other SSL software along with Homebrew or another package manager. +OpenSSL or some other SSL software along with Homebrew or another package manager. If issues persist, see https://devguide.python.org/setup/#macos-and-os-x for more information. @@ -92,7 +92,7 @@ For example:: make test (This will fail if you *also* built at the top-level directory. You should do -a ``make clean`` at the toplevel first.) +a ``make clean`` at the top-level first.) To get an optimized build of Python, ``configure --enable-optimizations`` before you run ``make``. This sets the default make targets up to enable @@ -146,7 +146,7 @@ detailed change log, read `Misc/NEWS accounting of changes can only be gleaned from the `commit history `_. -If you want to install multiple versions of Python see the section below +If you want to install multiple versions of Python, see the section below entitled "Installing multiple versions". From 05222914403c1e2a656c753fbcd20f844af9dd69 Mon Sep 17 00:00:00 2001 From: Daniel Porteous Date: Thu, 2 May 2019 04:20:59 -0400 Subject: [PATCH 147/212] Fix tiny tiny typo in 3.8 what's new (GH-13049) I feel silly even making such a tiny typo fix, but I couldn't help but notice it. --- Doc/whatsnew/3.8.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index c958fc36d667c0..82be92786ab005 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -227,8 +227,8 @@ collections ----------- The :meth:`_asdict()` method for :func:`collections.namedtuple` now returns -a :class:`dict` instead of a :class:`collections.OrderedDict`. This works because -regular dicts have guaranteed ordering in since Python 3.7. If the extra +a :class:`dict` instead of a :class:`collections.OrderedDict`. This works because +regular dicts have guaranteed ordering since Python 3.7. If the extra features of :class:`OrderedDict` are required, the suggested remediation is to cast the result to the desired type: ``OrderedDict(nt._asdict())``. (Contributed by Raymond Hettinger in :issue:`35864`.) From 0d5864fa07ab4f03188c690a5eb07bdd1fd1cb9c Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Thu, 2 May 2019 10:35:02 +0200 Subject: [PATCH 148/212] bpo-13611: Include C14N 2.0 test data in installation (GH-13053) * Include C14N 2.0 test data in installation. * Add README file to the C14N test data directory to reference the original source and licensing conditions. --- Lib/test/xmltestdata/c14n-20/README | 14 ++++++++++++++ Makefile.pre.in | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 Lib/test/xmltestdata/c14n-20/README diff --git a/Lib/test/xmltestdata/c14n-20/README b/Lib/test/xmltestdata/c14n-20/README new file mode 100644 index 00000000000000..06e63704542028 --- /dev/null +++ b/Lib/test/xmltestdata/c14n-20/README @@ -0,0 +1,14 @@ +C14N 2.0 test files +=================== + +This directory contains files from the draft note document listing +test cases for the W3C C14N 2.0 specification: +https://www.w3.org/TR/xml-c14n2-testcases/ + +Direct source: +https://www.w3.org/TR/xml-c14n2-testcases/files/ + +Copied and distributed under these terms: + +Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), +http://www.w3.org/Consortium/Legal/2015/doc-license diff --git a/Makefile.pre.in b/Makefile.pre.in index 619e3fb3645e23..75eb66be3c0135 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1296,7 +1296,8 @@ LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \ tkinter/test/test_ttk site-packages test \ test/audiodata \ test/capath test/data \ - test/cjkencodings test/decimaltestdata test/xmltestdata \ + test/cjkencodings test/decimaltestdata \ + test/xmltestdata test/xmltestdata/c14n-20 \ test/dtracedata \ test/eintrdata \ test/imghdrdata \ From c4e78b116f9a4299f3b3bfbbd18ef49782bb1143 Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Thu, 2 May 2019 09:03:43 -0600 Subject: [PATCH 149/212] bpo-14546: Fix the argument handling in Tools/scripts/lll.py (GH-13026) --- Lib/test/test_tools/test_lll.py | 38 +++++++++++++++++++ .../2019-04-30-14-30-29.bpo-14546.r38Y-6.rst | 1 + Tools/scripts/lll.py | 7 ++-- 3 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 Lib/test/test_tools/test_lll.py create mode 100644 Misc/NEWS.d/next/Tools-Demos/2019-04-30-14-30-29.bpo-14546.r38Y-6.rst diff --git a/Lib/test/test_tools/test_lll.py b/Lib/test/test_tools/test_lll.py new file mode 100644 index 00000000000000..a8f6d5f1f43cdd --- /dev/null +++ b/Lib/test/test_tools/test_lll.py @@ -0,0 +1,38 @@ +"""Tests for the lll script in the Tools/script directory.""" + +import os +import tempfile +from test import support +from test.test_tools import skip_if_missing, import_tool +import unittest + +skip_if_missing() + + +class lllTests(unittest.TestCase): + + def setUp(self): + self.lll = import_tool('lll') + + def test_lll_multiple_dirs(self): + with tempfile.TemporaryDirectory() as dir1, \ + tempfile.TemporaryDirectory() as dir2: + fn1 = os.path.join(dir1, 'foo1') + fn2 = os.path.join(dir2, 'foo2') + for fn, dir in (fn1, dir1), (fn2, dir2): + open(fn, 'w').close() + os.symlink(fn, os.path.join(dir, 'symlink')) + + with support.captured_stdout() as output: + self.lll.main([dir1, dir2]) + self.assertEqual(output.getvalue(), + f'{dir1}:\n' + f'symlink -> {fn1}\n' + f'\n' + f'{dir2}:\n' + f'symlink -> {fn2}\n' + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/Misc/NEWS.d/next/Tools-Demos/2019-04-30-14-30-29.bpo-14546.r38Y-6.rst b/Misc/NEWS.d/next/Tools-Demos/2019-04-30-14-30-29.bpo-14546.r38Y-6.rst new file mode 100644 index 00000000000000..b8659b886af816 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2019-04-30-14-30-29.bpo-14546.r38Y-6.rst @@ -0,0 +1 @@ +Fix the argument handling in Tools/scripts/lll.py. diff --git a/Tools/scripts/lll.py b/Tools/scripts/lll.py index aa4e55091e5902..1b48eac8aad879 100755 --- a/Tools/scripts/lll.py +++ b/Tools/scripts/lll.py @@ -13,8 +13,7 @@ def lll(dirname): full = os.path.join(dirname, name) if os.path.islink(full): print(name, '->', os.readlink(full)) -def main(): - args = sys.argv[1:] +def main(args): if not args: args = [os.curdir] first = 1 for arg in args: @@ -22,7 +21,7 @@ def main(): if not first: print() first = 0 print(arg + ':') - lll(arg) + lll(arg) if __name__ == '__main__': - main() + main(sys.argv[1:]) From e251095a3f4778102f554cecffcfd837f4d1db6c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 2 May 2019 11:28:57 -0400 Subject: [PATCH 150/212] bpo-36775: Add _Py_FORCE_UTF8_FS_ENCODING macro (GH-13056) Add _Py_FORCE_UTF8_LOCALE and _Py_FORCE_UTF8_FS_ENCODING macros to avoid factorize "#if defined(__ANDROID__) || defined(__VXWORKS__)" and "#if defined(__APPLE__)". Cleanup also config_init_fs_encoding(). --- Include/pyport.h | 10 ++++++ Objects/unicodeobject.c | 4 +-- Python/coreconfig.c | 72 ++++++++++++++++------------------------- Python/fileutils.c | 16 ++++----- Python/pylifecycle.c | 3 +- 5 files changed, 48 insertions(+), 57 deletions(-) diff --git a/Include/pyport.h b/Include/pyport.h index 568ab8f757d217..97fb5e59f9e544 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -819,4 +819,14 @@ extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler; # error "Py_TRACE_REFS ABI is not compatible with release and debug ABI" #endif +#if defined(__ANDROID__) || defined(__VXWORKS__) + /* Ignore the locale encoding: force UTF-8 */ +# define _Py_FORCE_UTF8_LOCALE +#endif + +#if defined(_Py_FORCE_UTF8_LOCALE) || defined(__APPLE__) + /* Use UTF-8 as filesystem encoding */ +# define _Py_FORCE_UTF8_FS_ENCODING +#endif + #endif /* Py_PYPORT_H */ diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index f6e68c94df55b1..9991362a333036 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3506,7 +3506,7 @@ PyUnicode_EncodeFSDefault(PyObject *unicode) { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); const _PyCoreConfig *config = &interp->core_config; -#if defined(__APPLE__) +#ifdef _Py_FORCE_UTF8_FS_ENCODING return _PyUnicode_AsUTF8String(unicode, config->filesystem_errors); #else /* Bootstrap check: if the filesystem codec is implemented in Python, we @@ -3730,7 +3730,7 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); const _PyCoreConfig *config = &interp->core_config; -#if defined(__APPLE__) +#ifdef _Py_FORCE_UTF8_FS_ENCODING return PyUnicode_DecodeUTF8Stateful(s, size, config->filesystem_errors, NULL); #else /* Bootstrap check: if the filesystem codec is implemented in Python, we diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 1cb4b52e600eea..c40c1f859ec2df 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1313,7 +1313,7 @@ config_get_locale_encoding(char **locale_encoding) #ifdef MS_WINDOWS char encoding[20]; PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP()); -#elif defined(__ANDROID__) || defined(__VXWORKS__) +#elif defined(_Py_FORCE_UTF8_LOCALE) const char *encoding = "UTF-8"; #else const char *encoding = nl_langinfo(CODESET); @@ -1450,66 +1450,40 @@ config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) { _PyInitError err; -#ifdef MS_WINDOWS - if (preconfig->legacy_windows_fs_encoding) { - /* Legacy Windows filesystem encoding: mbcs/replace */ - if (config->filesystem_encoding == NULL) { - err = _PyCoreConfig_SetString(&config->filesystem_encoding, - "mbcs"); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - if (config->filesystem_errors == NULL) { - err = _PyCoreConfig_SetString(&config->filesystem_errors, - "replace"); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - } - - /* Windows defaults to utf-8/surrogatepass (PEP 529). - - Note: UTF-8 Mode takes the same code path and the Legacy Windows FS - encoding has the priortiy over UTF-8 Mode. */ if (config->filesystem_encoding == NULL) { +#ifdef _Py_FORCE_UTF8_FS_ENCODING err = _PyCoreConfig_SetString(&config->filesystem_encoding, "utf-8"); - if (_Py_INIT_FAILED(err)) { - return err; - } - } +#else - if (config->filesystem_errors == NULL) { - err = _PyCoreConfig_SetString(&config->filesystem_errors, - "surrogatepass"); - if (_Py_INIT_FAILED(err)) { - return err; +#ifdef MS_WINDOWS + if (preconfig->legacy_windows_fs_encoding) { + /* Legacy Windows filesystem encoding: mbcs/replace */ + err = _PyCoreConfig_SetString(&config->filesystem_encoding, + "mbcs"); } - } -#else - if (config->filesystem_encoding == NULL) { + else +#endif if (preconfig->utf8_mode) { - /* UTF-8 Mode use: utf-8/surrogateescape */ err = _PyCoreConfig_SetString(&config->filesystem_encoding, "utf-8"); - /* errors defaults to surrogateescape above */ } +#ifndef MS_WINDOWS else if (_Py_GetForceASCII()) { err = _PyCoreConfig_SetString(&config->filesystem_encoding, "ascii"); } +#endif else { - /* macOS and Android use UTF-8, - other platforms use the locale encoding. */ -#if defined(__APPLE__) || defined(__ANDROID__) +#ifdef MS_WINDOWS + /* Windows defaults to utf-8/surrogatepass (PEP 529). */ err = _PyCoreConfig_SetString(&config->filesystem_encoding, "utf-8"); #else err = config_get_locale_encoding(&config->filesystem_encoding); #endif } +#endif /* !_Py_FORCE_UTF8_FS_ENCODING */ if (_Py_INIT_FAILED(err)) { return err; @@ -1517,14 +1491,22 @@ config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) } if (config->filesystem_errors == NULL) { - /* by default, use the "surrogateescape" error handler */ - err = _PyCoreConfig_SetString(&config->filesystem_errors, - "surrogateescape"); + const char *errors; +#ifdef MS_WINDOWS + if (preconfig->legacy_windows_fs_encoding) { + errors = "replace"; + } + else { + errors = "surrogatepass"; + } +#else + errors = "surrogateescape"; +#endif + err = _PyCoreConfig_SetString(&config->filesystem_errors, errors); if (_Py_INIT_FAILED(err)) { return err; } } -#endif return _Py_INIT_OK(); } diff --git a/Python/fileutils.c b/Python/fileutils.c index b933874193b483..dfad48edb81a1d 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -85,7 +85,7 @@ _Py_device_encoding(int fd) Py_RETURN_NONE; } -#if !defined(__APPLE__) && !defined(__ANDROID__) && !defined(MS_WINDOWS) +#if !defined(_Py_FORCE_UTF8_FS_ENCODING) && !defined(MS_WINDOWS) #define USE_FORCE_ASCII @@ -309,7 +309,7 @@ _Py_ResetForceASCII(void) { /* nothing to do */ } -#endif /* !defined(__APPLE__) && !defined(__ANDROID__) && !defined(MS_WINDOWS) */ +#endif /* !defined(_Py_FORCE_UTF8_FS_ENCODING) && !defined(MS_WINDOWS) */ #if !defined(HAVE_MBRTOWC) || defined(USE_FORCE_ASCII) @@ -536,7 +536,7 @@ _Py_DecodeLocaleEx(const char* arg, wchar_t **wstr, size_t *wlen, int current_locale, _Py_error_handler errors) { if (current_locale) { -#if defined(__ANDROID__) || defined(__VXWORKS__) +#ifdef _Py_FORCE_UTF8_LOCALE return _Py_DecodeUTF8Ex(arg, strlen(arg), wstr, wlen, reason, errors); #else @@ -544,7 +544,7 @@ _Py_DecodeLocaleEx(const char* arg, wchar_t **wstr, size_t *wlen, #endif } -#if defined(__APPLE__) || defined(__ANDROID__) || defined(__VXWORKS__) +#ifdef _Py_FORCE_UTF8_FS_ENCODING return _Py_DecodeUTF8Ex(arg, strlen(arg), wstr, wlen, reason, errors); #else @@ -569,7 +569,7 @@ _Py_DecodeLocaleEx(const char* arg, wchar_t **wstr, size_t *wlen, #endif return decode_current_locale(arg, wstr, wlen, reason, errors); -#endif /* __APPLE__ or __ANDROID__ or __VXWORKS__ */ +#endif /* !_Py_FORCE_UTF8_FS_ENCODING */ } @@ -727,7 +727,7 @@ encode_locale_ex(const wchar_t *text, char **str, size_t *error_pos, int raw_malloc, int current_locale, _Py_error_handler errors) { if (current_locale) { -#ifdef __ANDROID__ +#ifdef _Py_FORCE_UTF8_LOCALE return _Py_EncodeUTF8Ex(text, str, error_pos, reason, raw_malloc, errors); #else @@ -736,7 +736,7 @@ encode_locale_ex(const wchar_t *text, char **str, size_t *error_pos, #endif } -#if defined(__APPLE__) || defined(__ANDROID__) +#ifdef _Py_FORCE_UTF8_FS_ENCODING return _Py_EncodeUTF8Ex(text, str, error_pos, reason, raw_malloc, errors); #else @@ -762,7 +762,7 @@ encode_locale_ex(const wchar_t *text, char **str, size_t *error_pos, return encode_current_locale(text, str, error_pos, reason, raw_malloc, errors); -#endif /* __APPLE__ or __ANDROID__ */ +#endif /* _Py_FORCE_UTF8_FS_ENCODING */ } static char* diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index afa683b7e84199..40eeebdd1a7f13 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -366,8 +366,7 @@ _Py_CoerceLegacyLocale(int warn) const char *new_locale = setlocale(LC_CTYPE, target->locale_name); if (new_locale != NULL) { -#if !defined(__APPLE__) && !defined(__ANDROID__) && \ -defined(HAVE_LANGINFO_H) && defined(CODESET) +#if !defined(_Py_FORCE_UTF8_LOCALE) && defined(HAVE_LANGINFO_H) && defined(CODESET) /* Also ensure that nl_langinfo works in this locale */ char *codeset = nl_langinfo(CODESET); if (!codeset || *codeset == '\0') { From 43fc3bb7cf0278735eb0010d7b3043775a120cb5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 2 May 2019 11:54:20 -0400 Subject: [PATCH 151/212] bpo-36775: Add _PyUnicode_InitEncodings() (GH-13057) Move get_codec_name() and initfsencoding() from pylifecycle.c to unicodeobject.c. Rename also "init" functions in pylifecycle.c. --- Include/internal/pycore_pylifecycle.h | 5 +- Objects/unicodeobject.c | 97 ++++++++++++++++++++++++ Python/pylifecycle.c | 105 ++++---------------------- 3 files changed, 115 insertions(+), 92 deletions(-) diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index f5da1431d94cc9..a2383d476ee9f7 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -16,10 +16,11 @@ PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt; PyAPI_FUNC(int) _Py_UnixMain(int argc, char **argv); -PyAPI_FUNC(int) _Py_SetFileSystemEncoding( +extern int _Py_SetFileSystemEncoding( const char *encoding, const char *errors); -PyAPI_FUNC(void) _Py_ClearFileSystemEncoding(void); +extern void _Py_ClearFileSystemEncoding(void); +extern _PyInitError _PyUnicode_InitEncodings(PyInterpreterState *interp); PyAPI_FUNC(void) _Py_ClearStandardStreamEncoding(void); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 9991362a333036..5b6b241cb62b68 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -42,6 +42,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "Python.h" #include "pycore_fileutils.h" #include "pycore_object.h" +#include "pycore_pylifecycle.h" #include "pycore_pystate.h" #include "ucnhash.h" #include "bytes_methods.h" @@ -15574,6 +15575,102 @@ PyUnicode_AsUnicodeCopy(PyObject *unicode) } +static char* +get_codec_name(const char *encoding) +{ + PyObject *codec, *name_obj = NULL; + + codec = _PyCodec_Lookup(encoding); + if (!codec) + goto error; + + name_obj = PyObject_GetAttrString(codec, "name"); + Py_CLEAR(codec); + if (!name_obj) { + goto error; + } + + const char *name_utf8 = PyUnicode_AsUTF8(name_obj); + if (name_utf8 == NULL) { + goto error; + } + + char *name = _PyMem_RawStrdup(name_utf8); + Py_DECREF(name_obj); + if (name == NULL) { + PyErr_NoMemory(); + return NULL; + } + return name; + +error: + Py_XDECREF(codec); + Py_XDECREF(name_obj); + return NULL; +} + + +static _PyInitError +init_stdio_encoding(PyInterpreterState *interp) +{ + _PyCoreConfig *config = &interp->core_config; + + char *codec_name = get_codec_name(config->stdio_encoding); + if (codec_name == NULL) { + return _Py_INIT_ERR("failed to get the Python codec name " + "of the stdio encoding"); + } + PyMem_RawFree(config->stdio_encoding); + config->stdio_encoding = codec_name; + return _Py_INIT_OK(); +} + + +static _PyInitError +init_fs_encoding(PyInterpreterState *interp) +{ + _PyCoreConfig *config = &interp->core_config; + + char *encoding = get_codec_name(config->filesystem_encoding); + if (encoding == NULL) { + /* Such error can only occurs in critical situations: no more + memory, import a module of the standard library failed, etc. */ + return _Py_INIT_ERR("failed to get the Python codec " + "of the filesystem encoding"); + } + + /* Update the filesystem encoding to the normalized Python codec name. + For example, replace "ANSI_X3.4-1968" (locale encoding) with "ascii" + (Python codec name). */ + PyMem_RawFree(config->filesystem_encoding); + config->filesystem_encoding = encoding; + + /* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors + global configuration variables. */ + if (_Py_SetFileSystemEncoding(config->filesystem_encoding, + config->filesystem_errors) < 0) { + return _Py_INIT_NO_MEMORY(); + } + + /* PyUnicode can now use the Python codec rather than C implementation + for the filesystem encoding */ + interp->fscodec_initialized = 1; + return _Py_INIT_OK(); +} + + +_PyInitError +_PyUnicode_InitEncodings(PyInterpreterState *interp) +{ + _PyInitError err = init_fs_encoding(interp); + if (_Py_INIT_FAILED(err)) { + return err; + } + + return init_stdio_encoding(interp); +} + + void _PyUnicode_Fini(void) { diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 40eeebdd1a7f13..01ef027b9d860f 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -59,10 +59,9 @@ extern grammar _PyParser_Grammar; /* From graminit.c */ /* Forward */ static _PyInitError add_main_module(PyInterpreterState *interp); -static _PyInitError initfsencoding(PyInterpreterState *interp); -static _PyInitError initsite(void); +static _PyInitError init_import_size(void); static _PyInitError init_sys_streams(PyInterpreterState *interp); -static _PyInitError initsigs(void); +static _PyInitError init_signals(void); static void call_py_exitfuncs(PyInterpreterState *); static void wait_for_thread_shutdown(void); static void call_ll_exitfuncs(_PyRuntimeState *runtime); @@ -144,42 +143,8 @@ Py_IsInitialized(void) */ -static char* -get_codec_name(const char *encoding) -{ - const char *name_utf8; - char *name_str; - PyObject *codec, *name = NULL; - - codec = _PyCodec_Lookup(encoding); - if (!codec) - goto error; - - name = _PyObject_GetAttrId(codec, &PyId_name); - Py_CLEAR(codec); - if (!name) - goto error; - - name_utf8 = PyUnicode_AsUTF8(name); - if (name_utf8 == NULL) - goto error; - name_str = _PyMem_RawStrdup(name_utf8); - Py_DECREF(name); - if (name_str == NULL) { - PyErr_NoMemory(); - return NULL; - } - return name_str; - -error: - Py_XDECREF(codec); - Py_XDECREF(name); - return NULL; -} - - static _PyInitError -initimport(PyInterpreterState *interp, PyObject *sysmod) +init_importlib(PyInterpreterState *interp, PyObject *sysmod) { PyObject *importlib; PyObject *impmod; @@ -229,7 +194,7 @@ initimport(PyInterpreterState *interp, PyObject *sysmod) } static _PyInitError -initexternalimport(PyInterpreterState *interp) +init_importlib_external(PyInterpreterState *interp) { PyObject *value; value = PyObject_CallMethod(interp->importlib, @@ -661,7 +626,7 @@ pycore_init_import_warnings(PyInterpreterState *interp, PyObject *sysmod) /* This call sets up builtin and frozen import support */ if (interp->core_config._install_importlib) { - err = initimport(interp, sysmod); + err = init_importlib(interp, sysmod); if (_Py_INIT_FAILED(err)) { return err; } @@ -940,7 +905,7 @@ _Py_InitializeMainInterpreter(_PyRuntimeState *runtime, return _Py_INIT_ERR("can't finish initializing sys"); } - _PyInitError err = initexternalimport(interp); + _PyInitError err = init_importlib_external(interp); if (_Py_INIT_FAILED(err)) { return err; } @@ -951,13 +916,13 @@ _Py_InitializeMainInterpreter(_PyRuntimeState *runtime, return err; } - err = initfsencoding(interp); + err = _PyUnicode_InitEncodings(interp); if (_Py_INIT_FAILED(err)) { return err; } if (core_config->install_signal_handlers) { - err = initsigs(); /* Signal handling stuff, including initintr() */ + err = init_signals(); if (_Py_INIT_FAILED(err)) { return err; } @@ -992,7 +957,7 @@ _Py_InitializeMainInterpreter(_PyRuntimeState *runtime, runtime->initialized = 1; if (core_config->site_import) { - err = initsite(); /* Module site */ + err = init_import_size(); /* Module site */ if (_Py_INIT_FAILED(err)) { return err; } @@ -1497,17 +1462,17 @@ new_interpreter(PyThreadState **tstate_p) return err; } - err = initimport(interp, sysmod); + err = init_importlib(interp, sysmod); if (_Py_INIT_FAILED(err)) { return err; } - err = initexternalimport(interp); + err = init_importlib_external(interp); if (_Py_INIT_FAILED(err)) { return err; } - err = initfsencoding(interp); + err = _PyUnicode_InitEncodings(interp); if (_Py_INIT_FAILED(err)) { return err; } @@ -1523,7 +1488,7 @@ new_interpreter(PyThreadState **tstate_p) } if (core_config->site_import) { - err = initsite(); + err = init_import_size(); if (_Py_INIT_FAILED(err)) { return err; } @@ -1649,42 +1614,10 @@ add_main_module(PyInterpreterState *interp) return _Py_INIT_OK(); } -static _PyInitError -initfsencoding(PyInterpreterState *interp) -{ - _PyCoreConfig *config = &interp->core_config; - - char *encoding = get_codec_name(config->filesystem_encoding); - if (encoding == NULL) { - /* Such error can only occurs in critical situations: no more - memory, import a module of the standard library failed, etc. */ - return _Py_INIT_ERR("failed to get the Python codec " - "of the filesystem encoding"); - } - - /* Update the filesystem encoding to the normalized Python codec name. - For example, replace "ANSI_X3.4-1968" (locale encoding) with "ascii" - (Python codec name). */ - PyMem_RawFree(config->filesystem_encoding); - config->filesystem_encoding = encoding; - - /* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors - global configuration variables. */ - if (_Py_SetFileSystemEncoding(config->filesystem_encoding, - config->filesystem_errors) < 0) { - return _Py_INIT_NO_MEMORY(); - } - - /* PyUnicode can now use the Python codec rather than C implementation - for the filesystem encoding */ - interp->fscodec_initialized = 1; - return _Py_INIT_OK(); -} - /* Import the site module (not into __main__ though) */ static _PyInitError -initsite(void) +init_import_size(void) { PyObject *m; m = PyImport_ImportModule("site"); @@ -1880,14 +1813,6 @@ init_sys_streams(PyInterpreterState *interp) } #endif - char *codec_name = get_codec_name(config->stdio_encoding); - if (codec_name == NULL) { - return _Py_INIT_ERR("failed to get the Python codec name " - "of the stdio encoding"); - } - PyMem_RawFree(config->stdio_encoding); - config->stdio_encoding = codec_name; - /* Hack to avoid a nasty recursion issue when Python is invoked in verbose mode: pre-import the Latin-1 and UTF-8 codecs */ if ((m = PyImport_ImportModule("encodings.utf_8")) == NULL) { @@ -2287,7 +2212,7 @@ Py_Exit(int sts) } static _PyInitError -initsigs(void) +init_signals(void) { #ifdef SIGPIPE PyOS_setsig(SIGPIPE, SIG_IGN); From 874ad1b3b4bfc782a5762c1f18234ba56b853caf Mon Sep 17 00:00:00 2001 From: Xtreak Date: Thu, 2 May 2019 23:50:59 +0530 Subject: [PATCH 152/212] Fix typo: quaatile to quantile (GH=13001) --- Lib/test/test_statistics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 903ee8f343cb1c..1922de5df4b0c5 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -2192,7 +2192,7 @@ def f(x): def test_specific_cases_inclusive(self): # Match results computed by hand and cross-checked # against the PERCENTILE.INC function in MS Excel - # and against the quaatile() function in SciPy. + # and against the quantile() function in SciPy. quantiles = statistics.quantiles data = [100, 200, 400, 800] random.shuffle(data) From 373893ce51b0eaf0dec901e36a3e4217fbed3e32 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 2 May 2019 14:46:29 -0400 Subject: [PATCH 153/212] bpo-36763: Add _PyCoreConfig._config_version (GH-13065) Add private _config_version field to _PyPreConfig and _PyCoreConfig to prepare future ABI compatibility. --- Include/cpython/coreconfig.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index 99388e635c75b3..1aab5e4f0e6249 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -65,7 +65,12 @@ typedef struct { /* --- _PyPreConfig ----------------------------------------------- */ +#define _Py_CONFIG_VERSION 1 + typedef struct { + int _config_version; /* Internal configuration version, + used for ABI compatibility */ + /* If greater than 0, enable isolated mode: sys.path contains neither the script's directory nor the user's site-packages directory. @@ -132,6 +137,7 @@ typedef struct { #define _PyPreConfig_INIT \ (_PyPreConfig){ \ _PyPreConfig_WINDOWS_INIT \ + ._config_version = _Py_CONFIG_VERSION, \ .isolated = -1, \ .use_environment = -1, \ .dev_mode = -1, \ @@ -141,9 +147,12 @@ typedef struct { /* --- _PyCoreConfig ---------------------------------------------- */ typedef struct { - int isolated; - int use_environment; - int dev_mode; + int _config_version; /* Internal configuration version, + used for ABI compatibility */ + + int isolated; /* Isolated mode? see _PyPreConfig.isolated */ + int use_environment; /* Use environment variables? see _PyPreConfig.use_environment */ + int dev_mode; /* Development mode? See _PyPreConfig.dev_mode */ /* Install signal handlers? Yes by default. */ int install_signal_handlers; @@ -397,6 +406,7 @@ typedef struct { #define _PyCoreConfig_INIT \ (_PyCoreConfig){ \ _PyCoreConfig_WINDOWS_INIT \ + ._config_version = _Py_CONFIG_VERSION, \ .isolated = -1, \ .use_environment = -1, \ .dev_mode = -1, \ From 6ae2bbbdfcb8969d1d362b17c2fbd5a684fa4f9d Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Thu, 2 May 2019 12:55:00 -0600 Subject: [PATCH 154/212] bpo-36776: Add @support.skip_unless_symlink to test_lll.py (GH-13058) --- Lib/test/test_tools/test_lll.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_tools/test_lll.py b/Lib/test/test_tools/test_lll.py index a8f6d5f1f43cdd..f3fbe961eee55a 100644 --- a/Lib/test/test_tools/test_lll.py +++ b/Lib/test/test_tools/test_lll.py @@ -14,6 +14,7 @@ class lllTests(unittest.TestCase): def setUp(self): self.lll = import_tool('lll') + @support.skip_unless_symlink def test_lll_multiple_dirs(self): with tempfile.TemporaryDirectory() as dir1, \ tempfile.TemporaryDirectory() as dir2: From 709d23dee69e700b87d5a4cb59e149d0e1af7993 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 2 May 2019 14:56:30 -0400 Subject: [PATCH 155/212] bpo-36775: _PyCoreConfig only uses wchar_t* (GH-13062) _PyCoreConfig: Change filesystem_encoding, filesystem_errors, stdio_encoding and stdio_errors fields type from char* to wchar_t*. Changes: * PyInterpreterState: replace fscodec_initialized (int) with fs_codec structure. * Add get_error_handler_wide() and unicode_encode_utf8() helper functions. * Add error_handler parameter to unicode_encode_locale() and unicode_decode_locale(). * Remove _PyCoreConfig_SetString(). * Rename _PyCoreConfig_SetWideString() to _PyCoreConfig_SetString(). * Rename _PyCoreConfig_SetWideStringFromString() to _PyCoreConfig_DecodeLocale(). --- Include/cpython/coreconfig.h | 8 +- Include/internal/pycore_coreconfig.h | 5 +- Include/internal/pycore_pylifecycle.h | 3 + Include/internal/pycore_pystate.h | 9 +- Objects/stringlib/codecs.h | 2 +- Objects/unicodeobject.c | 314 ++++++++++++++++++++------ Programs/_testembed.c | 4 +- Python/coreconfig.c | 169 ++++++-------- Python/preconfig.c | 5 +- Python/pylifecycle.c | 25 +- Python/sysmodule.c | 27 +-- 11 files changed, 354 insertions(+), 217 deletions(-) diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index 1aab5e4f0e6249..5672080b784fde 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -207,8 +207,8 @@ typedef struct { See Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors. */ - char *filesystem_encoding; - char *filesystem_errors; + wchar_t *filesystem_encoding; + wchar_t *filesystem_errors; wchar_t *pycache_prefix; /* PYTHONPYCACHEPREFIX, -X pycache_prefix=PATH */ wchar_t *program_name; /* Program name, see also Py_GetProgramName() */ @@ -334,13 +334,13 @@ typedef struct { Value set from PYTHONIOENCODING environment variable and Py_SetStandardStreamEncoding() function. See also 'stdio_errors' attribute. */ - char *stdio_encoding; + wchar_t *stdio_encoding; /* Error handler of sys.stdin and sys.stdout. Value set from PYTHONIOENCODING environment variable and Py_SetStandardStreamEncoding() function. See also 'stdio_encoding' attribute. */ - char *stdio_errors; + wchar_t *stdio_errors; #ifdef MS_WINDOWS /* If greater than zero, use io.FileIO instead of WindowsConsoleIO for sys diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index 8af310d2b0ceaf..d48904e482a45d 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -106,12 +106,9 @@ PyAPI_FUNC(_PyInitError) _PyCoreConfig_Copy( _PyCoreConfig *config, const _PyCoreConfig *config2); PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetString( - char **config_str, - const char *str); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideString( wchar_t **config_str, const wchar_t *str); -PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideStringFromString( +PyAPI_FUNC(_PyInitError) _PyCoreConfig_DecodeLocale( wchar_t **config_str, const char *str); PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPathConfig(_PyCoreConfig *config); diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index a2383d476ee9f7..321cc5d27889bd 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -21,6 +21,9 @@ extern int _Py_SetFileSystemEncoding( const char *errors); extern void _Py_ClearFileSystemEncoding(void); extern _PyInitError _PyUnicode_InitEncodings(PyInterpreterState *interp); +#ifdef MS_WINDOWS +extern int _PyUnicode_EnableLegacyWindowsFSEncoding(void); +#endif PyAPI_FUNC(void) _Py_ClearStandardStreamEncoding(void); diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 2c24f679dc0203..67bcd147e2829f 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -56,7 +56,14 @@ struct _is { PyObject *codec_search_cache; PyObject *codec_error_registry; int codecs_initialized; - int fscodec_initialized; + + /* fs_codec.encoding is initialized to NULL. + Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */ + struct { + char *encoding; /* Filesystem encoding (encoded to UTF-8) */ + char *errors; /* Filesystem errors (encoded to UTF-8) */ + _Py_error_handler error_handler; + } fs_codec; _PyCoreConfig core_config; #ifdef HAVE_DLOPEN diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h index 0abb4c8abb9282..8645bc26cff8ca 100644 --- a/Objects/stringlib/codecs.h +++ b/Objects/stringlib/codecs.h @@ -260,6 +260,7 @@ Py_LOCAL_INLINE(PyObject *) STRINGLIB(utf8_encoder)(PyObject *unicode, STRINGLIB_CHAR *data, Py_ssize_t size, + _Py_error_handler error_handler, const char *errors) { Py_ssize_t i; /* index into data of next input character */ @@ -268,7 +269,6 @@ STRINGLIB(utf8_encoder)(PyObject *unicode, PyObject *error_handler_obj = NULL; PyObject *exc = NULL; PyObject *rep = NULL; - _Py_error_handler error_handler = _Py_ERROR_UNKNOWN; #endif #if STRINGLIB_SIZEOF_CHAR == 1 const Py_ssize_t max_char_size = 2; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 5b6b241cb62b68..4d86519e863769 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -40,6 +40,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_coreconfig.h" #include "pycore_fileutils.h" #include "pycore_object.h" #include "pycore_pylifecycle.h" @@ -264,6 +265,13 @@ unicode_fill(enum PyUnicode_Kind kind, void *data, Py_UCS4 value, /* Forward declaration */ static inline int _PyUnicodeWriter_WriteCharInline(_PyUnicodeWriter *writer, Py_UCS4 ch); +static PyObject * +unicode_encode_utf8(PyObject *unicode, _Py_error_handler error_handler, + const char *errors); +static PyObject * +unicode_decode_utf8(const char *s, Py_ssize_t size, + _Py_error_handler error_handler, const char *errors, + Py_ssize_t *consumed); /* List of static strings. */ static _Py_Identifier *static_strings = NULL; @@ -388,6 +396,35 @@ _Py_GetErrorHandler(const char *errors) return _Py_ERROR_OTHER; } + +static _Py_error_handler +get_error_handler_wide(const wchar_t *errors) +{ + if (errors == NULL || wcscmp(errors, L"strict") == 0) { + return _Py_ERROR_STRICT; + } + if (wcscmp(errors, L"surrogateescape") == 0) { + return _Py_ERROR_SURROGATEESCAPE; + } + if (wcscmp(errors, L"replace") == 0) { + return _Py_ERROR_REPLACE; + } + if (wcscmp(errors, L"ignore") == 0) { + return _Py_ERROR_IGNORE; + } + if (wcscmp(errors, L"backslashreplace") == 0) { + return _Py_ERROR_BACKSLASHREPLACE; + } + if (wcscmp(errors, L"surrogatepass") == 0) { + return _Py_ERROR_SURROGATEPASS; + } + if (wcscmp(errors, L"xmlcharrefreplace") == 0) { + return _Py_ERROR_XMLCHARREFREPLACE; + } + return _Py_ERROR_OTHER; +} + + /* The max unicode value is always 0x10FFFF while using the PEP-393 API. This function is kept for backward compatibility with the old API. */ Py_UNICODE @@ -3445,11 +3482,9 @@ PyUnicode_AsEncodedObject(PyObject *unicode, static PyObject * -unicode_encode_locale(PyObject *unicode, const char *errors, +unicode_encode_locale(PyObject *unicode, _Py_error_handler error_handler, int current_locale) { - _Py_error_handler error_handler = _Py_GetErrorHandler(errors); - Py_ssize_t wlen; wchar_t *wstr = PyUnicode_AsWideCharString(unicode, &wlen); if (wstr == NULL) { @@ -3499,30 +3534,44 @@ unicode_encode_locale(PyObject *unicode, const char *errors, PyObject * PyUnicode_EncodeLocale(PyObject *unicode, const char *errors) { - return unicode_encode_locale(unicode, errors, 1); + _Py_error_handler error_handler = _Py_GetErrorHandler(errors); + return unicode_encode_locale(unicode, error_handler, 1); } PyObject * PyUnicode_EncodeFSDefault(PyObject *unicode) { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); - const _PyCoreConfig *config = &interp->core_config; #ifdef _Py_FORCE_UTF8_FS_ENCODING - return _PyUnicode_AsUTF8String(unicode, config->filesystem_errors); + if (interp->fs_codec.encoding) { + return unicode_encode_utf8(unicode, + interp->fs_codec.error_handler, + interp->fs_codec.errors); + } + else { + const _PyCoreConfig *config = &interp->core_config; + _Py_error_handler errors; + errors = get_error_handler_wide(config->filesystem_errors); + assert(errors != _Py_ERROR_UNKNOWN); + return unicode_encode_utf8(unicode, errors, NULL); + } #else /* Bootstrap check: if the filesystem codec is implemented in Python, we cannot use it to encode and decode filenames before it is loaded. Load the Python codec requires to encode at least its own filename. Use the C implementation of the locale codec until the codec registry is initialized and the Python codec is loaded. See initfsencoding(). */ - if (interp->fscodec_initialized) { + if (interp->fs_codec.encoding) { return PyUnicode_AsEncodedString(unicode, - config->filesystem_encoding, - config->filesystem_errors); + interp->fs_codec.encoding, + interp->fs_codec.errors); } else { - return unicode_encode_locale(unicode, - config->filesystem_errors, 0); + const _PyCoreConfig *config = &interp->core_config; + _Py_error_handler errors; + errors = get_error_handler_wide(config->filesystem_errors); + assert(errors != _Py_ERROR_UNKNOWN); + return unicode_encode_locale(unicode, errors, 0); } #endif } @@ -3663,11 +3712,9 @@ PyUnicode_AsEncodedUnicode(PyObject *unicode, } static PyObject* -unicode_decode_locale(const char *str, Py_ssize_t len, const char *errors, - int current_locale) +unicode_decode_locale(const char *str, Py_ssize_t len, + _Py_error_handler errors, int current_locale) { - _Py_error_handler error_handler = _Py_GetErrorHandler(errors); - if (str[len] != '\0' || (size_t)len != strlen(str)) { PyErr_SetString(PyExc_ValueError, "embedded null byte"); return NULL; @@ -3677,7 +3724,7 @@ unicode_decode_locale(const char *str, Py_ssize_t len, const char *errors, size_t wlen; const char *reason; int res = _Py_DecodeLocaleEx(str, &wstr, &wlen, &reason, - current_locale, error_handler); + current_locale, errors); if (res != 0) { if (res == -2) { PyObject *exc; @@ -3709,14 +3756,16 @@ PyObject* PyUnicode_DecodeLocaleAndSize(const char *str, Py_ssize_t len, const char *errors) { - return unicode_decode_locale(str, len, errors, 1); + _Py_error_handler error_handler = _Py_GetErrorHandler(errors); + return unicode_decode_locale(str, len, error_handler, 1); } PyObject* PyUnicode_DecodeLocale(const char *str, const char *errors) { Py_ssize_t size = (Py_ssize_t)strlen(str); - return unicode_decode_locale(str, size, errors, 1); + _Py_error_handler error_handler = _Py_GetErrorHandler(errors); + return unicode_decode_locale(str, size, error_handler, 1); } @@ -3730,23 +3779,36 @@ PyObject* PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); - const _PyCoreConfig *config = &interp->core_config; #ifdef _Py_FORCE_UTF8_FS_ENCODING - return PyUnicode_DecodeUTF8Stateful(s, size, config->filesystem_errors, NULL); + if (interp->fs_codec.encoding) { + return unicode_decode_utf8(s, size, + interp->fs_codec.error_handler, + interp->fs_codec.errors, + NULL); + } + else { + const _PyCoreConfig *config = &interp->core_config; + _Py_error_handler errors; + errors = get_error_handler_wide(config->filesystem_errors); + assert(errors != _Py_ERROR_UNKNOWN); + return unicode_decode_utf8(s, size, errors, NULL, NULL); + } #else /* Bootstrap check: if the filesystem codec is implemented in Python, we cannot use it to encode and decode filenames before it is loaded. Load the Python codec requires to encode at least its own filename. Use the C implementation of the locale codec until the codec registry is initialized and the Python codec is loaded. See initfsencoding(). */ - if (interp->fscodec_initialized) { + if (interp->fs_codec.encoding) { return PyUnicode_Decode(s, size, - config->filesystem_encoding, - config->filesystem_errors); + interp->fs_codec.encoding, + interp->fs_codec.errors); } else { - return unicode_decode_locale(s, size, - config->filesystem_errors, 0); + const _PyCoreConfig *config = &interp->core_config; + _Py_error_handler errors; + errors = get_error_handler_wide(config->filesystem_errors); + return unicode_decode_locale(s, size, errors, 0); } #endif } @@ -4810,11 +4872,10 @@ ascii_decode(const char *start, const char *end, Py_UCS1 *dest) return p - start; } -PyObject * -PyUnicode_DecodeUTF8Stateful(const char *s, - Py_ssize_t size, - const char *errors, - Py_ssize_t *consumed) +static PyObject * +unicode_decode_utf8(const char *s, Py_ssize_t size, + _Py_error_handler error_handler, const char *errors, + Py_ssize_t *consumed) { _PyUnicodeWriter writer; const char *starts = s; @@ -4825,7 +4886,6 @@ PyUnicode_DecodeUTF8Stateful(const char *s, const char *errmsg = ""; PyObject *error_handler_obj = NULL; PyObject *exc = NULL; - _Py_error_handler error_handler = _Py_ERROR_UNKNOWN; if (size == 0) { if (consumed) @@ -4948,6 +5008,16 @@ PyUnicode_DecodeUTF8Stateful(const char *s, } +PyObject * +PyUnicode_DecodeUTF8Stateful(const char *s, + Py_ssize_t size, + const char *errors, + Py_ssize_t *consumed) +{ + return unicode_decode_utf8(s, size, _Py_ERROR_UNKNOWN, errors, consumed); +} + + /* UTF-8 decoder: use surrogateescape error handler if 'surrogateescape' is non-zero, use strict error handler otherwise. @@ -5231,8 +5301,9 @@ _Py_EncodeUTF8Ex(const wchar_t *text, char **str, size_t *error_pos, maximum possible needed (4 result bytes per Unicode character), and return the excess memory at the end. */ -PyObject * -_PyUnicode_AsUTF8String(PyObject *unicode, const char *errors) +static PyObject * +unicode_encode_utf8(PyObject *unicode, _Py_error_handler error_handler, + const char *errors) { enum PyUnicode_Kind kind; void *data; @@ -5260,14 +5331,21 @@ _PyUnicode_AsUTF8String(PyObject *unicode, const char *errors) case PyUnicode_1BYTE_KIND: /* the string cannot be ASCII, or PyUnicode_UTF8() would be set */ assert(!PyUnicode_IS_ASCII(unicode)); - return ucs1lib_utf8_encoder(unicode, data, size, errors); + return ucs1lib_utf8_encoder(unicode, data, size, error_handler, errors); case PyUnicode_2BYTE_KIND: - return ucs2lib_utf8_encoder(unicode, data, size, errors); + return ucs2lib_utf8_encoder(unicode, data, size, error_handler, errors); case PyUnicode_4BYTE_KIND: - return ucs4lib_utf8_encoder(unicode, data, size, errors); + return ucs4lib_utf8_encoder(unicode, data, size, error_handler, errors); } } +PyObject * +_PyUnicode_AsUTF8String(PyObject *unicode, const char *errors) +{ + return unicode_encode_utf8(unicode, _Py_ERROR_UNKNOWN, errors); +} + + PyObject * PyUnicode_EncodeUTF8(const Py_UNICODE *s, Py_ssize_t size, @@ -15575,12 +15653,35 @@ PyUnicode_AsUnicodeCopy(PyObject *unicode) } -static char* -get_codec_name(const char *encoding) +static int +encode_wstr_utf8(wchar_t *wstr, char **str, const char *name) { - PyObject *codec, *name_obj = NULL; + int res; + res = _Py_EncodeUTF8Ex(wstr, str, NULL, NULL, 1, _Py_ERROR_STRICT); + if (res == -2) { + PyErr_Format(PyExc_RuntimeWarning, "cannot decode %s", name); + return -1; + } + if (res < 0) { + PyErr_NoMemory(); + return -1; + } + return 0; +} + + +static int +config_get_codec_name(wchar_t **config_encoding) +{ + char *encoding; + if (encode_wstr_utf8(*config_encoding, &encoding, "stdio_encoding") < 0) { + return -1; + } + + PyObject *name_obj = NULL; + PyObject *codec = _PyCodec_Lookup(encoding); + PyMem_RawFree(encoding); - codec = _PyCodec_Lookup(encoding); if (!codec) goto error; @@ -15590,71 +15691,107 @@ get_codec_name(const char *encoding) goto error; } - const char *name_utf8 = PyUnicode_AsUTF8(name_obj); - if (name_utf8 == NULL) { + wchar_t *wname = PyUnicode_AsWideCharString(name_obj, NULL); + Py_DECREF(name_obj); + if (wname == NULL) { goto error; } - char *name = _PyMem_RawStrdup(name_utf8); - Py_DECREF(name_obj); - if (name == NULL) { + wchar_t *raw_wname = _PyMem_RawWcsdup(wname); + if (raw_wname == NULL) { + PyMem_Free(wname); PyErr_NoMemory(); - return NULL; + goto error; } - return name; + + PyMem_RawFree(*config_encoding); + *config_encoding = raw_wname; + + PyMem_Free(wname); + return 0; error: Py_XDECREF(codec); Py_XDECREF(name_obj); - return NULL; + return -1; } static _PyInitError init_stdio_encoding(PyInterpreterState *interp) { + /* Update the stdio encoding to the normalized Python codec name. */ _PyCoreConfig *config = &interp->core_config; - - char *codec_name = get_codec_name(config->stdio_encoding); - if (codec_name == NULL) { + if (config_get_codec_name(&config->stdio_encoding) < 0) { return _Py_INIT_ERR("failed to get the Python codec name " "of the stdio encoding"); } - PyMem_RawFree(config->stdio_encoding); - config->stdio_encoding = codec_name; return _Py_INIT_OK(); } -static _PyInitError -init_fs_encoding(PyInterpreterState *interp) +static int +init_fs_codec(PyInterpreterState *interp) { _PyCoreConfig *config = &interp->core_config; - char *encoding = get_codec_name(config->filesystem_encoding); - if (encoding == NULL) { - /* Such error can only occurs in critical situations: no more - memory, import a module of the standard library failed, etc. */ - return _Py_INIT_ERR("failed to get the Python codec " - "of the filesystem encoding"); + _Py_error_handler error_handler; + error_handler = get_error_handler_wide(config->filesystem_errors); + if (error_handler == _Py_ERROR_UNKNOWN) { + PyErr_SetString(PyExc_RuntimeError, "unknow filesystem error handler"); + return -1; } - /* Update the filesystem encoding to the normalized Python codec name. - For example, replace "ANSI_X3.4-1968" (locale encoding) with "ascii" - (Python codec name). */ - PyMem_RawFree(config->filesystem_encoding); - config->filesystem_encoding = encoding; + char *encoding, *errors; + if (encode_wstr_utf8(config->filesystem_encoding, + &encoding, + "filesystem_encoding") < 0) { + return -1; + } + + if (encode_wstr_utf8(config->filesystem_errors, + &errors, + "filesystem_errors") < 0) { + PyMem_RawFree(encoding); + return -1; + } + + PyMem_RawFree(interp->fs_codec.encoding); + interp->fs_codec.encoding = encoding; + PyMem_RawFree(interp->fs_codec.errors); + interp->fs_codec.errors = errors; + interp->fs_codec.error_handler = error_handler; + + /* At this point, PyUnicode_EncodeFSDefault() and + PyUnicode_DecodeFSDefault() can now use the Python codec rather than + the C implementation of the filesystem encoding. */ /* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors global configuration variables. */ - if (_Py_SetFileSystemEncoding(config->filesystem_encoding, - config->filesystem_errors) < 0) { - return _Py_INIT_NO_MEMORY(); + if (_Py_SetFileSystemEncoding(interp->fs_codec.encoding, + interp->fs_codec.errors) < 0) { + PyErr_NoMemory(); + return -1; + } + return 0; +} + + +static _PyInitError +init_fs_encoding(PyInterpreterState *interp) +{ + /* Update the filesystem encoding to the normalized Python codec name. + For example, replace "ANSI_X3.4-1968" (locale encoding) with "ascii" + (Python codec name). */ + _PyCoreConfig *config = &interp->core_config; + if (config_get_codec_name(&config->filesystem_encoding) < 0) { + return _Py_INIT_ERR("failed to get the Python codec " + "of the filesystem encoding"); } - /* PyUnicode can now use the Python codec rather than C implementation - for the filesystem encoding */ - interp->fscodec_initialized = 1; + if (init_fs_codec(interp) < 0) { + return _Py_INIT_ERR("cannot initialize filesystem codec"); + } return _Py_INIT_OK(); } @@ -15671,6 +15808,33 @@ _PyUnicode_InitEncodings(PyInterpreterState *interp) } +#ifdef MS_WINDOWS +int +_PyUnicode_EnableLegacyWindowsFSEncoding(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); + _PyCoreConfig *config = &interp->core_config; + + /* Set the filesystem encoding to mbcs/replace (PEP 529) */ + wchar_t *encoding = _PyMem_RawWcsdup(L"mbcs"); + wchar_t *errors = _PyMem_RawWcsdup(L"replace"); + if (encoding == NULL || errors == NULL) { + PyMem_RawFree(encoding); + PyMem_RawFree(errors); + PyErr_NoMemory(); + return -1; + } + + PyMem_RawFree(config->filesystem_encoding); + config->filesystem_encoding = encoding; + PyMem_RawFree(config->filesystem_errors); + config->filesystem_errors = errors; + + return init_fs_codec(interp); +} +#endif + + void _PyUnicode_Fini(void) { @@ -15694,6 +15858,12 @@ _PyUnicode_Fini(void) } _PyUnicode_ClearStaticStrings(); (void)PyUnicode_ClearFreeList(); + + PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); + PyMem_RawFree(interp->fs_codec.encoding); + interp->fs_codec.encoding = NULL; + PyMem_RawFree(interp->fs_codec.errors); + interp->fs_codec.errors = NULL; } diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 6e764e3b6cce57..2cadf82cb17faa 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -488,8 +488,8 @@ static int test_init_from_config(void) Force it to 0 through the config. */ config.legacy_windows_stdio = 0; #endif - config.stdio_encoding = "iso8859-1"; - config.stdio_errors = "replace"; + config.stdio_encoding = L"iso8859-1"; + config.stdio_errors = L"replace"; putenv("PYTHONNOUSERSITE="); Py_NoUserSiteDirectory = 0; diff --git a/Python/coreconfig.c b/Python/coreconfig.c index c40c1f859ec2df..15643be3765aa0 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -523,27 +523,7 @@ _PyCoreConfig_Clear(_PyCoreConfig *config) /* Copy str into *config_str (duplicate the string) */ _PyInitError -_PyCoreConfig_SetString(char **config_str, const char *str) -{ - char *str2; - if (str != NULL) { - str2 = _PyMem_RawStrdup(str); - if (str2 == NULL) { - return _Py_INIT_NO_MEMORY(); - } - } - else { - str2 = NULL; - } - PyMem_RawFree(*config_str); - *config_str = str2; - return _Py_INIT_OK(); -} - - -/* Copy str into *config_str (duplicate the string) */ -_PyInitError -_PyCoreConfig_SetWideString(wchar_t **config_str, const wchar_t *str) +_PyCoreConfig_SetString(wchar_t **config_str, const wchar_t *str) { wchar_t *str2; if (str != NULL) { @@ -563,8 +543,8 @@ _PyCoreConfig_SetWideString(wchar_t **config_str, const wchar_t *str) /* Decode str using Py_DecodeLocale() and set the result into *config_str */ static _PyInitError -_PyCoreConfig_SetWideStringFromStringErr(wchar_t **config_str, const char *str, - const char *decode_err_msg) +_PyCoreConfig_DecodeLocaleErr(wchar_t **config_str, const char *str, + const char *decode_err_msg) { wchar_t *str2; if (str != NULL) { @@ -588,19 +568,17 @@ _PyCoreConfig_SetWideStringFromStringErr(wchar_t **config_str, const char *str, } +#define CONFIG_DECODE_LOCALE(config_str, str, NAME) \ + _PyCoreConfig_DecodeLocaleErr(config_str, str, "cannot decode " NAME) + + _PyInitError -_PyCoreConfig_SetWideStringFromString(wchar_t **config_str, const char *str) +_PyCoreConfig_DecodeLocale(wchar_t **config_str, const char *str) { - return _PyCoreConfig_SetWideStringFromStringErr( - config_str, str, "cannot decode string"); + return CONFIG_DECODE_LOCALE(config_str, str, "string"); } -#define CONFIG_DECODE_LOCALE(config_str, str, NAME) \ - _PyCoreConfig_SetWideStringFromStringErr(config_str, str, \ - "cannot decode " NAME) - - _PyInitError _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) { @@ -608,16 +586,9 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) _PyCoreConfig_Clear(config); #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR -#define COPY_STR_ATTR(ATTR) \ - do { \ - err = _PyCoreConfig_SetString(&config->ATTR, config2->ATTR); \ - if (_Py_INIT_FAILED(err)) { \ - return err; \ - } \ - } while (0) #define COPY_WSTR_ATTR(ATTR) \ do { \ - err = _PyCoreConfig_SetWideString(&config->ATTR, config2->ATTR); \ + err = _PyCoreConfig_SetString(&config->ATTR, config2->ATTR); \ if (_Py_INIT_FAILED(err)) { \ return err; \ } \ @@ -676,10 +647,10 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_ATTR(quiet); COPY_ATTR(user_site_directory); COPY_ATTR(buffered_stdio); - COPY_STR_ATTR(filesystem_encoding); - COPY_STR_ATTR(filesystem_errors); - COPY_STR_ATTR(stdio_encoding); - COPY_STR_ATTR(stdio_errors); + COPY_WSTR_ATTR(filesystem_encoding); + COPY_WSTR_ATTR(filesystem_errors); + COPY_WSTR_ATTR(stdio_encoding); + COPY_WSTR_ATTR(stdio_errors); #ifdef MS_WINDOWS COPY_ATTR(legacy_windows_stdio); #endif @@ -692,7 +663,6 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_ATTR(_init_main); #undef COPY_ATTR -#undef COPY_STR_ATTR #undef COPY_WSTR_ATTR #undef COPY_WSTRLIST return _Py_INIT_OK(); @@ -721,16 +691,10 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) goto fail; \ } \ } while (0) -#define FROM_STRING(STR) \ - ((STR != NULL) ? \ - PyUnicode_FromString(STR) \ - : (Py_INCREF(Py_None), Py_None)) #define SET_ITEM_INT(ATTR) \ SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR)) #define SET_ITEM_UINT(ATTR) \ SET_ITEM(#ATTR, PyLong_FromUnsignedLong(config->ATTR)) -#define SET_ITEM_STR(ATTR) \ - SET_ITEM(#ATTR, FROM_STRING(config->ATTR)) #define FROM_WSTRING(STR) \ ((STR != NULL) ? \ PyUnicode_FromWideChar(STR, -1) \ @@ -753,8 +717,8 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) SET_ITEM_INT(show_alloc_count); SET_ITEM_INT(dump_refs); SET_ITEM_INT(malloc_stats); - SET_ITEM_STR(filesystem_encoding); - SET_ITEM_STR(filesystem_errors); + SET_ITEM_WSTR(filesystem_encoding); + SET_ITEM_WSTR(filesystem_errors); SET_ITEM_WSTR(pycache_prefix); SET_ITEM_WSTR(program_name); SET_ITEM_WSTRLIST(argv); @@ -783,8 +747,8 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) SET_ITEM_INT(quiet); SET_ITEM_INT(user_site_directory); SET_ITEM_INT(buffered_stdio); - SET_ITEM_STR(stdio_encoding); - SET_ITEM_STR(stdio_errors); + SET_ITEM_WSTR(stdio_encoding); + SET_ITEM_WSTR(stdio_errors); #ifdef MS_WINDOWS SET_ITEM_INT(legacy_windows_stdio); #endif @@ -803,12 +767,10 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) Py_DECREF(dict); return NULL; -#undef FROM_STRING #undef FROM_WSTRING #undef SET_ITEM #undef SET_ITEM_INT #undef SET_ITEM_UINT -#undef SET_ITEM_STR #undef SET_ITEM_WSTR #undef SET_ITEM_WSTRLIST } @@ -845,7 +807,7 @@ _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, return _Py_INIT_OK(); } - return _PyCoreConfig_SetWideString(dest, var); + return _PyCoreConfig_SetString(dest, var); #else const char *var = getenv(name); if (!var || var[0] == '\0') { @@ -853,7 +815,7 @@ _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, return _Py_INIT_OK(); } - return _PyCoreConfig_SetWideStringFromStringErr(dest, var, decode_err_msg); + return _PyCoreConfig_DecodeLocaleErr(dest, var, decode_err_msg); #endif } @@ -996,8 +958,7 @@ config_init_program_name(_PyCoreConfig *config) /* Use argv[0] by default, if available */ if (config->program != NULL) { - err = _PyCoreConfig_SetWideString(&config->program_name, - config->program); + err = _PyCoreConfig_SetString(&config->program_name, config->program); if (_Py_INIT_FAILED(err)) { return err; } @@ -1010,7 +971,7 @@ config_init_program_name(_PyCoreConfig *config) #else const wchar_t *default_program_name = L"python3"; #endif - err = _PyCoreConfig_SetWideString(&config->program_name, default_program_name); + err = _PyCoreConfig_SetString(&config->program_name, default_program_name); if (_Py_INIT_FAILED(err)) { return err; } @@ -1025,8 +986,8 @@ config_init_executable(_PyCoreConfig *config) /* If Py_SetProgramFullPath() was called, use its value */ const wchar_t *program_full_path = _Py_path_config.program_full_path; if (program_full_path != NULL) { - _PyInitError err = _PyCoreConfig_SetWideString(&config->executable, - program_full_path); + _PyInitError err = _PyCoreConfig_SetString(&config->executable, + program_full_path); if (_Py_INIT_FAILED(err)) { return err; } @@ -1051,7 +1012,7 @@ config_init_home(_PyCoreConfig *config) /* If Py_SetPythonHome() was called, use its value */ wchar_t *home = _Py_path_config.home; if (home) { - _PyInitError err = _PyCoreConfig_SetWideString(&config->home, home); + _PyInitError err = _PyCoreConfig_SetString(&config->home, home); if (_Py_INIT_FAILED(err)) { return err; } @@ -1280,7 +1241,7 @@ config_read_complex_options(_PyCoreConfig *config) } -static const char * +static const wchar_t * config_get_stdio_errors(const _PyCoreConfig *config) { #ifndef MS_WINDOWS @@ -1288,43 +1249,44 @@ config_get_stdio_errors(const _PyCoreConfig *config) if (loc != NULL) { /* surrogateescape is the default in the legacy C and POSIX locales */ if (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0) { - return "surrogateescape"; + return L"surrogateescape"; } #ifdef PY_COERCE_C_LOCALE /* surrogateescape is the default in locale coercion target locales */ if (_Py_IsLocaleCoercionTarget(loc)) { - return "surrogateescape"; + return L"surrogateescape"; } #endif } - return "strict"; + return L"strict"; #else /* On Windows, always use surrogateescape by default */ - return "surrogateescape"; + return L"surrogateescape"; #endif } static _PyInitError -config_get_locale_encoding(char **locale_encoding) +config_get_locale_encoding(wchar_t **locale_encoding) { #ifdef MS_WINDOWS char encoding[20]; PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP()); + return _PyCoreConfig_DecodeLocale(locale_encoding, encoding); #elif defined(_Py_FORCE_UTF8_LOCALE) - const char *encoding = "UTF-8"; + return _PyCoreConfig_SetString(locale_encoding, L"utf-8"); #else const char *encoding = nl_langinfo(CODESET); if (!encoding || encoding[0] == '\0') { return _Py_INIT_ERR("failed to get the locale encoding: " "nl_langinfo(CODESET) failed"); } + /* nl_langinfo(CODESET) is decoded by Py_DecodeLocale() */ + return CONFIG_DECODE_LOCALE(locale_encoding, encoding, + "nl_langinfo(CODESET)"); #endif - - assert(*locale_encoding == NULL); - return _PyCoreConfig_SetString(locale_encoding, encoding); } @@ -1337,16 +1299,18 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* If Py_SetStandardStreamEncoding() have been called, use these parameters. */ if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) { - err = _PyCoreConfig_SetString(&config->stdio_encoding, - _Py_StandardStreamEncoding); + err = CONFIG_DECODE_LOCALE(&config->stdio_encoding, + _Py_StandardStreamEncoding, + "_Py_StandardStreamEncoding"); if (_Py_INIT_FAILED(err)) { return err; } } if (config->stdio_errors == NULL && _Py_StandardStreamErrors != NULL) { - err = _PyCoreConfig_SetString(&config->stdio_errors, - _Py_StandardStreamErrors); + err = CONFIG_DECODE_LOCALE(&config->stdio_errors, + _Py_StandardStreamErrors, + "_Py_StandardStreamErrors"); if (_Py_INIT_FAILED(err)) { return err; } @@ -1359,11 +1323,9 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* PYTHONIOENCODING environment variable */ const char *opt = _PyCoreConfig_GetEnv(config, "PYTHONIOENCODING"); if (opt) { - /* _PyCoreConfig_SetString() requires dest to be initialized to NULL */ - char *pythonioencoding = NULL; - err = _PyCoreConfig_SetString(&pythonioencoding, opt); - if (_Py_INIT_FAILED(err)) { - return err; + char *pythonioencoding = _PyMem_RawStrdup(opt); + if (pythonioencoding == NULL) { + return _Py_INIT_NO_MEMORY(); } char *errors = strchr(pythonioencoding, ':'); @@ -1378,8 +1340,9 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* Does PYTHONIOENCODING contain an encoding? */ if (pythonioencoding[0]) { if (config->stdio_encoding == NULL) { - err = _PyCoreConfig_SetString(&config->stdio_encoding, - pythonioencoding); + err = CONFIG_DECODE_LOCALE(&config->stdio_encoding, + pythonioencoding, + "PYTHONIOENCODING environment variable"); if (_Py_INIT_FAILED(err)) { PyMem_RawFree(pythonioencoding); return err; @@ -1396,7 +1359,9 @@ config_init_stdio_encoding(_PyCoreConfig *config, } if (config->stdio_errors == NULL && errors != NULL) { - err = _PyCoreConfig_SetString(&config->stdio_errors, errors); + err = CONFIG_DECODE_LOCALE(&config->stdio_errors, + errors, + "PYTHONIOENCODING environment variable"); if (_Py_INIT_FAILED(err)) { PyMem_RawFree(pythonioencoding); return err; @@ -1409,15 +1374,14 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* UTF-8 Mode uses UTF-8/surrogateescape */ if (preconfig->utf8_mode) { if (config->stdio_encoding == NULL) { - err = _PyCoreConfig_SetString(&config->stdio_encoding, - "utf-8"); + err = _PyCoreConfig_SetString(&config->stdio_encoding, L"utf-8"); if (_Py_INIT_FAILED(err)) { return err; } } if (config->stdio_errors == NULL) { err = _PyCoreConfig_SetString(&config->stdio_errors, - "surrogateescape"); + L"surrogateescape"); if (_Py_INIT_FAILED(err)) { return err; } @@ -1432,7 +1396,7 @@ config_init_stdio_encoding(_PyCoreConfig *config, } } if (config->stdio_errors == NULL) { - const char *errors = config_get_stdio_errors(config); + const wchar_t *errors = config_get_stdio_errors(config); assert(errors != NULL); err = _PyCoreConfig_SetString(&config->stdio_errors, errors); @@ -1452,33 +1416,32 @@ config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) if (config->filesystem_encoding == NULL) { #ifdef _Py_FORCE_UTF8_FS_ENCODING - err = _PyCoreConfig_SetString(&config->filesystem_encoding, - "utf-8"); + err = _PyCoreConfig_SetString(&config->filesystem_encoding, L"utf-8"); #else #ifdef MS_WINDOWS if (preconfig->legacy_windows_fs_encoding) { /* Legacy Windows filesystem encoding: mbcs/replace */ err = _PyCoreConfig_SetString(&config->filesystem_encoding, - "mbcs"); + L"mbcs"); } else #endif if (preconfig->utf8_mode) { err = _PyCoreConfig_SetString(&config->filesystem_encoding, - "utf-8"); + L"utf-8"); } #ifndef MS_WINDOWS else if (_Py_GetForceASCII()) { err = _PyCoreConfig_SetString(&config->filesystem_encoding, - "ascii"); + L"ascii"); } #endif else { #ifdef MS_WINDOWS /* Windows defaults to utf-8/surrogatepass (PEP 529). */ err = _PyCoreConfig_SetString(&config->filesystem_encoding, - "utf-8"); + L"utf-8"); #else err = config_get_locale_encoding(&config->filesystem_encoding); #endif @@ -1491,16 +1454,16 @@ config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) } if (config->filesystem_errors == NULL) { - const char *errors; + const wchar_t *errors; #ifdef MS_WINDOWS if (preconfig->legacy_windows_fs_encoding) { - errors = "replace"; + errors = L"replace"; } else { - errors = "surrogatepass"; + errors = L"surrogatepass"; } #else - errors = "surrogateescape"; + errors = L"surrogateescape"; #endif err = _PyCoreConfig_SetString(&config->filesystem_errors, errors); if (_Py_INIT_FAILED(err)) { @@ -1745,8 +1708,8 @@ config_parse_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline, || wcscmp(_PyOS_optarg, L"never") == 0 || wcscmp(_PyOS_optarg, L"default") == 0) { - err = _PyCoreConfig_SetWideString(&config->check_hash_pycs_mode, - _PyOS_optarg); + err = _PyCoreConfig_SetString(&config->check_hash_pycs_mode, + _PyOS_optarg); if (_Py_INIT_FAILED(err)) { return err; } @@ -2119,7 +2082,7 @@ config_read_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline) } if (config->check_hash_pycs_mode == NULL) { - err = _PyCoreConfig_SetWideString(&config->check_hash_pycs_mode, L"default"); + err = _PyCoreConfig_SetString(&config->check_hash_pycs_mode, L"default"); if (_Py_INIT_FAILED(err)) { goto done; } diff --git a/Python/preconfig.c b/Python/preconfig.c index 108cbc66606176..48b9e8383aae14 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -14,7 +14,10 @@ /* --- File system encoding/errors -------------------------------- */ /* The filesystem encoding is chosen by config_init_fs_encoding(), - see also initfsencoding(). */ + see also initfsencoding(). + + Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors + are encoded to UTF-8. */ const char *Py_FileSystemDefaultEncoding = NULL; int Py_HasFileSystemDefaultEncoding = 0; const char *Py_FileSystemDefaultEncodeErrors = NULL; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 01ef027b9d860f..2a633cf1cf9273 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1668,7 +1668,7 @@ is_valid_fd(int fd) static PyObject* create_stdio(const _PyCoreConfig *config, PyObject* io, int fd, int write_mode, const char* name, - const char* encoding, const char* errors) + const wchar_t* encoding, const wchar_t* errors) { PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res; const char* mode; @@ -1718,7 +1718,7 @@ create_stdio(const _PyCoreConfig *config, PyObject* io, #ifdef MS_WINDOWS /* Windows console IO is always UTF-8 encoded */ if (PyWindowsConsoleIO_Check(raw)) - encoding = "utf-8"; + encoding = L"utf-8"; #endif text = PyUnicode_FromString(name); @@ -1754,10 +1754,25 @@ create_stdio(const _PyCoreConfig *config, PyObject* io, newline = "\n"; #endif - stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OsssOO", - buf, encoding, errors, + PyObject *encoding_str = PyUnicode_FromWideChar(encoding, -1); + if (encoding_str == NULL) { + Py_CLEAR(buf); + goto error; + } + + PyObject *errors_str = PyUnicode_FromWideChar(errors, -1); + if (errors_str == NULL) { + Py_CLEAR(buf); + Py_CLEAR(encoding_str); + goto error; + } + + stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OOOsOO", + buf, encoding_str, errors_str, newline, line_buffering, write_through); Py_CLEAR(buf); + Py_CLEAR(encoding_str); + Py_CLEAR(errors_str); if (stream == NULL) goto error; @@ -1874,7 +1889,7 @@ init_sys_streams(PyInterpreterState *interp) fd = fileno(stderr); std = create_stdio(config, iomod, fd, 1, "", config->stdio_encoding, - "backslashreplace"); + L"backslashreplace"); if (std == NULL) goto error; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 0f7af2c69da538..fbdeb9b5565cf8 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -424,7 +424,7 @@ sys_getfilesystemencoding_impl(PyObject *module) { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); const _PyCoreConfig *config = &interp->core_config; - return PyUnicode_FromString(config->filesystem_encoding); + return PyUnicode_FromWideChar(config->filesystem_encoding, -1); } /*[clinic input] @@ -439,7 +439,7 @@ sys_getfilesystemencodeerrors_impl(PyObject *module) { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); const _PyCoreConfig *config = &interp->core_config; - return PyUnicode_FromString(config->filesystem_errors); + return PyUnicode_FromWideChar(config->filesystem_errors, -1); } /*[clinic input] @@ -1211,30 +1211,9 @@ static PyObject * sys__enablelegacywindowsfsencoding_impl(PyObject *module) /*[clinic end generated code: output=f5c3855b45e24fe9 input=2bfa931a20704492]*/ { - PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); - _PyCoreConfig *config = &interp->core_config; - - /* Set the filesystem encoding to mbcs/replace (PEP 529) */ - char *encoding = _PyMem_RawStrdup("mbcs"); - char *errors = _PyMem_RawStrdup("replace"); - if (encoding == NULL || errors == NULL) { - PyMem_Free(encoding); - PyMem_Free(errors); - PyErr_NoMemory(); - return NULL; - } - - PyMem_RawFree(config->filesystem_encoding); - config->filesystem_encoding = encoding; - PyMem_RawFree(config->filesystem_errors); - config->filesystem_errors = errors; - - if (_Py_SetFileSystemEncoding(config->filesystem_encoding, - config->filesystem_errors) < 0) { - PyErr_NoMemory(); + if (_PyUnicode_EnableLegacyWindowsFSEncoding() < 0) { return NULL; } - Py_RETURN_NONE; } From 70005ac0fddd8585725b92acd1bc2b8e7b81999c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 2 May 2019 15:25:34 -0400 Subject: [PATCH 156/212] bpo-36763: _PyCoreConfig_SetPyArgv() preinitializes Python (GH-13037) _PyCoreConfig_SetPyArgv() and _PyCoreConfig_SetWideString() now pre-initialize Python if needed to ensure that the locale encoding is properly configured. * Add _Py_PreInitializeFromPyArgv() internal function. * Add 'args' parameter to _Py_PreInitializeFromCoreConfig() --- Include/internal/pycore_pylifecycle.h | 9 ++++++-- Modules/main.c | 9 +------- Python/coreconfig.c | 31 +++++++++++++++++++++++++-- Python/pylifecycle.c | 28 +++++++++++------------- 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 321cc5d27889bd..adb1f5d90a5960 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -8,7 +8,8 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_pystate.h" /* _PyRuntimeState */ +#include "pycore_coreconfig.h" /* _PyArgv */ +#include "pycore_pystate.h" /* _PyRuntimeState */ /* True if the main interpreter thread exited due to an unhandled * KeyboardInterrupt exception, suggesting the user pressed ^C. */ @@ -90,8 +91,12 @@ extern void _PyGILState_Fini(_PyRuntimeState *runtime); PyAPI_FUNC(void) _PyGC_DumpShutdownStats(_PyRuntimeState *runtime); +PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromPyArgv( + const _PyPreConfig *src_config, + const _PyArgv *args); PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromCoreConfig( - const _PyCoreConfig *coreconfig); + const _PyCoreConfig *coreconfig, + const _PyArgv *args); #ifdef __cplusplus } diff --git a/Modules/main.c b/Modules/main.c index 575683cd7f889f..e117ef29e54dcc 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -57,14 +57,7 @@ pymain_init(const _PyArgv *args) environment variables (PYTHONUTF8 and PYTHONCOERCECLOCALE) */ preconfig.coerce_c_locale = -1; preconfig.utf8_mode = -1; - if (args->use_bytes_argv) { - err = _Py_PreInitializeFromArgs(&preconfig, - args->argc, args->bytes_argv); - } - else { - err = _Py_PreInitializeFromWideArgs(&preconfig, - args->argc, args->wchar_argv); - } + err = _Py_PreInitializeFromPyArgv(&preconfig, args); if (_Py_INIT_FAILED(err)) { return err; } diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 15643be3765aa0..52026949e202c3 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -541,11 +541,15 @@ _PyCoreConfig_SetString(wchar_t **config_str, const wchar_t *str) } -/* Decode str using Py_DecodeLocale() and set the result into *config_str */ static _PyInitError _PyCoreConfig_DecodeLocaleErr(wchar_t **config_str, const char *str, const char *decode_err_msg) { + _PyInitError err = _Py_PreInitialize(NULL); + if (_Py_INIT_FAILED(err)) { + return err; + } + wchar_t *str2; if (str != NULL) { size_t len; @@ -572,6 +576,9 @@ _PyCoreConfig_DecodeLocaleErr(wchar_t **config_str, const char *str, _PyCoreConfig_DecodeLocaleErr(config_str, str, "cannot decode " NAME) +/* Decode str using Py_DecodeLocale() and set the result into *config_str. + Pre-initialize Python if needed to ensure that encodings are properly + configured. */ _PyInitError _PyCoreConfig_DecodeLocale(wchar_t **config_str, const char *str) { @@ -2100,10 +2107,30 @@ config_read_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline) _PyInitError _PyCoreConfig_SetPyArgv(_PyCoreConfig *config, const _PyArgv *args) { + if (args->use_bytes_argv) { + _PyInitError err; + + err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyRuntimeState *runtime = &_PyRuntime; + + /* do nothing if Python is already pre-initialized: + _PyCoreConfig_Write() will update _PyRuntime.preconfig later */ + if (!runtime->pre_initialized) { + err = _Py_PreInitializeFromCoreConfig(config, args); + if (_Py_INIT_FAILED(err)) { + return err; + } + } + } return _PyArgv_AsWstrList(args, &config->argv); } +/* Set config.argv: decode argv using Py_DecodeLocale(). Pre-initialize Python + if needed to ensure that encodings are properly configured. */ _PyInitError _PyCoreConfig_SetArgv(_PyCoreConfig *config, int argc, char **argv) { @@ -2138,7 +2165,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config) { _PyInitError err; - err = _Py_PreInitializeFromCoreConfig(config); + err = _Py_PreInitializeFromCoreConfig(config, NULL); if (_Py_INIT_FAILED(err)) { return err; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 2a633cf1cf9273..2ba43b99cf3a44 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -683,8 +683,8 @@ _Py_InitializeCore_impl(_PyRuntimeState *runtime, } -static _PyInitError -preinit(const _PyPreConfig *src_config, const _PyArgv *args) +_PyInitError +_Py_PreInitializeFromPyArgv(const _PyPreConfig *src_config, const _PyArgv *args) { _PyInitError err; @@ -726,11 +726,12 @@ preinit(const _PyPreConfig *src_config, const _PyArgv *args) return err; } + _PyInitError _Py_PreInitializeFromArgs(const _PyPreConfig *src_config, int argc, char **argv) { _PyArgv args = {.use_bytes_argv = 1, .argc = argc, .bytes_argv = argv}; - return preinit(src_config, &args); + return _Py_PreInitializeFromPyArgv(src_config, &args); } @@ -738,24 +739,26 @@ _PyInitError _Py_PreInitializeFromWideArgs(const _PyPreConfig *src_config, int argc, wchar_t **argv) { _PyArgv args = {.use_bytes_argv = 0, .argc = argc, .wchar_argv = argv}; - return preinit(src_config, &args); + return _Py_PreInitializeFromPyArgv(src_config, &args); } _PyInitError _Py_PreInitialize(const _PyPreConfig *src_config) { - return preinit(src_config, NULL); + return _Py_PreInitializeFromPyArgv(src_config, NULL); } _PyInitError -_Py_PreInitializeFromCoreConfig(const _PyCoreConfig *coreconfig) +_Py_PreInitializeFromCoreConfig(const _PyCoreConfig *coreconfig, + const _PyArgv *args) { - assert(coreconfig != NULL); _PyPreConfig config = _PyPreConfig_INIT; - _PyCoreConfig_GetCoreConfig(&config, coreconfig); - return _Py_PreInitialize(&config); + if (coreconfig != NULL) { + _PyCoreConfig_GetCoreConfig(&config, coreconfig); + } + return _Py_PreInitializeFromPyArgv(&config, args); /* No need to clear config: _PyCoreConfig_GetCoreConfig() doesn't allocate memory */ } @@ -823,12 +826,7 @@ _Py_InitializeCore(_PyRuntimeState *runtime, { _PyInitError err; - if (src_config) { - err = _Py_PreInitializeFromCoreConfig(src_config); - } - else { - err = _Py_PreInitialize(NULL); - } + err = _Py_PreInitializeFromCoreConfig(src_config, args); if (_Py_INIT_FAILED(err)) { return err; } From 4631da1242fc96002a3c0462a87d087e567368aa Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 2 May 2019 15:30:21 -0400 Subject: [PATCH 157/212] bpo-36763: Remove _PyCoreConfig._init_main (GH-13066) --- Include/cpython/coreconfig.h | 6 +----- Lib/test/test_embed.py | 13 ++++++++----- Programs/_freeze_importlib.c | 1 - Programs/_testembed.c | 5 ----- Python/coreconfig.c | 2 -- Python/pylifecycle.c | 2 +- 6 files changed, 10 insertions(+), 19 deletions(-) diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index 5672080b784fde..47a6baa1118fca 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -391,9 +391,6 @@ typedef struct { If set to -1 (default), inherit Py_FrozenFlag value. */ int _frozen; - /* If non-zero, use "main" Python initialization */ - int _init_main; - } _PyCoreConfig; #ifdef MS_WINDOWS @@ -428,8 +425,7 @@ typedef struct { .buffered_stdio = -1, \ ._install_importlib = 1, \ .check_hash_pycs_mode = NULL, \ - ._frozen = -1, \ - ._init_main = 1} + ._frozen = -1} /* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */ #ifdef __cplusplus diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index fb0051957aad0c..fdf5793789dfed 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -348,7 +348,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): '_install_importlib': 1, 'check_hash_pycs_mode': 'default', '_frozen': 0, - '_init_main': 1, } if MS_WINDOWS: DEFAULT_PRE_CONFIG.update({ @@ -443,7 +442,10 @@ def get_expected_config(self, expected, env): raise Exception(f"failed to get the default config: " f"stdout={proc.stdout!r} stderr={proc.stderr!r}") stdout = proc.stdout.decode('utf-8') - config = json.loads(stdout) + try: + config = json.loads(stdout) + except json.JSONDecodeError: + self.fail(f"fail to decode stdout: {stdout!r}") for key, value in expected.items(): if value is self.GET_DEFAULT_CONFIG: @@ -496,7 +498,10 @@ def check_config(self, testname, expected_config, expected_preconfig): out, err = self.run_embedded_interpreter(testname, env=env) # Ignore err - config = json.loads(out) + try: + config = json.loads(out) + except json.JSONDecodeError: + self.fail(f"fail to decode stdout: {out!r}") expected_preconfig = dict(self.DEFAULT_PRE_CONFIG, **expected_preconfig) expected_config = self.get_expected_config(expected_config, env) @@ -533,7 +538,6 @@ def test_init_global_config(self): 'filesystem_encoding': 'utf-8', 'filesystem_errors': self.UTF8_MODE_ERRORS, 'user_site_directory': 0, - '_frozen': 1, } self.check_config("init_global_config", config, preconfig) @@ -578,7 +582,6 @@ def test_init_from_config(self): 'faulthandler': 1, 'check_hash_pycs_mode': 'always', - '_frozen': 1, } self.check_config("init_from_config", config, preconfig) diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c index 6f77e86a9e6666..0818012d8c5abd 100644 --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -84,7 +84,6 @@ main(int argc, char *argv[]) /* Don't install importlib, since it could execute outdated bytecode. */ config._install_importlib = 0; config._frozen = 1; - config._init_main = 0; _PyInitError err = _Py_InitializeFromConfig(&config); /* No need to call _PyCoreConfig_Clear() since we didn't allocate any diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 2cadf82cb17faa..b12594799bfc93 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -354,8 +354,6 @@ static int test_init_global_config(void) putenv("PYTHONUNBUFFERED="); Py_UnbufferedStdioFlag = 1; - Py_FrozenFlag = 1; - /* FIXME: test Py_LegacyWindowsFSEncodingFlag */ /* FIXME: test Py_LegacyWindowsStdioFlag */ @@ -497,9 +495,6 @@ static int test_init_from_config(void) config.check_hash_pycs_mode = L"always"; - Py_FrozenFlag = 0; - config._frozen = 1; - err = _Py_InitializeFromConfig(&config); if (_Py_INIT_FAILED(err)) { _Py_ExitInitError(err); diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 52026949e202c3..ac01712127ac0a 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -667,7 +667,6 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_WSTR_ATTR(run_filename); COPY_WSTR_ATTR(check_hash_pycs_mode); COPY_ATTR(_frozen); - COPY_ATTR(_init_main); #undef COPY_ATTR #undef COPY_WSTR_ATTR @@ -766,7 +765,6 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) SET_ITEM_INT(_install_importlib); SET_ITEM_WSTR(check_hash_pycs_mode); SET_ITEM_INT(_frozen); - SET_ITEM_INT(_init_main); return dict; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 2ba43b99cf3a44..bd4d1d92662a69 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -988,7 +988,7 @@ init_python(const _PyCoreConfig *config, const _PyArgv *args) } config = &interp->core_config; - if (config->_init_main) { + if (!config->_frozen) { err = _Py_InitializeMainInterpreter(runtime, interp); if (_Py_INIT_FAILED(err)) { return err; From 45e92fc02d57a7219f4f4922179929f19b3d1c28 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Thu, 2 May 2019 22:11:04 +0200 Subject: [PATCH 158/212] Add correct license for C14N test suite to license docs. (GH-13055) --- Doc/license.rst | 37 +++++++++++++++++++++++++++++ Lib/test/xmltestdata/c14n-20/README | 28 +++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/Doc/license.rst b/Doc/license.rst index a315b6f8134d48..d3733f53a116f4 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -913,3 +913,40 @@ library unless the build is configured ``--with-system-libmpdec``:: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +W3C C14N test suite +------------------- + +The C14N 2.0 test suite in the :mod:`test` package +(``Lib/test/xmltestdata/c14n-20/``) was retrieved from the W3C website at +https://www.w3.org/TR/xml-c14n2-testcases/ and is distributed under the +3-clause BSD license: + + Copyright (c) 2013 W3C(R) (MIT, ERCIM, Keio, Beihang), + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of works must retain the original copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the original copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the W3C nor the names of its contributors may be + used to endorse or promote products derived from this work without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Lib/test/xmltestdata/c14n-20/README b/Lib/test/xmltestdata/c14n-20/README index 06e63704542028..45e75b9bd98eb5 100644 --- a/Lib/test/xmltestdata/c14n-20/README +++ b/Lib/test/xmltestdata/c14n-20/README @@ -9,6 +9,32 @@ Direct source: https://www.w3.org/TR/xml-c14n2-testcases/files/ Copied and distributed under these terms: +https://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), -http://www.w3.org/Consortium/Legal/2015/doc-license +All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of works must retain the original copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the original copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of the W3C nor the names of its contributors may be + used to endorse or promote products derived from this work without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 22c526394b2ef51b985873ddbfbcc32c16411919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Srinivas=20Reddy=20Thatiparthy=20=28=E0=B0=B6=E0=B1=8D?= =?UTF-8?q?=E0=B0=B0=E0=B1=80=E0=B0=A8=E0=B0=BF=E0=B0=B5=E0=B0=BE=E0=B0=B8?= =?UTF-8?q?=E0=B1=8D=20=20=E0=B0=B0=E0=B1=86=E0=B0=A1=E0=B1=8D=E0=B0=A1?= =?UTF-8?q?=E0=B0=BF=20=E0=B0=A4=E0=B0=BE=E0=B0=9F=E0=B0=BF=E0=B0=AA?= =?UTF-8?q?=E0=B0=B0=E0=B1=8D=E0=B0=A4=E0=B0=BF=29?= Date: Fri, 3 May 2019 17:52:12 +0530 Subject: [PATCH 159/212] bpo:34848 : Correct an incorrect docstring for range().index method (GH-9877) --- Objects/rangeobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 4b8e5ed4cfd4cd..ac868f6951c29c 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -645,7 +645,7 @@ PyDoc_STRVAR(count_doc, "rangeobject.count(value) -> integer -- return number of occurrences of value"); PyDoc_STRVAR(index_doc, -"rangeobject.index(value, [start, [stop]]) -> integer -- return index of value.\n" +"rangeobject.index(value) -> integer -- return index of value.\n" "Raise ValueError if the value is not present."); static PyMethodDef range_methods[] = { From 5861cddf76215b8390d48069a35d30a5c3ec92c1 Mon Sep 17 00:00:00 2001 From: Andre Delfino Date: Fri, 3 May 2019 11:59:05 -0300 Subject: [PATCH 160/212] Don't use the LHS/RHS acronym in Simple statements (GH-12996) Prefer the full wording instead, as it is more meaningful for someone not familiar with the terms. Also, LFS/RHS is not used anywhere else in the documentation, while left/right-hand side mentions are common. --- Doc/reference/simple_stmts.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index 207057cbc12414..af7c0caff62797 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -169,12 +169,12 @@ Assignment of an object to a single target is recursively defined as follows. .. _attr-target-note: Note: If the object is a class instance and the attribute reference occurs on - both sides of the assignment operator, the RHS expression, ``a.x`` can access + both sides of the assignment operator, the right-hand side expression, ``a.x`` can access either an instance attribute or (if no instance attribute exists) a class - attribute. The LHS target ``a.x`` is always set as an instance attribute, + attribute. The left-hand side target ``a.x`` is always set as an instance attribute, creating it if necessary. Thus, the two occurrences of ``a.x`` do not - necessarily refer to the same attribute: if the RHS expression refers to a - class attribute, the LHS creates a new instance attribute as the target of the + necessarily refer to the same attribute: if the right-hand side expression refers to a + class attribute, the left-hand side creates a new instance attribute as the target of the assignment:: class Cls: From a8a79cacca4a03e2e682bf10108c80f502791755 Mon Sep 17 00:00:00 2001 From: Andre Delfino Date: Fri, 3 May 2019 12:08:10 -0300 Subject: [PATCH 161/212] Improve grammar on async context managers and shorten text (GH-12379) --- Doc/reference/datamodel.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 1683d25db9247a..bad611e81c3e65 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2680,13 +2680,13 @@ Asynchronous context managers can be used in an :keyword:`async with` statement. .. method:: object.__aenter__(self) - This method is semantically similar to the :meth:`__enter__`, with only - difference that it must return an *awaitable*. + Semantically similar to :meth:`__enter__`, the only + difference being that it must return an *awaitable*. .. method:: object.__aexit__(self, exc_type, exc_value, traceback) - This method is semantically similar to the :meth:`__exit__`, with only - difference that it must return an *awaitable*. + Semantically similar to :meth:`__exit__`, the only + difference being that it must return an *awaitable*. An example of an asynchronous context manager class:: From 4461d704e23a13dfbe78ea3020e4cbeff4b68dc2 Mon Sep 17 00:00:00 2001 From: xdegaye Date: Fri, 3 May 2019 17:09:17 +0200 Subject: [PATCH 162/212] bpo-36341: Fix tests calling bind() on AF_UNIX sockets (GH-12399) Those tests may fail with PermissionError. https://bugs.python.org/issue36341 --- Lib/test/test_asyncio/test_server.py | 2 +- Lib/test/test_socket.py | 9 +++++++-- Lib/test/test_stat.py | 5 +++-- .../next/Tests/2019-03-18-10-47-45.bpo-36341.UXlY0P.rst | 2 ++ 4 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-03-18-10-47-45.bpo-36341.UXlY0P.rst diff --git a/Lib/test/test_asyncio/test_server.py b/Lib/test/test_asyncio/test_server.py index 6de058a1e9bff5..ab7f3debbc152e 100644 --- a/Lib/test/test_asyncio/test_server.py +++ b/Lib/test/test_asyncio/test_server.py @@ -73,7 +73,7 @@ class SelectorStartServerTests(BaseStartServer, unittest.TestCase): def new_loop(self): return asyncio.SelectorEventLoop() - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'no Unix sockets') + @support.skip_unless_bind_unix_socket def test_start_unix_server_1(self): HELLO_MSG = b'1' * 1024 * 5 + b'\n' started = threading.Event() diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 815f9adce6772a..0094cecb79cca6 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1796,8 +1796,13 @@ def test_socket_fileno(self): self.addCleanup(shutil.rmtree, tmpdir) s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.addCleanup(s.close) - s.bind(os.path.join(tmpdir, 'socket')) - self._test_socket_fileno(s, socket.AF_UNIX, socket.SOCK_STREAM) + try: + s.bind(os.path.join(tmpdir, 'socket')) + except PermissionError: + pass + else: + self._test_socket_fileno(s, socket.AF_UNIX, + socket.SOCK_STREAM) def test_socket_fileno_rejects_float(self): with self.assertRaisesRegex(TypeError, "integer argument expected"): diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py index 38ff2bcf8a6b64..17443bed0738b5 100644 --- a/Lib/test/test_stat.py +++ b/Lib/test/test_stat.py @@ -2,7 +2,8 @@ import os import socket import sys -from test.support import TESTFN, import_fresh_module +from test.support import (TESTFN, import_fresh_module, + skip_unless_bind_unix_socket) c_stat = import_fresh_module('stat', fresh=['_stat']) py_stat = import_fresh_module('stat', blocked=['_stat']) @@ -192,7 +193,7 @@ def test_devices(self): self.assertS_IS("BLK", st_mode) break - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'requires unix socket') + @skip_unless_bind_unix_socket def test_socket(self): with socket.socket(socket.AF_UNIX) as s: s.bind(TESTFN) diff --git a/Misc/NEWS.d/next/Tests/2019-03-18-10-47-45.bpo-36341.UXlY0P.rst b/Misc/NEWS.d/next/Tests/2019-03-18-10-47-45.bpo-36341.UXlY0P.rst new file mode 100644 index 00000000000000..b76447d6cf97fd --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-03-18-10-47-45.bpo-36341.UXlY0P.rst @@ -0,0 +1,2 @@ +Fix tests that may fail with PermissionError upon calling bind() on AF_UNIX +sockets. From c1964e9e2177eabe821f3e4243be8b99e0d2d542 Mon Sep 17 00:00:00 2001 From: gescheit Date: Fri, 3 May 2019 18:18:02 +0300 Subject: [PATCH 163/212] bpo-36613: call remove_done_callback if exception (GH-12800) Call remove_done_callback() in finally block. https://bugs.python.org/issue36613 --- Lib/asyncio/tasks.py | 3 ++- .../next/Library/2019-04-12-13-52-15.bpo-36613.hqT1qn.rst | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-12-13-52-15.bpo-36613.hqT1qn.rst diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index d8508376d92a48..007a459857d208 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -495,10 +495,11 @@ def _on_completion(f): finally: if timeout_handle is not None: timeout_handle.cancel() + for f in fs: + f.remove_done_callback(_on_completion) done, pending = set(), set() for f in fs: - f.remove_done_callback(_on_completion) if f.done(): done.add(f) else: diff --git a/Misc/NEWS.d/next/Library/2019-04-12-13-52-15.bpo-36613.hqT1qn.rst b/Misc/NEWS.d/next/Library/2019-04-12-13-52-15.bpo-36613.hqT1qn.rst new file mode 100644 index 00000000000000..8828dccad69c51 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-12-13-52-15.bpo-36613.hqT1qn.rst @@ -0,0 +1 @@ +Fix :mod:`asyncio` wait() not removing callback if exception \ No newline at end of file From ceb842e155f5fa0109fa88d52da3d1f5e73490ad Mon Sep 17 00:00:00 2001 From: Alexander Vasin Date: Fri, 3 May 2019 18:25:36 +0300 Subject: [PATCH 164/212] Fixed typo (GH-11522) Given example does not run, loop variable is missing. Secondly, this is bad example how to handle shutdown signal, because it would cause `RuntimeError: Event loop stopped before Future completed.` Perhaps it would be better to cancel all tasks instead of closing loop directly? Did not create issue, because question is quite simple. --- Doc/library/asyncio-eventloop.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index bf7c93a86fd041..e2b31245392122 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -1601,7 +1601,7 @@ using the :meth:`loop.add_signal_handler` method:: import os import signal - def ask_exit(signame): + def ask_exit(signame, loop): print("got signal %s: exit" % signame) loop.stop() @@ -1611,7 +1611,7 @@ using the :meth:`loop.add_signal_handler` method:: for signame in {'SIGINT', 'SIGTERM'}: loop.add_signal_handler( getattr(signal, signame), - functools.partial(ask_exit, signame)) + functools.partial(ask_exit, signame, loop)) await asyncio.sleep(3600) From 4737b923df6fbdb9e2bf3fdccea2112270556e0a Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Fri, 3 May 2019 09:35:26 -0600 Subject: [PATCH 165/212] bpo-24638: Improve the error message in asyncio.ensure_future() (#12848) --- Lib/asyncio/tasks.py | 3 ++- Lib/test/test_asyncio/test_tasks.py | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 007a459857d208..b007b74344edb5 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -628,7 +628,8 @@ def ensure_future(coro_or_future, *, loop=None): return task elif futures.isfuture(coro_or_future): if loop is not None and loop is not futures._get_loop(coro_or_future): - raise ValueError('loop argument must agree with Future') + raise ValueError('The future belongs to a different loop than ' + 'the one specified as the loop argument') return coro_or_future elif inspect.isawaitable(coro_or_future): return ensure_future(_wrap_awaitable(coro_or_future), loop=loop) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 1cdff528def49d..c4f6d703549ca2 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -236,6 +236,15 @@ def test_ensure_future_neither(self): with self.assertRaises(TypeError): asyncio.ensure_future('ok') + def test_ensure_future_error_msg(self): + loop = asyncio.new_event_loop() + f = self.new_future(self.loop) + with self.assertRaisesRegex(ValueError, 'The future belongs to a ' + 'different loop than the one specified as ' + 'the loop argument'): + asyncio.ensure_future(f, loop=loop) + loop.close() + def test_get_stack(self): T = None From cf48e55f7f7718482fa712552f0cbc0aea1c826f Mon Sep 17 00:00:00 2001 From: Andre Delfino Date: Fri, 3 May 2019 13:53:22 -0300 Subject: [PATCH 166/212] bpo-33882: mention breakpoint() in debugger-related FAQ (GH-7759) --- Doc/faq/programming.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 31614189a62d2c..f14e8cc824ef74 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -16,6 +16,9 @@ Is there a source code level debugger with breakpoints, single-stepping, etc.? Yes. +Several debuggers for Python are described below, and the built-in function +:func:`breakpoint` allows you to drop into any of them. + The pdb module is a simple but adequate console-mode debugger for Python. It is part of the standard Python library, and is :mod:`documented in the Library Reference Manual `. You can also write your own debugger by using the code From 47541689ccea79dfcb055c6be5800b13fcb6bdd2 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Fri, 3 May 2019 20:58:16 +0200 Subject: [PATCH 167/212] bpo-28238: Implement "{*}tag" and "{ns}*" wildcard tag selection support for ElementPath, and extend the surrounding tests and docs. (GH-12997) --- Doc/library/xml.etree.elementtree.rst | 17 +++- Doc/whatsnew/3.8.rst | 5 ++ Lib/test/test_xml_etree.py | 56 +++++++++++- Lib/xml/etree/ElementPath.py | 90 ++++++++++++++++--- .../2019-04-28-15-01-29.bpo-28238.gdk38f.rst | 3 + Modules/_elementtree.c | 15 +++- 6 files changed, 171 insertions(+), 15 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-28-15-01-29.bpo-28238.gdk38f.rst diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index ef74d0c852cd75..c4667315793e4c 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -399,6 +399,12 @@ module. We'll be using the ``countrydata`` XML document from the # All 'neighbor' nodes that are the second child of their parent root.findall(".//neighbor[2]") +For XML with namespaces, use the usual qualified ``{namespace}tag`` notation:: + + # All dublin-core "title" tags in the document + root.findall(".//{http://purl.org/dc/elements/1.1/}title") + + Supported XPath syntax ^^^^^^^^^^^^^^^^^^^^^^ @@ -411,9 +417,16 @@ Supported XPath syntax | | For example, ``spam`` selects all child elements | | | named ``spam``, and ``spam/egg`` selects all | | | grandchildren named ``egg`` in all children named | -| | ``spam``. | +| | ``spam``. ``{namespace}*`` selects all tags in the | +| | given namespace, ``{*}spam`` selects tags named | +| | ``spam`` in any (or no) namespace, and ``{}*`` | +| | only selects tags that are not in a namespace. | +| | | +| | .. versionchanged:: 3.8 | +| | Support for star-wildcards was added. | +-----------------------+------------------------------------------------------+ -| ``*`` | Selects all child elements. For example, ``*/egg`` | +| ``*`` | Selects all child elements, including comments and | +| | processing instructions. For example, ``*/egg`` | | | selects all grandchildren named ``egg``. | +-----------------------+------------------------------------------------------+ | ``.`` | Selects the current node. This is mostly useful | diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 82be92786ab005..764bd00544d9f5 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -532,6 +532,11 @@ xml external entities by default. (Contributed by Christian Heimes in :issue:`17239`.) +* The ``.find*()`` methods in the :mod:`xml.etree.ElementTree` module + support wildcard searches like ``{*}tag`` which ignores the namespace + and ``{namespace}*`` which returns all tags in the given namespace. + (Contributed by Stefan Behnel in :issue:`28238`.) + * The :mod:`xml.etree.ElementTree` module provides a new function :func:`–xml.etree.ElementTree.canonicalize()` that implements C14N 2.0. (Contributed by Stefan Behnel in :issue:`13611`.) diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index a59a11f025da31..ca6862cae44adf 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -1137,16 +1137,21 @@ def test_doctype_public(self): def test_xpath_tokenizer(self): # Test the XPath tokenizer. from xml.etree import ElementPath - def check(p, expected): + def check(p, expected, namespaces=None): self.assertEqual([op or tag - for op, tag in ElementPath.xpath_tokenizer(p)], + for op, tag in ElementPath.xpath_tokenizer(p, namespaces)], expected) # tests from the xml specification check("*", ['*']) + check("{ns}*", ['{ns}*']) + check("{}*", ['{}*']) + check("{*}tag", ['{*}tag']) + check("{*}*", ['{*}*']) check("text()", ['text', '()']) check("@name", ['@', 'name']) check("@*", ['@', '*']) + check("@{ns}attr", ['@', '{ns}attr']) check("para[1]", ['para', '[', '1', ']']) check("para[last()]", ['para', '[', 'last', '()', ']']) check("*/para", ['*', '/', 'para']) @@ -1158,6 +1163,7 @@ def check(p, expected): check("//olist/item", ['//', 'olist', '/', 'item']) check(".", ['.']) check(".//para", ['.', '//', 'para']) + check(".//{*}tag", ['.', '//', '{*}tag']) check("..", ['..']) check("../@lang", ['..', '/', '@', 'lang']) check("chapter[title]", ['chapter', '[', 'title', ']']) @@ -1168,6 +1174,8 @@ def check(p, expected): check("{http://spam}egg", ['{http://spam}egg']) check("./spam.egg", ['.', '/', 'spam.egg']) check(".//{http://spam}egg", ['.', '//', '{http://spam}egg']) + check("./xsd:type", ['.', '/', '{http://www.w3.org/2001/XMLSchema}type'], + {'xsd': 'http://www.w3.org/2001/XMLSchema'}) def test_processinginstruction(self): # Test ProcessingInstruction directly @@ -2669,6 +2677,50 @@ def test_findall_different_nsmaps(self): self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2) self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1) + def test_findall_wildcard(self): + root = ET.XML(''' + + + + + ''') + root.append(ET.Comment('test')) + + self.assertEqual(summarize_list(root.findall("{*}b")), + ['{X}b', 'b', '{Y}b']) + self.assertEqual(summarize_list(root.findall("{*}c")), + ['c']) + self.assertEqual(summarize_list(root.findall("{X}*")), + ['{X}b']) + self.assertEqual(summarize_list(root.findall("{Y}*")), + ['{Y}b']) + self.assertEqual(summarize_list(root.findall("{}*")), + ['b', 'c']) + self.assertEqual(summarize_list(root.findall("{}b")), # only for consistency + ['b']) + self.assertEqual(summarize_list(root.findall("{}b")), + summarize_list(root.findall("b"))) + self.assertEqual(summarize_list(root.findall("{*}*")), + ['{X}b', 'b', 'c', '{Y}b']) + # This is an unfortunate difference, but that's how find('*') works. + self.assertEqual(summarize_list(root.findall("{*}*") + [root[-1]]), + summarize_list(root.findall("*"))) + + self.assertEqual(summarize_list(root.findall(".//{*}b")), + ['{X}b', 'b', '{X}b', 'b', '{Y}b']) + self.assertEqual(summarize_list(root.findall(".//{*}c")), + ['c', 'c']) + self.assertEqual(summarize_list(root.findall(".//{X}*")), + ['{X}b', '{X}b']) + self.assertEqual(summarize_list(root.findall(".//{Y}*")), + ['{Y}b']) + self.assertEqual(summarize_list(root.findall(".//{}*")), + ['c', 'b', 'c', 'b']) + self.assertEqual(summarize_list(root.findall(".//{}b")), # only for consistency + ['b', 'b']) + self.assertEqual(summarize_list(root.findall(".//{}b")), + summarize_list(root.findall(".//b"))) + def test_bad_find(self): e = ET.XML(SAMPLE_XML) with self.assertRaisesRegex(SyntaxError, 'cannot use absolute path'): diff --git a/Lib/xml/etree/ElementPath.py b/Lib/xml/etree/ElementPath.py index b670d58f3f0121..cfe72f2f9d4251 100644 --- a/Lib/xml/etree/ElementPath.py +++ b/Lib/xml/etree/ElementPath.py @@ -99,13 +99,70 @@ def get_parent_map(context): parent_map[e] = p return parent_map + + +def _is_wildcard_tag(tag): + return tag[:3] == '{*}' or tag[-2:] == '}*' + + +def _prepare_tag(tag): + _isinstance, _str = isinstance, str + if tag == '{*}*': + # Same as '*', but no comments or processing instructions. + # It can be a surprise that '*' includes those, but there is no + # justification for '{*}*' doing the same. + def select(context, result): + for elem in result: + if _isinstance(elem.tag, _str): + yield elem + elif tag == '{}*': + # Any tag that is not in a namespace. + def select(context, result): + for elem in result: + el_tag = elem.tag + if _isinstance(el_tag, _str) and el_tag[0] != '{': + yield elem + elif tag[:3] == '{*}': + # The tag in any (or no) namespace. + suffix = tag[2:] # '}name' + no_ns = slice(-len(suffix), None) + tag = tag[3:] + def select(context, result): + for elem in result: + el_tag = elem.tag + if el_tag == tag or _isinstance(el_tag, _str) and el_tag[no_ns] == suffix: + yield elem + elif tag[-2:] == '}*': + # Any tag in the given namespace. + ns = tag[:-1] + ns_only = slice(None, len(ns)) + def select(context, result): + for elem in result: + el_tag = elem.tag + if _isinstance(el_tag, _str) and el_tag[ns_only] == ns: + yield elem + else: + raise RuntimeError(f"internal parser error, got {tag}") + return select + + def prepare_child(next, token): tag = token[1] - def select(context, result): - for elem in result: - for e in elem: - if e.tag == tag: - yield e + if _is_wildcard_tag(tag): + select_tag = _prepare_tag(tag) + def select(context, result): + def select_child(result): + for elem in result: + yield from elem + return select_tag(context, select_child(result)) + else: + if tag[:2] == '{}': + tag = tag[2:] # '{}tag' == 'tag' + def select(context, result): + for elem in result: + for e in elem: + if e.tag == tag: + yield e return select def prepare_star(next, token): @@ -130,11 +187,24 @@ def prepare_descendant(next, token): tag = token[1] else: raise SyntaxError("invalid descendant") - def select(context, result): - for elem in result: - for e in elem.iter(tag): - if e is not elem: - yield e + + if _is_wildcard_tag(tag): + select_tag = _prepare_tag(tag) + def select(context, result): + def select_child(result): + for elem in result: + for e in elem.iter(): + if e is not elem: + yield e + return select_tag(context, select_child(result)) + else: + if tag[:2] == '{}': + tag = tag[2:] # '{}tag' == 'tag' + def select(context, result): + for elem in result: + for e in elem.iter(tag): + if e is not elem: + yield e return select def prepare_parent(next, token): diff --git a/Misc/NEWS.d/next/Library/2019-04-28-15-01-29.bpo-28238.gdk38f.rst b/Misc/NEWS.d/next/Library/2019-04-28-15-01-29.bpo-28238.gdk38f.rst new file mode 100644 index 00000000000000..62003a3d26e6f2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-28-15-01-29.bpo-28238.gdk38f.rst @@ -0,0 +1,3 @@ +The ``.find*()`` methods of xml.etree.ElementTree can now search for +wildcards like ``{*}tag`` and ``{ns}*`` that match a tag in any namespace +or all tags in a namespace. Patch by Stefan Behnel. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index b69e3a45fe308f..1e58ddbfe19a9b 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1149,6 +1149,13 @@ checkpath(PyObject* tag) const Py_ssize_t len = PyUnicode_GET_LENGTH(tag); void *data = PyUnicode_DATA(tag); unsigned int kind = PyUnicode_KIND(tag); + if (len >= 3 && PyUnicode_READ(kind, data, 0) == '{' && ( + PyUnicode_READ(kind, data, 1) == '}' || ( + PyUnicode_READ(kind, data, 1) == '*' && + PyUnicode_READ(kind, data, 2) == '}'))) { + /* wildcard: '{}tag' or '{*}tag' */ + return 1; + } for (i = 0; i < len; i++) { Py_UCS4 ch = PyUnicode_READ(kind, data, i); if (ch == '{') @@ -1162,7 +1169,13 @@ checkpath(PyObject* tag) } if (PyBytes_Check(tag)) { char *p = PyBytes_AS_STRING(tag); - for (i = 0; i < PyBytes_GET_SIZE(tag); i++) { + const Py_ssize_t len = PyBytes_GET_SIZE(tag); + if (len >= 3 && p[0] == '{' && ( + p[1] == '}' || p[1] == '*' && p[2] == '}')) { + /* wildcard: '{}tag' or '{*}tag' */ + return 1; + } + for (i = 0; i < len; i++) { if (p[i] == '{') check = 0; else if (p[i] == '}') From f0900199d53df97bd792ac5a1678f8c477f117bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lapeyre?= Date: Sat, 4 May 2019 01:30:53 +0200 Subject: [PATCH 168/212] Suppress clang warning (GH-12384) --- Modules/posixmodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 56ec3ee5a0eed3..221f7101b21356 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1259,7 +1259,8 @@ _Py_Sigset_Converter(PyObject *obj, void *addr) long signum; int overflow; - if (sigemptyset(mask)) { + // The extra parens suppress the unreachable-code warning with clang on MacOS + if (sigemptyset(mask) < (0)) { /* Probably only if mask == NULL. */ PyErr_SetFromErrno(PyExc_OSError); return 0; From 6b5b013bcc22a27d6231c2796882e44ddb42be67 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com> Date: Sat, 4 May 2019 11:27:10 -0400 Subject: [PATCH 169/212] bpo-26978: Implement pathlib.Path.link_to (Using os.link) (GH-12990) --- Doc/library/pathlib.rst | 7 +++++++ Doc/whatsnew/3.8.rst | 4 ++++ Lib/pathlib.py | 10 ++++++++++ Lib/test/test_pathlib.py | 19 +++++++++++++++++++ .../2019-04-28-01-52-39.bpo-26978.Lpm-SI.rst | 2 ++ 5 files changed, 42 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2019-04-28-01-52-39.bpo-26978.Lpm-SI.rst diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 450e8ff378a3a5..7a4a20dc61182f 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -1054,6 +1054,13 @@ call fails (for example because the path doesn't exist). use :func:`Path.rmdir` instead. +.. method:: Path.link_to(target) + + Create a hard link pointing to a path named *target*. + + .. versionchanged:: 3.8 + + .. method:: Path.write_bytes(data) Open the file pointed to in bytes mode, write *data* to it, and close the diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 764bd00544d9f5..64ef6e1840605b 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -369,6 +369,10 @@ pathlib contain characters unrepresentable at the OS level. (Contributed by Serhiy Storchaka in :issue:`33721`.) +Added :meth:`pathlib.Path.link_to()` which creates a hard link pointing +to a path. +(Contributed by Joannah Nanjekye in :issue:`26978`) + socket ------ diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 911b774b564984..1ba98b19e83344 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -411,6 +411,8 @@ def lchmod(self, pathobj, mode): unlink = os.unlink + link_to = os.link + rmdir = os.rmdir rename = os.rename @@ -1303,6 +1305,14 @@ def lstat(self): self._raise_closed() return self._accessor.lstat(self) + def link_to(self, target): + """ + Create a hard link pointing to a path named target. + """ + if self._closed: + self._raise_closed() + self._accessor.link_to(self, target) + def rename(self, target): """ Rename this path to the given path. diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index f8325eb93275a6..990207b9c4e488 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1643,6 +1643,25 @@ def test_rmdir(self): self.assertFileNotFound(p.stat) self.assertFileNotFound(p.unlink) + def test_link_to(self): + P = self.cls(BASE) + p = P / 'fileA' + size = p.stat().st_size + # linking to another path. + q = P / 'dirA' / 'fileAA' + try: + p.link_to(q) + except PermissionError as e: + self.skipTest('os.link(): %s' % e) + self.assertEqual(q.stat().st_size, size) + self.assertEqual(os.path.samefile(p, q), True) + self.assertTrue(p.stat) + # Linking to a str of a relative path. + r = rel_join('fileAAA') + q.link_to(r) + self.assertEqual(os.stat(r).st_size, size) + self.assertTrue(q.stat) + def test_rename(self): P = self.cls(BASE) p = P / 'fileA' diff --git a/Misc/NEWS.d/next/Library/2019-04-28-01-52-39.bpo-26978.Lpm-SI.rst b/Misc/NEWS.d/next/Library/2019-04-28-01-52-39.bpo-26978.Lpm-SI.rst new file mode 100644 index 00000000000000..0b14920ad45a81 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-28-01-52-39.bpo-26978.Lpm-SI.rst @@ -0,0 +1,2 @@ +`pathlib.path.link_to()` is now implemented. It creates a hard link pointing +to a path. From c664b342a47e4b4650706d07e3e40a295e3a4407 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 4 May 2019 11:48:05 -0400 Subject: [PATCH 170/212] bpo-36475: Make PyThread_exit_thread with _Py_NO_RETURN (GH-13068) --- Include/pyerrors.h | 11 ----------- Include/pyport.h | 14 ++++++++++++++ Include/pythread.h | 2 +- Python/ceval.c | 1 - Python/thread_nt.h | 2 +- Python/thread_pthread.h | 2 +- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Include/pyerrors.h b/Include/pyerrors.h index 5c6751868df489..94af3cb3420ec6 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -21,17 +21,6 @@ PyAPI_FUNC(void) PyErr_GetExcInfo(PyObject **, PyObject **, PyObject **); PyAPI_FUNC(void) PyErr_SetExcInfo(PyObject *, PyObject *, PyObject *); #endif -#if defined(__clang__) || \ - (defined(__GNUC__) && \ - ((__GNUC__ >= 3) || \ - (__GNUC__ == 2) && (__GNUC_MINOR__ >= 5))) -# define _Py_NO_RETURN __attribute__((__noreturn__)) -#elif defined(_MSC_VER) -# define _Py_NO_RETURN __declspec(noreturn) -#else -# define _Py_NO_RETURN -#endif - /* Defined in Python/pylifecycle.c */ PyAPI_FUNC(void) _Py_NO_RETURN Py_FatalError(const char *message); diff --git a/Include/pyport.h b/Include/pyport.h index 97fb5e59f9e544..ab88a9ac5c529e 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -829,4 +829,18 @@ extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler; # define _Py_FORCE_UTF8_FS_ENCODING #endif +/* Mark a function which cannot return. Example: + + PyAPI_FUNC(void) _Py_NO_RETURN PyThread_exit_thread(void); */ +#if defined(__clang__) || \ + (defined(__GNUC__) && \ + ((__GNUC__ >= 3) || \ + (__GNUC__ == 2) && (__GNUC_MINOR__ >= 5))) +# define _Py_NO_RETURN __attribute__((__noreturn__)) +#elif defined(_MSC_VER) +# define _Py_NO_RETURN __declspec(noreturn) +#else +# define _Py_NO_RETURN +#endif + #endif /* Py_PYPORT_H */ diff --git a/Include/pythread.h b/Include/pythread.h index eb61033b2d9089..bc1d92cd1ff199 100644 --- a/Include/pythread.h +++ b/Include/pythread.h @@ -23,7 +23,7 @@ typedef enum PyLockStatus { PyAPI_FUNC(void) PyThread_init_thread(void); PyAPI_FUNC(unsigned long) PyThread_start_new_thread(void (*)(void *), void *); -PyAPI_FUNC(void) PyThread_exit_thread(void); +PyAPI_FUNC(void) _Py_NO_RETURN PyThread_exit_thread(void); PyAPI_FUNC(unsigned long) PyThread_get_thread_ident(void); PyAPI_FUNC(PyThread_type_lock) PyThread_allocate_lock(void); diff --git a/Python/ceval.c b/Python/ceval.c index 8ae273e0820d2a..e616a3f539898d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -211,7 +211,6 @@ exit_thread_if_finalizing(PyThreadState *tstate) if (_Py_IsFinalizing() && !_Py_CURRENTLY_FINALIZING(tstate)) { drop_gil(tstate); PyThread_exit_thread(); - Py_UNREACHABLE(); } } diff --git a/Python/thread_nt.h b/Python/thread_nt.h index fdb192b7d77a16..5e00c351146055 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -227,7 +227,7 @@ PyThread_get_thread_ident(void) return GetCurrentThreadId(); } -void +void _Py_NO_RETURN PyThread_exit_thread(void) { dprintf(("%lu: PyThread_exit_thread called\n", PyThread_get_thread_ident())); diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 25f58d9446d8d6..1f4f36d52d5552 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -302,7 +302,7 @@ PyThread_get_thread_ident(void) return (unsigned long) threadid; } -void +void _Py_NO_RETURN PyThread_exit_thread(void) { dprintf(("PyThread_exit_thread called\n")); From 5e98f05e55d13981c7c92fb14b9c013e4227c3c1 Mon Sep 17 00:00:00 2001 From: Catherine Alvarado Date: Sat, 4 May 2019 17:54:35 -0400 Subject: [PATCH 171/212] bpo-36166: Change to rst datamodel file. (GH-13089) --- Doc/reference/datamodel.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index bad611e81c3e65..9fc9f3a3848a4e 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1311,9 +1311,9 @@ Basic customization Called by the :func:`format` built-in function, and by extension, evaluation of :ref:`formatted string literals ` and the :meth:`str.format` method, to produce a "formatted" - string representation of an object. The ``format_spec`` argument is + string representation of an object. The *format_spec* argument is a string that contains a description of the formatting options desired. - The interpretation of the ``format_spec`` argument is up to the type + The interpretation of the *format_spec* argument is up to the type implementing :meth:`__format__`, however most classes will either delegate formatting to one of the built-in types, or use a similar formatting option syntax. From 98a1e06c47f655c7601b130cf8d549de9f08369e Mon Sep 17 00:00:00 2001 From: Jonatan Date: Sat, 4 May 2019 14:55:29 -0700 Subject: [PATCH 172/212] bpo-36189: Fixing typo in tutorial introduction (GH-13090) --- Doc/tutorial/introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst index 3e0c99558ed7f3..a4dbd6351b77d8 100644 --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -383,7 +383,7 @@ items of different types, but usually the items all have the same type. :: >>> squares [1, 4, 9, 16, 25] -Like strings (and all other built-in :term:`sequence` type), lists can be +Like strings (and all other built-in :term:`sequence` types), lists can be indexed and sliced:: >>> squares[0] # indexing returns the item From c4d92c8ada7ecfc479ebb1dd4a819c9202155970 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Sun, 5 May 2019 18:06:30 +0900 Subject: [PATCH 173/212] simplify StartupImportTests (GH-13096) _osx_support and copyreg are not imported from site on macOS for now. --- Lib/test/test_site.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 8643da0540f37b..41c4229919507b 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -526,15 +526,15 @@ def test_startup_imports(self): # http://bugs.python.org/issue19205 re_mods = {'re', '_sre', 'sre_compile', 'sre_constants', 'sre_parse'} - # _osx_support uses the re module in many placs - if sys.platform != 'darwin': - self.assertFalse(modules.intersection(re_mods), stderr) + self.assertFalse(modules.intersection(re_mods), stderr) + # http://bugs.python.org/issue9548 self.assertNotIn('locale', modules, stderr) - if sys.platform != 'darwin': - # http://bugs.python.org/issue19209 - self.assertNotIn('copyreg', modules, stderr) - # http://bugs.python.org/issue19218> + + # http://bugs.python.org/issue19209 + self.assertNotIn('copyreg', modules, stderr) + + # http://bugs.python.org/issue19218 collection_mods = {'_collections', 'collections', 'functools', 'heapq', 'itertools', 'keyword', 'operator', 'reprlib', 'types', 'weakref' From 88f07a804a0adc0b6ee87687b59d8416113c7331 Mon Sep 17 00:00:00 2001 From: twisteroid ambassador Date: Sun, 5 May 2019 19:14:35 +0800 Subject: [PATCH 174/212] bpo-33530: Implement Happy Eyeballs in asyncio, v2 (GH-7237) Added two keyword arguments, `delay` and `interleave`, to `BaseEventLoop.create_connection`. Happy eyeballs is activated if `delay` is specified. We now have documentation for the new arguments. `staggered_race()` is in its own module, but not exported to the main asyncio package. https://bugs.python.org/issue33530 --- Doc/library/asyncio-eventloop.rst | 24 ++- Lib/asyncio/base_events.py | 125 ++++++++++----- Lib/asyncio/events.py | 3 +- Lib/asyncio/staggered.py | 147 ++++++++++++++++++ .../2018-05-29-18-34-53.bpo-33530._4Q_bi.rst | 3 + 5 files changed, 264 insertions(+), 38 deletions(-) create mode 100644 Lib/asyncio/staggered.py create mode 100644 Misc/NEWS.d/next/Library/2018-05-29-18-34-53.bpo-33530._4Q_bi.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index e2b31245392122..06f673be7902c2 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -397,9 +397,27 @@ Opening network connections If given, these should all be integers from the corresponding :mod:`socket` module constants. + * *happy_eyeballs_delay*, if given, enables Happy Eyeballs for this + connection. It should + be a floating-point number representing the amount of time in seconds + to wait for a connection attempt to complete, before starting the next + attempt in parallel. This is the "Connection Attempt Delay" as defined + in :rfc:`8305`. A sensible default value recommended by the RFC is ``0.25`` + (250 milliseconds). + + * *interleave* controls address reordering when a host name resolves to + multiple IP addresses. + If ``0`` or unspecified, no reordering is done, and addresses are + tried in the order returned by :meth:`getaddrinfo`. If a positive integer + is specified, the addresses are interleaved by address family, and the + given integer is interpreted as "First Address Family Count" as defined + in :rfc:`8305`. The default is ``0`` if *happy_eyeballs_delay* is not + specified, and ``1`` if it is. + * *sock*, if given, should be an existing, already connected :class:`socket.socket` object to be used by the transport. - If *sock* is given, none of *host*, *port*, *family*, *proto*, *flags* + If *sock* is given, none of *host*, *port*, *family*, *proto*, *flags*, + *happy_eyeballs_delay*, *interleave* and *local_addr* should be specified. * *local_addr*, if given, is a ``(local_host, local_port)`` tuple used @@ -410,6 +428,10 @@ Opening network connections to wait for the TLS handshake to complete before aborting the connection. ``60.0`` seconds if ``None`` (default). + .. versionadded:: 3.8 + + The *happy_eyeballs_delay* and *interleave* parameters. + .. versionadded:: 3.7 The *ssl_handshake_timeout* parameter. diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 9b4b846131de10..c58906f8b4897f 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -16,6 +16,7 @@ import collections import collections.abc import concurrent.futures +import functools import heapq import itertools import os @@ -41,6 +42,7 @@ from . import futures from . import protocols from . import sslproto +from . import staggered from . import tasks from . import transports from .log import logger @@ -159,6 +161,28 @@ def _ipaddr_info(host, port, family, type, proto): return None +def _interleave_addrinfos(addrinfos, first_address_family_count=1): + """Interleave list of addrinfo tuples by family.""" + # Group addresses by family + addrinfos_by_family = collections.OrderedDict() + for addr in addrinfos: + family = addr[0] + if family not in addrinfos_by_family: + addrinfos_by_family[family] = [] + addrinfos_by_family[family].append(addr) + addrinfos_lists = list(addrinfos_by_family.values()) + + reordered = [] + if first_address_family_count > 1: + reordered.extend(addrinfos_lists[0][:first_address_family_count - 1]) + del addrinfos_lists[0][:first_address_family_count - 1] + reordered.extend( + a for a in itertools.chain.from_iterable( + itertools.zip_longest(*addrinfos_lists) + ) if a is not None) + return reordered + + def _run_until_complete_cb(fut): if not fut.cancelled(): exc = fut.exception() @@ -871,12 +895,49 @@ def _check_sendfile_params(self, sock, file, offset, count): "offset must be a non-negative integer (got {!r})".format( offset)) + async def _connect_sock(self, exceptions, addr_info, local_addr_infos=None): + """Create, bind and connect one socket.""" + my_exceptions = [] + exceptions.append(my_exceptions) + family, type_, proto, _, address = addr_info + sock = None + try: + sock = socket.socket(family=family, type=type_, proto=proto) + sock.setblocking(False) + if local_addr_infos is not None: + for _, _, _, _, laddr in local_addr_infos: + try: + sock.bind(laddr) + break + except OSError as exc: + msg = ( + f'error while attempting to bind on ' + f'address {laddr!r}: ' + f'{exc.strerror.lower()}' + ) + exc = OSError(exc.errno, msg) + my_exceptions.append(exc) + else: # all bind attempts failed + raise my_exceptions.pop() + await self.sock_connect(sock, address) + return sock + except OSError as exc: + my_exceptions.append(exc) + if sock is not None: + sock.close() + raise + except: + if sock is not None: + sock.close() + raise + async def create_connection( self, protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, - ssl_handshake_timeout=None): + ssl_handshake_timeout=None, + happy_eyeballs_delay=None, interleave=None): """Connect to a TCP server. Create a streaming transport connection to a given Internet host and @@ -911,6 +972,10 @@ async def create_connection( raise ValueError( 'ssl_handshake_timeout is only meaningful with ssl') + if happy_eyeballs_delay is not None and interleave is None: + # If using happy eyeballs, default to interleave addresses by family + interleave = 1 + if host is not None or port is not None: if sock is not None: raise ValueError( @@ -929,43 +994,31 @@ async def create_connection( flags=flags, loop=self) if not laddr_infos: raise OSError('getaddrinfo() returned empty list') + else: + laddr_infos = None + + if interleave: + infos = _interleave_addrinfos(infos, interleave) exceptions = [] - for family, type, proto, cname, address in infos: - try: - sock = socket.socket(family=family, type=type, proto=proto) - sock.setblocking(False) - if local_addr is not None: - for _, _, _, _, laddr in laddr_infos: - try: - sock.bind(laddr) - break - except OSError as exc: - msg = ( - f'error while attempting to bind on ' - f'address {laddr!r}: ' - f'{exc.strerror.lower()}' - ) - exc = OSError(exc.errno, msg) - exceptions.append(exc) - else: - sock.close() - sock = None - continue - if self._debug: - logger.debug("connect %r to %r", sock, address) - await self.sock_connect(sock, address) - except OSError as exc: - if sock is not None: - sock.close() - exceptions.append(exc) - except: - if sock is not None: - sock.close() - raise - else: - break - else: + if happy_eyeballs_delay is None: + # not using happy eyeballs + for addrinfo in infos: + try: + sock = await self._connect_sock( + exceptions, addrinfo, laddr_infos) + break + except OSError: + continue + else: # using happy eyeballs + sock, _, _ = await staggered.staggered_race( + (functools.partial(self._connect_sock, + exceptions, addrinfo, laddr_infos) + for addrinfo in infos), + happy_eyeballs_delay, loop=self) + + if sock is None: + exceptions = [exc for sub in exceptions for exc in sub] if len(exceptions) == 1: raise exceptions[0] else: diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 163b868afeee36..9a923514db0993 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -298,7 +298,8 @@ async def create_connection( *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, - ssl_handshake_timeout=None): + ssl_handshake_timeout=None, + happy_eyeballs_delay=None, interleave=None): raise NotImplementedError async def create_server( diff --git a/Lib/asyncio/staggered.py b/Lib/asyncio/staggered.py new file mode 100644 index 00000000000000..feec681b4371bf --- /dev/null +++ b/Lib/asyncio/staggered.py @@ -0,0 +1,147 @@ +"""Support for running coroutines in parallel with staggered start times.""" + +__all__ = 'staggered_race', + +import contextlib +import typing + +from . import events +from . import futures +from . import locks +from . import tasks + + +async def staggered_race( + coro_fns: typing.Iterable[typing.Callable[[], typing.Awaitable]], + delay: typing.Optional[float], + *, + loop: events.AbstractEventLoop = None, +) -> typing.Tuple[ + typing.Any, + typing.Optional[int], + typing.List[typing.Optional[Exception]] +]: + """Run coroutines with staggered start times and take the first to finish. + + This method takes an iterable of coroutine functions. The first one is + started immediately. From then on, whenever the immediately preceding one + fails (raises an exception), or when *delay* seconds has passed, the next + coroutine is started. This continues until one of the coroutines complete + successfully, in which case all others are cancelled, or until all + coroutines fail. + + The coroutines provided should be well-behaved in the following way: + + * They should only ``return`` if completed successfully. + + * They should always raise an exception if they did not complete + successfully. In particular, if they handle cancellation, they should + probably reraise, like this:: + + try: + # do work + except asyncio.CancelledError: + # undo partially completed work + raise + + Args: + coro_fns: an iterable of coroutine functions, i.e. callables that + return a coroutine object when called. Use ``functools.partial`` or + lambdas to pass arguments. + + delay: amount of time, in seconds, between starting coroutines. If + ``None``, the coroutines will run sequentially. + + loop: the event loop to use. + + Returns: + tuple *(winner_result, winner_index, exceptions)* where + + - *winner_result*: the result of the winning coroutine, or ``None`` + if no coroutines won. + + - *winner_index*: the index of the winning coroutine in + ``coro_fns``, or ``None`` if no coroutines won. If the winning + coroutine may return None on success, *winner_index* can be used + to definitively determine whether any coroutine won. + + - *exceptions*: list of exceptions returned by the coroutines. + ``len(exceptions)`` is equal to the number of coroutines actually + started, and the order is the same as in ``coro_fns``. The winning + coroutine's entry is ``None``. + + """ + # TODO: when we have aiter() and anext(), allow async iterables in coro_fns. + loop = loop or events.get_running_loop() + enum_coro_fns = enumerate(coro_fns) + winner_result = None + winner_index = None + exceptions = [] + running_tasks = [] + + async def run_one_coro( + previous_failed: typing.Optional[locks.Event]) -> None: + # Wait for the previous task to finish, or for delay seconds + if previous_failed is not None: + with contextlib.suppress(futures.TimeoutError): + # Use asyncio.wait_for() instead of asyncio.wait() here, so + # that if we get cancelled at this point, Event.wait() is also + # cancelled, otherwise there will be a "Task destroyed but it is + # pending" later. + await tasks.wait_for(previous_failed.wait(), delay) + # Get the next coroutine to run + try: + this_index, coro_fn = next(enum_coro_fns) + except StopIteration: + return + # Start task that will run the next coroutine + this_failed = locks.Event() + next_task = loop.create_task(run_one_coro(this_failed)) + running_tasks.append(next_task) + assert len(running_tasks) == this_index + 2 + # Prepare place to put this coroutine's exceptions if not won + exceptions.append(None) + assert len(exceptions) == this_index + 1 + + try: + result = await coro_fn() + except Exception as e: + exceptions[this_index] = e + this_failed.set() # Kickstart the next coroutine + else: + # Store winner's results + nonlocal winner_index, winner_result + assert winner_index is None + winner_index = this_index + winner_result = result + # Cancel all other tasks. We take care to not cancel the current + # task as well. If we do so, then since there is no `await` after + # here and CancelledError are usually thrown at one, we will + # encounter a curious corner case where the current task will end + # up as done() == True, cancelled() == False, exception() == + # asyncio.CancelledError. This behavior is specified in + # https://bugs.python.org/issue30048 + for i, t in enumerate(running_tasks): + if i != this_index: + t.cancel() + + first_task = loop.create_task(run_one_coro(None)) + running_tasks.append(first_task) + try: + # Wait for a growing list of tasks to all finish: poor man's version of + # curio's TaskGroup or trio's nursery + done_count = 0 + while done_count != len(running_tasks): + done, _ = await tasks.wait(running_tasks) + done_count = len(done) + # If run_one_coro raises an unhandled exception, it's probably a + # programming error, and I want to see it. + if __debug__: + for d in done: + if d.done() and not d.cancelled() and d.exception(): + raise d.exception() + return winner_result, winner_index, exceptions + finally: + # Make sure no tasks are left running if we leave this function + for t in running_tasks: + t.cancel() diff --git a/Misc/NEWS.d/next/Library/2018-05-29-18-34-53.bpo-33530._4Q_bi.rst b/Misc/NEWS.d/next/Library/2018-05-29-18-34-53.bpo-33530._4Q_bi.rst new file mode 100644 index 00000000000000..747219b1bfb899 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-18-34-53.bpo-33530._4Q_bi.rst @@ -0,0 +1,3 @@ +Implemented Happy Eyeballs in `asyncio.create_connection()`. Added two new +arguments, *happy_eyeballs_delay* and *interleave*, +to specify Happy Eyeballs behavior. From 29500737d45cbca9604d9ce845fb2acc3f531401 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 5 May 2019 14:26:23 +0300 Subject: [PATCH 175/212] bpo-36791: Safer detection of integer overflow in sum(). (GH-13080) --- Python/bltinmodule.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 7a2b259cbd89c8..047cca057b41ae 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2375,9 +2375,11 @@ builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start) } if (PyLong_CheckExact(item)) { long b = PyLong_AsLongAndOverflow(item, &overflow); - long x = i_result + b; - if (overflow == 0 && ((x^i_result) >= 0 || (x^b) >= 0)) { - i_result = x; + if (overflow == 0 && + (i_result >= 0 ? (b <= LONG_MAX - i_result) + : (b >= LONG_MIN - i_result))) + { + i_result += b; Py_DECREF(item); continue; } From e152169da95b52fa41931572bc90857253c4a5dd Mon Sep 17 00:00:00 2001 From: Cheryl Sabella Date: Mon, 6 May 2019 08:39:13 -0400 Subject: [PATCH 176/212] bpo-16024: Doc cleanup regarding path_fd, dir_fd, follow_symlinks (GH-5505) --- Doc/library/os.rst | 142 ++++++++++++++++++++++++--------------------- 1 file changed, 76 insertions(+), 66 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index f3b5d964ac58a8..e77a8fed377ad6 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1453,16 +1453,19 @@ features: .. _path_fd: * **specifying a file descriptor:** - For some functions, the *path* argument can be not only a string giving a path - name, but also a file descriptor. The function will then operate on the file - referred to by the descriptor. (For POSIX systems, Python will call the - ``f...`` version of the function.) - - You can check whether or not *path* can be specified as a file descriptor on - your platform using :data:`os.supports_fd`. If it is unavailable, using it - will raise a :exc:`NotImplementedError`. + Normally the *path* argument provided to functions in the :mod:`os` module + must be a string specifying a file path. However, some functions now + alternatively accept an open file descriptor for their *path* argument. + The function will then operate on the file referred to by the descriptor. + (For POSIX systems, Python will call the variant of the function prefixed + with ``f`` (e.g. call ``fchdir`` instead of ``chdir``).) + + You can check whether or not *path* can be specified as a file descriptor + for a particular function on your platform using :data:`os.supports_fd`. + If this functionality is unavailable, using it will raise a + :exc:`NotImplementedError`. - If the function also supports *dir_fd* or *follow_symlinks* arguments, it is + If the function also supports *dir_fd* or *follow_symlinks* arguments, it's an error to specify one of those when supplying *path* as a file descriptor. .. _dir_fd: @@ -1471,23 +1474,24 @@ features: should be a file descriptor referring to a directory, and the path to operate on should be relative; path will then be relative to that directory. If the path is absolute, *dir_fd* is ignored. (For POSIX systems, Python will call - the ``...at`` or ``f...at`` version of the function.) + the variant of the function with an ``at`` suffix and possibly prefixed with + ``f`` (e.g. call ``faccessat`` instead of ``access``). - You can check whether or not *dir_fd* is supported on your platform using - :data:`os.supports_dir_fd`. If it is unavailable, using it will raise a - :exc:`NotImplementedError`. + You can check whether or not *dir_fd* is supported for a particular function + on your platform using :data:`os.supports_dir_fd`. If it's unavailable, + using it will raise a :exc:`NotImplementedError`. .. _follow_symlinks: * **not following symlinks:** If *follow_symlinks* is ``False``, and the last element of the path to operate on is a symbolic link, - the function will operate on the symbolic link itself instead of the file the - link points to. (For POSIX systems, Python will call the ``l...`` version of - the function.) + the function will operate on the symbolic link itself rather than the file + pointed to by the link. (For POSIX systems, Python will call the ``l...`` + variant of the function.) - You can check whether or not *follow_symlinks* is supported on your platform - using :data:`os.supports_follow_symlinks`. If it is unavailable, using it - will raise a :exc:`NotImplementedError`. + You can check whether or not *follow_symlinks* is supported for a particular + function on your platform using :data:`os.supports_follow_symlinks`. + If it's unavailable, using it will raise a :exc:`NotImplementedError`. @@ -1662,7 +1666,7 @@ features: .. availability:: Unix. .. versionadded:: 3.3 - Added support for specifying an open file descriptor for *path*, + Added support for specifying *path* as an open file descriptor, and the *dir_fd* and *follow_symlinks* arguments. .. versionchanged:: 3.6 @@ -1781,7 +1785,7 @@ features: The *path* parameter became optional. .. versionadded:: 3.3 - Added support for specifying an open file descriptor for *path*. + Added support for specifying *path* as an open file descriptor. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. @@ -2593,7 +2597,7 @@ features: The :const:`ST_RDONLY` and :const:`ST_NOSUID` constants were added. .. versionadded:: 3.3 - Added support for specifying an open file descriptor for *path*. + Added support for specifying *path* as an open file descriptor. .. versionchanged:: 3.4 The :const:`ST_NODEV`, :const:`ST_NOEXEC`, :const:`ST_SYNCHRONOUS`, @@ -2610,59 +2614,61 @@ features: .. data:: supports_dir_fd - A :class:`~collections.abc.Set` object indicating which functions in the - :mod:`os` module permit use of their *dir_fd* parameter. Different platforms - provide different functionality, and an option that might work on one might - be unsupported on another. For consistency's sakes, functions that support - *dir_fd* always allow specifying the parameter, but will raise an exception - if the functionality is not actually available. - - To check whether a particular function permits use of its *dir_fd* - parameter, use the ``in`` operator on ``supports_dir_fd``. As an example, - this expression determines whether the *dir_fd* parameter of :func:`os.stat` - is locally available:: + A :class:`set` object indicating which functions in the :mod:`os` + module accept an open file descriptor for their *dir_fd* parameter. + Different platforms provide different features, and the underlying + functionality Python uses to implement the *dir_fd* parameter is not + available on all platforms Python supports. For consistency's sake, + functions that may support *dir_fd* always allow specifying the + parameter, but will throw an exception if the functionality is used + when it's not locally available. (Specifying ``None`` for *dir_fd* + is always supported on all platforms.) + + To check whether a particular function accepts an open file descriptor + for its *dir_fd* parameter, use the ``in`` operator on ``supports_dir_fd``. + As an example, this expression evaluates to ``True`` if :func:`os.stat` + accepts open file descriptors for *dir_fd* on the local platform:: os.stat in os.supports_dir_fd - Currently *dir_fd* parameters only work on Unix platforms; none of them work - on Windows. + Currently *dir_fd* parameters only work on Unix platforms; + none of them work on Windows. .. versionadded:: 3.3 .. data:: supports_effective_ids - A :class:`~collections.abc.Set` object indicating which functions in the - :mod:`os` module permit use of the *effective_ids* parameter for - :func:`os.access`. If the local platform supports it, the collection will - contain :func:`os.access`, otherwise it will be empty. + A :class:`set` object indicating whether :func:`os.access` permits + specifying ``True`` for its *effective_ids* parameter on the local platform. + (Specifying ``False`` for *effective_ids* is always supported on all + platforms.) If the local platform supports it, the collection will contain + :func:`os.access`; otherwise it will be empty. - To check whether you can use the *effective_ids* parameter for - :func:`os.access`, use the ``in`` operator on ``supports_effective_ids``, - like so:: + This expression evaluates to ``True`` if :func:`os.access` supports + ``effective_ids=True`` on the local platform:: os.access in os.supports_effective_ids - Currently *effective_ids* only works on Unix platforms; it does not work on - Windows. + Currently *effective_ids* is only supported on Unix platforms; + it does not work on Windows. .. versionadded:: 3.3 .. data:: supports_fd - A :class:`~collections.abc.Set` object indicating which functions in the + A :class:`set` object indicating which functions in the :mod:`os` module permit specifying their *path* parameter as an open file - descriptor. Different platforms provide different functionality, and an - option that might work on one might be unsupported on another. For - consistency's sakes, functions that support *fd* always allow specifying - the parameter, but will raise an exception if the functionality is not - actually available. + descriptor on the local platform. Different platforms provide different + features, and the underlying functionality Python uses to accept open file + descriptors as *path* arguments is not available on all platforms Python + supports. - To check whether a particular function permits specifying an open file + To determine whether a particular function permits specifying an open file descriptor for its *path* parameter, use the ``in`` operator on - ``supports_fd``. As an example, this expression determines whether - :func:`os.chdir` accepts open file descriptors when called on your local + ``supports_fd``. As an example, this expression evaluates to ``True`` if + :func:`os.chdir` accepts open file descriptors for *path* on your local platform:: os.chdir in os.supports_fd @@ -2672,17 +2678,21 @@ features: .. data:: supports_follow_symlinks - A :class:`~collections.abc.Set` object indicating which functions in the - :mod:`os` module permit use of their *follow_symlinks* parameter. Different - platforms provide different functionality, and an option that might work on - one might be unsupported on another. For consistency's sakes, functions that - support *follow_symlinks* always allow specifying the parameter, but will - raise an exception if the functionality is not actually available. - - To check whether a particular function permits use of its *follow_symlinks* - parameter, use the ``in`` operator on ``supports_follow_symlinks``. As an - example, this expression determines whether the *follow_symlinks* parameter - of :func:`os.stat` is locally available:: + A :class:`set` object indicating which functions in the :mod:`os` module + accept ``False`` for their *follow_symlinks* parameter on the local platform. + Different platforms provide different features, and the underlying + functionality Python uses to implement *follow_symlinks* is not available + on all platforms Python supports. For consistency's sake, functions that + may support *follow_symlinks* always allow specifying the parameter, but + will throw an exception if the functionality is used when it's not locally + available. (Specifying ``True`` for *follow_symlinks* is always supported + on all platforms.) + + To check whether a particular function accepts ``False`` for its + *follow_symlinks* parameter, use the ``in`` operator on + ``supports_follow_symlinks``. As an example, this expression evaluates + to ``True`` if you may specify ``follow_symlinks=False`` when calling + :func:`os.stat` on the local platform:: os.stat in os.supports_follow_symlinks @@ -2801,7 +2811,7 @@ features: following symlinks `. .. versionadded:: 3.3 - Added support for specifying an open file descriptor for *path*, + Added support for specifying *path* as an open file descriptor, and the *dir_fd*, *follow_symlinks*, and *ns* parameters. .. versionchanged:: 3.6 @@ -3162,7 +3172,7 @@ to be ignored. .. availability:: Unix, Windows. .. versionadded:: 3.3 - Added support for specifying an open file descriptor for *path* + Added support for specifying *path* as an open file descriptor for :func:`execve`. .. versionchanged:: 3.6 From 8b1271b12fdbb1ac01217d929d8b112119e3f53b Mon Sep 17 00:00:00 2001 From: Eddie Elizondo Date: Mon, 6 May 2019 11:28:50 -0400 Subject: [PATCH 177/212] Only count number of members once (#12691) --- Objects/typeobject.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 37df4d23e4c192..eeaae1f9f78947 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2895,6 +2895,7 @@ PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) nmembers = 0; for (slot = spec->slots; slot->slot; slot++) { if (slot->slot == Py_tp_members) { + nmembers = 0; for (memb = slot->pfunc; memb->name != NULL; memb++) { nmembers++; } From 6b95149eccac540a911a5ada03fcb7d623a0de37 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Mon, 6 May 2019 17:36:35 +0200 Subject: [PATCH 178/212] bpo-36811: Fix a C compiler warning in _elementtree.c. (GH-13109) --- Modules/_elementtree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 1e58ddbfe19a9b..e9a0ea21b292fa 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1171,7 +1171,7 @@ checkpath(PyObject* tag) char *p = PyBytes_AS_STRING(tag); const Py_ssize_t len = PyBytes_GET_SIZE(tag); if (len >= 3 && p[0] == '{' && ( - p[1] == '}' || p[1] == '*' && p[2] == '}')) { + p[1] == '}' || (p[1] == '*' && p[2] == '}'))) { /* wildcard: '{}tag' or '{*}tag' */ return 1; } From cec01849f142ea96731b4725975b89d3af757656 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 6 May 2019 17:39:06 +0200 Subject: [PATCH 179/212] Doc/c-api/exceptions.rst: fix grammar (#12091) * Doc/c-api/exceptions.rst: fix grammar skip issue skip news * Use ", in that case" Co-Authored-By: blueyed --- Doc/c-api/exceptions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 8c5f66cbef722b..13f0aff1cf99b6 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -53,8 +53,8 @@ Printing and clearing .. c:function:: void PyErr_PrintEx(int set_sys_last_vars) Print a standard traceback to ``sys.stderr`` and clear the error indicator. - **Unless** the error is a ``SystemExit``. In that case the no traceback - is printed and Python process will exit with the error code specified by + **Unless** the error is a ``SystemExit``, in that case no traceback is + printed and the Python process will exit with the error code specified by the ``SystemExit`` instance. Call this function **only** when the error indicator is set. Otherwise it From f7b494c4d473c99ade2c8ab4e63005552f168f2b Mon Sep 17 00:00:00 2001 From: Andre Delfino Date: Mon, 6 May 2019 13:01:17 -0300 Subject: [PATCH 180/212] Update wsgiref.rst (#10488) --- Doc/library/wsgiref.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst index ec5136742fa2c4..6edd0714b9df3b 100644 --- a/Doc/library/wsgiref.rst +++ b/Doc/library/wsgiref.rst @@ -767,7 +767,7 @@ This is a working "Hello World" WSGI application:: # use a function (note that you're not limited to a function, you can # use a class for example). The first argument passed to the function # is a dictionary containing CGI-style environment variables and the - # second variable is the callable object (see PEP 333). + # second variable is the callable object. def hello_world_app(environ, start_response): status = '200 OK' # HTTP Status headers = [('Content-type', 'text/plain; charset=utf-8')] # HTTP Headers From ae2c32f32b61f3b141ba4b0b1ad71781d2f9a1a1 Mon Sep 17 00:00:00 2001 From: Logan Jones Date: Mon, 6 May 2019 12:32:44 -0400 Subject: [PATCH 181/212] bpo-36798: Updating f-string docs for := use case (GH-13107) --- Doc/reference/lexical_analysis.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index fb04ccc839aaa3..13adc1a2e433fc 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -680,11 +680,12 @@ with a closing curly bracket ``'}'``. Expressions in formatted string literals are treated like regular Python expressions surrounded by parentheses, with a few exceptions. -An empty expression is not allowed, and a :keyword:`lambda` expression -must be surrounded by explicit parentheses. Replacement expressions -can contain line breaks (e.g. in triple-quoted strings), but they -cannot contain comments. Each expression is evaluated in the context -where the formatted string literal appears, in order from left to right. +An empty expression is not allowed, and both :keyword:`lambda` and +assignment expressions ``:=`` must be surrounded by explicit parentheses. +Replacement expressions can contain line breaks (e.g. in triple-quoted +strings), but they cannot contain comments. Each expression is evaluated +in the context where the formatted string literal appears, in order from +left to right. If a conversion is specified, the result of evaluating the expression is converted before formatting. Conversion ``'!s'`` calls :func:`str` on From 1a2252ed39bc1b71cdaa935d7726d82909af93ab Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Mon, 6 May 2019 10:56:51 -0600 Subject: [PATCH 182/212] bpo-36594: Fix incorrect use of %p in format strings (GH-12769) In addition, fix some other minor violations of C99. --- .../2019-04-10-18-12-11.bpo-36594.fbnJAc.rst | 2 ++ Modules/_ctypes/_ctypes_test.c | 8 ++++---- Modules/_ctypes/callproc.c | 4 ++-- Modules/_xxsubinterpretersmodule.c | 2 +- Modules/hashtable.c | 2 +- Objects/object.c | 10 +++++----- Objects/obmalloc.c | 2 +- Objects/unicodeobject.c | 6 +++--- Programs/_freeze_importlib.c | 2 +- Python/sysmodule.c | 8 ++++---- Python/thread_pthread.h | 4 ++-- 11 files changed, 26 insertions(+), 24 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-10-18-12-11.bpo-36594.fbnJAc.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-10-18-12-11.bpo-36594.fbnJAc.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-10-18-12-11.bpo-36594.fbnJAc.rst new file mode 100644 index 00000000000000..7ca5dd998d9882 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-04-10-18-12-11.bpo-36594.fbnJAc.rst @@ -0,0 +1,2 @@ +Fix incorrect use of ``%p`` in format strings. +Patch by Zackery Spytz. diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c index f8420580ffa811..bae4976a08d31b 100644 --- a/Modules/_ctypes/_ctypes_test.c +++ b/Modules/_ctypes/_ctypes_test.c @@ -87,7 +87,7 @@ EXPORT(void)testfunc_array(int values[4]) EXPORT(long double)testfunc_Ddd(double a, double b) { long double result = (long double)(a * b); - printf("testfunc_Ddd(%p, %p)\n", &a, &b); + printf("testfunc_Ddd(%p, %p)\n", (void *)&a, (void *)&b); printf("testfunc_Ddd(%g, %g)\n", a, b); return result; } @@ -95,7 +95,7 @@ EXPORT(long double)testfunc_Ddd(double a, double b) EXPORT(long double)testfunc_DDD(long double a, long double b) { long double result = a * b; - printf("testfunc_DDD(%p, %p)\n", &a, &b); + printf("testfunc_DDD(%p, %p)\n", (void *)&a, (void *)&b); printf("testfunc_DDD(%Lg, %Lg)\n", a, b); return result; } @@ -103,7 +103,7 @@ EXPORT(long double)testfunc_DDD(long double a, long double b) EXPORT(int)testfunc_iii(int a, int b) { int result = a * b; - printf("testfunc_iii(%p, %p)\n", &a, &b); + printf("testfunc_iii(%p, %p)\n", (void *)&a, (void *)&b); return result; } @@ -361,7 +361,7 @@ static void _xxx_init(void *(*Xalloc)(int), void (*Xfree)(void *)) { void *ptr; - printf("_xxx_init got %p %p\n", Xalloc, Xfree); + printf("_xxx_init got %p %p\n", (void *)Xalloc, (void *)Xfree); printf("calling\n"); ptr = Xalloc(32); Xfree(ptr); diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 1ad842eb3d4098..a8ba84be4a7612 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -531,11 +531,11 @@ PyCArg_repr(PyCArgObject *self) default: if (is_literal_char((unsigned char)self->tag)) { sprintf(buffer, "", - (unsigned char)self->tag, self); + (unsigned char)self->tag, (void *)self); } else { sprintf(buffer, "", - (unsigned char)self->tag, self); + (unsigned char)self->tag, (void *)self); } break; } diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index 1cf43b7ac76e04..0d8e5f3127d5cf 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1250,7 +1250,7 @@ _channel_finish_closing(struct _channel *chan) { // Do the things that would have been done in _channels_close(). ref->chan = NULL; _channel_free(chan); -}; +} /* "high"-level channel-related functions */ diff --git a/Modules/hashtable.c b/Modules/hashtable.c index e6f8daf7966408..4a36a1e71cdd05 100644 --- a/Modules/hashtable.c +++ b/Modules/hashtable.c @@ -240,7 +240,7 @@ _Py_hashtable_print_stats(_Py_hashtable_t *ht) } printf("hash table %p: entries=%" PY_FORMAT_SIZE_T "u/%" PY_FORMAT_SIZE_T "u (%.0f%%), ", - ht, ht->entries, ht->num_buckets, load * 100.0); + (void *)ht, ht->entries, ht->num_buckets, load * 100.0); if (nchains) printf("avg_chain_len=%.1f, ", (double)total_chain_len / nchains); printf("max_chain_len=%" PY_FORMAT_SIZE_T "u, %" PY_FORMAT_SIZE_T "u KiB\n", diff --git a/Objects/object.c b/Objects/object.c index 589bf365e870fd..732f9ccefa8774 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -385,7 +385,7 @@ PyObject_Print(PyObject *op, FILE *fp, int flags) universally available */ Py_BEGIN_ALLOW_THREADS fprintf(fp, "", - (long)op->ob_refcnt, op); + (long)op->ob_refcnt, (void *)op); Py_END_ALLOW_THREADS } else { @@ -499,7 +499,7 @@ _PyObject_Dump(PyObject* op) "address : %p\n", Py_TYPE(op)==NULL ? "NULL" : Py_TYPE(op)->tp_name, (long)op->ob_refcnt, - op); + (void *)op); fflush(stderr); } @@ -1894,7 +1894,7 @@ _Py_PrintReferences(FILE *fp) PyObject *op; fprintf(fp, "Remaining objects:\n"); for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) { - fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] ", op, op->ob_refcnt); + fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] ", (void *)op, op->ob_refcnt); if (PyObject_Print(op, fp, 0) != 0) PyErr_Clear(); putc('\n', fp); @@ -1910,7 +1910,7 @@ _Py_PrintReferenceAddresses(FILE *fp) PyObject *op; fprintf(fp, "Remaining object addresses:\n"); for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) - fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] %s\n", op, + fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] %s\n", (void *)op, op->ob_refcnt, Py_TYPE(op)->tp_name); } @@ -2167,7 +2167,7 @@ _PyObject_AssertFailed(PyObject *obj, const char *expr, const char *msg, fprintf(stderr, "\n"); } else if (_PyObject_IsFreed((PyObject *)Py_TYPE(obj))) { - fprintf(stderr, "\n", Py_TYPE(obj)); + fprintf(stderr, "\n", (void *)Py_TYPE(obj)); } else { /* Diplay the traceback where the object has been allocated. diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 3ee143549d217f..7cfd28965967f9 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -2354,7 +2354,7 @@ _PyObject_DebugDumpAddress(const void *p) } tail = q + nbytes; - fprintf(stderr, " The %d pad bytes at tail=%p are ", SST, tail); + fprintf(stderr, " The %d pad bytes at tail=%p are ", SST, (void *)tail); ok = 1; for (i = 0; i < SST; ++i) { if (tail[i] != FORBIDDENBYTE) { diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 4d86519e863769..eaba5836cb1c71 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1251,7 +1251,7 @@ void *_PyUnicode_compact_data(void *unicode_raw) { } void *_PyUnicode_data(void *unicode_raw) { PyObject *unicode = _PyObject_CAST(unicode_raw); - printf("obj %p\n", unicode); + printf("obj %p\n", (void*)unicode); printf("compact %d\n", PyUnicode_IS_COMPACT(unicode)); printf("compact ascii %d\n", PyUnicode_IS_COMPACT_ASCII(unicode)); printf("ascii op %p\n", ((void*)((PyASCIIObject*)(unicode) + 1))); @@ -1282,14 +1282,14 @@ _PyUnicode_Dump(PyObject *op) if (ascii->wstr == data) printf("shared "); - printf("wstr=%p", ascii->wstr); + printf("wstr=%p", (void *)ascii->wstr); if (!(ascii->state.ascii == 1 && ascii->state.compact == 1)) { printf(" (%" PY_FORMAT_SIZE_T "u), ", compact->wstr_length); if (!ascii->state.compact && compact->utf8 == unicode->data.any) printf("shared "); printf("utf8=%p (%" PY_FORMAT_SIZE_T "u)", - compact->utf8, compact->utf8_length); + (void *)compact->utf8, compact->utf8_length); } printf(", data=%p\n", data); } diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c index 0818012d8c5abd..4b2ed70de97c10 100644 --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -127,7 +127,7 @@ main(int argc, char *argv[]) size_t i, end = Py_MIN(n + 16, data_size); fprintf(outfile, " "); for (i = n; i < end; i++) { - fprintf(outfile, "%d,", (unsigned int) data[i]); + fprintf(outfile, "%u,", (unsigned int) data[i]); } fprintf(outfile, "\n"); } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index fbdeb9b5565cf8..1290164edbf68d 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1750,7 +1750,7 @@ _alloc_preinit_entry(const wchar_t *value) PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); return node; -}; +} static int _append_preinit_entry(_Py_PreInitEntry *optionlist, const wchar_t *value) @@ -1772,7 +1772,7 @@ _append_preinit_entry(_Py_PreInitEntry *optionlist, const wchar_t *value) last_entry->next = new_entry; } return 0; -}; +} static void _clear_preinit_entries(_Py_PreInitEntry *optionlist) @@ -1789,7 +1789,7 @@ _clear_preinit_entries(_Py_PreInitEntry *optionlist) current = next; } PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); -}; +} static void _clear_all_preinit_options(void) @@ -1820,7 +1820,7 @@ _PySys_ReadPreInitOptions(void) _clear_all_preinit_options(); return 0; -}; +} static PyObject * get_warnoptions(void) diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 1f4f36d52d5552..4c106d9959c10b 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -339,7 +339,7 @@ PyThread_allocate_lock(void) } } - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); + dprintf(("PyThread_allocate_lock() -> %p\n", (void *)lock)); return (PyThread_type_lock)lock; } @@ -521,7 +521,7 @@ PyThread_allocate_lock(void) } } - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); + dprintf(("PyThread_allocate_lock() -> %p\n", (void *)lock)); return (PyThread_type_lock) lock; } From 678bb9d1b51d46801d10f8e35585a369aca1c593 Mon Sep 17 00:00:00 2001 From: Brett Cannon <54418+brettcannon@users.noreply.github.com> Date: Mon, 6 May 2019 13:44:49 -0400 Subject: [PATCH 183/212] Unroll import-team in CODEOWNERS (#13118) --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9b7a4032fb4370..fae5138435665e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -26,8 +26,8 @@ Objects/dict* @methane # Ignoring importlib.h so as to not get flagged on # all pull requests that change the emitted # bytecode. -**/*import*.c @python/import-team -**/*import*.py @python/import-team +**/*import*.c @brettcannon @encukou @ericsnowcurrently @ncoghlan @warsaw +**/*import*.py @brettcannon @encukou @ericsnowcurrently @ncoghlan @warsaw # SSL From c1004b85464579771db3b50f5b150449275bbbd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Mon, 6 May 2019 20:30:25 +0200 Subject: [PATCH 184/212] Python 3.8.0a4 --- Include/patchlevel.h | 4 +- Lib/pydoc_data/topics.py | 93 +- Misc/NEWS.d/3.8.0a4.rst | 1421 +++++++++++++++++ .../2019-04-02-09-25-23.bpo-36503.0xzfkQ.rst | 2 - .../2019-04-02-17-01-23.bpo-36508.SN5Y6N.rst | 3 - .../2019-04-06-18-53-03.bpo-36544.hJr2_a.rst | 1 - .../2019-04-09-17-31-47.bpo-36577.34kuUW.rst | 1 - .../2019-04-09-18-19-43.bpo-36465.-w6vx6.rst | 6 - .../2019-04-11-18-50-58.bpo-36605.gk5czf.rst | 2 - .../2019-04-12-19-49-10.bpo-36618.gcI9iq.rst | 8 - .../2019-04-15-15-01-29.bpo-31904.38fdkg.rst | 1 - .../2019-04-16-13-58-52.bpo-36635.JKlzkf.rst | 5 - .../2019-04-24-02-29-15.bpo-36707.8ZNB67.rst | 3 - .../2019-04-25-01-51-52.bpo-21536.ACQkiC.rst | 12 - .../2019-04-29-09-57-20.bpo-36747.1YEyu-.rst | 1 - .../2019-01-23-12-38-11.bpo-35810.wpbWeb.rst | 4 - .../2019-02-19-08-23-42.bpo-36025.tnwylQ.rst | 5 - .../2019-03-27-15-58-23.bpo-36443.tAfZR9.rst | 6 - .../2019-04-11-12-20-35.bpo-36389.P9QFoP.rst | 5 - .../2019-04-16-21-18-19.bpo-36641.pz-DIR.rst | 2 - .../2019-05-01-00-42-08.bpo-36763.vghb86.rst | 2 - .../2018-12-08-03-40-43.bpo-18372.DT1nR0.rst | 2 - .../2019-03-20-00-37-24.bpo-36143.fnKoKo.rst | 2 - .../2019-03-25-13-45-19.bpo-36440.gkvzhi.rst | 2 - .../2019-03-25-23-37-26.bpo-36430.sd9xxQ.rst | 1 - .../2019-03-26-17-23-02.bpo-36433.-8XzZf.rst | 1 - .../2019-03-27-22-35-16.bpo-36459.UAvkKp.rst | 1 - .../2019-03-27-23-53-00.bpo-36452.xhK2lT.rst | 5 - .../2019-03-28-15-22-45.bpo-24214.tZ6lYU.rst | 2 - .../2019-03-29-18-47-50.bpo-20844.ge-7SM.rst | 2 - .../2019-04-02-04-10-32.bpo-36504.k_V8Bm.rst | 1 - .../2019-04-02-20-02-22.bpo-36475.CjRps3.rst | 4 - .../2019-04-06-20-59-19.bpo-36540.SzVUfC.rst | 2 - .../2019-04-11-12-41-31.bpo-36549.QSp8of.rst | 2 - .../2019-04-11-14-36-55.bpo-36588.wejLoC.rst | 5 - .../2019-04-12-12-32-39.bpo-36611.zbo9WQ.rst | 5 - .../2019-04-12-15-49-15.bpo-20180.KUqVk7.rst | 2 - .../2019-04-13-02-08-44.bpo-36623.HR_xhB.rst | 2 - .../2019-04-16-11-56-12.bpo-32849.aeSg-D.rst | 2 - .../2019-04-25-21-02-40.bpo-36722.8NApVM.rst | 2 - .../2019-04-29-23-30-21.bpo-36751.3NCRbm.rst | 3 - .../2018-02-22-15-48-16.bpo-32913.f3utho.rst | 1 - .../2018-06-15-15-57-37.bpo-33832.xBFhKw.rst | 1 - .../2018-12-25-12-56-57.bpo-35581.aA7r6T.rst | 1 - .../2019-02-24-03-15-10.bpo-33043.8knWTS.rst | 1 - .../2019-03-08-15-39-47.bpo-36157.nF1pP1.rst | 1 - .../2019-03-23-09-25-12.bpo-36345.L704Zv.rst | 2 - .../2019-03-26-14-58-34.bpo-36345.r2stx3.rst | 3 - .../2019-03-27-22-46-00.bpo-36425.kG9gx1.rst | 2 - .../2019-04-04-19-11-47.bpo-36523.sG1Tr4.rst | 1 - .../2019-04-14-19-46-21.bpo-30840.R-JFzw.rst | 1 - .../2019-04-15-12-02-45.bpo-36625.x3LMCF.rst | 1 - .../2019-03-26-00-09-50.bpo-36429.w-jL2e.rst | 2 - .../2017-08-30-20-27-00.bpo-31292.dKIaZb.rst | 2 - .../2018-04-06-11-06-23.bpo-31310.eq9ky0.rst | 1 - .../2018-04-11-11-41-52.bpo-33291.-xLGf8.rst | 3 - .../2018-05-29-18-34-53.bpo-33530._4Q_bi.rst | 3 - .../2018-07-18-11-25-34.bpo-34139.tKbmW7.rst | 1 - .../2018-07-30-12-00-15.bpo-31658._bx7a_.rst | 2 - .../2018-10-05-16-01-00.bpo-34547.abbaa.rst | 2 - .../2018-10-27-11-54-12.bpo-35082.HDj1nr.rst | 2 - .../2018-11-07-23-44-25.bpo-25451.re_8db.rst | 2 - .../2018-12-05-09-55-05.bpo-35416.XALKZG.rst | 1 - .../2019-01-18-23-10-10.bpo-23078.l4dFoj.rst | 2 - .../2019-02-07-20-25-39.bpo-35934.QmfNmY.rst | 4 - .../2019-02-13-18-56-22.bpo-17396.oKRkrD.rst | 2 - .../2019-02-13-18-56-27.bpo-35376.UFhYLj.rst | 2 - .../2019-02-16-22-19-32.bpo-35936.Ay5WtD.rst | 2 - .../2019-02-17-12-55-51.bpo-36004.hCt_KK.rst | 4 - .../2019-03-07-20-02-18.bpo-36227.i2Z1XR.rst | 2 - .../2019-03-13-16-48-42.bpo-31904.9sjd38.rst | 1 - .../2019-03-18-16-16-55.bpo-36348.E0w_US.rst | 2 - .../2019-03-20-15-13-18.bpo-36366.n0eav_.rst | 4 - .../2019-03-22-13-47-52.bpo-36326.WCnEI5.rst | 2 - .../2019-03-23-17-16-15.bpo-36407.LG3aC4.rst | 2 - .../2019-03-26-14-20-59.bpo-36434.PTdidw.rst | 1 - .../2019-03-27-02-09-22.bpo-36385.we2F45.rst | 1 - .../2019-03-28-21-17-08.bpo-30427.lxzvbw.rst | 2 - .../2019-03-31-01-18-52.bpo-27181.LVUWcc.rst | 1 - .../2019-03-31-10-21-54.bpo-36492.f7vyUs.rst | 5 - .../2019-04-03-20-46-47.bpo-36522.g5x3By.rst | 1 - .../2019-04-05-21-29-53.bpo-36050.x9DRKE.rst | 2 - .../2019-04-06-14-23-00.bpo-36546.YXjbyY.rst | 1 - .../2019-04-06-20-25-25.bpo-36232.SClmhb.rst | 2 - .../2019-04-08-14-41-22.bpo-34373.lEAl_-.rst | 1 - .../2019-04-09-04-08-46.bpo-17561.hOhVnh.rst | 1 - .../2019-04-09-12-02-35.bpo-36559.LbDRrw.rst | 2 - .../2019-04-09-14-46-28.bpo-33461.SYJM-E.rst | 2 - .../2019-04-09-22-40-52.bpo-36575.Vg_p92.rst | 4 - .../2019-04-11-16-09-42.bpo-18748.QW7upB.rst | 3 - .../2019-04-11-22-11-24.bpo-36598.hfzDUl.rst | 2 - .../2019-04-12-13-52-15.bpo-36613.hqT1qn.rst | 1 - .../2019-04-13-23-42-33.bpo-30485.JHhjJS.rst | 3 - .../2019-04-15-12-22-09.bpo-25430.7_8kqc.rst | 1 - .../2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst | 5 - .../2019-04-18-16-10-29.bpo-28552.MW1TLt.rst | 4 - .../2019-04-19-15-29-55.bpo-36650._EVdrz.rst | 4 - .../2019-04-20-09-50-32.bpo-36673.XF4Egb.rst | 3 - .../2019-04-20-13-10-34.bpo-36676.XF4Egb.rst | 3 - .../2019-04-24-17-08-45.bpo-36669.X4g0fu.rst | 1 - .../2019-04-26-10-10-34.bpo-13611.XEF4bg.rst | 2 - .../2019-04-26-17-14-20.bpo-36734.p2MaiN.rst | 2 - ...2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst | 3 - .../2019-04-28-01-52-39.bpo-26978.Lpm-SI.rst | 2 - .../2019-04-28-15-01-29.bpo-28238.gdk38f.rst | 3 - .../2019-04-29-11-47-06.bpo-35952.3uNuyo.rst | 1 - .../2019-01-17-10-03-48.bpo-35755.GmllIs.rst | 5 - .../2019-04-10-08-53-30.bpo-30458.51E-DA.rst | 1 - .../2019-04-29-15-34-59.bpo-36742.QCUY0i.rst | 1 - .../2019-03-18-10-47-45.bpo-36341.UXlY0P.rst | 2 - .../2019-03-19-17-39-25.bpo-31904.QxhhRx.rst | 1 - .../2019-03-26-13-49-21.bpo-36436.yAtN0V.rst | 1 - .../2019-04-01-16-06-36.bpo-31904.peaceF.rst | 1 - .../2019-04-08-09-24-36.bpo-31904.ab03ea.rst | 1 - .../2019-04-08-19-01-21.bpo-36565.2bxgtU.rst | 2 - .../2019-04-09-14-08-02.bpo-36560._ejeOr.rst | 4 - .../2019-04-12-12-44-42.bpo-36611.UtorXL.rst | 2 - .../2019-04-15-11-57-39.bpo-36629.ySnaL3.rst | 2 - .../2019-04-15-16-55-49.bpo-36635.__FTq9.rst | 1 - .../2019-04-21-17-53-50.bpo-32424.Q4rBmn.rst | 2 - .../2019-04-21-17-55-18.bpo-32424.yDy49h.rst | 1 - .../2019-04-23-17-48-11.bpo-36454.0q4lQz.rst | 3 - .../2019-04-26-04-12-29.bpo-36725.B8-ghi.rst | 3 - .../2019-04-26-09-02-49.bpo-36719.ys2uqH.rst | 4 - .../2019-04-30-14-30-29.bpo-14546.r38Y-6.rst | 1 - .../2017-10-04-12-40-45.bpo-31512.YQeBt2.rst | 2 - .../2018-07-20-13-09-19.bpo-34060.v-z87j.rst | 2 - .../2019-02-11-14-53-17.bpo-35947.9vI4hP.rst | 2 - .../2019-03-05-18-09-43.bpo-29515.vwUTv0.rst | 27 - .../2019-03-16-10-24-58.bpo-36010.dttWfp.rst | 1 - .../2019-03-18-11-44-49.bpo-36085.mLfxfc.rst | 2 - .../2019-03-26-11-46-15.bpo-36441.lYjGF1.rst | 1 - .../2019-03-28-03-51-16.bpo-35941.UnlAEE.rst | 3 - .../2019-04-02-10-11-18.bpo-36509.DdaM67.rst | 4 - .../2019-04-10-04-35-31.bpo-34144._KzB5z.rst | 2 - .../2019-04-17-11-39-24.bpo-36649.arbzIo.rst | 1 - .../2019-04-22-16-59-20.bpo-35920.VSfGOI.rst | 3 - .../2019-04-29-10-54-14.bpo-34602.Lrl2zU.rst | 3 - README.rst | 2 +- 139 files changed, 1477 insertions(+), 385 deletions(-) create mode 100644 Misc/NEWS.d/3.8.0a4.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-02-09-25-23.bpo-36503.0xzfkQ.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-02-17-01-23.bpo-36508.SN5Y6N.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-06-18-53-03.bpo-36544.hJr2_a.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-09-17-31-47.bpo-36577.34kuUW.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-11-18-50-58.bpo-36605.gk5czf.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-12-19-49-10.bpo-36618.gcI9iq.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-15-15-01-29.bpo-31904.38fdkg.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-16-13-58-52.bpo-36635.JKlzkf.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-24-02-29-15.bpo-36707.8ZNB67.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst delete mode 100644 Misc/NEWS.d/next/Build/2019-04-29-09-57-20.bpo-36747.1YEyu-.rst delete mode 100644 Misc/NEWS.d/next/C API/2019-01-23-12-38-11.bpo-35810.wpbWeb.rst delete mode 100644 Misc/NEWS.d/next/C API/2019-02-19-08-23-42.bpo-36025.tnwylQ.rst delete mode 100644 Misc/NEWS.d/next/C API/2019-03-27-15-58-23.bpo-36443.tAfZR9.rst delete mode 100644 Misc/NEWS.d/next/C API/2019-04-11-12-20-35.bpo-36389.P9QFoP.rst delete mode 100644 Misc/NEWS.d/next/C API/2019-04-16-21-18-19.bpo-36641.pz-DIR.rst delete mode 100644 Misc/NEWS.d/next/C API/2019-05-01-00-42-08.bpo-36763.vghb86.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-12-08-03-40-43.bpo-18372.DT1nR0.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-03-20-00-37-24.bpo-36143.fnKoKo.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-03-25-13-45-19.bpo-36440.gkvzhi.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-03-25-23-37-26.bpo-36430.sd9xxQ.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-03-26-17-23-02.bpo-36433.-8XzZf.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-03-27-22-35-16.bpo-36459.UAvkKp.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-03-27-23-53-00.bpo-36452.xhK2lT.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-03-28-15-22-45.bpo-24214.tZ6lYU.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-03-29-18-47-50.bpo-20844.ge-7SM.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-02-04-10-32.bpo-36504.k_V8Bm.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-02-20-02-22.bpo-36475.CjRps3.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-06-20-59-19.bpo-36540.SzVUfC.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-11-12-41-31.bpo-36549.QSp8of.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-11-14-36-55.bpo-36588.wejLoC.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-12-12-32-39.bpo-36611.zbo9WQ.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-12-15-49-15.bpo-20180.KUqVk7.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-13-02-08-44.bpo-36623.HR_xhB.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-25-21-02-40.bpo-36722.8NApVM.rst delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-04-29-23-30-21.bpo-36751.3NCRbm.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2018-02-22-15-48-16.bpo-32913.f3utho.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2018-06-15-15-57-37.bpo-33832.xBFhKw.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2018-12-25-12-56-57.bpo-35581.aA7r6T.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2019-02-24-03-15-10.bpo-33043.8knWTS.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2019-03-08-15-39-47.bpo-36157.nF1pP1.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2019-03-23-09-25-12.bpo-36345.L704Zv.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2019-03-26-14-58-34.bpo-36345.r2stx3.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2019-03-27-22-46-00.bpo-36425.kG9gx1.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2019-04-04-19-11-47.bpo-36523.sG1Tr4.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2019-04-14-19-46-21.bpo-30840.R-JFzw.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2019-04-15-12-02-45.bpo-36625.x3LMCF.rst delete mode 100644 Misc/NEWS.d/next/IDLE/2019-03-26-00-09-50.bpo-36429.w-jL2e.rst delete mode 100644 Misc/NEWS.d/next/Library/2017-08-30-20-27-00.bpo-31292.dKIaZb.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-04-06-11-06-23.bpo-31310.eq9ky0.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-04-11-11-41-52.bpo-33291.-xLGf8.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-05-29-18-34-53.bpo-33530._4Q_bi.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-07-18-11-25-34.bpo-34139.tKbmW7.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-07-30-12-00-15.bpo-31658._bx7a_.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-10-05-16-01-00.bpo-34547.abbaa.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-11-07-23-44-25.bpo-25451.re_8db.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-12-05-09-55-05.bpo-35416.XALKZG.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-02-07-20-25-39.bpo-35934.QmfNmY.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-02-13-18-56-22.bpo-17396.oKRkrD.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-02-13-18-56-27.bpo-35376.UFhYLj.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-02-16-22-19-32.bpo-35936.Ay5WtD.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-02-17-12-55-51.bpo-36004.hCt_KK.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-07-20-02-18.bpo-36227.i2Z1XR.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-13-16-48-42.bpo-31904.9sjd38.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-18-16-16-55.bpo-36348.E0w_US.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-22-13-47-52.bpo-36326.WCnEI5.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-23-17-16-15.bpo-36407.LG3aC4.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-26-14-20-59.bpo-36434.PTdidw.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-27-02-09-22.bpo-36385.we2F45.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-28-21-17-08.bpo-30427.lxzvbw.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-31-01-18-52.bpo-27181.LVUWcc.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-03-31-10-21-54.bpo-36492.f7vyUs.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-03-20-46-47.bpo-36522.g5x3By.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-05-21-29-53.bpo-36050.x9DRKE.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-06-14-23-00.bpo-36546.YXjbyY.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-06-20-25-25.bpo-36232.SClmhb.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-08-14-41-22.bpo-34373.lEAl_-.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-09-04-08-46.bpo-17561.hOhVnh.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-09-12-02-35.bpo-36559.LbDRrw.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-09-14-46-28.bpo-33461.SYJM-E.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-09-22-40-52.bpo-36575.Vg_p92.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-11-16-09-42.bpo-18748.QW7upB.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-11-22-11-24.bpo-36598.hfzDUl.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-12-13-52-15.bpo-36613.hqT1qn.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-13-23-42-33.bpo-30485.JHhjJS.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-15-12-22-09.bpo-25430.7_8kqc.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-18-16-10-29.bpo-28552.MW1TLt.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-19-15-29-55.bpo-36650._EVdrz.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-20-09-50-32.bpo-36673.XF4Egb.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-20-13-10-34.bpo-36676.XF4Egb.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-24-17-08-45.bpo-36669.X4g0fu.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-26-10-10-34.bpo-13611.XEF4bg.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-26-17-14-20.bpo-36734.p2MaiN.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-28-01-52-39.bpo-26978.Lpm-SI.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-28-15-01-29.bpo-28238.gdk38f.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-29-11-47-06.bpo-35952.3uNuyo.rst delete mode 100644 Misc/NEWS.d/next/Security/2019-01-17-10-03-48.bpo-35755.GmllIs.rst delete mode 100644 Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-30458.51E-DA.rst delete mode 100644 Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-03-18-10-47-45.bpo-36341.UXlY0P.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-03-19-17-39-25.bpo-31904.QxhhRx.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-03-26-13-49-21.bpo-36436.yAtN0V.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-01-16-06-36.bpo-31904.peaceF.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-08-09-24-36.bpo-31904.ab03ea.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-08-19-01-21.bpo-36565.2bxgtU.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-09-14-08-02.bpo-36560._ejeOr.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-12-12-44-42.bpo-36611.UtorXL.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-15-11-57-39.bpo-36629.ySnaL3.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-15-16-55-49.bpo-36635.__FTq9.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-21-17-53-50.bpo-32424.Q4rBmn.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-21-17-55-18.bpo-32424.yDy49h.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-23-17-48-11.bpo-36454.0q4lQz.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-26-04-12-29.bpo-36725.B8-ghi.rst delete mode 100644 Misc/NEWS.d/next/Tests/2019-04-26-09-02-49.bpo-36719.ys2uqH.rst delete mode 100644 Misc/NEWS.d/next/Tools-Demos/2019-04-30-14-30-29.bpo-14546.r38Y-6.rst delete mode 100644 Misc/NEWS.d/next/Windows/2017-10-04-12-40-45.bpo-31512.YQeBt2.rst delete mode 100644 Misc/NEWS.d/next/Windows/2018-07-20-13-09-19.bpo-34060.v-z87j.rst delete mode 100644 Misc/NEWS.d/next/Windows/2019-02-11-14-53-17.bpo-35947.9vI4hP.rst delete mode 100644 Misc/NEWS.d/next/Windows/2019-03-05-18-09-43.bpo-29515.vwUTv0.rst delete mode 100644 Misc/NEWS.d/next/Windows/2019-03-16-10-24-58.bpo-36010.dttWfp.rst delete mode 100644 Misc/NEWS.d/next/Windows/2019-03-18-11-44-49.bpo-36085.mLfxfc.rst delete mode 100644 Misc/NEWS.d/next/Windows/2019-03-26-11-46-15.bpo-36441.lYjGF1.rst delete mode 100644 Misc/NEWS.d/next/Windows/2019-03-28-03-51-16.bpo-35941.UnlAEE.rst delete mode 100644 Misc/NEWS.d/next/Windows/2019-04-02-10-11-18.bpo-36509.DdaM67.rst delete mode 100644 Misc/NEWS.d/next/Windows/2019-04-10-04-35-31.bpo-34144._KzB5z.rst delete mode 100644 Misc/NEWS.d/next/Windows/2019-04-17-11-39-24.bpo-36649.arbzIo.rst delete mode 100644 Misc/NEWS.d/next/Windows/2019-04-22-16-59-20.bpo-35920.VSfGOI.rst delete mode 100644 Misc/NEWS.d/next/macOS/2019-04-29-10-54-14.bpo-34602.Lrl2zU.rst diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 497dda046ae9a5..c0a1a6fb0d8bfc 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 8 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 3 +#define PY_RELEASE_SERIAL 4 /* Version as a string */ -#define PY_VERSION "3.8.0a3+" +#define PY_VERSION "3.8.0a4" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 3e11f54fd78aa7..875d6e890347c3 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Mon Mar 25 20:32:23 2019 +# Autogenerated by Sphinx on Mon May 6 20:27:55 2019 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -162,20 +162,21 @@ '\n' ' Note: If the object is a class instance and the attribute ' 'reference\n' - ' occurs on both sides of the assignment operator, the RHS ' - 'expression,\n' - ' "a.x" can access either an instance attribute or (if no ' - 'instance\n' - ' attribute exists) a class attribute. The LHS target "a.x" ' - 'is always\n' - ' set as an instance attribute, creating it if necessary. ' - 'Thus, the\n' - ' two occurrences of "a.x" do not necessarily refer to the ' - 'same\n' - ' attribute: if the RHS expression refers to a class ' - 'attribute, the\n' - ' LHS creates a new instance attribute as the target of the\n' - ' assignment:\n' + ' occurs on both sides of the assignment operator, the ' + 'right-hand side\n' + ' expression, "a.x" can access either an instance attribute or ' + '(if no\n' + ' instance attribute exists) a class attribute. The left-hand ' + 'side\n' + ' target "a.x" is always set as an instance attribute, ' + 'creating it if\n' + ' necessary. Thus, the two occurrences of "a.x" do not ' + 'necessarily\n' + ' refer to the same attribute: if the right-hand side ' + 'expression\n' + ' refers to a class attribute, the left-hand side creates a ' + 'new\n' + ' instance attribute as the target of the assignment:\n' '\n' ' class Cls:\n' ' x = 3 # class variable\n' @@ -3302,11 +3303,11 @@ '"str.format()"\n' ' method, to produce a “formatted” string representation ' 'of an\n' - ' object. The "format_spec" argument is a string that ' + ' object. The *format_spec* argument is a string that ' 'contains a\n' ' description of the formatting options desired. The ' 'interpretation\n' - ' of the "format_spec" argument is up to the type ' + ' of the *format_spec* argument is up to the type ' 'implementing\n' ' "__format__()", however most classes will either ' 'delegate\n' @@ -6189,8 +6190,8 @@ 'end up importing "pkg.mod". If you execute "from ..subpkg2 import ' 'mod"\n' 'from within "pkg.subpkg1" you will import "pkg.subpkg2.mod". The\n' - 'specification for relative imports is contained within **PEP ' - '328**.\n' + 'specification for relative imports is contained in the Package\n' + 'Relative Imports section.\n' '\n' '"importlib.import_module()" is provided to support applications ' 'that\n' @@ -8002,11 +8003,11 @@ '"str.format()"\n' ' method, to produce a “formatted” string representation of ' 'an\n' - ' object. The "format_spec" argument is a string that ' + ' object. The *format_spec* argument is a string that ' 'contains a\n' ' description of the formatting options desired. The ' 'interpretation\n' - ' of the "format_spec" argument is up to the type ' + ' of the *format_spec* argument is up to the type ' 'implementing\n' ' "__format__()", however most classes will either ' 'delegate\n' @@ -8768,15 +8769,15 @@ 'When a class definition is executed, the following steps ' 'occur:\n' '\n' - '* MRO entries are resolved\n' + '* MRO entries are resolved;\n' '\n' - '* the appropriate metaclass is determined\n' + '* the appropriate metaclass is determined;\n' '\n' - '* the class namespace is prepared\n' + '* the class namespace is prepared;\n' '\n' - '* the class body is executed\n' + '* the class body is executed;\n' '\n' - '* the class object is created\n' + '* the class object is created.\n' '\n' '\n' 'Resolving MRO entries\n' @@ -8806,16 +8807,16 @@ '\n' '* if no bases and no explicit metaclass are given, then ' '"type()" is\n' - ' used\n' + ' used;\n' '\n' '* if an explicit metaclass is given and it is *not* an ' 'instance of\n' - ' "type()", then it is used directly as the metaclass\n' + ' "type()", then it is used directly as the metaclass;\n' '\n' '* if an instance of "type()" is given as the explicit ' 'metaclass, or\n' ' bases are defined, then the most derived metaclass is ' - 'used\n' + 'used.\n' '\n' 'The most derived metaclass is selected from the explicitly ' 'specified\n' @@ -8931,7 +8932,7 @@ 'with the\n' ' class being defined and the assigned name of that ' 'particular\n' - ' descriptor; and\n' + ' descriptor;\n' '\n' '* finally, the "__init_subclass__()" hook is called on the ' 'immediate\n' @@ -9030,7 +9031,7 @@ '\n' 'One can implement the generic class syntax as specified by ' '**PEP 484**\n' - '(for example "List[int]") by defining a special method\n' + '(for example "List[int]") by defining a special method:\n' '\n' 'classmethod object.__class_getitem__(cls, key)\n' '\n' @@ -9672,6 +9673,14 @@ 'capitalized\n' ' and the rest lowercased.\n' '\n' + ' Changed in version 3.8: The first character is now put ' + 'into\n' + ' titlecase rather than uppercase. This means that ' + 'characters like\n' + ' digraphs will only have their first letter capitalized, ' + 'instead of\n' + ' the full character.\n' + '\n' 'str.casefold()\n' '\n' ' Return a casefolded copy of the string. Casefolded ' @@ -10416,9 +10425,7 @@ ' >>> def titlecase(s):\n' ' ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n' ' ... lambda mo: ' - 'mo.group(0)[0].upper() +\n' - ' ... ' - 'mo.group(0)[1:].lower(),\n' + 'mo.group(0).capitalize(),\n' ' ... s)\n' ' ...\n' ' >>> titlecase("they\'re bill\'s friends.")\n' @@ -11286,17 +11293,17 @@ '| |\n' ' | | unavailable; not inherited by ' '| |\n' - ' | | subclasses ' + ' | | subclasses. ' '| |\n' ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__name__" | The function’s name ' + ' | "__name__" | The function’s name. ' '| Writable |\n' ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__qualname__" | The function’s *qualified name* ' + ' | "__qualname__" | The function’s *qualified ' '| Writable |\n' - ' | | New in version 3.3. ' + ' | | name*. New in version 3.3. ' '| |\n' ' ' '+---------------------------+---------------------------------+-------------+\n' @@ -11316,7 +11323,7 @@ '| |\n' ' | | or "None" if no arguments have ' '| |\n' - ' | | a default value ' + ' | | a default value. ' '| |\n' ' ' '+---------------------------+---------------------------------+-------------+\n' @@ -12172,7 +12179,13 @@ '\n' ' "fromkeys()" is a class method that returns a new ' 'dictionary.\n' - ' *value* defaults to "None".\n' + ' *value* defaults to "None". All of the values refer ' + 'to just a\n' + ' single instance, so it generally doesn’t make sense ' + 'for *value*\n' + ' to be a mutable object such as an empty list. To get ' + 'distinct\n' + ' values, use a dict comprehension instead.\n' '\n' ' get(key[, default])\n' '\n' diff --git a/Misc/NEWS.d/3.8.0a4.rst b/Misc/NEWS.d/3.8.0a4.rst new file mode 100644 index 00000000000000..76bb4970ff851a --- /dev/null +++ b/Misc/NEWS.d/3.8.0a4.rst @@ -0,0 +1,1421 @@ +.. bpo: 36742 +.. date: 2019-04-29-15-34-59 +.. nonce: QCUY0i +.. release date: 2019-05-06 +.. section: Security + +Fixes mishandling of pre-normalization characters in urlsplit(). + +.. + +.. bpo: 30458 +.. date: 2019-04-10-08-53-30 +.. nonce: 51E-DA +.. section: Security + +Address CVE-2019-9740 by disallowing URL paths with embedded whitespace or +control characters through into the underlying http client request. Such +potentially malicious header injection URLs now cause an +http.client.InvalidURL exception to be raised. + +.. + +.. bpo: 35755 +.. date: 2019-01-17-10-03-48 +.. nonce: GmllIs +.. section: Security + +:func:`shutil.which` now uses ``os.confstr("CS_PATH")`` if available and if +the :envvar:`PATH` environment variable is not set. Remove also the current +directory from :data:`posixpath.defpath`. On Unix, :func:`shutil.which` and +the :mod:`subprocess` module no longer search the executable in the current +directory if the :envvar:`PATH` environment variable is not set. + +.. + +.. bpo: 36751 +.. date: 2019-04-29-23-30-21 +.. nonce: 3NCRbm +.. section: Core and Builtins + +The :func:`~inspect.getfullargspec` function in the :mod:`inspect` module is +deprecated in favor of the :func:`inspect.signature` API. Contributed by +Pablo Galindo. + +.. + +.. bpo: 36722 +.. date: 2019-04-25-21-02-40 +.. nonce: 8NApVM +.. section: Core and Builtins + +In debug build, import now also looks for C extensions compiled in release +mode and for C extensions compiled in the stable ABI. + +.. + +.. bpo: 32849 +.. date: 2019-04-16-11-56-12 +.. nonce: aeSg-D +.. section: Core and Builtins + +Fix Python Initialization code on FreeBSD to detect properly when stdin file +descriptor (fd 0) is invalid. + +.. + +.. bpo: 36623 +.. date: 2019-04-13-02-08-44 +.. nonce: HR_xhB +.. section: Core and Builtins + +Remove parser headers and related function declarations that lack +implementations after the removal of pgen. + +.. + +.. bpo: 20180 +.. date: 2019-04-12-15-49-15 +.. nonce: KUqVk7 +.. section: Core and Builtins + +``dict.pop()`` is now up to 33% faster thanks to Argument Clinic. Patch by +Inada Naoki. + +.. + +.. bpo: 36611 +.. date: 2019-04-12-12-32-39 +.. nonce: zbo9WQ +.. section: Core and Builtins + +Debug memory allocators: disable serialno field by default from debug hooks +on Python memory allocators to reduce the memory footprint by 5%. Enable +:mod:`tracemalloc` to get the traceback where a memory block has been +allocated when a fatal memory error is logged to decide where to put a +breakpoint. Compile Python with ``PYMEM_DEBUG_SERIALNO`` defined to get back +the field. + +.. + +.. bpo: 36588 +.. date: 2019-04-11-14-36-55 +.. nonce: wejLoC +.. section: Core and Builtins + +On AIX, :attr:`sys.platform` doesn't contain the major version anymore. +Always return ``'aix'``, instead of ``'aix3'`` .. ``'aix7'``. Since older +Python versions include the version number, it is recommended to always use +``sys.platform.startswith('aix')``. Contributed by M. Felt. + +.. + +.. bpo: 36549 +.. date: 2019-04-11-12-41-31 +.. nonce: QSp8of +.. section: Core and Builtins + +Change str.capitalize to use titlecase for the first character instead of +uppercase. + +.. + +.. bpo: 36540 +.. date: 2019-04-06-20-59-19 +.. nonce: SzVUfC +.. section: Core and Builtins + +Implement :pep:`570` (Python positional-only parameters). Patch by Pablo +Galindo. + +.. + +.. bpo: 36475 +.. date: 2019-04-02-20-02-22 +.. nonce: CjRps3 +.. section: Core and Builtins + +:c:func:`PyEval_AcquireLock` and :c:func:`PyEval_AcquireThread` now +terminate the current thread if called while the interpreter is finalizing, +making them consistent with :c:func:`PyEval_RestoreThread`, +:c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`. + +.. + +.. bpo: 36504 +.. date: 2019-04-02-04-10-32 +.. nonce: k_V8Bm +.. section: Core and Builtins + +Fix signed integer overflow in _ctypes.c's ``PyCArrayType_new()``. + +.. + +.. bpo: 20844 +.. date: 2019-03-29-18-47-50 +.. nonce: ge-7SM +.. section: Core and Builtins + +Fix running script with encoding cookie and LF line ending may fail on +Windows. + +.. + +.. bpo: 24214 +.. date: 2019-03-28-15-22-45 +.. nonce: tZ6lYU +.. section: Core and Builtins + +Fixed support of the surrogatepass error handler in the UTF-8 incremental +decoder. + +.. + +.. bpo: 36452 +.. date: 2019-03-27-23-53-00 +.. nonce: xhK2lT +.. section: Core and Builtins + +Changing ``dict`` keys during iteration of the dict itself, ``keys()``, +``values()``, or ``items()`` will now be detected in certain corner cases +where keys are deleted/added so that the number of keys isn't changed. A +`RuntimeError` will be raised after ``len(dict)`` iterations. Contributed by +Thomas Perl. + +.. + +.. bpo: 36459 +.. date: 2019-03-27-22-35-16 +.. nonce: UAvkKp +.. section: Core and Builtins + +Fix a possible double ``PyMem_FREE()`` due to tokenizer.c's ``tok_nextc()``. + +.. + +.. bpo: 36433 +.. date: 2019-03-26-17-23-02 +.. nonce: -8XzZf +.. section: Core and Builtins + +Fixed TypeError message in classmethoddescr_call. + +.. + +.. bpo: 36430 +.. date: 2019-03-25-23-37-26 +.. nonce: sd9xxQ +.. section: Core and Builtins + +Fix a possible reference leak in :func:`itertools.count`. + +.. + +.. bpo: 36440 +.. date: 2019-03-25-13-45-19 +.. nonce: gkvzhi +.. section: Core and Builtins + +Include node names in ``ParserError`` messages, instead of numeric IDs. +Patch by A. Skrobov. + +.. + +.. bpo: 36143 +.. date: 2019-03-20-00-37-24 +.. nonce: fnKoKo +.. section: Core and Builtins + +Regenerate :mod:`keyword` from the Grammar and Tokens file using pgen. Patch +by Pablo Galindo. + +.. + +.. bpo: 18372 +.. date: 2018-12-08-03-40-43 +.. nonce: DT1nR0 +.. section: Core and Builtins + +Add missing :c:func:`PyObject_GC_Track` calls in the :mod:`pickle` module. +Patch by Zackery Spytz. + +.. + +.. bpo: 35952 +.. date: 2019-04-29-11-47-06 +.. nonce: 3uNuyo +.. section: Library + +Fix pythoninfo when the compiler is missing. + +.. + +.. bpo: 28238 +.. date: 2019-04-28-15-01-29 +.. nonce: gdk38f +.. section: Library + +The ``.find*()`` methods of xml.etree.ElementTree can now search for +wildcards like ``{*}tag`` and ``{ns}*`` that match a tag in any namespace or +all tags in a namespace. Patch by Stefan Behnel. + +.. + +.. bpo: 26978 +.. date: 2019-04-28-01-52-39 +.. nonce: Lpm-SI +.. section: Library + +`pathlib.path.link_to()` is now implemented. It creates a hard link pointing +to a path. + +.. + +.. bpo: 1613500 +.. date: 2019-04-27-21-09-33 +.. nonce: Ogp4P0 +.. section: Library + +:class:`fileinput.FileInput` now uses the input file mode to correctly set +the output file mode (previously it was hardcoded to ``'w'``) when +``inplace=True`` is passed to its constructor. + +.. + +.. bpo: 36734 +.. date: 2019-04-26-17-14-20 +.. nonce: p2MaiN +.. section: Library + +Fix compilation of ``faulthandler.c`` on HP-UX. Initialize ``stack_t +current_stack`` to zero using ``memset()``. + +.. + +.. bpo: 13611 +.. date: 2019-04-26-10-10-34 +.. nonce: XEF4bg +.. section: Library + +The xml.etree.ElementTree packages gained support for C14N 2.0 +serialisation. Patch by Stefan Behnel. + +.. + +.. bpo: 36669 +.. date: 2019-04-24-17-08-45 +.. nonce: X4g0fu +.. section: Library + +Add missing matrix multiplication operator support to weakref.proxy. + +.. + +.. bpo: 36676 +.. date: 2019-04-20-13-10-34 +.. nonce: XF4Egb +.. section: Library + +The XMLParser() in xml.etree.ElementTree provides namespace prefix context +to the parser target if it defines the callback methods "start_ns()" and/or +"end_ns()". Patch by Stefan Behnel. + +.. + +.. bpo: 36673 +.. date: 2019-04-20-09-50-32 +.. nonce: XF4Egb +.. section: Library + +The TreeBuilder and XMLPullParser in xml.etree.ElementTree gained support +for parsing comments and processing instructions. Patch by Stefan Behnel. + +.. + +.. bpo: 36650 +.. date: 2019-04-19-15-29-55 +.. nonce: _EVdrz +.. section: Library + +The C version of functools.lru_cache() was treating calls with an empty +``**kwargs`` dictionary as being distinct from calls with no keywords at +all. This did not result in an incorrect answer, but it did trigger an +unexpected cache miss. + +.. + +.. bpo: 28552 +.. date: 2019-04-18-16-10-29 +.. nonce: MW1TLt +.. section: Library + +Fix :mod:`distutils.sysconfig` if :data:`sys.executable` is ``None`` or an +empty string: use :func:`os.getcwd` to initialize ``project_base``. Fix +also the distutils build command: don't use :data:`sys.executable` if it is +``None`` or an empty string. + +.. + +.. bpo: 35755 +.. date: 2019-04-16-17-50-39 +.. nonce: Fg4EXb +.. section: Library + +:func:`shutil.which` and :func:`distutils.spawn.find_executable` now use +``os.confstr("CS_PATH")`` if available instead of :data:`os.defpath`, if the +``PATH`` environment variable is not set. Moreover, don't use +``os.confstr("CS_PATH")`` nor :data:`os.defpath` if the ``PATH`` environment +variable is set to an empty string. + +.. + +.. bpo: 25430 +.. date: 2019-04-15-12-22-09 +.. nonce: 7_8kqc +.. section: Library + +improve performance of ``IPNetwork.__contains__()`` + +.. + +.. bpo: 30485 +.. date: 2019-04-13-23-42-33 +.. nonce: JHhjJS +.. section: Library + +Path expressions in xml.etree.ElementTree can now avoid explicit namespace +prefixes for tags (or the "{namespace}tag" notation) by passing a default +namespace with an empty string prefix. + +.. + +.. bpo: 36613 +.. date: 2019-04-12-13-52-15 +.. nonce: hqT1qn +.. section: Library + +Fix :mod:`asyncio` wait() not removing callback if exception + +.. + +.. bpo: 36598 +.. date: 2019-04-11-22-11-24 +.. nonce: hfzDUl +.. section: Library + +Fix ``isinstance`` check for Mock objects with spec when the code is +executed under tracing. Patch by Karthikeyan Singaravelan. + +.. + +.. bpo: 18748 +.. date: 2019-04-11-16-09-42 +.. nonce: QW7upB +.. section: Library + +In development mode (:option:`-X` ``dev``) and in debug build, the +:class:`io.IOBase` destructor now logs ``close()`` exceptions. These +exceptions are silent by default in release mode. + +.. + +.. bpo: 36575 +.. date: 2019-04-09-22-40-52 +.. nonce: Vg_p92 +.. section: Library + +The ``_lsprof`` module now uses internal timer same to +``time.perf_counter()`` by default. ``gettimeofday(2)`` was used on Unix. +New timer has better resolution on most Unix platforms and timings are no +longer impacted by system clock updates since ``perf_counter()`` is +monotonic. Patch by Inada Naoki. + +.. + +.. bpo: 33461 +.. date: 2019-04-09-14-46-28 +.. nonce: SYJM-E +.. section: Library + +``json.loads`` now emits ``DeprecationWarning`` when ``encoding`` option is +specified. Patch by Matthias Bussonnier. + +.. + +.. bpo: 36559 +.. date: 2019-04-09-12-02-35 +.. nonce: LbDRrw +.. section: Library + +The random module now prefers the lean internal _sha512 module over hashlib +for seed(version=2) to optimize import time. + +.. + +.. bpo: 17561 +.. date: 2019-04-09-04-08-46 +.. nonce: hOhVnh +.. section: Library + +Set backlog=None as the default for socket.create_server. + +.. + +.. bpo: 34373 +.. date: 2019-04-08-14-41-22 +.. nonce: lEAl_- +.. section: Library + +Fix :func:`time.mktime` error handling on AIX for year before 1970. + +.. + +.. bpo: 36232 +.. date: 2019-04-06-20-25-25 +.. nonce: SClmhb +.. section: Library + +Improve error message when trying to open existing DBM database that +actually doesn't exist. Patch by Marco Rougeth. + +.. + +.. bpo: 36546 +.. date: 2019-04-06-14-23-00 +.. nonce: YXjbyY +.. section: Library + +Add statistics.quantiles() + +.. + +.. bpo: 36050 +.. date: 2019-04-05-21-29-53 +.. nonce: x9DRKE +.. section: Library + +Optimized ``http.client.HTTPResponse.read()`` for large response. Patch by +Inada Naoki. + +.. + +.. bpo: 36522 +.. date: 2019-04-03-20-46-47 +.. nonce: g5x3By +.. section: Library + +If *debuglevel* is set to >0 in :mod:`http.client`, print all values for +headers with multiple values for the same header name. Patch by Matt +Houglum. + +.. + +.. bpo: 36492 +.. date: 2019-03-31-10-21-54 +.. nonce: f7vyUs +.. section: Library + +Deprecated passing required arguments like *func* as keyword arguments in +functions which should accept arbitrary keyword arguments and pass them to +other function. Arbitrary keyword arguments (even with names "self" and +"func") can now be passed to these functions if the required arguments are +passed as positional arguments. + +.. + +.. bpo: 27181 +.. date: 2019-03-31-01-18-52 +.. nonce: LVUWcc +.. section: Library + +Add statistics.geometric_mean(). + +.. + +.. bpo: 30427 +.. date: 2019-03-28-21-17-08 +.. nonce: lxzvbw +.. section: Library + +``os.path.normcase()`` relies on ``os.fspath()`` to check the type of its +argument. Redundant checks have been removed from its +``posixpath.normcase()`` and ``ntpath.normcase()`` implementations. Patch by +Wolfgang Maier. + +.. + +.. bpo: 36385 +.. date: 2019-03-27-02-09-22 +.. nonce: we2F45 +.. section: Library + +Stop rejecting IPv4 octets for being ambiguously octal. Leading zeros are +ignored, and no longer are assumed to specify octal octets. Octets are +always decimal numbers. Octets must still be no more than three digits, +including leading zeroes. + +.. + +.. bpo: 36434 +.. date: 2019-03-26-14-20-59 +.. nonce: PTdidw +.. section: Library + +Errors during writing to a ZIP file no longer prevent to properly close it. + +.. + +.. bpo: 36407 +.. date: 2019-03-23-17-16-15 +.. nonce: LG3aC4 +.. section: Library + +Fixed wrong indentation writing for CDATA section in xml.dom.minidom. Patch +by Vladimir Surjaninov. + +.. + +.. bpo: 36326 +.. date: 2019-03-22-13-47-52 +.. nonce: WCnEI5 +.. section: Library + +inspect.getdoc() can now find docstrings for member objects when __slots__ +is a dictionary. + +.. + +.. bpo: 36366 +.. date: 2019-03-20-15-13-18 +.. nonce: n0eav_ +.. section: Library + +Calling ``stop()`` on an unstarted or stopped :func:`unittest.mock.patch` +object will now return `None` instead of raising :exc:`RuntimeError`, making +the method idempotent. Patch by Karthikeyan Singaravelan. + +.. + +.. bpo: 36348 +.. date: 2019-03-18-16-16-55 +.. nonce: E0w_US +.. section: Library + +The :meth:`imap.IMAP4.logout` method no longer ignores silently arbitrary +exceptions. + +.. + +.. bpo: 31904 +.. date: 2019-03-13-16-48-42 +.. nonce: 9sjd38 +.. section: Library + +Add time module support and fix test_time faiures for VxWorks. + +.. + +.. bpo: 36227 +.. date: 2019-03-07-20-02-18 +.. nonce: i2Z1XR +.. section: Library + +Added support for keyword arguments `default_namespace` and +`xml_declaration` in functions ElementTree.tostring() and +ElementTree.tostringlist(). + +.. + +.. bpo: 36004 +.. date: 2019-02-17-12-55-51 +.. nonce: hCt_KK +.. section: Library + +Added new alternate constructors :meth:`datetime.date.fromisocalendar` and +:meth:`datetime.datetime.fromisocalendar`, which construct date objects from +ISO year, week number and weekday; these are the inverse of each class's +``isocalendar`` method. Patch by Paul Ganssle. + +.. + +.. bpo: 35936 +.. date: 2019-02-16-22-19-32 +.. nonce: Ay5WtD +.. section: Library + +:mod:`modulefinder` no longer depends on the deprecated :mod:`imp` module, +and the initializer for :class:`modulefinder.ModuleFinder` now has immutable +default arguments. Patch by Brandt Bucher. + +.. + +.. bpo: 35376 +.. date: 2019-02-13-18-56-27 +.. nonce: UFhYLj +.. section: Library + +:mod:`modulefinder` correctly handles modules that have the same name as a +bad package. Patch by Brandt Bucher. + +.. + +.. bpo: 17396 +.. date: 2019-02-13-18-56-22 +.. nonce: oKRkrD +.. section: Library + +:mod:`modulefinder` no longer crashes when encountering syntax errors in +followed imports. Patch by Brandt Bucher. + +.. + +.. bpo: 35934 +.. date: 2019-02-07-20-25-39 +.. nonce: QmfNmY +.. section: Library + +Added :meth:`~socket.create_server()` and +:meth:`~socket.has_dualstack_ipv6()` convenience functions to automate the +necessary tasks usually involved when creating a server socket, including +accepting both IPv4 and IPv6 connections on the same socket. (Contributed +by Giampaolo Rodola in :issue:`17561`.) + +.. + +.. bpo: 23078 +.. date: 2019-01-18-23-10-10 +.. nonce: l4dFoj +.. section: Library + +Add support for :func:`classmethod` and :func:`staticmethod` to +:func:`unittest.mock.create_autospec`. Initial patch by Felipe Ochoa. + +.. + +.. bpo: 35416 +.. date: 2018-12-05-09-55-05 +.. nonce: XALKZG +.. section: Library + +Fix potential resource warnings in distutils. Patch by Mickaël Schoentgen. + +.. + +.. bpo: 25451 +.. date: 2018-11-07-23-44-25 +.. nonce: re_8db +.. section: Library + +Add transparency methods to :class:`tkinter.PhotoImage`. Patch by Zackery +Spytz. + +.. + +.. bpo: 35082 +.. date: 2018-10-27-11-54-12 +.. nonce: HDj1nr +.. section: Library + +Don't return deleted attributes when calling dir on a +:class:`unittest.mock.Mock`. + +.. + +.. bpo: 34547 +.. date: 2018-10-05-16-01-00 +.. nonce: abbaa +.. section: Library + +:class:`wsgiref.handlers.BaseHandler` now handles abrupt client connection +terminations gracefully. Patch by Petter Strandmark. + +.. + +.. bpo: 31658 +.. date: 2018-07-30-12-00-15 +.. nonce: _bx7a_ +.. section: Library + +:func:`xml.sax.parse` now supports :term:`path-like `. +Patch by Mickaël Schoentgen. + +.. + +.. bpo: 34139 +.. date: 2018-07-18-11-25-34 +.. nonce: tKbmW7 +.. section: Library + +Remove stale unix datagram socket before binding + +.. + +.. bpo: 33530 +.. date: 2018-05-29-18-34-53 +.. nonce: _4Q_bi +.. section: Library + +Implemented Happy Eyeballs in `asyncio.create_connection()`. Added two new +arguments, *happy_eyeballs_delay* and *interleave*, to specify Happy +Eyeballs behavior. + +.. + +.. bpo: 33291 +.. date: 2018-04-11-11-41-52 +.. nonce: -xLGf8 +.. section: Library + +Do not raise AttributeError when calling the inspect functions +isgeneratorfunction, iscoroutinefunction, isasyncgenfunction on a method +created from an arbitrary callable. Instead, return False. + +.. + +.. bpo: 31310 +.. date: 2018-04-06-11-06-23 +.. nonce: eq9ky0 +.. section: Library + +Fix the multiprocessing.semaphore_tracker so it is reused by child processes + +.. + +.. bpo: 31292 +.. date: 2017-08-30-20-27-00 +.. nonce: dKIaZb +.. section: Library + +Fix ``setup.py check --restructuredtext`` for files containing ``include`` +directives. + +.. + +.. bpo: 36625 +.. date: 2019-04-15-12-02-45 +.. nonce: x3LMCF +.. section: Documentation + +Remove obsolete comments from docstrings in fractions.Fraction + +.. + +.. bpo: 30840 +.. date: 2019-04-14-19-46-21 +.. nonce: R-JFzw +.. section: Documentation + +Document relative imports + +.. + +.. bpo: 36523 +.. date: 2019-04-04-19-11-47 +.. nonce: sG1Tr4 +.. section: Documentation + +Add docstring for io.IOBase.writelines(). + +.. + +.. bpo: 36425 +.. date: 2019-03-27-22-46-00 +.. nonce: kG9gx1 +.. section: Documentation + +New documentation translation: `Simplified Chinese +`_. + +.. + +.. bpo: 36345 +.. date: 2019-03-26-14-58-34 +.. nonce: r2stx3 +.. section: Documentation + +Avoid the duplication of code from ``Tools/scripts/serve.py`` in using the +:rst:dir:`literalinclude` directive for the basic wsgiref-based web server +in the documentation of :mod:`wsgiref`. Contributed by Stéphane Wirtel. + +.. + +.. bpo: 36345 +.. date: 2019-03-23-09-25-12 +.. nonce: L704Zv +.. section: Documentation + +Using the code of the ``Tools/scripts/serve.py`` script as an example in the +:mod:`wsgiref` documentation. Contributed by Stéphane Wirtel. + +.. + +.. bpo: 36157 +.. date: 2019-03-08-15-39-47 +.. nonce: nF1pP1 +.. section: Documentation + +Added Documention for PyInterpreterState_Main(). + +.. + +.. bpo: 33043 +.. date: 2019-02-24-03-15-10 +.. nonce: 8knWTS +.. section: Documentation + +Updates the docs.python.org page with the addition of a 'Contributing to +Docs' link at the end of the page (between 'Reporting Bugs' and 'About +Documentation'). Updates the 'Found a Bug' page with additional links and +information in the Documentation Bugs section. + +.. + +.. bpo: 35581 +.. date: 2018-12-25-12-56-57 +.. nonce: aA7r6T +.. section: Documentation + +@typing.type_check_only now allows type stubs to mark functions and classes +not available during runtime. + +.. + +.. bpo: 33832 +.. date: 2018-06-15-15-57-37 +.. nonce: xBFhKw +.. section: Documentation + +Add glossary entry for 'magic method'. + +.. + +.. bpo: 32913 +.. date: 2018-02-22-15-48-16 +.. nonce: f3utho +.. section: Documentation + +Added re.Match.groupdict example to regex HOWTO. + +.. + +.. bpo: 36719 +.. date: 2019-04-26-09-02-49 +.. nonce: ys2uqH +.. section: Tests + +regrtest now always detects uncollectable objects. Previously, the check was +only enabled by ``--findleaks``. The check now also works with +``-jN/--multiprocess N``. ``--findleaks`` becomes a deprecated alias to +``--fail-env-changed``. + +.. + +.. bpo: 36725 +.. date: 2019-04-26-04-12-29 +.. nonce: B8-ghi +.. section: Tests + +When using mulitprocessing mode (-jN), regrtest now better reports errors if +a worker process fails, and it exits immediately on a worker thread failure +or when interrupted. + +.. + +.. bpo: 36454 +.. date: 2019-04-23-17-48-11 +.. nonce: 0q4lQz +.. section: Tests + +Change test_time.test_monotonic() to test only the lower bound of elapsed +time after a sleep command rather than the upper bound. This prevents +unnecessary test failures on slow buildbots. Patch by Victor Stinner. + +.. + +.. bpo: 32424 +.. date: 2019-04-21-17-55-18 +.. nonce: yDy49h +.. section: Tests + +Improve test coverage for xml.etree.ElementTree. Patch by Gordon P. Hemsley. + +.. + +.. bpo: 32424 +.. date: 2019-04-21-17-53-50 +.. nonce: Q4rBmn +.. section: Tests + +Fix typo in test_cyclic_gc() test for xml.etree.ElementTree. Patch by Gordon +P. Hemsley. + +.. + +.. bpo: 36635 +.. date: 2019-04-15-16-55-49 +.. nonce: __FTq9 +.. section: Tests + +Add a new :mod:`_testinternalcapi` module to test the internal C API. + +.. + +.. bpo: 36629 +.. date: 2019-04-15-11-57-39 +.. nonce: ySnaL3 +.. section: Tests + +Fix ``test_imap4_host_default_value()`` of ``test_imaplib``: catch also +:data:`errno.ENETUNREACH` error. + +.. + +.. bpo: 36611 +.. date: 2019-04-12-12-44-42 +.. nonce: UtorXL +.. section: Tests + +Fix ``test_sys.test_getallocatedblocks()`` when :mod:`tracemalloc` is +enabled. + +.. + +.. bpo: 36560 +.. date: 2019-04-09-14-08-02 +.. nonce: _ejeOr +.. section: Tests + +Fix reference leak hunting in regrtest: compute also deltas (of reference +count, allocated memory blocks, file descriptor count) during warmup, to +ensure that everything is initialized before starting to hunt reference +leaks. + +.. + +.. bpo: 36565 +.. date: 2019-04-08-19-01-21 +.. nonce: 2bxgtU +.. section: Tests + +Fix reference hunting (``python3 -m test -R 3:3``) when Python has no +built-in abc module. + +.. + +.. bpo: 31904 +.. date: 2019-04-08-09-24-36 +.. nonce: ab03ea +.. section: Tests + +Port test_resource to VxWorks: skip tests cases setting RLIMIT_FSIZE and +RLIMIT_CPU. + +.. + +.. bpo: 31904 +.. date: 2019-04-01-16-06-36 +.. nonce: peaceF +.. section: Tests + +Fix test_tabnanny on VxWorks: adjust ENOENT error message. + +.. + +.. bpo: 36436 +.. date: 2019-03-26-13-49-21 +.. nonce: yAtN0V +.. section: Tests + +Fix ``_testcapi.pymem_buffer_overflow()``: handle memory allocation failure. + +.. + +.. bpo: 31904 +.. date: 2019-03-19-17-39-25 +.. nonce: QxhhRx +.. section: Tests + +Fix test_utf8_mode on VxWorks: Python always use UTF-8 on VxWorks. + +.. + +.. bpo: 36341 +.. date: 2019-03-18-10-47-45 +.. nonce: UXlY0P +.. section: Tests + +Fix tests that may fail with PermissionError upon calling bind() on AF_UNIX +sockets. + +.. + +.. bpo: 36747 +.. date: 2019-04-29-09-57-20 +.. nonce: 1YEyu- +.. section: Build + +Remove the stale scriptsinstall Makefile target. + +.. + +.. bpo: 21536 +.. date: 2019-04-25-01-51-52 +.. nonce: ACQkiC +.. section: Build + +On Unix, C extensions are no longer linked to libpython except on Android. + +It is now possible for a statically linked Python to load a C extension +built using a shared library Python. + +When Python is embedded, ``libpython`` must not be loaded with +``RTLD_LOCAL``, but ``RTLD_GLOBAL`` instead. Previously, using +``RTLD_LOCAL``, it was already not possible to load C extensions which were +not linked to ``libpython``, such as C extensions of the standard library +built by the ``*shared*`` section of ``Modules/Setup``. + +distutils, python-config and python-config.py have been modified. + +.. + +.. bpo: 36707 +.. date: 2019-04-24-02-29-15 +.. nonce: 8ZNB67 +.. section: Build + +``./configure --with-pymalloc`` no longer adds the ``m`` flag to SOABI +(sys.implementation.cache_tag). Enabling or disabling pymalloc has no impact +on the ABI. + +.. + +.. bpo: 36635 +.. date: 2019-04-16-13-58-52 +.. nonce: JKlzkf +.. section: Build + +Change ``PyAPI_FUNC(type)``, ``PyAPI_DATA(type)`` and ``PyMODINIT_FUNC`` +macros of ``pyport.h`` when ``Py_BUILD_CORE_MODULE`` is defined. The +``Py_BUILD_CORE_MODULE`` define must be now be used to build a C extension +as a dynamic library accessing Python internals: export the PyInit_xxx() +function in DLL exports on Windows. + +.. + +.. bpo: 31904 +.. date: 2019-04-15-15-01-29 +.. nonce: 38fdkg +.. section: Build + +Don't build the ``_crypt`` extension on VxWorks. + +.. + +.. bpo: 36618 +.. date: 2019-04-12-19-49-10 +.. nonce: gcI9iq +.. section: Build + +Add ``-fmax-type-align=8`` to CFLAGS when clang compiler is detected. The +pymalloc memory allocator aligns memory on 8 bytes. On x86-64, clang expects +alignment on 16 bytes by default and so uses MOVAPS instruction which can +lead to segmentation fault. Instruct clang that Python is limited to +alignemnt on 8 bytes to use MOVUPS instruction instead: slower but don't +trigger a SIGSEGV if the memory is not aligned on 16 bytes. Sadly, the flag +must be added to ``CFLAGS`` and not just ``CFLAGS_NODIST``, since third +party C extensions can have the same issue. + +.. + +.. bpo: 36605 +.. date: 2019-04-11-18-50-58 +.. nonce: gk5czf +.. section: Build + +``make tags`` and ``make TAGS`` now also parse ``Modules/_io/*.c`` and +``Modules/_io/*.h``. + +.. + +.. bpo: 36465 +.. date: 2019-04-09-18-19-43 +.. nonce: -w6vx6 +.. section: Build + +Release builds and debug builds are now ABI compatible: defining the +``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro, which +introduces the only ABI incompatibility. The ``Py_TRACE_REFS`` macro, which +adds the :func:`sys.getobjects` function and the :envvar:`PYTHONDUMPREFS` +environment variable, can be set using the new ``./configure +--with-trace-refs`` build option. + +.. + +.. bpo: 36577 +.. date: 2019-04-09-17-31-47 +.. nonce: 34kuUW +.. section: Build + +setup.py now correctly reports missing OpenSSL headers and libraries again. + +.. + +.. bpo: 36544 +.. date: 2019-04-06-18-53-03 +.. nonce: hJr2_a +.. section: Build + +Fix regression introduced in bpo-36146 refactoring setup.py + +.. + +.. bpo: 36508 +.. date: 2019-04-02-17-01-23 +.. nonce: SN5Y6N +.. section: Build + +``python-config --ldflags`` no longer includes flags of the +``LINKFORSHARED`` variable. The ``LINKFORSHARED`` variable must only be used +to build executables. + +.. + +.. bpo: 36503 +.. date: 2019-04-02-09-25-23 +.. nonce: 0xzfkQ +.. section: Build + +Remove references to "aix3" and "aix4". Patch by M. Felt. + +.. + +.. bpo: 35920 +.. date: 2019-04-22-16-59-20 +.. nonce: VSfGOI +.. section: Windows + +Added platform.win32_edition() and platform.win32_is_iot(). Added support +for cross-compiling packages for Windows ARM32. Skip tests that are not +expected to work on Windows IoT Core ARM32. + +.. + +.. bpo: 36649 +.. date: 2019-04-17-11-39-24 +.. nonce: arbzIo +.. section: Windows + +Remove trailing spaces for registry keys when installed via the Store. + +.. + +.. bpo: 34144 +.. date: 2019-04-10-04-35-31 +.. nonce: _KzB5z +.. section: Windows + +Fixed activate.bat to correctly update codepage when chcp.com returns dots +in output. Patch by Lorenz Mende. + +.. + +.. bpo: 36509 +.. date: 2019-04-02-10-11-18 +.. nonce: DdaM67 +.. section: Windows + +Added preset-iot layout for Windows IoT ARM containers. This layout doesn't +contain UI components like tkinter or IDLE. It also doesn't contain files to +support on-target builds since Windows ARM32 builds must be cross-compiled +when using MSVC. + +.. + +.. bpo: 35941 +.. date: 2019-03-28-03-51-16 +.. nonce: UnlAEE +.. section: Windows + +enum_certificates function of the ssl module now returns certificates from +all available certificate stores inside windows in a query instead of +returning only certificates from the system wide certificate store. This +includes certificates from these certificate stores: local machine, local +machine enterprise, local machine group policy, current user, current user +group policy, services, users. ssl.enum_crls() function is changed in the +same way to return all certificate revocation lists inside the windows +certificate revocation list stores. + +.. + +.. bpo: 36441 +.. date: 2019-03-26-11-46-15 +.. nonce: lYjGF1 +.. section: Windows + +Fixes creating a venv when debug binaries are installed. + +.. + +.. bpo: 36085 +.. date: 2019-03-18-11-44-49 +.. nonce: mLfxfc +.. section: Windows + +Enable better DLL resolution on Windows by using safe DLL search paths and +adding :func:`os.add_dll_directory`. + +.. + +.. bpo: 36010 +.. date: 2019-03-16-10-24-58 +.. nonce: dttWfp +.. section: Windows + +Add the venv standard library module to the nuget distribution for Windows. + +.. + +.. bpo: 29515 +.. date: 2019-03-05-18-09-43 +.. nonce: vwUTv0 +.. section: Windows + +Add the following socket module constants on Windows: IPPROTO_AH IPPROTO_CBT +IPPROTO_DSTOPTS IPPROTO_EGP IPPROTO_ESP IPPROTO_FRAGMENT IPPROTO_GGP +IPPROTO_HOPOPTS IPPROTO_ICLFXBM IPPROTO_ICMPV6 IPPROTO_IDP IPPROTO_IGMP +IPPROTO_IGP IPPROTO_IPV4 IPPROTO_IPV6 IPPROTO_L2TP IPPROTO_MAX IPPROTO_ND +IPPROTO_NONE IPPROTO_PGM IPPROTO_PIM IPPROTO_PUP IPPROTO_RDP IPPROTO_ROUTING +IPPROTO_SCTP IPPROTO_ST + +.. + +.. bpo: 35947 +.. date: 2019-02-11-14-53-17 +.. nonce: 9vI4hP +.. section: Windows + +Added current version of libffi to cpython-source-deps. Change _ctypes to +use current version of libffi on Windows. + +.. + +.. bpo: 34060 +.. date: 2018-07-20-13-09-19 +.. nonce: v-z87j +.. section: Windows + +Report system load when running test suite on Windows. Patch by Ammar Askar. +Based on prior work by Jeremy Kloth. + +.. + +.. bpo: 31512 +.. date: 2017-10-04-12-40-45 +.. nonce: YQeBt2 +.. section: Windows + +With the Windows 10 Creators Update, non-elevated users can now create +symlinks as long as the computer has Developer Mode enabled. + +.. + +.. bpo: 34602 +.. date: 2019-04-29-10-54-14 +.. nonce: Lrl2zU +.. section: macOS + +Avoid failures setting macOS stack resource limit with resource.setrlimit. +This reverts an earlier fix for bpo-18075 which forced a non-default stack +size when building the interpreter executable on macOS. + +.. + +.. bpo: 36429 +.. date: 2019-03-26-00-09-50 +.. nonce: w-jL2e +.. section: IDLE + +Fix starting IDLE with pyshell. Add idlelib.pyshell alias at top; remove +pyshell alias at bottom. Remove obsolete __name__=='__main__' command. + +.. + +.. bpo: 14546 +.. date: 2019-04-30-14-30-29 +.. nonce: r38Y-6 +.. section: Tools/Demos + +Fix the argument handling in Tools/scripts/lll.py. + +.. + +.. bpo: 36763 +.. date: 2019-05-01-00-42-08 +.. nonce: vghb86 +.. section: C API + +Fix memory leak in :c:func:`Py_SetStandardStreamEncoding`: release memory if +the function is called twice. + +.. + +.. bpo: 36641 +.. date: 2019-04-16-21-18-19 +.. nonce: pz-DIR +.. section: C API + +:c:macro:`PyDoc_VAR(name)` and :c:macro:`PyDoc_STRVAR(name,str)` now create +``static const char name[]`` instead of ``static char name[]``. Patch by +Inada Naoki. + +.. + +.. bpo: 36389 +.. date: 2019-04-11-12-20-35 +.. nonce: P9QFoP +.. section: C API + +Change the value of ``CLEANBYTE``, ``DEADDYTE`` and ``FORBIDDENBYTE`` +internal constants used by debug hooks on Python memory allocators +(:c:func:`PyMem_SetupDebugHooks` function). Byte patterns ``0xCB``, ``0xDB`` +and ``0xFB`` have been replaced with ``0xCD``, ``0xDD`` and ``0xFD`` to use +the same values than Windows CRT debug ``malloc()`` and ``free()``. + +.. + +.. bpo: 36443 +.. date: 2019-03-27-15-58-23 +.. nonce: tAfZR9 +.. section: C API + +Since Python 3.7.0, calling :c:func:`Py_DecodeLocale` before +:c:func:`Py_Initialize` produces mojibake if the ``LC_CTYPE`` locale is +coerced and/or if the UTF-8 Mode is enabled by the user configuration. The +LC_CTYPE coercion and UTF-8 Mode are now disabled by default to fix the +mojibake issue. They must now be enabled explicitly (opt-in) using the new +:c:func:`_Py_PreInitialize` API with ``_PyPreConfig``. + +.. + +.. bpo: 36025 +.. date: 2019-02-19-08-23-42 +.. nonce: tnwylQ +.. section: C API + +Fixed an accidental change to the datetime C API where the arguments to the +:c:func:`PyDate_FromTimestamp` function were incorrectly interpreted as a +single timestamp rather than an arguments tuple, which causes existing code +to start raising :exc:`TypeError`. The backwards-incompatible change was +only present in alpha releases of Python 3.8. Patch by Paul Ganssle. + +.. + +.. bpo: 35810 +.. date: 2019-01-23-12-38-11 +.. nonce: wpbWeb +.. section: C API + +Modify ``PyObject_Init`` to correctly increase the refcount of heap- +allocated Type objects. Also fix the refcounts of the heap-allocated types +that were either doing this manually or not decreasing the type's refcount +in tp_dealloc diff --git a/Misc/NEWS.d/next/Build/2019-04-02-09-25-23.bpo-36503.0xzfkQ.rst b/Misc/NEWS.d/next/Build/2019-04-02-09-25-23.bpo-36503.0xzfkQ.rst deleted file mode 100644 index 764c397f8f8db9..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-02-09-25-23.bpo-36503.0xzfkQ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove references to "aix3" and "aix4". -Patch by M. Felt. diff --git a/Misc/NEWS.d/next/Build/2019-04-02-17-01-23.bpo-36508.SN5Y6N.rst b/Misc/NEWS.d/next/Build/2019-04-02-17-01-23.bpo-36508.SN5Y6N.rst deleted file mode 100644 index 62f80840a044b3..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-02-17-01-23.bpo-36508.SN5Y6N.rst +++ /dev/null @@ -1,3 +0,0 @@ -``python-config --ldflags`` no longer includes flags of the -``LINKFORSHARED`` variable. The ``LINKFORSHARED`` variable must only be used -to build executables. diff --git a/Misc/NEWS.d/next/Build/2019-04-06-18-53-03.bpo-36544.hJr2_a.rst b/Misc/NEWS.d/next/Build/2019-04-06-18-53-03.bpo-36544.hJr2_a.rst deleted file mode 100644 index 71f5c21847b696..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-06-18-53-03.bpo-36544.hJr2_a.rst +++ /dev/null @@ -1 +0,0 @@ -Fix regression introduced in bpo-36146 refactoring setup.py diff --git a/Misc/NEWS.d/next/Build/2019-04-09-17-31-47.bpo-36577.34kuUW.rst b/Misc/NEWS.d/next/Build/2019-04-09-17-31-47.bpo-36577.34kuUW.rst deleted file mode 100644 index 58c0151273096f..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-09-17-31-47.bpo-36577.34kuUW.rst +++ /dev/null @@ -1 +0,0 @@ -setup.py now correctly reports missing OpenSSL headers and libraries again. diff --git a/Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst b/Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst deleted file mode 100644 index 8969d3c4df1872..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-09-18-19-43.bpo-36465.-w6vx6.rst +++ /dev/null @@ -1,6 +0,0 @@ -Release builds and debug builds are now ABI compatible: defining the -``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro, which -introduces the only ABI incompatibility. The ``Py_TRACE_REFS`` macro, which -adds the :func:`sys.getobjects` function and the :envvar:`PYTHONDUMPREFS` -environment variable, can be set using the new ``./configure --with-trace-refs`` -build option. diff --git a/Misc/NEWS.d/next/Build/2019-04-11-18-50-58.bpo-36605.gk5czf.rst b/Misc/NEWS.d/next/Build/2019-04-11-18-50-58.bpo-36605.gk5czf.rst deleted file mode 100644 index 4a558fa94d6f75..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-11-18-50-58.bpo-36605.gk5czf.rst +++ /dev/null @@ -1,2 +0,0 @@ -``make tags`` and ``make TAGS`` now also parse ``Modules/_io/*.c`` and -``Modules/_io/*.h``. diff --git a/Misc/NEWS.d/next/Build/2019-04-12-19-49-10.bpo-36618.gcI9iq.rst b/Misc/NEWS.d/next/Build/2019-04-12-19-49-10.bpo-36618.gcI9iq.rst deleted file mode 100644 index 4408227b326c49..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-12-19-49-10.bpo-36618.gcI9iq.rst +++ /dev/null @@ -1,8 +0,0 @@ -Add ``-fmax-type-align=8`` to CFLAGS when clang compiler is detected. The -pymalloc memory allocator aligns memory on 8 bytes. On x86-64, clang expects -alignment on 16 bytes by default and so uses MOVAPS instruction which can -lead to segmentation fault. Instruct clang that Python is limited to -alignemnt on 8 bytes to use MOVUPS instruction instead: slower but don't -trigger a SIGSEGV if the memory is not aligned on 16 bytes. Sadly, the flag -must be added to ``CFLAGS`` and not just ``CFLAGS_NODIST``, since third party C -extensions can have the same issue. diff --git a/Misc/NEWS.d/next/Build/2019-04-15-15-01-29.bpo-31904.38fdkg.rst b/Misc/NEWS.d/next/Build/2019-04-15-15-01-29.bpo-31904.38fdkg.rst deleted file mode 100644 index c82636ed7b5b51..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-15-15-01-29.bpo-31904.38fdkg.rst +++ /dev/null @@ -1 +0,0 @@ -Don't build the ``_crypt`` extension on VxWorks. diff --git a/Misc/NEWS.d/next/Build/2019-04-16-13-58-52.bpo-36635.JKlzkf.rst b/Misc/NEWS.d/next/Build/2019-04-16-13-58-52.bpo-36635.JKlzkf.rst deleted file mode 100644 index 6d346d22b80762..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-16-13-58-52.bpo-36635.JKlzkf.rst +++ /dev/null @@ -1,5 +0,0 @@ -Change ``PyAPI_FUNC(type)``, ``PyAPI_DATA(type)`` and ``PyMODINIT_FUNC`` -macros of ``pyport.h`` when ``Py_BUILD_CORE_MODULE`` is defined. The -``Py_BUILD_CORE_MODULE`` define must be now be used to build a C extension -as a dynamic library accessing Python internals: export the PyInit_xxx() -function in DLL exports on Windows. diff --git a/Misc/NEWS.d/next/Build/2019-04-24-02-29-15.bpo-36707.8ZNB67.rst b/Misc/NEWS.d/next/Build/2019-04-24-02-29-15.bpo-36707.8ZNB67.rst deleted file mode 100644 index 77bd4d73b2a218..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-24-02-29-15.bpo-36707.8ZNB67.rst +++ /dev/null @@ -1,3 +0,0 @@ -``./configure --with-pymalloc`` no longer adds the ``m`` flag to SOABI -(sys.implementation.cache_tag). Enabling or disabling pymalloc has no impact -on the ABI. diff --git a/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst b/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst deleted file mode 100644 index 59efab83265f4b..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst +++ /dev/null @@ -1,12 +0,0 @@ -On Unix, C extensions are no longer linked to libpython except on Android. - -It is now possible for a statically linked Python to load a C extension built -using a shared library Python. - -When Python is embedded, ``libpython`` must not be loaded with ``RTLD_LOCAL``, -but ``RTLD_GLOBAL`` instead. Previously, using ``RTLD_LOCAL``, it was already -not possible to load C extensions which were not linked to ``libpython``, such -as C extensions of the standard library built by the ``*shared*`` section of -``Modules/Setup``. - -distutils, python-config and python-config.py have been modified. diff --git a/Misc/NEWS.d/next/Build/2019-04-29-09-57-20.bpo-36747.1YEyu-.rst b/Misc/NEWS.d/next/Build/2019-04-29-09-57-20.bpo-36747.1YEyu-.rst deleted file mode 100644 index dd5a00801a9313..00000000000000 --- a/Misc/NEWS.d/next/Build/2019-04-29-09-57-20.bpo-36747.1YEyu-.rst +++ /dev/null @@ -1 +0,0 @@ -Remove the stale scriptsinstall Makefile target. diff --git a/Misc/NEWS.d/next/C API/2019-01-23-12-38-11.bpo-35810.wpbWeb.rst b/Misc/NEWS.d/next/C API/2019-01-23-12-38-11.bpo-35810.wpbWeb.rst deleted file mode 100644 index 47d25a5924c700..00000000000000 --- a/Misc/NEWS.d/next/C API/2019-01-23-12-38-11.bpo-35810.wpbWeb.rst +++ /dev/null @@ -1,4 +0,0 @@ -Modify ``PyObject_Init`` to correctly increase the refcount of heap- -allocated Type objects. Also fix the refcounts of the heap-allocated types -that were either doing this manually or not decreasing the type's refcount -in tp_dealloc diff --git a/Misc/NEWS.d/next/C API/2019-02-19-08-23-42.bpo-36025.tnwylQ.rst b/Misc/NEWS.d/next/C API/2019-02-19-08-23-42.bpo-36025.tnwylQ.rst deleted file mode 100644 index b00a33d109c255..00000000000000 --- a/Misc/NEWS.d/next/C API/2019-02-19-08-23-42.bpo-36025.tnwylQ.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fixed an accidental change to the datetime C API where the arguments to the -:c:func:`PyDate_FromTimestamp` function were incorrectly interpreted as a -single timestamp rather than an arguments tuple, which causes existing code to -start raising :exc:`TypeError`. The backwards-incompatible change was only -present in alpha releases of Python 3.8. Patch by Paul Ganssle. diff --git a/Misc/NEWS.d/next/C API/2019-03-27-15-58-23.bpo-36443.tAfZR9.rst b/Misc/NEWS.d/next/C API/2019-03-27-15-58-23.bpo-36443.tAfZR9.rst deleted file mode 100644 index 3d98c318d401f3..00000000000000 --- a/Misc/NEWS.d/next/C API/2019-03-27-15-58-23.bpo-36443.tAfZR9.rst +++ /dev/null @@ -1,6 +0,0 @@ -Since Python 3.7.0, calling :c:func:`Py_DecodeLocale` before -:c:func:`Py_Initialize` produces mojibake if the ``LC_CTYPE`` locale is coerced -and/or if the UTF-8 Mode is enabled by the user configuration. The LC_CTYPE -coercion and UTF-8 Mode are now disabled by default to fix the mojibake issue. -They must now be enabled explicitly (opt-in) using the new -:c:func:`_Py_PreInitialize` API with ``_PyPreConfig``. diff --git a/Misc/NEWS.d/next/C API/2019-04-11-12-20-35.bpo-36389.P9QFoP.rst b/Misc/NEWS.d/next/C API/2019-04-11-12-20-35.bpo-36389.P9QFoP.rst deleted file mode 100644 index f2b507a9c23074..00000000000000 --- a/Misc/NEWS.d/next/C API/2019-04-11-12-20-35.bpo-36389.P9QFoP.rst +++ /dev/null @@ -1,5 +0,0 @@ -Change the value of ``CLEANBYTE``, ``DEADDYTE`` and ``FORBIDDENBYTE`` internal -constants used by debug hooks on Python memory allocators -(:c:func:`PyMem_SetupDebugHooks` function). Byte patterns ``0xCB``, ``0xDB`` -and ``0xFB`` have been replaced with ``0xCD``, ``0xDD`` and ``0xFD`` to use the -same values than Windows CRT debug ``malloc()`` and ``free()``. diff --git a/Misc/NEWS.d/next/C API/2019-04-16-21-18-19.bpo-36641.pz-DIR.rst b/Misc/NEWS.d/next/C API/2019-04-16-21-18-19.bpo-36641.pz-DIR.rst deleted file mode 100644 index f92af63029be0f..00000000000000 --- a/Misc/NEWS.d/next/C API/2019-04-16-21-18-19.bpo-36641.pz-DIR.rst +++ /dev/null @@ -1,2 +0,0 @@ -:c:macro:`PyDoc_VAR(name)` and :c:macro:`PyDoc_STRVAR(name,str)` now create -``static const char name[]`` instead of ``static char name[]``. Patch by Inada Naoki. diff --git a/Misc/NEWS.d/next/C API/2019-05-01-00-42-08.bpo-36763.vghb86.rst b/Misc/NEWS.d/next/C API/2019-05-01-00-42-08.bpo-36763.vghb86.rst deleted file mode 100644 index 1c34920827fc62..00000000000000 --- a/Misc/NEWS.d/next/C API/2019-05-01-00-42-08.bpo-36763.vghb86.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix memory leak in :c:func:`Py_SetStandardStreamEncoding`: release memory if -the function is called twice. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-12-08-03-40-43.bpo-18372.DT1nR0.rst b/Misc/NEWS.d/next/Core and Builtins/2018-12-08-03-40-43.bpo-18372.DT1nR0.rst deleted file mode 100644 index d8205b8d32d0e4..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-12-08-03-40-43.bpo-18372.DT1nR0.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add missing :c:func:`PyObject_GC_Track` calls in the :mod:`pickle` module. -Patch by Zackery Spytz. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-20-00-37-24.bpo-36143.fnKoKo.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-20-00-37-24.bpo-36143.fnKoKo.rst deleted file mode 100644 index 10d6c496273476..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-03-20-00-37-24.bpo-36143.fnKoKo.rst +++ /dev/null @@ -1,2 +0,0 @@ -Regenerate :mod:`keyword` from the Grammar and Tokens file using pgen. Patch -by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-25-13-45-19.bpo-36440.gkvzhi.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-25-13-45-19.bpo-36440.gkvzhi.rst deleted file mode 100644 index 372b1f77100994..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-03-25-13-45-19.bpo-36440.gkvzhi.rst +++ /dev/null @@ -1,2 +0,0 @@ -Include node names in ``ParserError`` messages, instead of numeric IDs. -Patch by A. Skrobov. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-25-23-37-26.bpo-36430.sd9xxQ.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-25-23-37-26.bpo-36430.sd9xxQ.rst deleted file mode 100644 index a65ee096efc4a2..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-03-25-23-37-26.bpo-36430.sd9xxQ.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a possible reference leak in :func:`itertools.count`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-26-17-23-02.bpo-36433.-8XzZf.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-26-17-23-02.bpo-36433.-8XzZf.rst deleted file mode 100644 index 6d1bd288bda1f3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-03-26-17-23-02.bpo-36433.-8XzZf.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed TypeError message in classmethoddescr_call. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-27-22-35-16.bpo-36459.UAvkKp.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-27-22-35-16.bpo-36459.UAvkKp.rst deleted file mode 100644 index 6c234a6a76d9a1..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-03-27-22-35-16.bpo-36459.UAvkKp.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a possible double ``PyMem_FREE()`` due to tokenizer.c's ``tok_nextc()``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-27-23-53-00.bpo-36452.xhK2lT.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-27-23-53-00.bpo-36452.xhK2lT.rst deleted file mode 100644 index 26d85682f88246..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-03-27-23-53-00.bpo-36452.xhK2lT.rst +++ /dev/null @@ -1,5 +0,0 @@ -Changing ``dict`` keys during iteration of the dict itself, ``keys()``, -``values()``, or ``items()`` will now be detected in certain corner cases where -keys are deleted/added so that the number of keys isn't changed. -A `RuntimeError` will be raised after ``len(dict)`` iterations. -Contributed by Thomas Perl. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-28-15-22-45.bpo-24214.tZ6lYU.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-28-15-22-45.bpo-24214.tZ6lYU.rst deleted file mode 100644 index abb27591f78a33..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-03-28-15-22-45.bpo-24214.tZ6lYU.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed support of the surrogatepass error handler in the UTF-8 incremental -decoder. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-03-29-18-47-50.bpo-20844.ge-7SM.rst b/Misc/NEWS.d/next/Core and Builtins/2019-03-29-18-47-50.bpo-20844.ge-7SM.rst deleted file mode 100644 index 22a400ae7c8f02..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-03-29-18-47-50.bpo-20844.ge-7SM.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix running script with encoding cookie and LF line ending -may fail on Windows. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-02-04-10-32.bpo-36504.k_V8Bm.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-02-04-10-32.bpo-36504.k_V8Bm.rst deleted file mode 100644 index 8ac209d4a789bd..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-02-04-10-32.bpo-36504.k_V8Bm.rst +++ /dev/null @@ -1 +0,0 @@ -Fix signed integer overflow in _ctypes.c's ``PyCArrayType_new()``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-02-20-02-22.bpo-36475.CjRps3.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-02-20-02-22.bpo-36475.CjRps3.rst deleted file mode 100644 index 6f0975107fa281..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-02-20-02-22.bpo-36475.CjRps3.rst +++ /dev/null @@ -1,4 +0,0 @@ -:c:func:`PyEval_AcquireLock` and :c:func:`PyEval_AcquireThread` now -terminate the current thread if called while the interpreter is -finalizing, making them consistent with :c:func:`PyEval_RestoreThread`, -:c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-06-20-59-19.bpo-36540.SzVUfC.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-06-20-59-19.bpo-36540.SzVUfC.rst deleted file mode 100644 index 359e8bfe0d16af..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-06-20-59-19.bpo-36540.SzVUfC.rst +++ /dev/null @@ -1,2 +0,0 @@ -Implement :pep:`570` (Python positional-only parameters). Patch by Pablo -Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-11-12-41-31.bpo-36549.QSp8of.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-11-12-41-31.bpo-36549.QSp8of.rst deleted file mode 100644 index 9c6834cb3f9024..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-11-12-41-31.bpo-36549.QSp8of.rst +++ /dev/null @@ -1,2 +0,0 @@ -Change str.capitalize to use titlecase for the first character instead of -uppercase. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-11-14-36-55.bpo-36588.wejLoC.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-11-14-36-55.bpo-36588.wejLoC.rst deleted file mode 100644 index 77d2fa4e299b3e..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-11-14-36-55.bpo-36588.wejLoC.rst +++ /dev/null @@ -1,5 +0,0 @@ -On AIX, :attr:`sys.platform` doesn't contain the major version anymore. -Always return ``'aix'``, instead of ``'aix3'`` .. ``'aix7'``. Since -older Python versions include the version number, it is recommended to -always use ``sys.platform.startswith('aix')``. -Contributed by M. Felt. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-12-12-32-39.bpo-36611.zbo9WQ.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-12-12-32-39.bpo-36611.zbo9WQ.rst deleted file mode 100644 index f55a9efc5d3886..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-12-12-32-39.bpo-36611.zbo9WQ.rst +++ /dev/null @@ -1,5 +0,0 @@ -Debug memory allocators: disable serialno field by default from debug hooks on -Python memory allocators to reduce the memory footprint by 5%. Enable -:mod:`tracemalloc` to get the traceback where a memory block has been allocated -when a fatal memory error is logged to decide where to put a breakpoint. -Compile Python with ``PYMEM_DEBUG_SERIALNO`` defined to get back the field. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-12-15-49-15.bpo-20180.KUqVk7.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-12-15-49-15.bpo-20180.KUqVk7.rst deleted file mode 100644 index 8c9067081aa10c..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-12-15-49-15.bpo-20180.KUqVk7.rst +++ /dev/null @@ -1,2 +0,0 @@ -``dict.pop()`` is now up to 33% faster thanks to Argument Clinic. Patch by -Inada Naoki. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-13-02-08-44.bpo-36623.HR_xhB.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-13-02-08-44.bpo-36623.HR_xhB.rst deleted file mode 100644 index cc90973e2964c5..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-13-02-08-44.bpo-36623.HR_xhB.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove parser headers and related function declarations that lack -implementations after the removal of pgen. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst deleted file mode 100644 index 6a9a85c4b13472..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-16-11-56-12.bpo-32849.aeSg-D.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix Python Initialization code on FreeBSD to detect properly when stdin file -descriptor (fd 0) is invalid. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-25-21-02-40.bpo-36722.8NApVM.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-25-21-02-40.bpo-36722.8NApVM.rst deleted file mode 100644 index 210a7e0525920d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-25-21-02-40.bpo-36722.8NApVM.rst +++ /dev/null @@ -1,2 +0,0 @@ -In debug build, import now also looks for C extensions compiled in release -mode and for C extensions compiled in the stable ABI. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-04-29-23-30-21.bpo-36751.3NCRbm.rst b/Misc/NEWS.d/next/Core and Builtins/2019-04-29-23-30-21.bpo-36751.3NCRbm.rst deleted file mode 100644 index 5b16aaa0b0c30e..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-04-29-23-30-21.bpo-36751.3NCRbm.rst +++ /dev/null @@ -1,3 +0,0 @@ -The :func:`~inspect.getfullargspec` function in the :mod:`inspect` module is -deprecated in favor of the :func:`inspect.signature` API. Contributed by -Pablo Galindo. diff --git a/Misc/NEWS.d/next/Documentation/2018-02-22-15-48-16.bpo-32913.f3utho.rst b/Misc/NEWS.d/next/Documentation/2018-02-22-15-48-16.bpo-32913.f3utho.rst deleted file mode 100644 index caa9590abbaf3e..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-02-22-15-48-16.bpo-32913.f3utho.rst +++ /dev/null @@ -1 +0,0 @@ -Added re.Match.groupdict example to regex HOWTO. diff --git a/Misc/NEWS.d/next/Documentation/2018-06-15-15-57-37.bpo-33832.xBFhKw.rst b/Misc/NEWS.d/next/Documentation/2018-06-15-15-57-37.bpo-33832.xBFhKw.rst deleted file mode 100644 index 3d1c63acca3bb0..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-06-15-15-57-37.bpo-33832.xBFhKw.rst +++ /dev/null @@ -1 +0,0 @@ -Add glossary entry for 'magic method'. diff --git a/Misc/NEWS.d/next/Documentation/2018-12-25-12-56-57.bpo-35581.aA7r6T.rst b/Misc/NEWS.d/next/Documentation/2018-12-25-12-56-57.bpo-35581.aA7r6T.rst deleted file mode 100644 index 2fad3003e3b689..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-12-25-12-56-57.bpo-35581.aA7r6T.rst +++ /dev/null @@ -1 +0,0 @@ -@typing.type_check_only now allows type stubs to mark functions and classes not available during runtime. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2019-02-24-03-15-10.bpo-33043.8knWTS.rst b/Misc/NEWS.d/next/Documentation/2019-02-24-03-15-10.bpo-33043.8knWTS.rst deleted file mode 100644 index 124aa5e027abd2..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-02-24-03-15-10.bpo-33043.8knWTS.rst +++ /dev/null @@ -1 +0,0 @@ -Updates the docs.python.org page with the addition of a 'Contributing to Docs' link at the end of the page (between 'Reporting Bugs' and 'About Documentation'). Updates the 'Found a Bug' page with additional links and information in the Documentation Bugs section. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2019-03-08-15-39-47.bpo-36157.nF1pP1.rst b/Misc/NEWS.d/next/Documentation/2019-03-08-15-39-47.bpo-36157.nF1pP1.rst deleted file mode 100644 index ff0293e8407fd8..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-03-08-15-39-47.bpo-36157.nF1pP1.rst +++ /dev/null @@ -1 +0,0 @@ -Added Documention for PyInterpreterState_Main(). \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2019-03-23-09-25-12.bpo-36345.L704Zv.rst b/Misc/NEWS.d/next/Documentation/2019-03-23-09-25-12.bpo-36345.L704Zv.rst deleted file mode 100644 index c6206a74ab29a9..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-03-23-09-25-12.bpo-36345.L704Zv.rst +++ /dev/null @@ -1,2 +0,0 @@ -Using the code of the ``Tools/scripts/serve.py`` script as an example in the -:mod:`wsgiref` documentation. Contributed by Stéphane Wirtel. diff --git a/Misc/NEWS.d/next/Documentation/2019-03-26-14-58-34.bpo-36345.r2stx3.rst b/Misc/NEWS.d/next/Documentation/2019-03-26-14-58-34.bpo-36345.r2stx3.rst deleted file mode 100644 index bbecc947cafa74..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-03-26-14-58-34.bpo-36345.r2stx3.rst +++ /dev/null @@ -1,3 +0,0 @@ -Avoid the duplication of code from ``Tools/scripts/serve.py`` in using the -:rst:dir:`literalinclude` directive for the basic wsgiref-based web server in the -documentation of :mod:`wsgiref`. Contributed by Stéphane Wirtel. diff --git a/Misc/NEWS.d/next/Documentation/2019-03-27-22-46-00.bpo-36425.kG9gx1.rst b/Misc/NEWS.d/next/Documentation/2019-03-27-22-46-00.bpo-36425.kG9gx1.rst deleted file mode 100644 index 12bd833a88b553..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-03-27-22-46-00.bpo-36425.kG9gx1.rst +++ /dev/null @@ -1,2 +0,0 @@ -New documentation translation: `Simplified Chinese -`_. diff --git a/Misc/NEWS.d/next/Documentation/2019-04-04-19-11-47.bpo-36523.sG1Tr4.rst b/Misc/NEWS.d/next/Documentation/2019-04-04-19-11-47.bpo-36523.sG1Tr4.rst deleted file mode 100644 index 9355f607d760ad..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-04-04-19-11-47.bpo-36523.sG1Tr4.rst +++ /dev/null @@ -1 +0,0 @@ -Add docstring for io.IOBase.writelines(). diff --git a/Misc/NEWS.d/next/Documentation/2019-04-14-19-46-21.bpo-30840.R-JFzw.rst b/Misc/NEWS.d/next/Documentation/2019-04-14-19-46-21.bpo-30840.R-JFzw.rst deleted file mode 100644 index 210f54f2593edb..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-04-14-19-46-21.bpo-30840.R-JFzw.rst +++ /dev/null @@ -1 +0,0 @@ -Document relative imports \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2019-04-15-12-02-45.bpo-36625.x3LMCF.rst b/Misc/NEWS.d/next/Documentation/2019-04-15-12-02-45.bpo-36625.x3LMCF.rst deleted file mode 100644 index af1a157332492f..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-04-15-12-02-45.bpo-36625.x3LMCF.rst +++ /dev/null @@ -1 +0,0 @@ -Remove obsolete comments from docstrings in fractions.Fraction diff --git a/Misc/NEWS.d/next/IDLE/2019-03-26-00-09-50.bpo-36429.w-jL2e.rst b/Misc/NEWS.d/next/IDLE/2019-03-26-00-09-50.bpo-36429.w-jL2e.rst deleted file mode 100644 index 1d6bb1a587b587..00000000000000 --- a/Misc/NEWS.d/next/IDLE/2019-03-26-00-09-50.bpo-36429.w-jL2e.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix starting IDLE with pyshell. Add idlelib.pyshell alias at top; remove -pyshell alias at bottom. Remove obsolete __name__=='__main__' command. diff --git a/Misc/NEWS.d/next/Library/2017-08-30-20-27-00.bpo-31292.dKIaZb.rst b/Misc/NEWS.d/next/Library/2017-08-30-20-27-00.bpo-31292.dKIaZb.rst deleted file mode 100644 index b62eee3c5ee494..00000000000000 --- a/Misc/NEWS.d/next/Library/2017-08-30-20-27-00.bpo-31292.dKIaZb.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``setup.py check --restructuredtext`` for -files containing ``include`` directives. diff --git a/Misc/NEWS.d/next/Library/2018-04-06-11-06-23.bpo-31310.eq9ky0.rst b/Misc/NEWS.d/next/Library/2018-04-06-11-06-23.bpo-31310.eq9ky0.rst deleted file mode 100644 index 32ebf4efb74bdb..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-06-11-06-23.bpo-31310.eq9ky0.rst +++ /dev/null @@ -1 +0,0 @@ -Fix the multiprocessing.semaphore_tracker so it is reused by child processes diff --git a/Misc/NEWS.d/next/Library/2018-04-11-11-41-52.bpo-33291.-xLGf8.rst b/Misc/NEWS.d/next/Library/2018-04-11-11-41-52.bpo-33291.-xLGf8.rst deleted file mode 100644 index 1ffb9ddccbb0f1..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-11-11-41-52.bpo-33291.-xLGf8.rst +++ /dev/null @@ -1,3 +0,0 @@ -Do not raise AttributeError when calling the inspect functions -isgeneratorfunction, iscoroutinefunction, isasyncgenfunction on a method -created from an arbitrary callable. Instead, return False. diff --git a/Misc/NEWS.d/next/Library/2018-05-29-18-34-53.bpo-33530._4Q_bi.rst b/Misc/NEWS.d/next/Library/2018-05-29-18-34-53.bpo-33530._4Q_bi.rst deleted file mode 100644 index 747219b1bfb899..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-29-18-34-53.bpo-33530._4Q_bi.rst +++ /dev/null @@ -1,3 +0,0 @@ -Implemented Happy Eyeballs in `asyncio.create_connection()`. Added two new -arguments, *happy_eyeballs_delay* and *interleave*, -to specify Happy Eyeballs behavior. diff --git a/Misc/NEWS.d/next/Library/2018-07-18-11-25-34.bpo-34139.tKbmW7.rst b/Misc/NEWS.d/next/Library/2018-07-18-11-25-34.bpo-34139.tKbmW7.rst deleted file mode 100644 index 44284a72ad8a6a..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-07-18-11-25-34.bpo-34139.tKbmW7.rst +++ /dev/null @@ -1 +0,0 @@ -Remove stale unix datagram socket before binding diff --git a/Misc/NEWS.d/next/Library/2018-07-30-12-00-15.bpo-31658._bx7a_.rst b/Misc/NEWS.d/next/Library/2018-07-30-12-00-15.bpo-31658._bx7a_.rst deleted file mode 100644 index 8b35060fd73740..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-07-30-12-00-15.bpo-31658._bx7a_.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`xml.sax.parse` now supports :term:`path-like `. -Patch by Mickaël Schoentgen. diff --git a/Misc/NEWS.d/next/Library/2018-10-05-16-01-00.bpo-34547.abbaa.rst b/Misc/NEWS.d/next/Library/2018-10-05-16-01-00.bpo-34547.abbaa.rst deleted file mode 100644 index 7b63c05ed2bed0..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-10-05-16-01-00.bpo-34547.abbaa.rst +++ /dev/null @@ -1,2 +0,0 @@ -:class:`wsgiref.handlers.BaseHandler` now handles abrupt client connection -terminations gracefully. Patch by Petter Strandmark. diff --git a/Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst b/Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst deleted file mode 100644 index 45a0729506e392..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-10-27-11-54-12.bpo-35082.HDj1nr.rst +++ /dev/null @@ -1,2 +0,0 @@ -Don't return deleted attributes when calling dir on a -:class:`unittest.mock.Mock`. diff --git a/Misc/NEWS.d/next/Library/2018-11-07-23-44-25.bpo-25451.re_8db.rst b/Misc/NEWS.d/next/Library/2018-11-07-23-44-25.bpo-25451.re_8db.rst deleted file mode 100644 index e0a9ea0c1fbd85..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-11-07-23-44-25.bpo-25451.re_8db.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add transparency methods to :class:`tkinter.PhotoImage`. Patch by Zackery -Spytz. diff --git a/Misc/NEWS.d/next/Library/2018-12-05-09-55-05.bpo-35416.XALKZG.rst b/Misc/NEWS.d/next/Library/2018-12-05-09-55-05.bpo-35416.XALKZG.rst deleted file mode 100644 index 66603bcd31adf3..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-12-05-09-55-05.bpo-35416.XALKZG.rst +++ /dev/null @@ -1 +0,0 @@ -Fix potential resource warnings in distutils. Patch by Mickaël Schoentgen. diff --git a/Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst b/Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst deleted file mode 100644 index 975cc9c0454c70..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-01-18-23-10-10.bpo-23078.l4dFoj.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add support for :func:`classmethod` and :func:`staticmethod` to -:func:`unittest.mock.create_autospec`. Initial patch by Felipe Ochoa. diff --git a/Misc/NEWS.d/next/Library/2019-02-07-20-25-39.bpo-35934.QmfNmY.rst b/Misc/NEWS.d/next/Library/2019-02-07-20-25-39.bpo-35934.QmfNmY.rst deleted file mode 100644 index 0601ac915fc84c..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-02-07-20-25-39.bpo-35934.QmfNmY.rst +++ /dev/null @@ -1,4 +0,0 @@ -Added :meth:`~socket.create_server()` and :meth:`~socket.has_dualstack_ipv6()` -convenience functions to automate the necessary tasks usually involved when -creating a server socket, including accepting both IPv4 and IPv6 connections -on the same socket. (Contributed by Giampaolo Rodola in :issue:`17561`.) diff --git a/Misc/NEWS.d/next/Library/2019-02-13-18-56-22.bpo-17396.oKRkrD.rst b/Misc/NEWS.d/next/Library/2019-02-13-18-56-22.bpo-17396.oKRkrD.rst deleted file mode 100644 index 50596cf9e43f09..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-02-13-18-56-22.bpo-17396.oKRkrD.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`modulefinder` no longer crashes when encountering syntax errors in followed imports. -Patch by Brandt Bucher. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-02-13-18-56-27.bpo-35376.UFhYLj.rst b/Misc/NEWS.d/next/Library/2019-02-13-18-56-27.bpo-35376.UFhYLj.rst deleted file mode 100644 index a9bf8c9a636ccb..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-02-13-18-56-27.bpo-35376.UFhYLj.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`modulefinder` correctly handles modules that have the same name as a bad package. -Patch by Brandt Bucher. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-02-16-22-19-32.bpo-35936.Ay5WtD.rst b/Misc/NEWS.d/next/Library/2019-02-16-22-19-32.bpo-35936.Ay5WtD.rst deleted file mode 100644 index 55a028ec8349cd..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-02-16-22-19-32.bpo-35936.Ay5WtD.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`modulefinder` no longer depends on the deprecated :mod:`imp` module, and the initializer for :class:`modulefinder.ModuleFinder` now has immutable default arguments. -Patch by Brandt Bucher. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-02-17-12-55-51.bpo-36004.hCt_KK.rst b/Misc/NEWS.d/next/Library/2019-02-17-12-55-51.bpo-36004.hCt_KK.rst deleted file mode 100644 index d2162be82f706c..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-02-17-12-55-51.bpo-36004.hCt_KK.rst +++ /dev/null @@ -1,4 +0,0 @@ -Added new alternate constructors :meth:`datetime.date.fromisocalendar` and -:meth:`datetime.datetime.fromisocalendar`, which construct date objects from -ISO year, week number and weekday; these are the inverse of each class's -``isocalendar`` method. Patch by Paul Ganssle. diff --git a/Misc/NEWS.d/next/Library/2019-03-07-20-02-18.bpo-36227.i2Z1XR.rst b/Misc/NEWS.d/next/Library/2019-03-07-20-02-18.bpo-36227.i2Z1XR.rst deleted file mode 100644 index 3b5b6cda09c800..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-07-20-02-18.bpo-36227.i2Z1XR.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added support for keyword arguments `default_namespace` and `xml_declaration` in functions -ElementTree.tostring() and ElementTree.tostringlist(). diff --git a/Misc/NEWS.d/next/Library/2019-03-13-16-48-42.bpo-31904.9sjd38.rst b/Misc/NEWS.d/next/Library/2019-03-13-16-48-42.bpo-31904.9sjd38.rst deleted file mode 100644 index 6fb5c89d41a52e..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-13-16-48-42.bpo-31904.9sjd38.rst +++ /dev/null @@ -1 +0,0 @@ -Add time module support and fix test_time faiures for VxWorks. diff --git a/Misc/NEWS.d/next/Library/2019-03-18-16-16-55.bpo-36348.E0w_US.rst b/Misc/NEWS.d/next/Library/2019-03-18-16-16-55.bpo-36348.E0w_US.rst deleted file mode 100644 index 2320b4c05b5367..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-18-16-16-55.bpo-36348.E0w_US.rst +++ /dev/null @@ -1,2 +0,0 @@ -The :meth:`imap.IMAP4.logout` method no longer ignores silently arbitrary -exceptions. diff --git a/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst b/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst deleted file mode 100644 index 8d1f9d940cc61c..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-20-15-13-18.bpo-36366.n0eav_.rst +++ /dev/null @@ -1,4 +0,0 @@ -Calling ``stop()`` on an unstarted or stopped :func:`unittest.mock.patch` -object will now return `None` instead of raising :exc:`RuntimeError`, -making the method idempotent. -Patch by Karthikeyan Singaravelan. diff --git a/Misc/NEWS.d/next/Library/2019-03-22-13-47-52.bpo-36326.WCnEI5.rst b/Misc/NEWS.d/next/Library/2019-03-22-13-47-52.bpo-36326.WCnEI5.rst deleted file mode 100644 index e458a7024da5cd..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-22-13-47-52.bpo-36326.WCnEI5.rst +++ /dev/null @@ -1,2 +0,0 @@ -inspect.getdoc() can now find docstrings for member objects when __slots__ -is a dictionary. diff --git a/Misc/NEWS.d/next/Library/2019-03-23-17-16-15.bpo-36407.LG3aC4.rst b/Misc/NEWS.d/next/Library/2019-03-23-17-16-15.bpo-36407.LG3aC4.rst deleted file mode 100644 index 3873329a51e11e..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-23-17-16-15.bpo-36407.LG3aC4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed wrong indentation writing for CDATA section in xml.dom.minidom. -Patch by Vladimir Surjaninov. diff --git a/Misc/NEWS.d/next/Library/2019-03-26-14-20-59.bpo-36434.PTdidw.rst b/Misc/NEWS.d/next/Library/2019-03-26-14-20-59.bpo-36434.PTdidw.rst deleted file mode 100644 index 6e3e050c89bdb8..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-26-14-20-59.bpo-36434.PTdidw.rst +++ /dev/null @@ -1 +0,0 @@ -Errors during writing to a ZIP file no longer prevent to properly close it. diff --git a/Misc/NEWS.d/next/Library/2019-03-27-02-09-22.bpo-36385.we2F45.rst b/Misc/NEWS.d/next/Library/2019-03-27-02-09-22.bpo-36385.we2F45.rst deleted file mode 100644 index 26f6dd7d5f47e2..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-27-02-09-22.bpo-36385.we2F45.rst +++ /dev/null @@ -1 +0,0 @@ -Stop rejecting IPv4 octets for being ambiguously octal. Leading zeros are ignored, and no longer are assumed to specify octal octets. Octets are always decimal numbers. Octets must still be no more than three digits, including leading zeroes. diff --git a/Misc/NEWS.d/next/Library/2019-03-28-21-17-08.bpo-30427.lxzvbw.rst b/Misc/NEWS.d/next/Library/2019-03-28-21-17-08.bpo-30427.lxzvbw.rst deleted file mode 100644 index 80e7c4a15e5272..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-28-21-17-08.bpo-30427.lxzvbw.rst +++ /dev/null @@ -1,2 +0,0 @@ -``os.path.normcase()`` relies on ``os.fspath()`` to check the type of its argument. Redundant checks have been removed from its ``posixpath.normcase()`` and ``ntpath.normcase()`` implementations. -Patch by Wolfgang Maier. diff --git a/Misc/NEWS.d/next/Library/2019-03-31-01-18-52.bpo-27181.LVUWcc.rst b/Misc/NEWS.d/next/Library/2019-03-31-01-18-52.bpo-27181.LVUWcc.rst deleted file mode 100644 index 3ce41c55798232..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-31-01-18-52.bpo-27181.LVUWcc.rst +++ /dev/null @@ -1 +0,0 @@ -Add statistics.geometric_mean(). diff --git a/Misc/NEWS.d/next/Library/2019-03-31-10-21-54.bpo-36492.f7vyUs.rst b/Misc/NEWS.d/next/Library/2019-03-31-10-21-54.bpo-36492.f7vyUs.rst deleted file mode 100644 index f294bd27b25d9b..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-31-10-21-54.bpo-36492.f7vyUs.rst +++ /dev/null @@ -1,5 +0,0 @@ -Deprecated passing required arguments like *func* as keyword arguments -in functions which should accept arbitrary keyword arguments and pass them -to other function. Arbitrary keyword arguments (even with names "self" and -"func") can now be passed to these functions if the required arguments are -passed as positional arguments. diff --git a/Misc/NEWS.d/next/Library/2019-04-03-20-46-47.bpo-36522.g5x3By.rst b/Misc/NEWS.d/next/Library/2019-04-03-20-46-47.bpo-36522.g5x3By.rst deleted file mode 100644 index 7869526b71c7ba..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-03-20-46-47.bpo-36522.g5x3By.rst +++ /dev/null @@ -1 +0,0 @@ -If *debuglevel* is set to >0 in :mod:`http.client`, print all values for headers with multiple values for the same header name. Patch by Matt Houglum. diff --git a/Misc/NEWS.d/next/Library/2019-04-05-21-29-53.bpo-36050.x9DRKE.rst b/Misc/NEWS.d/next/Library/2019-04-05-21-29-53.bpo-36050.x9DRKE.rst deleted file mode 100644 index 92318f877b6084..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-05-21-29-53.bpo-36050.x9DRKE.rst +++ /dev/null @@ -1,2 +0,0 @@ -Optimized ``http.client.HTTPResponse.read()`` for large response. Patch by -Inada Naoki. diff --git a/Misc/NEWS.d/next/Library/2019-04-06-14-23-00.bpo-36546.YXjbyY.rst b/Misc/NEWS.d/next/Library/2019-04-06-14-23-00.bpo-36546.YXjbyY.rst deleted file mode 100644 index c69aadf3b69e8e..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-06-14-23-00.bpo-36546.YXjbyY.rst +++ /dev/null @@ -1 +0,0 @@ -Add statistics.quantiles() diff --git a/Misc/NEWS.d/next/Library/2019-04-06-20-25-25.bpo-36232.SClmhb.rst b/Misc/NEWS.d/next/Library/2019-04-06-20-25-25.bpo-36232.SClmhb.rst deleted file mode 100644 index 25290be7c9c5ac..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-06-20-25-25.bpo-36232.SClmhb.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve error message when trying to open existing DBM database that -actually doesn't exist. Patch by Marco Rougeth. diff --git a/Misc/NEWS.d/next/Library/2019-04-08-14-41-22.bpo-34373.lEAl_-.rst b/Misc/NEWS.d/next/Library/2019-04-08-14-41-22.bpo-34373.lEAl_-.rst deleted file mode 100644 index 19b38fef64141f..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-08-14-41-22.bpo-34373.lEAl_-.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :func:`time.mktime` error handling on AIX for year before 1970. diff --git a/Misc/NEWS.d/next/Library/2019-04-09-04-08-46.bpo-17561.hOhVnh.rst b/Misc/NEWS.d/next/Library/2019-04-09-04-08-46.bpo-17561.hOhVnh.rst deleted file mode 100644 index e281c22305b9a9..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-09-04-08-46.bpo-17561.hOhVnh.rst +++ /dev/null @@ -1 +0,0 @@ -Set backlog=None as the default for socket.create_server. diff --git a/Misc/NEWS.d/next/Library/2019-04-09-12-02-35.bpo-36559.LbDRrw.rst b/Misc/NEWS.d/next/Library/2019-04-09-12-02-35.bpo-36559.LbDRrw.rst deleted file mode 100644 index 2f6ee785e7de87..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-09-12-02-35.bpo-36559.LbDRrw.rst +++ /dev/null @@ -1,2 +0,0 @@ -The random module now prefers the lean internal _sha512 module over hashlib -for seed(version=2) to optimize import time. diff --git a/Misc/NEWS.d/next/Library/2019-04-09-14-46-28.bpo-33461.SYJM-E.rst b/Misc/NEWS.d/next/Library/2019-04-09-14-46-28.bpo-33461.SYJM-E.rst deleted file mode 100644 index 12b3bceaf8e3c0..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-09-14-46-28.bpo-33461.SYJM-E.rst +++ /dev/null @@ -1,2 +0,0 @@ -``json.loads`` now emits ``DeprecationWarning`` when ``encoding`` option is -specified. Patch by Matthias Bussonnier. diff --git a/Misc/NEWS.d/next/Library/2019-04-09-22-40-52.bpo-36575.Vg_p92.rst b/Misc/NEWS.d/next/Library/2019-04-09-22-40-52.bpo-36575.Vg_p92.rst deleted file mode 100644 index 3e305f132c0775..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-09-22-40-52.bpo-36575.Vg_p92.rst +++ /dev/null @@ -1,4 +0,0 @@ -The ``_lsprof`` module now uses internal timer same to ``time.perf_counter()`` by default. -``gettimeofday(2)`` was used on Unix. New timer has better resolution on most Unix -platforms and timings are no longer impacted by system clock updates since ``perf_counter()`` -is monotonic. Patch by Inada Naoki. diff --git a/Misc/NEWS.d/next/Library/2019-04-11-16-09-42.bpo-18748.QW7upB.rst b/Misc/NEWS.d/next/Library/2019-04-11-16-09-42.bpo-18748.QW7upB.rst deleted file mode 100644 index 2e0cef8d181876..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-11-16-09-42.bpo-18748.QW7upB.rst +++ /dev/null @@ -1,3 +0,0 @@ -In development mode (:option:`-X` ``dev``) and in debug build, the -:class:`io.IOBase` destructor now logs ``close()`` exceptions. These exceptions -are silent by default in release mode. diff --git a/Misc/NEWS.d/next/Library/2019-04-11-22-11-24.bpo-36598.hfzDUl.rst b/Misc/NEWS.d/next/Library/2019-04-11-22-11-24.bpo-36598.hfzDUl.rst deleted file mode 100644 index 2a798020913695..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-11-22-11-24.bpo-36598.hfzDUl.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``isinstance`` check for Mock objects with spec when the code is -executed under tracing. Patch by Karthikeyan Singaravelan. diff --git a/Misc/NEWS.d/next/Library/2019-04-12-13-52-15.bpo-36613.hqT1qn.rst b/Misc/NEWS.d/next/Library/2019-04-12-13-52-15.bpo-36613.hqT1qn.rst deleted file mode 100644 index 8828dccad69c51..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-12-13-52-15.bpo-36613.hqT1qn.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :mod:`asyncio` wait() not removing callback if exception \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-04-13-23-42-33.bpo-30485.JHhjJS.rst b/Misc/NEWS.d/next/Library/2019-04-13-23-42-33.bpo-30485.JHhjJS.rst deleted file mode 100644 index 900edf8c755355..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-13-23-42-33.bpo-30485.JHhjJS.rst +++ /dev/null @@ -1,3 +0,0 @@ -Path expressions in xml.etree.ElementTree can now avoid explicit namespace -prefixes for tags (or the "{namespace}tag" notation) by passing a default -namespace with an empty string prefix. diff --git a/Misc/NEWS.d/next/Library/2019-04-15-12-22-09.bpo-25430.7_8kqc.rst b/Misc/NEWS.d/next/Library/2019-04-15-12-22-09.bpo-25430.7_8kqc.rst deleted file mode 100644 index 922bdef56ec31e..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-15-12-22-09.bpo-25430.7_8kqc.rst +++ /dev/null @@ -1 +0,0 @@ -improve performance of ``IPNetwork.__contains__()`` \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst b/Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst deleted file mode 100644 index d84f63bf7b838b..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-16-17-50-39.bpo-35755.Fg4EXb.rst +++ /dev/null @@ -1,5 +0,0 @@ -:func:`shutil.which` and :func:`distutils.spawn.find_executable` now use -``os.confstr("CS_PATH")`` if available instead of :data:`os.defpath`, if the -``PATH`` environment variable is not set. Moreover, don't use -``os.confstr("CS_PATH")`` nor :data:`os.defpath` if the ``PATH`` environment -variable is set to an empty string. diff --git a/Misc/NEWS.d/next/Library/2019-04-18-16-10-29.bpo-28552.MW1TLt.rst b/Misc/NEWS.d/next/Library/2019-04-18-16-10-29.bpo-28552.MW1TLt.rst deleted file mode 100644 index 2aa30c98c4524a..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-18-16-10-29.bpo-28552.MW1TLt.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix :mod:`distutils.sysconfig` if :data:`sys.executable` is ``None`` or an -empty string: use :func:`os.getcwd` to initialize ``project_base``. Fix -also the distutils build command: don't use :data:`sys.executable` if it is -``None`` or an empty string. diff --git a/Misc/NEWS.d/next/Library/2019-04-19-15-29-55.bpo-36650._EVdrz.rst b/Misc/NEWS.d/next/Library/2019-04-19-15-29-55.bpo-36650._EVdrz.rst deleted file mode 100644 index de10575fc2720e..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-19-15-29-55.bpo-36650._EVdrz.rst +++ /dev/null @@ -1,4 +0,0 @@ -The C version of functools.lru_cache() was treating calls with an empty -``**kwargs`` dictionary as being distinct from calls with no keywords at all. -This did not result in an incorrect answer, but it did trigger an unexpected -cache miss. diff --git a/Misc/NEWS.d/next/Library/2019-04-20-09-50-32.bpo-36673.XF4Egb.rst b/Misc/NEWS.d/next/Library/2019-04-20-09-50-32.bpo-36673.XF4Egb.rst deleted file mode 100644 index 76bf914e22b196..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-20-09-50-32.bpo-36673.XF4Egb.rst +++ /dev/null @@ -1,3 +0,0 @@ -The TreeBuilder and XMLPullParser in xml.etree.ElementTree gained support -for parsing comments and processing instructions. -Patch by Stefan Behnel. diff --git a/Misc/NEWS.d/next/Library/2019-04-20-13-10-34.bpo-36676.XF4Egb.rst b/Misc/NEWS.d/next/Library/2019-04-20-13-10-34.bpo-36676.XF4Egb.rst deleted file mode 100644 index e0bede81eec108..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-20-13-10-34.bpo-36676.XF4Egb.rst +++ /dev/null @@ -1,3 +0,0 @@ -The XMLParser() in xml.etree.ElementTree provides namespace prefix context to the -parser target if it defines the callback methods "start_ns()" and/or "end_ns()". -Patch by Stefan Behnel. diff --git a/Misc/NEWS.d/next/Library/2019-04-24-17-08-45.bpo-36669.X4g0fu.rst b/Misc/NEWS.d/next/Library/2019-04-24-17-08-45.bpo-36669.X4g0fu.rst deleted file mode 100644 index 53bdefee12f2c5..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-24-17-08-45.bpo-36669.X4g0fu.rst +++ /dev/null @@ -1 +0,0 @@ -Add missing matrix multiplication operator support to weakref.proxy. diff --git a/Misc/NEWS.d/next/Library/2019-04-26-10-10-34.bpo-13611.XEF4bg.rst b/Misc/NEWS.d/next/Library/2019-04-26-10-10-34.bpo-13611.XEF4bg.rst deleted file mode 100644 index d01decb9617ab5..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-26-10-10-34.bpo-13611.XEF4bg.rst +++ /dev/null @@ -1,2 +0,0 @@ -The xml.etree.ElementTree packages gained support for C14N 2.0 serialisation. -Patch by Stefan Behnel. diff --git a/Misc/NEWS.d/next/Library/2019-04-26-17-14-20.bpo-36734.p2MaiN.rst b/Misc/NEWS.d/next/Library/2019-04-26-17-14-20.bpo-36734.p2MaiN.rst deleted file mode 100644 index 09341990a63d17..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-26-17-14-20.bpo-36734.p2MaiN.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix compilation of ``faulthandler.c`` on HP-UX. Initialize ``stack_t -current_stack`` to zero using ``memset()``. diff --git a/Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst b/Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst deleted file mode 100644 index 4501819ac360e6..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-27-21-09-33.bpo-1613500.Ogp4P0.rst +++ /dev/null @@ -1,3 +0,0 @@ -:class:`fileinput.FileInput` now uses the input file mode to correctly set -the output file mode (previously it was hardcoded to ``'w'``) when -``inplace=True`` is passed to its constructor. diff --git a/Misc/NEWS.d/next/Library/2019-04-28-01-52-39.bpo-26978.Lpm-SI.rst b/Misc/NEWS.d/next/Library/2019-04-28-01-52-39.bpo-26978.Lpm-SI.rst deleted file mode 100644 index 0b14920ad45a81..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-28-01-52-39.bpo-26978.Lpm-SI.rst +++ /dev/null @@ -1,2 +0,0 @@ -`pathlib.path.link_to()` is now implemented. It creates a hard link pointing -to a path. diff --git a/Misc/NEWS.d/next/Library/2019-04-28-15-01-29.bpo-28238.gdk38f.rst b/Misc/NEWS.d/next/Library/2019-04-28-15-01-29.bpo-28238.gdk38f.rst deleted file mode 100644 index 62003a3d26e6f2..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-28-15-01-29.bpo-28238.gdk38f.rst +++ /dev/null @@ -1,3 +0,0 @@ -The ``.find*()`` methods of xml.etree.ElementTree can now search for -wildcards like ``{*}tag`` and ``{ns}*`` that match a tag in any namespace -or all tags in a namespace. Patch by Stefan Behnel. diff --git a/Misc/NEWS.d/next/Library/2019-04-29-11-47-06.bpo-35952.3uNuyo.rst b/Misc/NEWS.d/next/Library/2019-04-29-11-47-06.bpo-35952.3uNuyo.rst deleted file mode 100644 index 9aeea90d8162b1..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-04-29-11-47-06.bpo-35952.3uNuyo.rst +++ /dev/null @@ -1 +0,0 @@ -Fix pythoninfo when the compiler is missing. diff --git a/Misc/NEWS.d/next/Security/2019-01-17-10-03-48.bpo-35755.GmllIs.rst b/Misc/NEWS.d/next/Security/2019-01-17-10-03-48.bpo-35755.GmllIs.rst deleted file mode 100644 index 959aafd73449e1..00000000000000 --- a/Misc/NEWS.d/next/Security/2019-01-17-10-03-48.bpo-35755.GmllIs.rst +++ /dev/null @@ -1,5 +0,0 @@ -:func:`shutil.which` now uses ``os.confstr("CS_PATH")`` if available and if the -:envvar:`PATH` environment variable is not set. Remove also the current -directory from :data:`posixpath.defpath`. On Unix, :func:`shutil.which` and the -:mod:`subprocess` module no longer search the executable in the current -directory if the :envvar:`PATH` environment variable is not set. diff --git a/Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-30458.51E-DA.rst b/Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-30458.51E-DA.rst deleted file mode 100644 index ed8027fb4d6420..00000000000000 --- a/Misc/NEWS.d/next/Security/2019-04-10-08-53-30.bpo-30458.51E-DA.rst +++ /dev/null @@ -1 +0,0 @@ -Address CVE-2019-9740 by disallowing URL paths with embedded whitespace or control characters through into the underlying http client request. Such potentially malicious header injection URLs now cause an http.client.InvalidURL exception to be raised. diff --git a/Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst b/Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst deleted file mode 100644 index d729ed2f3cd507..00000000000000 --- a/Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst +++ /dev/null @@ -1 +0,0 @@ -Fixes mishandling of pre-normalization characters in urlsplit(). diff --git a/Misc/NEWS.d/next/Tests/2019-03-18-10-47-45.bpo-36341.UXlY0P.rst b/Misc/NEWS.d/next/Tests/2019-03-18-10-47-45.bpo-36341.UXlY0P.rst deleted file mode 100644 index b76447d6cf97fd..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-03-18-10-47-45.bpo-36341.UXlY0P.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix tests that may fail with PermissionError upon calling bind() on AF_UNIX -sockets. diff --git a/Misc/NEWS.d/next/Tests/2019-03-19-17-39-25.bpo-31904.QxhhRx.rst b/Misc/NEWS.d/next/Tests/2019-03-19-17-39-25.bpo-31904.QxhhRx.rst deleted file mode 100644 index 95771508619e5b..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-03-19-17-39-25.bpo-31904.QxhhRx.rst +++ /dev/null @@ -1 +0,0 @@ -Fix test_utf8_mode on VxWorks: Python always use UTF-8 on VxWorks. diff --git a/Misc/NEWS.d/next/Tests/2019-03-26-13-49-21.bpo-36436.yAtN0V.rst b/Misc/NEWS.d/next/Tests/2019-03-26-13-49-21.bpo-36436.yAtN0V.rst deleted file mode 100644 index efc9296ad622c2..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-03-26-13-49-21.bpo-36436.yAtN0V.rst +++ /dev/null @@ -1 +0,0 @@ -Fix ``_testcapi.pymem_buffer_overflow()``: handle memory allocation failure. diff --git a/Misc/NEWS.d/next/Tests/2019-04-01-16-06-36.bpo-31904.peaceF.rst b/Misc/NEWS.d/next/Tests/2019-04-01-16-06-36.bpo-31904.peaceF.rst deleted file mode 100644 index 6297717e0fc68e..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-01-16-06-36.bpo-31904.peaceF.rst +++ /dev/null @@ -1 +0,0 @@ -Fix test_tabnanny on VxWorks: adjust ENOENT error message. diff --git a/Misc/NEWS.d/next/Tests/2019-04-08-09-24-36.bpo-31904.ab03ea.rst b/Misc/NEWS.d/next/Tests/2019-04-08-09-24-36.bpo-31904.ab03ea.rst deleted file mode 100644 index 2b361011abaed6..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-08-09-24-36.bpo-31904.ab03ea.rst +++ /dev/null @@ -1 +0,0 @@ -Port test_resource to VxWorks: skip tests cases setting RLIMIT_FSIZE and RLIMIT_CPU. diff --git a/Misc/NEWS.d/next/Tests/2019-04-08-19-01-21.bpo-36565.2bxgtU.rst b/Misc/NEWS.d/next/Tests/2019-04-08-19-01-21.bpo-36565.2bxgtU.rst deleted file mode 100644 index 8a14d08ba88f75..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-08-19-01-21.bpo-36565.2bxgtU.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix reference hunting (``python3 -m test -R 3:3``) when Python has no -built-in abc module. diff --git a/Misc/NEWS.d/next/Tests/2019-04-09-14-08-02.bpo-36560._ejeOr.rst b/Misc/NEWS.d/next/Tests/2019-04-09-14-08-02.bpo-36560._ejeOr.rst deleted file mode 100644 index ad0f681ae877d9..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-09-14-08-02.bpo-36560._ejeOr.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix reference leak hunting in regrtest: compute also deltas (of reference -count, allocated memory blocks, file descriptor count) during warmup, to -ensure that everything is initialized before starting to hunt reference -leaks. diff --git a/Misc/NEWS.d/next/Tests/2019-04-12-12-44-42.bpo-36611.UtorXL.rst b/Misc/NEWS.d/next/Tests/2019-04-12-12-44-42.bpo-36611.UtorXL.rst deleted file mode 100644 index e4da7f1099f8b0..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-12-12-44-42.bpo-36611.UtorXL.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``test_sys.test_getallocatedblocks()`` when :mod:`tracemalloc` is -enabled. diff --git a/Misc/NEWS.d/next/Tests/2019-04-15-11-57-39.bpo-36629.ySnaL3.rst b/Misc/NEWS.d/next/Tests/2019-04-15-11-57-39.bpo-36629.ySnaL3.rst deleted file mode 100644 index 0837a233d58225..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-15-11-57-39.bpo-36629.ySnaL3.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``test_imap4_host_default_value()`` of ``test_imaplib``: catch also -:data:`errno.ENETUNREACH` error. diff --git a/Misc/NEWS.d/next/Tests/2019-04-15-16-55-49.bpo-36635.__FTq9.rst b/Misc/NEWS.d/next/Tests/2019-04-15-16-55-49.bpo-36635.__FTq9.rst deleted file mode 100644 index 855d1cb27764ca..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-15-16-55-49.bpo-36635.__FTq9.rst +++ /dev/null @@ -1 +0,0 @@ -Add a new :mod:`_testinternalcapi` module to test the internal C API. diff --git a/Misc/NEWS.d/next/Tests/2019-04-21-17-53-50.bpo-32424.Q4rBmn.rst b/Misc/NEWS.d/next/Tests/2019-04-21-17-53-50.bpo-32424.Q4rBmn.rst deleted file mode 100644 index f057d7e7730ecf..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-21-17-53-50.bpo-32424.Q4rBmn.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix typo in test_cyclic_gc() test for xml.etree.ElementTree. Patch by Gordon -P. Hemsley. diff --git a/Misc/NEWS.d/next/Tests/2019-04-21-17-55-18.bpo-32424.yDy49h.rst b/Misc/NEWS.d/next/Tests/2019-04-21-17-55-18.bpo-32424.yDy49h.rst deleted file mode 100644 index bb0839f7a31829..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-21-17-55-18.bpo-32424.yDy49h.rst +++ /dev/null @@ -1 +0,0 @@ -Improve test coverage for xml.etree.ElementTree. Patch by Gordon P. Hemsley. diff --git a/Misc/NEWS.d/next/Tests/2019-04-23-17-48-11.bpo-36454.0q4lQz.rst b/Misc/NEWS.d/next/Tests/2019-04-23-17-48-11.bpo-36454.0q4lQz.rst deleted file mode 100644 index 151c7ab0404026..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-23-17-48-11.bpo-36454.0q4lQz.rst +++ /dev/null @@ -1,3 +0,0 @@ -Change test_time.test_monotonic() to test only the lower bound of elapsed time -after a sleep command rather than the upper bound. This prevents unnecessary -test failures on slow buildbots. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2019-04-26-04-12-29.bpo-36725.B8-ghi.rst b/Misc/NEWS.d/next/Tests/2019-04-26-04-12-29.bpo-36725.B8-ghi.rst deleted file mode 100644 index b632c46d2b674f..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-26-04-12-29.bpo-36725.B8-ghi.rst +++ /dev/null @@ -1,3 +0,0 @@ -When using mulitprocessing mode (-jN), regrtest now better reports errors if -a worker process fails, and it exits immediately on a worker thread failure -or when interrupted. diff --git a/Misc/NEWS.d/next/Tests/2019-04-26-09-02-49.bpo-36719.ys2uqH.rst b/Misc/NEWS.d/next/Tests/2019-04-26-09-02-49.bpo-36719.ys2uqH.rst deleted file mode 100644 index 4b6ef76bc6d69a..00000000000000 --- a/Misc/NEWS.d/next/Tests/2019-04-26-09-02-49.bpo-36719.ys2uqH.rst +++ /dev/null @@ -1,4 +0,0 @@ -regrtest now always detects uncollectable objects. Previously, the check was -only enabled by ``--findleaks``. The check now also works with -``-jN/--multiprocess N``. ``--findleaks`` becomes a deprecated alias to -``--fail-env-changed``. diff --git a/Misc/NEWS.d/next/Tools-Demos/2019-04-30-14-30-29.bpo-14546.r38Y-6.rst b/Misc/NEWS.d/next/Tools-Demos/2019-04-30-14-30-29.bpo-14546.r38Y-6.rst deleted file mode 100644 index b8659b886af816..00000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2019-04-30-14-30-29.bpo-14546.r38Y-6.rst +++ /dev/null @@ -1 +0,0 @@ -Fix the argument handling in Tools/scripts/lll.py. diff --git a/Misc/NEWS.d/next/Windows/2017-10-04-12-40-45.bpo-31512.YQeBt2.rst b/Misc/NEWS.d/next/Windows/2017-10-04-12-40-45.bpo-31512.YQeBt2.rst deleted file mode 100644 index a6dbb5c0639b61..00000000000000 --- a/Misc/NEWS.d/next/Windows/2017-10-04-12-40-45.bpo-31512.YQeBt2.rst +++ /dev/null @@ -1,2 +0,0 @@ -With the Windows 10 Creators Update, non-elevated users can now create -symlinks as long as the computer has Developer Mode enabled. diff --git a/Misc/NEWS.d/next/Windows/2018-07-20-13-09-19.bpo-34060.v-z87j.rst b/Misc/NEWS.d/next/Windows/2018-07-20-13-09-19.bpo-34060.v-z87j.rst deleted file mode 100644 index b77d805b7f2aff..00000000000000 --- a/Misc/NEWS.d/next/Windows/2018-07-20-13-09-19.bpo-34060.v-z87j.rst +++ /dev/null @@ -1,2 +0,0 @@ -Report system load when running test suite on Windows. Patch by Ammar Askar. -Based on prior work by Jeremy Kloth. diff --git a/Misc/NEWS.d/next/Windows/2019-02-11-14-53-17.bpo-35947.9vI4hP.rst b/Misc/NEWS.d/next/Windows/2019-02-11-14-53-17.bpo-35947.9vI4hP.rst deleted file mode 100644 index ae3c5a751b46df..00000000000000 --- a/Misc/NEWS.d/next/Windows/2019-02-11-14-53-17.bpo-35947.9vI4hP.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added current version of libffi to cpython-source-deps. -Change _ctypes to use current version of libffi on Windows. diff --git a/Misc/NEWS.d/next/Windows/2019-03-05-18-09-43.bpo-29515.vwUTv0.rst b/Misc/NEWS.d/next/Windows/2019-03-05-18-09-43.bpo-29515.vwUTv0.rst deleted file mode 100644 index 2f3f0991d9a283..00000000000000 --- a/Misc/NEWS.d/next/Windows/2019-03-05-18-09-43.bpo-29515.vwUTv0.rst +++ /dev/null @@ -1,27 +0,0 @@ -Add the following socket module constants on Windows: -IPPROTO_AH -IPPROTO_CBT -IPPROTO_DSTOPTS -IPPROTO_EGP -IPPROTO_ESP -IPPROTO_FRAGMENT -IPPROTO_GGP -IPPROTO_HOPOPTS -IPPROTO_ICLFXBM -IPPROTO_ICMPV6 -IPPROTO_IDP -IPPROTO_IGMP -IPPROTO_IGP -IPPROTO_IPV4 -IPPROTO_IPV6 -IPPROTO_L2TP -IPPROTO_MAX -IPPROTO_ND -IPPROTO_NONE -IPPROTO_PGM -IPPROTO_PIM -IPPROTO_PUP -IPPROTO_RDP -IPPROTO_ROUTING -IPPROTO_SCTP -IPPROTO_ST diff --git a/Misc/NEWS.d/next/Windows/2019-03-16-10-24-58.bpo-36010.dttWfp.rst b/Misc/NEWS.d/next/Windows/2019-03-16-10-24-58.bpo-36010.dttWfp.rst deleted file mode 100644 index 32c57c49ae4176..00000000000000 --- a/Misc/NEWS.d/next/Windows/2019-03-16-10-24-58.bpo-36010.dttWfp.rst +++ /dev/null @@ -1 +0,0 @@ -Add the venv standard library module to the nuget distribution for Windows. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Windows/2019-03-18-11-44-49.bpo-36085.mLfxfc.rst b/Misc/NEWS.d/next/Windows/2019-03-18-11-44-49.bpo-36085.mLfxfc.rst deleted file mode 100644 index 41f23e655652ce..00000000000000 --- a/Misc/NEWS.d/next/Windows/2019-03-18-11-44-49.bpo-36085.mLfxfc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Enable better DLL resolution on Windows by using safe DLL search paths and -adding :func:`os.add_dll_directory`. diff --git a/Misc/NEWS.d/next/Windows/2019-03-26-11-46-15.bpo-36441.lYjGF1.rst b/Misc/NEWS.d/next/Windows/2019-03-26-11-46-15.bpo-36441.lYjGF1.rst deleted file mode 100644 index b27abff620983d..00000000000000 --- a/Misc/NEWS.d/next/Windows/2019-03-26-11-46-15.bpo-36441.lYjGF1.rst +++ /dev/null @@ -1 +0,0 @@ -Fixes creating a venv when debug binaries are installed. diff --git a/Misc/NEWS.d/next/Windows/2019-03-28-03-51-16.bpo-35941.UnlAEE.rst b/Misc/NEWS.d/next/Windows/2019-03-28-03-51-16.bpo-35941.UnlAEE.rst deleted file mode 100644 index cda654bfa5b9aa..00000000000000 --- a/Misc/NEWS.d/next/Windows/2019-03-28-03-51-16.bpo-35941.UnlAEE.rst +++ /dev/null @@ -1,3 +0,0 @@ -enum_certificates function of the ssl module now returns certificates from all available certificate stores inside windows in a query instead of returning only certificates from the system wide certificate store. -This includes certificates from these certificate stores: local machine, local machine enterprise, local machine group policy, current user, current user group policy, services, users. -ssl.enum_crls() function is changed in the same way to return all certificate revocation lists inside the windows certificate revocation list stores. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Windows/2019-04-02-10-11-18.bpo-36509.DdaM67.rst b/Misc/NEWS.d/next/Windows/2019-04-02-10-11-18.bpo-36509.DdaM67.rst deleted file mode 100644 index 722f7638a144c1..00000000000000 --- a/Misc/NEWS.d/next/Windows/2019-04-02-10-11-18.bpo-36509.DdaM67.rst +++ /dev/null @@ -1,4 +0,0 @@ -Added preset-iot layout for Windows IoT ARM containers. This layout doesn't -contain UI components like tkinter or IDLE. It also doesn't contain files to -support on-target builds since Windows ARM32 builds must be cross-compiled -when using MSVC. diff --git a/Misc/NEWS.d/next/Windows/2019-04-10-04-35-31.bpo-34144._KzB5z.rst b/Misc/NEWS.d/next/Windows/2019-04-10-04-35-31.bpo-34144._KzB5z.rst deleted file mode 100644 index 7b8ca821b40155..00000000000000 --- a/Misc/NEWS.d/next/Windows/2019-04-10-04-35-31.bpo-34144._KzB5z.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed activate.bat to correctly update codepage when chcp.com returns dots in output. -Patch by Lorenz Mende. diff --git a/Misc/NEWS.d/next/Windows/2019-04-17-11-39-24.bpo-36649.arbzIo.rst b/Misc/NEWS.d/next/Windows/2019-04-17-11-39-24.bpo-36649.arbzIo.rst deleted file mode 100644 index 8b44feb9f4c03c..00000000000000 --- a/Misc/NEWS.d/next/Windows/2019-04-17-11-39-24.bpo-36649.arbzIo.rst +++ /dev/null @@ -1 +0,0 @@ -Remove trailing spaces for registry keys when installed via the Store. diff --git a/Misc/NEWS.d/next/Windows/2019-04-22-16-59-20.bpo-35920.VSfGOI.rst b/Misc/NEWS.d/next/Windows/2019-04-22-16-59-20.bpo-35920.VSfGOI.rst deleted file mode 100644 index 455e82450eb2b5..00000000000000 --- a/Misc/NEWS.d/next/Windows/2019-04-22-16-59-20.bpo-35920.VSfGOI.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added platform.win32_edition() and platform.win32_is_iot(). Added support -for cross-compiling packages for Windows ARM32. Skip tests that are not -expected to work on Windows IoT Core ARM32. diff --git a/Misc/NEWS.d/next/macOS/2019-04-29-10-54-14.bpo-34602.Lrl2zU.rst b/Misc/NEWS.d/next/macOS/2019-04-29-10-54-14.bpo-34602.Lrl2zU.rst deleted file mode 100644 index 6f7ac881c82e2e..00000000000000 --- a/Misc/NEWS.d/next/macOS/2019-04-29-10-54-14.bpo-34602.Lrl2zU.rst +++ /dev/null @@ -1,3 +0,0 @@ -Avoid failures setting macOS stack resource limit with resource.setrlimit. -This reverts an earlier fix for bpo-18075 which forced a non-default stack -size when building the interpreter executable on macOS. diff --git a/README.rst b/README.rst index 0f0c32b7cf50d0..388543b8dcfc92 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.8.0 alpha 3 +This is Python version 3.8.0 alpha 4 ==================================== .. image:: https://travis-ci.org/python/cpython.svg?branch=master From 4920c093da8a3061faea62d62f2ddf0c5c443360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20M=C3=BChlbauer?= Date: Mon, 6 May 2019 20:32:42 +0200 Subject: [PATCH 185/212] bpo-30668: add missing word in license.rst (GH-13115) --- Doc/license.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/license.rst b/Doc/license.rst index d3733f53a116f4..bf2e4c522ce172 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -561,7 +561,7 @@ SipHash24 --------- The file :file:`Python/pyhash.c` contains Marek Majkowski' implementation of -Dan Bernstein's SipHash24 algorithm. The contains the following note:: +Dan Bernstein's SipHash24 algorithm. It contains the following note:: Copyright (c) 2013 Marek Majkowski From e9b49d1b4eec21f2da838db3360f6458cf648c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Wirtel?= Date: Mon, 6 May 2019 14:48:17 -0400 Subject: [PATCH 186/212] Clarify the download unit in the download section (GH-13122) --- Doc/tools/templates/download.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Doc/tools/templates/download.html b/Doc/tools/templates/download.html index 1a99b18bbb268e..d9364d6ced729f 100644 --- a/Doc/tools/templates/download.html +++ b/Doc/tools/templates/download.html @@ -12,8 +12,7 @@

    Download Python {{ release }} Documentation

    {% if last_updated %}

    Last updated on: {{ last_updated }}.

    {% endif %}

    To download an archive containing all the documents for this version of -Python in one of various formats, follow one of links in this table. The numbers -in the table are the size of the download files in megabytes.

    +Python in one of various formats, follow one of links in this table.

    From 3921b1cc34c2fc8b8b480c19a95ec306de710fdd Mon Sep 17 00:00:00 2001 From: Sebastian Koslowski Date: Mon, 6 May 2019 14:51:09 -0400 Subject: [PATCH 187/212] bpo-36275: enhance documentation for venv.create() (GH-13114) --- Doc/library/venv.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Doc/library/venv.rst b/Doc/library/venv.rst index 412808ad44866d..4f083a3181e7a9 100644 --- a/Doc/library/venv.rst +++ b/Doc/library/venv.rst @@ -234,14 +234,19 @@ creation according to their needs, the :class:`EnvBuilder` class. There is also a module-level convenience function: .. function:: create(env_dir, system_site_packages=False, clear=False, \ - symlinks=False, with_pip=False) + symlinks=False, with_pip=False, prompt=None) Create an :class:`EnvBuilder` with the given keyword arguments, and call its :meth:`~EnvBuilder.create` method with the *env_dir* argument. + .. versionadded:: 3.3 + .. versionchanged:: 3.4 Added the ``with_pip`` parameter + .. versionchanged:: 3.6 + Added the ``prompt`` parameter + An example of extending ``EnvBuilder`` -------------------------------------- From 964663089547ca110199e23867b46b07ff4be88c Mon Sep 17 00:00:00 2001 From: penguindustin Date: Mon, 6 May 2019 14:57:17 -0400 Subject: [PATCH 188/212] bpo-36766: Typos in docs and code comments (GH-13116) --- Doc/library/email.generator.rst | 2 +- Doc/library/pyclbr.rst | 2 +- Lib/idlelib/configdialog.py | 2 +- Lib/idlelib/help.html | 2 +- Lib/idlelib/help.py | 2 +- Lib/idlelib/idle_test/test_config.py | 2 +- Lib/lib2to3/pgen2/tokenize.py | 2 +- Lib/multiprocessing/resource_sharer.py | 2 +- Lib/pathlib.py | 2 +- Lib/platform.py | 2 +- Lib/pstats.py | 2 +- Lib/test/datetimetester.py | 2 +- Lib/test/pickletester.py | 2 +- Lib/test/support/__init__.py | 2 +- Lib/test/test_dataclasses.py | 2 +- Lib/test/test_importlib/test_lazy.py | 2 +- Lib/test/test_random.py | 2 +- Lib/test/test_ssl.py | 2 +- Lib/test/test_tools/test_i18n.py | 2 +- Lib/tokenize.py | 2 +- Lib/turtle.py | 2 +- Objects/object.c | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Doc/library/email.generator.rst b/Doc/library/email.generator.rst index fc535a3e4399ff..c09ae8cbc60410 100644 --- a/Doc/library/email.generator.rst +++ b/Doc/library/email.generator.rst @@ -188,7 +188,7 @@ to be using :class:`BytesGenerator`, and not :class:`Generator`. (This is required because strings cannot represent non-ASCII bytes.) Convert any bytes with the high bit set as needed using an ASCII-compatible :mailheader:`Content-Transfer-Encoding`. That is, - transform parts with non-ASCII :mailheader:`Cotnent-Transfer-Encoding` + transform parts with non-ASCII :mailheader:`Content-Transfer-Encoding` (:mailheader:`Content-Transfer-Encoding: 8bit`) to an ASCII compatible :mailheader:`Content-Transfer-Encoding`, and encode RFC-invalid non-ASCII bytes in headers using the MIME ``unknown-8bit`` character set, thus diff --git a/Doc/library/pyclbr.rst b/Doc/library/pyclbr.rst index a70c8df6a7b119..b80a2faed9b424 100644 --- a/Doc/library/pyclbr.rst +++ b/Doc/library/pyclbr.rst @@ -44,7 +44,7 @@ modules. .. versionadded:: 3.7 Descriptors for nested definitions. They are accessed through the - new children attibute. Each has a new parent attribute. + new children attribute. Each has a new parent attribute. The descriptors returned by these functions are instances of Function and Class classes. Users are not expected to create instances diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 31520a3b0d1e36..4aaec1321f7d68 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -2225,7 +2225,7 @@ def detach(self): 'General': ''' General: -AutoComplete: Popupwait is milleseconds to wait after key char, without +AutoComplete: Popupwait is milliseconds to wait after key char, without cursor movement, before popping up completion box. Key char is '.' after identifier or a '/' (or '\\' on Windows) within a string. diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 7e743e6d8137b5..ba44331e87b223 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -721,7 +721,7 @@

    Developing tkinter applicationsroot = tk.Tk() in standard Python and nothing appears. Enter the same in IDLE and a tk window appears. In standard Python, one must also enter root.update() to see the window. IDLE does the equivalent in the -background, about 20 times a second, which is about every 50 milleseconds. +background, about 20 times a second, which is about every 50 milliseconds. Next enter b = tk.Button(root, text='button'); b.pack(). Again, nothing visibly changes in standard Python until one enters root.update().

    Most tkinter programs run root.mainloop(), which usually does not diff --git a/Lib/idlelib/help.py b/Lib/idlelib/help.py index 0603ede822badf..652444a7f14937 100644 --- a/Lib/idlelib/help.py +++ b/Lib/idlelib/help.py @@ -2,7 +2,7 @@ Contents are subject to revision at any time, without notice. -Help => About IDLE: diplay About Idle dialog +Help => About IDLE: display About Idle dialog diff --git a/Lib/idlelib/idle_test/test_config.py b/Lib/idlelib/idle_test/test_config.py index 7e2c1fd2958cee..255210df7d9608 100644 --- a/Lib/idlelib/idle_test/test_config.py +++ b/Lib/idlelib/idle_test/test_config.py @@ -521,7 +521,7 @@ def test_get_current_keyset(self): def test_get_keyset(self): conf = self.mock_config() - # Conflic with key set, should be disable to '' + # Conflict with key set, should be disable to '' conf.defaultCfg['extensions'].add_section('Foobar') conf.defaultCfg['extensions'].add_section('Foobar_cfgBindings') conf.defaultCfg['extensions'].set('Foobar', 'enable', 'True') diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py index c07b34f7c6452d..279d322971da99 100644 --- a/Lib/lib2to3/pgen2/tokenize.py +++ b/Lib/lib2to3/pgen2/tokenize.py @@ -321,7 +321,7 @@ def untokenize(iterable): Round-trip invariant for full input: Untokenized source will match input source exactly - Round-trip invariant for limited intput: + Round-trip invariant for limited input: # Output text will tokenize the back to the input t1 = [tok[:2] for tok in generate_tokens(f.readline)] newcode = untokenize(t1) diff --git a/Lib/multiprocessing/resource_sharer.py b/Lib/multiprocessing/resource_sharer.py index 730b2aa17bdf0b..8d5c9900f69fed 100644 --- a/Lib/multiprocessing/resource_sharer.py +++ b/Lib/multiprocessing/resource_sharer.py @@ -59,7 +59,7 @@ def detach(self): class _ResourceSharer(object): - '''Manager for resouces using background thread.''' + '''Manager for resources using background thread.''' def __init__(self): self._key = 0 self._cache = {} diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 1ba98b19e83344..952cd94921e4b7 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -34,7 +34,7 @@ # Internals # -# EBADF - guard agains macOS `stat` throwing EBADF +# EBADF - guard against macOS `stat` throwing EBADF _IGNORED_ERROS = (ENOENT, ENOTDIR, EBADF) _IGNORED_WINERRORS = ( diff --git a/Lib/platform.py b/Lib/platform.py index 9f7bd95980a15c..6fbb7b08c598e3 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -72,7 +72,7 @@ # type information # 0.4.0 - added win32_ver() and modified the platform() output for WinXX # 0.3.4 - fixed a bug in _follow_symlinks() -# 0.3.3 - fixed popen() and "file" command invokation bugs +# 0.3.3 - fixed popen() and "file" command invocation bugs # 0.3.2 - added architecture() API and support for it in platform() # 0.3.1 - fixed syscmd_ver() RE to support Windows NT # 0.3.0 - added system alias support diff --git a/Lib/pstats.py b/Lib/pstats.py index ded5ae59f7da21..b7649ebc6f1c65 100644 --- a/Lib/pstats.py +++ b/Lib/pstats.py @@ -509,7 +509,7 @@ def func_std_string(func_name): # match what old profile produced return "%s:%d(%s)" % func_name #************************************************************************** -# The following functions combine statists for pairs functions. +# The following functions combine statistics for pairs functions. # The bulk of the processing involves correctly handling "call" lists, # such as callers and callees. #************************************************************************** diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 9fe32ebc5b395f..af0047fafd8770 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -3483,7 +3483,7 @@ def utcoffset(self, t): self.assertEqual(got, expected) # However, if they're different members, uctoffset is not ignored. - # Note that a time can't actually have an operand-depedent offset, + # Note that a time can't actually have an operand-dependent offset, # though (and time.utcoffset() passes None to tzinfo.utcoffset()), # so skip this test for time. if cls is not time: diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index 8f687c49e69049..bb8e6ce0964fc4 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -2222,7 +2222,7 @@ def remove_frames(pickled, keep_frame=None): frame_size = self.FRAME_SIZE_TARGET num_frames = 20 - # Large byte objects (dict values) intermitted with small objects + # Large byte objects (dict values) intermittent with small objects # (dict keys) obj = {i: bytes([i]) * frame_size for i in range(num_frames)} diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index dc96318b38f7b9..9e60d960ab12f4 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1006,7 +1006,7 @@ def temp_dir(path=None, quiet=False): yield path finally: # In case the process forks, let only the parent remove the - # directory. The child has a diffent process id. (bpo-30028) + # directory. The child has a different process id. (bpo-30028) if dir_created and pid == os.getpid(): rmtree(path) diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index d320a969876e3b..867210688f5737 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1458,7 +1458,7 @@ class C: } ) - # Make sure that the returned dicts are actuall OrderedDicts. + # Make sure that the returned dicts are actually OrderedDicts. self.assertIs(type(d), OrderedDict) self.assertIs(type(d['y'][1]), OrderedDict) diff --git a/Lib/test/test_importlib/test_lazy.py b/Lib/test/test_importlib/test_lazy.py index ffd8dc6cb04116..28608e95d060fe 100644 --- a/Lib/test/test_importlib/test_lazy.py +++ b/Lib/test/test_importlib/test_lazy.py @@ -56,7 +56,7 @@ class LazyLoaderTests(unittest.TestCase): def test_init(self): with self.assertRaises(TypeError): - # Classes that dono't define exec_module() trigger TypeError. + # Classes that don't define exec_module() trigger TypeError. util.LazyLoader(object) def new_module(self, source_code=None): diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index e818a7b28d4333..ff1ddcaf140745 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -719,7 +719,7 @@ def test_choices_algorithms(self): c = self.gen.choices(range(n), cum_weights=range(1, n+1), k=10000) self.assertEqual(a, c) - # Amerian Roulette + # American Roulette population = ['Red', 'Black', 'Green'] weights = [18, 18, 2] cum_weights = [18, 36, 38] diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 4444e945952fc3..5b53b8250f68a5 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -4332,7 +4332,7 @@ def test_pha_optional_nocert(self): self.assertEqual(s.recv(1024), b'FALSE\n') s.write(b'PHA') self.assertEqual(s.recv(1024), b'OK\n') - # optional doens't fail when client does not have a cert + # optional doesn't fail when client does not have a cert s.write(b'HASCERT') self.assertEqual(s.recv(1024), b'FALSE\n') diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index 8b2b90d6142bb4..42e20f8f7716db 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -211,7 +211,7 @@ def foo3(bar: 'func'=lambda x: x) -> {1: 2}: self.assertIn('doc3', msgids) def test_classdocstring_early_colon(self): - """ Test docstring extraction for a class with colons occuring within + """ Test docstring extraction for a class with colons occurring within the parentheses. """ msgids = self.extract_docstrings_from_str(dedent('''\ diff --git a/Lib/tokenize.py b/Lib/tokenize.py index cf1ecc99a94438..0f9d5dd554d530 100644 --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -82,7 +82,7 @@ def maybe(*choices): return group(*choices) + '?' # Return the empty string, plus all of the valid string prefixes. def _all_string_prefixes(): # The valid string prefixes. Only contain the lower case versions, - # and don't contain any permuations (include 'fr', but not + # and don't contain any permutations (include 'fr', but not # 'rf'). The various permutations will be generated. _valid_string_prefixes = ['b', 'r', 'u', 'f', 'br', 'fr'] # if we add binary f-strings, add: ['fb', 'fbr'] diff --git a/Lib/turtle.py b/Lib/turtle.py index 47a94f2a4702ff..044d91cf6d837e 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -1568,7 +1568,7 @@ def degrees(self, fullcircle=360.0): fullcircle - a number Set angle measurement units, i. e. set number - of 'degrees' for a full circle. Dafault value is + of 'degrees' for a full circle. Default value is 360 degrees. Example (for a Turtle instance named turtle): diff --git a/Objects/object.c b/Objects/object.c index 732f9ccefa8774..cb727943cb342e 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2170,7 +2170,7 @@ _PyObject_AssertFailed(PyObject *obj, const char *expr, const char *msg, fprintf(stderr, "\n", (void *)Py_TYPE(obj)); } else { - /* Diplay the traceback where the object has been allocated. + /* Display the traceback where the object has been allocated. Do it before dumping repr(obj), since repr() is more likely to crash than dumping the traceback. */ void *ptr; From 96aeaec64738b730c719562125070a52ed570210 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 6 May 2019 22:29:40 +0300 Subject: [PATCH 189/212] bpo-36793: Remove unneeded __str__ definitions. (GH-13081) Classes that define __str__ the same as __repr__ can just inherit it from object. --- Doc/whatsnew/3.8.rst | 7 +++++++ Lib/_pydecimal.py | 2 -- Lib/asyncore.py | 2 -- Lib/doctest.py | 3 +-- Lib/email/charset.py | 4 +--- Lib/http/client.py | 3 +-- Lib/json/encoder.py | 4 ++-- Lib/logging/__init__.py | 4 +--- Lib/sre_constants.py | 4 +--- Lib/subprocess.py | 1 - Lib/xmlrpc/client.py | 7 +------ .../2019-05-04-16-15-33.bpo-36793.Izog4Z.rst | 3 +++ Modules/_decimal/_decimal.c | 2 +- Modules/_json.c | 4 ++-- Objects/boolobject.c | 2 +- Objects/complexobject.c | 2 +- Objects/floatobject.c | 2 +- Objects/longobject.c | 2 +- 18 files changed, 25 insertions(+), 33 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-05-04-16-15-33.bpo-36793.Izog4Z.rst diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 64ef6e1840605b..d6388f8faaba4f 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -811,6 +811,13 @@ Changes in Python behavior raised when getting the attribute from the type dictionary are no longer ignored. (Contributed by Serhiy Storchaka in :issue:`35459`.) +* Removed ``__str__`` implementations from builtin types :class:`bool`, + :class:`int`, :class:`float`, :class:`complex` and few classes from + the standard library. They now inherit ``__str__()`` from :class:`object`. + As result, defining the ``__repr__()`` method in the subclass of these + classes will affect they string representation. + (Contributed by Serhiy Storchaka in :issue:`36793`.) + * On AIX, :attr:`sys.platform` doesn't contain the major version anymore. It is always ``'aix'``, instead of ``'aix3'`` .. ``'aix7'``. Since older Python versions include the version number, it is recommended to diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index 44ea5b41b2a1f6..c14d8ca86a1181 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -5631,8 +5631,6 @@ def __init__(self, value=None): def __repr__(self): return "(%r, %r, %r)" % (self.sign, self.int, self.exp) - __str__ = __repr__ - def _normalize(op1, op2, prec = 0): diff --git a/Lib/asyncore.py b/Lib/asyncore.py index 828f4d4fe7897b..0e92be3ad1912c 100644 --- a/Lib/asyncore.py +++ b/Lib/asyncore.py @@ -262,8 +262,6 @@ def __repr__(self): status.append(repr(self.addr)) return '<%s at %#x>' % (' '.join(status), id(self)) - __str__ = __repr__ - def add_channel(self, map=None): #self.log_info('adding channel %s' % self) if map is None: diff --git a/Lib/doctest.py b/Lib/doctest.py index 79d91a040c2eee..bf4889f59e0da4 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -2300,7 +2300,7 @@ def __repr__(self): name = self._dt_test.name.split('.') return "%s (%s)" % (name[-1], '.'.join(name[:-1])) - __str__ = __repr__ + __str__ = object.__str__ def shortDescription(self): return "Doctest: " + self._dt_test.name @@ -2399,7 +2399,6 @@ def id(self): def __repr__(self): return self._dt_test.filename - __str__ = __repr__ def format_failure(self, err): return ('Failed doctest test for %s\n File "%s", line 0\n\n%s' diff --git a/Lib/email/charset.py b/Lib/email/charset.py index ee564040c68f8b..d3d759ad9115f0 100644 --- a/Lib/email/charset.py +++ b/Lib/email/charset.py @@ -241,11 +241,9 @@ def __init__(self, input_charset=DEFAULT_CHARSET): self.output_codec = CODEC_MAP.get(self.output_charset, self.output_charset) - def __str__(self): + def __repr__(self): return self.input_charset.lower() - __repr__ = __str__ - def __eq__(self, other): return str(self) == str(other).lower() diff --git a/Lib/http/client.py b/Lib/http/client.py index f71a062d2b5783..82908ebe3afd65 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -1419,8 +1419,7 @@ def __repr__(self): e = '' return '%s(%i bytes read%s)' % (self.__class__.__name__, len(self.partial), e) - def __str__(self): - return repr(self) + __str__ = object.__str__ class ImproperConnectionState(HTTPException): pass diff --git a/Lib/json/encoder.py b/Lib/json/encoder.py index 2d7b8989c711da..c8c78b9c237652 100644 --- a/Lib/json/encoder.py +++ b/Lib/json/encoder.py @@ -268,7 +268,7 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, list=list, str=str, tuple=tuple, - _intstr=int.__str__, + _intstr=int.__repr__, ): if _indent is not None and not isinstance(_indent, str): @@ -307,7 +307,7 @@ def _iterencode_list(lst, _current_indent_level): elif value is False: yield buf + 'false' elif isinstance(value, int): - # Subclasses of int/float may override __str__, but we still + # Subclasses of int/float may override __repr__, but we still # want to encode them as integers/floats in JSON. One example # within the standard library is IntEnum. yield buf + _intstr(value) diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 7355396541a3e9..e093982a0cdfbc 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -364,12 +364,10 @@ def __init__(self, name, level, pathname, lineno, else: self.process = None - def __str__(self): + def __repr__(self): return ''%(self.name, self.levelno, self.pathname, self.lineno, self.msg) - __repr__ = __str__ - def getMessage(self): """ Return the message for this LogRecord. diff --git a/Lib/sre_constants.py b/Lib/sre_constants.py index 13deb00bc81c25..8e613cb3fa5dcb 100644 --- a/Lib/sre_constants.py +++ b/Lib/sre_constants.py @@ -59,11 +59,9 @@ def __new__(cls, value, name): self.name = name return self - def __str__(self): + def __repr__(self): return self.name - __repr__ = __str__ - MAXREPEAT = _NamedIntConstant(MAXREPEAT, 'MAXREPEAT') def _makecodes(names): diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 0496b447e8ea03..6cc9eb322e280b 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -203,7 +203,6 @@ def __repr__(self): return "%s(%d)" % (self.__class__.__name__, int(self)) __del__ = Close - __str__ = __repr__ else: # When select or poll has indicated that the file is writable, # we can write up to _PIPE_BUF bytes without risk of blocking. diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index a0e923a2032229..b9875745000feb 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -186,8 +186,7 @@ def escape(s): class Error(Exception): """Base class for client errors.""" - def __str__(self): - return repr(self) + __str__ = object.__str__ ## # Indicates an HTTP-level protocol error. This is raised by the HTTP @@ -869,8 +868,6 @@ def __init__(self, server): def __repr__(self): return "<%s at %#x>" % (self.__class__.__name__, id(self)) - __str__ = __repr__ - def __getattr__(self, name): return _MultiCallMethod(self.__call_list, name) @@ -1468,8 +1465,6 @@ def __repr__(self): (self.__class__.__name__, self.__host, self.__handler) ) - __str__ = __repr__ - def __getattr__(self, name): # magic method dispatcher return _Method(self.__request, name) diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-05-04-16-15-33.bpo-36793.Izog4Z.rst b/Misc/NEWS.d/next/Core and Builtins/2019-05-04-16-15-33.bpo-36793.Izog4Z.rst new file mode 100644 index 00000000000000..6c79f97dacac90 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-05-04-16-15-33.bpo-36793.Izog4Z.rst @@ -0,0 +1,3 @@ +Removed ``__str__`` implementations from builtin types :class:`bool`, +:class:`int`, :class:`float`, :class:`complex` and few classes from the +standard library. They now inherit ``__str__()`` from :class:`object`. diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 51aed2c67dc65e..d977b14f5b0cb8 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -5390,7 +5390,7 @@ static PyTypeObject PyDecContext_Type = 0, /* tp_as_mapping */ (hashfunc) 0, /* tp_hash */ 0, /* tp_call */ - (reprfunc) context_repr, /* tp_str */ + 0, /* tp_str */ (getattrofunc) context_getattr, /* tp_getattro */ (setattrofunc) context_setattr, /* tp_setattro */ (PyBufferProcs *) 0, /* tp_as_buffer */ diff --git a/Modules/_json.c b/Modules/_json.c index 2d7c1bf1e1c77d..4faa9cc22edf01 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1482,7 +1482,7 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc, return _steal_accumulate(acc, encoded); } else if (PyLong_Check(obj)) { - PyObject *encoded = PyLong_Type.tp_str(obj); + PyObject *encoded = PyLong_Type.tp_repr(obj); if (encoded == NULL) return -1; return _steal_accumulate(acc, encoded); @@ -1646,7 +1646,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, goto bail; } else if (PyLong_Check(key)) { - kstr = PyLong_Type.tp_str(key); + kstr = PyLong_Type.tp_repr(key); if (kstr == NULL) { goto bail; } diff --git a/Objects/boolobject.c b/Objects/boolobject.c index b92fafe620c102..508ea61f180017 100644 --- a/Objects/boolobject.c +++ b/Objects/boolobject.c @@ -147,7 +147,7 @@ PyTypeObject PyBool_Type = { 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ - bool_repr, /* tp_str */ + 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 6e3d47b62d1937..cae2bf11dc9b39 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -1129,7 +1129,7 @@ PyTypeObject PyComplex_Type = { 0, /* tp_as_mapping */ (hashfunc)complex_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)complex_repr, /* tp_str */ + 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ diff --git a/Objects/floatobject.c b/Objects/floatobject.c index b952df8807224a..adb9b80c271349 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1923,7 +1923,7 @@ PyTypeObject PyFloat_Type = { 0, /* tp_as_mapping */ (hashfunc)float_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)float_repr, /* tp_str */ + 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ diff --git a/Objects/longobject.c b/Objects/longobject.c index da697a784faad0..9fb1fb02c276bd 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5592,7 +5592,7 @@ PyTypeObject PyLong_Type = { 0, /* tp_as_mapping */ (hashfunc)long_hash, /* tp_hash */ 0, /* tp_call */ - long_to_decimal_string, /* tp_str */ + 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ From d53cf99dca4605ace4b81b1e585616b3e1b74fa6 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 6 May 2019 22:40:27 +0300 Subject: [PATCH 190/212] bpo-36542: Allow to overwrite the signature for Python functions. (GH-12705) --- Lib/bdb.py | 1 + Lib/cProfile.py | 1 + Lib/collections/__init__.py | 2 ++ Lib/concurrent/futures/_base.py | 1 + Lib/concurrent/futures/process.py | 1 + Lib/concurrent/futures/thread.py | 1 + Lib/contextlib.py | 2 ++ Lib/curses/__init__.py | 1 + Lib/functools.py | 1 + Lib/inspect.py | 9 +++++++-- Lib/multiprocessing/managers.py | 2 ++ Lib/profile.py | 1 + Lib/test/test_inspect.py | 11 +++++++++++ Lib/trace.py | 1 + Lib/unittest/case.py | 5 ++++- Lib/weakref.py | 1 + .../Library/2019-04-06-12-36-09.bpo-36542.Q0qyYV.rst | 2 ++ 17 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-06-12-36-09.bpo-36542.Q0qyYV.rst diff --git a/Lib/bdb.py b/Lib/bdb.py index 54aa98437450a2..69174364c46aef 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -649,6 +649,7 @@ def runcall(*args, **kwds): self.quitting = True sys.settrace(None) return res + runcall.__text_signature__ = '($self, func, /, *args, **kwds)' def set_trace(): diff --git a/Lib/cProfile.py b/Lib/cProfile.py index 2e449cc576cebd..369d02e22e24aa 100755 --- a/Lib/cProfile.py +++ b/Lib/cProfile.py @@ -124,6 +124,7 @@ def runcall(*args, **kw): return func(*args, **kw) finally: self.disable() + runcall.__text_signature__ = '($self, func, /, *args, **kw)' def __enter__(self): self.enable() diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 9657c1cf83bc58..e6cafb320fabf7 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -1018,6 +1018,8 @@ def __init__(*args, **kwargs): self.update(dict) if kwargs: self.update(kwargs) + __init__.__text_signature__ = '($self, dict=None, /, **kwargs)' + def __len__(self): return len(self.data) def __getitem__(self, key): if key in self.data: diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index ea16eef841c518..8f155f0ea82bdc 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -567,6 +567,7 @@ def submit(*args, **kwargs): 'got %d' % (len(args)-1)) raise NotImplementedError() + submit.__text_signature__ = '($self, fn, /, *args, **kwargs)' def map(self, fn, *iterables, timeout=None, chunksize=1): """Returns an iterator equivalent to map(fn, iter). diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index e6ce278b5d44c6..21bf4a447f084c 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -630,6 +630,7 @@ def submit(*args, **kwargs): self._start_queue_management_thread() return f + submit.__text_signature__ = _base.Executor.submit.__text_signature__ submit.__doc__ = _base.Executor.submit.__doc__ def map(self, fn, *iterables, timeout=None, chunksize=1): diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py index 0a61e3a9ac1bd1..2af31a106dd914 100644 --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -174,6 +174,7 @@ def submit(*args, **kwargs): self._work_queue.put(w) self._adjust_thread_count() return f + submit.__text_signature__ = _base.Executor.submit.__text_signature__ submit.__doc__ = _base.Executor.submit.__doc__ def _adjust_thread_count(self): diff --git a/Lib/contextlib.py b/Lib/contextlib.py index ae498a2b6ef5e2..de989a001c6dfb 100644 --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -454,6 +454,7 @@ def callback(*args, **kwds): _exit_wrapper.__wrapped__ = callback self._push_exit_callback(_exit_wrapper) return callback # Allow use as a decorator + callback.__text_signature__ = '($self, callback, /, *args, **kwds)' def _push_cm_exit(self, cm, cm_exit): """Helper to correctly register callbacks to __exit__ methods.""" @@ -615,6 +616,7 @@ def push_async_callback(*args, **kwds): _exit_wrapper.__wrapped__ = callback self._push_exit_callback(_exit_wrapper, False) return callback # Allow use as a decorator + push_async_callback.__text_signature__ = '($self, callback, /, *args, **kwds)' async def aclose(self): """Immediately unwind the context stack.""" diff --git a/Lib/curses/__init__.py b/Lib/curses/__init__.py index 44a198428820f7..24ff3ca93a8933 100644 --- a/Lib/curses/__init__.py +++ b/Lib/curses/__init__.py @@ -110,3 +110,4 @@ def wrapper(*args, **kwds): echo() nocbreak() endwin() +wrapper.__text_signature__ = '(func, /, *args, **kwds)' diff --git a/Lib/functools.py b/Lib/functools.py index 1f1874db9b4cce..28d9f6f75fdb8b 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -388,6 +388,7 @@ def __init__(*args, **keywords): self.func = func self.args = args self.keywords = keywords + __init__.__text_signature__ = '($self, func, /, *args, **keywords)' def __repr__(self): args = ", ".join(map(repr, self.args)) diff --git a/Lib/inspect.py b/Lib/inspect.py index c460309bb5a1b6..6c3027987b3001 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2121,7 +2121,7 @@ def _signature_from_builtin(cls, func, skip_bound_arg=True): return _signature_fromstr(cls, func, s, skip_bound_arg) -def _signature_from_function(cls, func): +def _signature_from_function(cls, func, skip_bound_arg=True): """Private helper: constructs Signature for the given python function.""" is_duck_function = False @@ -2133,6 +2133,10 @@ def _signature_from_function(cls, func): # of pure function: raise TypeError('{!r} is not a Python function'.format(func)) + s = getattr(func, "__text_signature__", None) + if s: + return _signature_fromstr(cls, func, s, skip_bound_arg) + Parameter = cls._parameter_cls # Parameter information. @@ -2301,7 +2305,8 @@ def _signature_from_callable(obj, *, if isfunction(obj) or _signature_is_functionlike(obj): # If it's a pure Python function, or an object that is duck type # of a Python function (Cython functions, for instance), then: - return _signature_from_function(sigcls, obj) + return _signature_from_function(sigcls, obj, + skip_bound_arg=skip_bound_arg) if _signature_is_builtin(obj): return _signature_from_builtin(sigcls, obj, diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py index 80c3ddb9154a4d..22abd47fb1f23f 100644 --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -419,6 +419,7 @@ def create(*args, **kwds): self.incref(c, ident) return ident, tuple(exposed) + create.__text_signature__ = '($self, c, typeid, /, *args, **kwds)' def get_methods(self, c, token): ''' @@ -1309,6 +1310,7 @@ def create(*args, **kwargs): if hasattr(self.registry[typeid][-1], "_shared_memory_proxy"): kwargs['shared_memory_context'] = self.shared_memory_context return Server.create(*args, **kwargs) + create.__text_signature__ = '($self, c, typeid, /, *args, **kwargs)' def shutdown(self, c): "Call unlink() on all tracked shared memory, terminate the Server." diff --git a/Lib/profile.py b/Lib/profile.py index 9a865d3f6f6ed7..1346297c04a593 100755 --- a/Lib/profile.py +++ b/Lib/profile.py @@ -447,6 +447,7 @@ def runcall(*args, **kw): return func(*args, **kw) finally: sys.setprofile(None) + runcall.__text_signature__ = '($self, func, /, *args, **kw)' #****************************************************************** diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 3c825b00e5e4a7..c54cdb23c242ff 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -3782,6 +3782,17 @@ def test_builtins_have_signatures(self): with self.subTest(builtin=name): self.assertIsNone(obj.__text_signature__) + def test_python_function_override_signature(self): + def func(*args, **kwargs): + pass + func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)' + sig = inspect.signature(func) + self.assertIsNotNone(sig) + self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)') + func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)' + sig = inspect.signature(func) + self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)') + class NTimesUnwrappable: def __init__(self, n): diff --git a/Lib/trace.py b/Lib/trace.py index fd40fbae8505c0..63008a134a8aec 100755 --- a/Lib/trace.py +++ b/Lib/trace.py @@ -476,6 +476,7 @@ def runfunc(*args, **kw): if not self.donothing: sys.settrace(None) return result + runfunc.__text_signature__ = '($self, func, /, *args, **kw)' def file_module_function_of(self, frame): code = frame.f_code diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 8ff2546fc207cc..8e01c3dc7bbd12 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -102,6 +102,7 @@ def addModuleCleanup(*args, **kwargs): args = tuple(args) _module_cleanups.append((function, args, kwargs)) +addModuleCleanup.__text_signature__ = '(function, /, *args, **kwargs)' def doModuleCleanups(): @@ -498,8 +499,8 @@ def addCleanup(*args, **kwargs): args = tuple(args) self._cleanups.append((function, args, kwargs)) + addCleanup.__text_signature__ = '($self, function, /, *args, **kwargs)' - @classmethod def addClassCleanup(*args, **kwargs): """Same as addCleanup, except the cleanup items are called even if setUpClass fails (unlike tearDownClass).""" @@ -514,6 +515,8 @@ def addClassCleanup(*args, **kwargs): args = tuple(args) cls._class_cleanups.append((function, args, kwargs)) + addClassCleanup.__text_signature__ = '($cls, function, /, *args, **kwargs)' + addClassCleanup = classmethod(addClassCleanup) def setUp(self): "Hook method for setting up the test fixture before exercising it." diff --git a/Lib/weakref.py b/Lib/weakref.py index 285c70792e0b8f..1eeb7b0a0b4446 100644 --- a/Lib/weakref.py +++ b/Lib/weakref.py @@ -569,6 +569,7 @@ def __init__(*args, **kwargs): info.index = next(self._index_iter) self._registry[self] = info finalize._dirty = True + __init__.__text_signature__ = '($self, obj, func, /, *args, **kwargs)' def __call__(self, _=None): """If alive then mark as dead and return func(*args, **kwargs); diff --git a/Misc/NEWS.d/next/Library/2019-04-06-12-36-09.bpo-36542.Q0qyYV.rst b/Misc/NEWS.d/next/Library/2019-04-06-12-36-09.bpo-36542.Q0qyYV.rst new file mode 100644 index 00000000000000..8374776e61eb8e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-06-12-36-09.bpo-36542.Q0qyYV.rst @@ -0,0 +1,2 @@ +The signature of Python functions can now be overridden by specifying the +``__text_signature__`` attribute. From 7b3a028c357dcc76b5aff7297e7c8052f897afb5 Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Mon, 6 May 2019 15:28:14 -0500 Subject: [PATCH 191/212] Fix rst formatting for several links in ssl documentation (GH-13133) --- 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 6a441983f8884e..20f5724447164d 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -665,7 +665,7 @@ Constants .. data:: PROTOCOL_SSLv23 - Alias for data:`PROTOCOL_TLS`. + Alias for :data:`PROTOCOL_TLS`. .. deprecated:: 3.6 @@ -1821,7 +1821,7 @@ to speed up repeated connections from the same clients. .. attribute:: SSLContext.sslsocket_class - The return type of :meth:`SSLContext.wrap_sockets`, defaults to + The return type of :meth:`SSLContext.wrap_socket`, defaults to :class:`SSLSocket`. The attribute can be overridden on instance of class in order to return a custom subclass of :class:`SSLSocket`. @@ -1831,7 +1831,7 @@ to speed up repeated connections from the same clients. server_hostname=None, session=None) Wrap the BIO objects *incoming* and *outgoing* and return an instance of - attr:`SSLContext.sslobject_class` (default :class:`SSLObject`). The SSL + :attr:`SSLContext.sslobject_class` (default :class:`SSLObject`). The SSL routines will read input data from the incoming BIO and write data to the outgoing BIO. From 2cc0223f43a1ffd59c887a73e2b0ce5202f3be90 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Mon, 6 May 2019 17:54:06 -0400 Subject: [PATCH 192/212] bpo-35925: Skip SSL tests that fail due to weak external certs. (GH-13124) Modern Linux distros such as Debian Buster have default OpenSSL system configurations that reject connections to servers with weak certificates by default. This causes our test suite run with external networking resources enabled to skip these tests when they encounter such a failure. Fixing the network servers is a separate issue. --- Lib/test/test_httplib.py | 25 +++++++++++-- Lib/test/test_nntplib.py | 37 +++++++++++++++---- .../2019-05-06-18-29-54.bpo-35925.gwQPuC.rst | 1 + 3 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-05-06-18-29-54.bpo-35925.gwQPuC.rst diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 65914616c7b5a9..968cbd86a1e426 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -4,6 +4,7 @@ import itertools import os import array +import re import socket import threading @@ -1619,14 +1620,30 @@ def test_networked_good_cert(self): # We feed the server's cert as a validating cert import ssl support.requires('network') - with support.transient_internet('self-signed.pythontest.net'): + selfsigned_pythontestdotnet = 'self-signed.pythontest.net' + with support.transient_internet(selfsigned_pythontestdotnet): context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) self.assertEqual(context.verify_mode, ssl.CERT_REQUIRED) self.assertEqual(context.check_hostname, True) context.load_verify_locations(CERT_selfsigned_pythontestdotnet) - h = client.HTTPSConnection('self-signed.pythontest.net', 443, context=context) - h.request('GET', '/') - resp = h.getresponse() + try: + h = client.HTTPSConnection(selfsigned_pythontestdotnet, 443, + context=context) + h.request('GET', '/') + resp = h.getresponse() + except ssl.SSLError as ssl_err: + ssl_err_str = str(ssl_err) + # In the error message of [SSL: CERTIFICATE_VERIFY_FAILED] on + # modern Linux distros (Debian Buster, etc) default OpenSSL + # configurations it'll fail saying "key too weak" until we + # address https://bugs.python.org/issue36816 to use a proper + # key size on self-signed.pythontest.net. + if re.search(r'(?i)key.too.weak', ssl_err_str): + raise unittest.SkipTest( + f'Got {ssl_err_str} trying to connect ' + f'to {selfsigned_pythontestdotnet}. ' + 'See https://bugs.python.org/issue36816.') + raise server_string = resp.getheader('server') resp.close() h.close() diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py index 8c1032b986bf61..618b403bfb5bd3 100644 --- a/Lib/test/test_nntplib.py +++ b/Lib/test/test_nntplib.py @@ -6,6 +6,7 @@ import functools import contextlib import os.path +import re import threading from test import support @@ -21,6 +22,13 @@ TIMEOUT = 30 certfile = os.path.join(os.path.dirname(__file__), 'keycert3.pem') +if ssl is not None: + SSLError = ssl.SSLError +else: + class SSLError(Exception): + """Non-existent exception class when we lack SSL support.""" + reason = "This will never be raised." + # TODO: # - test the `file` arg to more commands # - test error conditions @@ -261,14 +269,21 @@ def is_connected(): return False return True - with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server: - self.assertTrue(is_connected()) - self.assertTrue(server.help()) - self.assertFalse(is_connected()) - - with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server: - server.quit() - self.assertFalse(is_connected()) + try: + with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server: + self.assertTrue(is_connected()) + self.assertTrue(server.help()) + self.assertFalse(is_connected()) + + with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server: + server.quit() + self.assertFalse(is_connected()) + except SSLError as ssl_err: + # matches "[SSL: DH_KEY_TOO_SMALL] dh key too small" + if re.search(r'(?i)KEY.TOO.SMALL', ssl_err.reason): + raise unittest.SkipTest(f"Got {ssl_err} connecting " + f"to {self.NNTP_HOST!r}") + raise NetworkedNNTPTestsMixin.wrap_methods() @@ -294,6 +309,12 @@ def setUpClass(cls): try: cls.server = cls.NNTP_CLASS(cls.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) + except SSLError as ssl_err: + # matches "[SSL: DH_KEY_TOO_SMALL] dh key too small" + if re.search(r'(?i)KEY.TOO.SMALL', ssl_err.reason): + raise unittest.SkipTest(f"{cls} got {ssl_err} connecting " + f"to {cls.NNTP_HOST!r}") + raise except EOF_ERRORS: raise unittest.SkipTest(f"{cls} got EOF error on connecting " f"to {cls.NNTP_HOST!r}") diff --git a/Misc/NEWS.d/next/Tests/2019-05-06-18-29-54.bpo-35925.gwQPuC.rst b/Misc/NEWS.d/next/Tests/2019-05-06-18-29-54.bpo-35925.gwQPuC.rst new file mode 100644 index 00000000000000..ad8cc8fc61a07f --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-05-06-18-29-54.bpo-35925.gwQPuC.rst @@ -0,0 +1 @@ +Skip httplib and nntplib networking tests when they would otherwise fail due to a modern OS or distro with a default OpenSSL policy of rejecting connections to servers with weak certificates. From ad4ed872415d00fcdfaa52a08108ec752b115000 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Mon, 6 May 2019 22:52:11 -0400 Subject: [PATCH 193/212] Forbid creating of stream objects outside of asyncio (#13101) --- Lib/asyncio/streams.py | 67 +++++-- Lib/asyncio/subprocess.py | 32 ++-- Lib/test/test_asyncio/test_streams.py | 166 ++++++++++++------ Lib/test/test_asyncio/test_subprocess.py | 12 ++ .../2019-05-05-16-14-38.bpo-36806.rAzF-x.rst | 2 + 5 files changed, 203 insertions(+), 76 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-05-05-16-14-38.bpo-36806.rAzF-x.rst diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 33fc303a6ffcfc..c9b1f32813d437 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -4,6 +4,7 @@ import socket import sys +import warnings import weakref if hasattr(socket, 'AF_UNIX'): @@ -42,11 +43,14 @@ async def open_connection(host=None, port=None, *, """ if loop is None: loop = events.get_event_loop() - reader = StreamReader(limit=limit, loop=loop) - protocol = StreamReaderProtocol(reader, loop=loop) + reader = StreamReader(limit=limit, loop=loop, + _asyncio_internal=True) + protocol = StreamReaderProtocol(reader, loop=loop, + _asyncio_internal=True) transport, _ = await loop.create_connection( lambda: protocol, host, port, **kwds) - writer = StreamWriter(transport, protocol, reader, loop) + writer = StreamWriter(transport, protocol, reader, loop, + _asyncio_internal=True) return reader, writer @@ -77,9 +81,11 @@ async def start_server(client_connected_cb, host=None, port=None, *, loop = events.get_event_loop() def factory(): - reader = StreamReader(limit=limit, loop=loop) + reader = StreamReader(limit=limit, loop=loop, + _asyncio_internal=True) protocol = StreamReaderProtocol(reader, client_connected_cb, - loop=loop) + loop=loop, + _asyncio_internal=True) return protocol return await loop.create_server(factory, host, port, **kwds) @@ -93,11 +99,14 @@ async def open_unix_connection(path=None, *, """Similar to `open_connection` but works with UNIX Domain Sockets.""" if loop is None: loop = events.get_event_loop() - reader = StreamReader(limit=limit, loop=loop) - protocol = StreamReaderProtocol(reader, loop=loop) + reader = StreamReader(limit=limit, loop=loop, + _asyncio_internal=True) + protocol = StreamReaderProtocol(reader, loop=loop, + _asyncio_internal=True) transport, _ = await loop.create_unix_connection( lambda: protocol, path, **kwds) - writer = StreamWriter(transport, protocol, reader, loop) + writer = StreamWriter(transport, protocol, reader, loop, + _asyncio_internal=True) return reader, writer async def start_unix_server(client_connected_cb, path=None, *, @@ -107,9 +116,11 @@ async def start_unix_server(client_connected_cb, path=None, *, loop = events.get_event_loop() def factory(): - reader = StreamReader(limit=limit, loop=loop) + reader = StreamReader(limit=limit, loop=loop, + _asyncio_internal=True) protocol = StreamReaderProtocol(reader, client_connected_cb, - loop=loop) + loop=loop, + _asyncio_internal=True) return protocol return await loop.create_unix_server(factory, path, **kwds) @@ -125,11 +136,20 @@ class FlowControlMixin(protocols.Protocol): StreamWriter.drain() must wait for _drain_helper() coroutine. """ - def __init__(self, loop=None): + def __init__(self, loop=None, *, _asyncio_internal=False): if loop is None: self._loop = events.get_event_loop() else: self._loop = loop + if not _asyncio_internal: + # NOTE: + # Avoid inheritance from FlowControlMixin + # Copy-paste the code to your project + # if you need flow control helpers + warnings.warn(f"{self.__class__} should be instaniated " + "by asyncio internals only, " + "please avoid its creation from user code", + DeprecationWarning) self._paused = False self._drain_waiter = None self._connection_lost = False @@ -191,8 +211,9 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol): _source_traceback = None - def __init__(self, stream_reader, client_connected_cb=None, loop=None): - super().__init__(loop=loop) + def __init__(self, stream_reader, client_connected_cb=None, loop=None, + *, _asyncio_internal=False): + super().__init__(loop=loop, _asyncio_internal=_asyncio_internal) if stream_reader is not None: self._stream_reader_wr = weakref.ref(stream_reader, self._on_reader_gc) @@ -253,7 +274,8 @@ def connection_made(self, transport): if self._client_connected_cb is not None: self._stream_writer = StreamWriter(transport, self, reader, - self._loop) + self._loop, + _asyncio_internal=True) res = self._client_connected_cb(reader, self._stream_writer) if coroutines.iscoroutine(res): @@ -311,7 +333,13 @@ class StreamWriter: directly. """ - def __init__(self, transport, protocol, reader, loop): + def __init__(self, transport, protocol, reader, loop, + *, _asyncio_internal=False): + if not _asyncio_internal: + warnings.warn(f"{self.__class__} should be instaniated " + "by asyncio internals only, " + "please avoid its creation from user code", + DeprecationWarning) self._transport = transport self._protocol = protocol # drain() expects that the reader has an exception() method @@ -388,7 +416,14 @@ class StreamReader: _source_traceback = None - def __init__(self, limit=_DEFAULT_LIMIT, loop=None): + def __init__(self, limit=_DEFAULT_LIMIT, loop=None, + *, _asyncio_internal=False): + if not _asyncio_internal: + warnings.warn(f"{self.__class__} should be instaniated " + "by asyncio internals only, " + "please avoid its creation from user code", + DeprecationWarning) + # The line length limit is a security feature; # it also doubles as half the buffer limit. diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py index 90fc00de8339fb..fa58e1e8586239 100644 --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -1,6 +1,7 @@ __all__ = 'create_subprocess_exec', 'create_subprocess_shell' import subprocess +import warnings from . import events from . import protocols @@ -18,8 +19,8 @@ class SubprocessStreamProtocol(streams.FlowControlMixin, protocols.SubprocessProtocol): """Like StreamReaderProtocol, but for a subprocess.""" - def __init__(self, limit, loop): - super().__init__(loop=loop) + def __init__(self, limit, loop, *, _asyncio_internal=False): + super().__init__(loop=loop, _asyncio_internal=_asyncio_internal) self._limit = limit self.stdin = self.stdout = self.stderr = None self._transport = None @@ -42,14 +43,16 @@ def connection_made(self, transport): stdout_transport = transport.get_pipe_transport(1) if stdout_transport is not None: self.stdout = streams.StreamReader(limit=self._limit, - loop=self._loop) + loop=self._loop, + _asyncio_internal=True) self.stdout.set_transport(stdout_transport) self._pipe_fds.append(1) stderr_transport = transport.get_pipe_transport(2) if stderr_transport is not None: self.stderr = streams.StreamReader(limit=self._limit, - loop=self._loop) + loop=self._loop, + _asyncio_internal=True) self.stderr.set_transport(stderr_transport) self._pipe_fds.append(2) @@ -58,7 +61,8 @@ def connection_made(self, transport): self.stdin = streams.StreamWriter(stdin_transport, protocol=self, reader=None, - loop=self._loop) + loop=self._loop, + _asyncio_internal=True) def pipe_data_received(self, fd, data): if fd == 1: @@ -104,7 +108,13 @@ def _maybe_close_transport(self): class Process: - def __init__(self, transport, protocol, loop): + def __init__(self, transport, protocol, loop, *, _asyncio_internal=False): + if not _asyncio_internal: + warnings.warn(f"{self.__class__} should be instaniated " + "by asyncio internals only, " + "please avoid its creation from user code", + DeprecationWarning) + self._transport = transport self._protocol = protocol self._loop = loop @@ -195,12 +205,13 @@ async def create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, if loop is None: loop = events.get_event_loop() protocol_factory = lambda: SubprocessStreamProtocol(limit=limit, - loop=loop) + loop=loop, + _asyncio_internal=True) transport, protocol = await loop.subprocess_shell( protocol_factory, cmd, stdin=stdin, stdout=stdout, stderr=stderr, **kwds) - return Process(transport, protocol, loop) + return Process(transport, protocol, loop, _asyncio_internal=True) async def create_subprocess_exec(program, *args, stdin=None, stdout=None, @@ -209,10 +220,11 @@ async def create_subprocess_exec(program, *args, stdin=None, stdout=None, if loop is None: loop = events.get_event_loop() protocol_factory = lambda: SubprocessStreamProtocol(limit=limit, - loop=loop) + loop=loop, + _asyncio_internal=True) transport, protocol = await loop.subprocess_exec( protocol_factory, program, *args, stdin=stdin, stdout=stdout, stderr=stderr, **kwds) - return Process(transport, protocol, loop) + return Process(transport, protocol, loop, _asyncio_internal=True) diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 630f91dbf4780f..c1cc9d7fa0e9a9 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -42,7 +42,7 @@ def tearDown(self): @mock.patch('asyncio.streams.events') def test_ctor_global_loop(self, m_events): - stream = asyncio.StreamReader() + stream = asyncio.StreamReader(_asyncio_internal=True) self.assertIs(stream._loop, m_events.get_event_loop.return_value) def _basetest_open_connection(self, open_connection_fut): @@ -135,20 +135,23 @@ def test_open_unix_connection_error(self): self._basetest_open_connection_error(conn_fut) def test_feed_empty_data(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'') self.assertEqual(b'', stream._buffer) def test_feed_nonempty_data(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(self.DATA) self.assertEqual(self.DATA, stream._buffer) def test_read_zero(self): # Read zero bytes. - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(self.DATA) data = self.loop.run_until_complete(stream.read(0)) @@ -157,7 +160,8 @@ def test_read_zero(self): def test_read(self): # Read bytes. - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) read_task = asyncio.Task(stream.read(30), loop=self.loop) def cb(): @@ -170,7 +174,8 @@ def cb(): def test_read_line_breaks(self): # Read bytes without line breaks. - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'line1') stream.feed_data(b'line2') @@ -181,7 +186,8 @@ def test_read_line_breaks(self): def test_read_eof(self): # Read bytes, stop at eof. - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) read_task = asyncio.Task(stream.read(1024), loop=self.loop) def cb(): @@ -194,7 +200,8 @@ def cb(): def test_read_until_eof(self): # Read all bytes until eof. - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) read_task = asyncio.Task(stream.read(-1), loop=self.loop) def cb(): @@ -209,7 +216,8 @@ def cb(): self.assertEqual(b'', stream._buffer) def test_read_exception(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'line\n') data = self.loop.run_until_complete(stream.read(2)) @@ -221,13 +229,16 @@ def test_read_exception(self): def test_invalid_limit(self): with self.assertRaisesRegex(ValueError, 'imit'): - asyncio.StreamReader(limit=0, loop=self.loop) + asyncio.StreamReader(limit=0, loop=self.loop, + _asyncio_internal=True) with self.assertRaisesRegex(ValueError, 'imit'): - asyncio.StreamReader(limit=-1, loop=self.loop) + asyncio.StreamReader(limit=-1, loop=self.loop, + _asyncio_internal=True) def test_read_limit(self): - stream = asyncio.StreamReader(limit=3, loop=self.loop) + stream = asyncio.StreamReader(limit=3, loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'chunk') data = self.loop.run_until_complete(stream.read(5)) self.assertEqual(b'chunk', data) @@ -236,7 +247,8 @@ def test_read_limit(self): def test_readline(self): # Read one line. 'readline' will need to wait for the data # to come from 'cb' - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'chunk1 ') read_task = asyncio.Task(stream.readline(), loop=self.loop) @@ -254,7 +266,8 @@ def test_readline_limit_with_existing_data(self): # Read one line. The data is in StreamReader's buffer # before the event loop is run. - stream = asyncio.StreamReader(limit=3, loop=self.loop) + stream = asyncio.StreamReader(limit=3, loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'li') stream.feed_data(b'ne1\nline2\n') @@ -263,7 +276,8 @@ def test_readline_limit_with_existing_data(self): # The buffer should contain the remaining data after exception self.assertEqual(b'line2\n', stream._buffer) - stream = asyncio.StreamReader(limit=3, loop=self.loop) + stream = asyncio.StreamReader(limit=3, loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'li') stream.feed_data(b'ne1') stream.feed_data(b'li') @@ -278,7 +292,8 @@ def test_readline_limit_with_existing_data(self): self.assertEqual(b'', stream._buffer) def test_at_eof(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) self.assertFalse(stream.at_eof()) stream.feed_data(b'some data\n') @@ -296,7 +311,8 @@ def test_readline_limit(self): # Read one line. StreamReaders are fed with data after # their 'readline' methods are called. - stream = asyncio.StreamReader(limit=7, loop=self.loop) + stream = asyncio.StreamReader(limit=7, loop=self.loop, + _asyncio_internal=True) def cb(): stream.feed_data(b'chunk1') stream.feed_data(b'chunk2') @@ -310,7 +326,8 @@ def cb(): # a ValueError it should be empty. self.assertEqual(b'', stream._buffer) - stream = asyncio.StreamReader(limit=7, loop=self.loop) + stream = asyncio.StreamReader(limit=7, loop=self.loop, + _asyncio_internal=True) def cb(): stream.feed_data(b'chunk1') stream.feed_data(b'chunk2\n') @@ -323,7 +340,8 @@ def cb(): self.assertEqual(b'chunk3\n', stream._buffer) # check strictness of the limit - stream = asyncio.StreamReader(limit=7, loop=self.loop) + stream = asyncio.StreamReader(limit=7, loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'1234567\n') line = self.loop.run_until_complete(stream.readline()) self.assertEqual(b'1234567\n', line) @@ -342,7 +360,8 @@ def cb(): def test_readline_nolimit_nowait(self): # All needed data for the first 'readline' call will be # in the buffer. - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(self.DATA[:6]) stream.feed_data(self.DATA[6:]) @@ -352,7 +371,8 @@ def test_readline_nolimit_nowait(self): self.assertEqual(b'line2\nline3\n', stream._buffer) def test_readline_eof(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'some data') stream.feed_eof() @@ -360,14 +380,16 @@ def test_readline_eof(self): self.assertEqual(b'some data', line) def test_readline_empty_eof(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_eof() line = self.loop.run_until_complete(stream.readline()) self.assertEqual(b'', line) def test_readline_read_byte_count(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(self.DATA) self.loop.run_until_complete(stream.readline()) @@ -378,7 +400,8 @@ def test_readline_read_byte_count(self): self.assertEqual(b'ine3\n', stream._buffer) def test_readline_exception(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'line\n') data = self.loop.run_until_complete(stream.readline()) @@ -390,12 +413,14 @@ def test_readline_exception(self): self.assertEqual(b'', stream._buffer) def test_readuntil_separator(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) with self.assertRaisesRegex(ValueError, 'Separator should be'): self.loop.run_until_complete(stream.readuntil(separator=b'')) def test_readuntil_multi_chunks(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'lineAAA') data = self.loop.run_until_complete(stream.readuntil(separator=b'AAA')) @@ -413,7 +438,8 @@ def test_readuntil_multi_chunks(self): self.assertEqual(b'xxx', stream._buffer) def test_readuntil_multi_chunks_1(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'QWEaa') stream.feed_data(b'XYaa') @@ -448,7 +474,8 @@ def test_readuntil_multi_chunks_1(self): self.assertEqual(b'', stream._buffer) def test_readuntil_eof(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'some dataAA') stream.feed_eof() @@ -459,7 +486,8 @@ def test_readuntil_eof(self): self.assertEqual(b'', stream._buffer) def test_readuntil_limit_found_sep(self): - stream = asyncio.StreamReader(loop=self.loop, limit=3) + stream = asyncio.StreamReader(loop=self.loop, limit=3, + _asyncio_internal=True) stream.feed_data(b'some dataAA') with self.assertRaisesRegex(asyncio.LimitOverrunError, @@ -477,7 +505,8 @@ def test_readuntil_limit_found_sep(self): def test_readexactly_zero_or_less(self): # Read exact number of bytes (zero or less). - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(self.DATA) data = self.loop.run_until_complete(stream.readexactly(0)) @@ -490,7 +519,8 @@ def test_readexactly_zero_or_less(self): def test_readexactly(self): # Read exact number of bytes. - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) n = 2 * len(self.DATA) read_task = asyncio.Task(stream.readexactly(n), loop=self.loop) @@ -506,7 +536,8 @@ def cb(): self.assertEqual(self.DATA, stream._buffer) def test_readexactly_limit(self): - stream = asyncio.StreamReader(limit=3, loop=self.loop) + stream = asyncio.StreamReader(limit=3, loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'chunk') data = self.loop.run_until_complete(stream.readexactly(5)) self.assertEqual(b'chunk', data) @@ -514,7 +545,8 @@ def test_readexactly_limit(self): def test_readexactly_eof(self): # Read exact number of bytes (eof). - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) n = 2 * len(self.DATA) read_task = asyncio.Task(stream.readexactly(n), loop=self.loop) @@ -532,7 +564,8 @@ def cb(): self.assertEqual(b'', stream._buffer) def test_readexactly_exception(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'line\n') data = self.loop.run_until_complete(stream.readexactly(2)) @@ -543,7 +576,8 @@ def test_readexactly_exception(self): ValueError, self.loop.run_until_complete, stream.readexactly(2)) def test_exception(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) self.assertIsNone(stream.exception()) exc = ValueError() @@ -551,7 +585,8 @@ def test_exception(self): self.assertIs(stream.exception(), exc) def test_exception_waiter(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) @asyncio.coroutine def set_err(): @@ -565,7 +600,8 @@ def set_err(): self.assertRaises(ValueError, t1.result) def test_exception_cancel(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) t = asyncio.Task(stream.readline(), loop=self.loop) test_utils.run_briefly(self.loop) @@ -742,8 +778,10 @@ def test_read_all_from_pipe_reader(self): args = [sys.executable, '-c', code, str(wfd)] pipe = open(rfd, 'rb', 0) - reader = asyncio.StreamReader(loop=self.loop, limit=1) - protocol = asyncio.StreamReaderProtocol(reader, loop=self.loop) + reader = asyncio.StreamReader(loop=self.loop, limit=1, + _asyncio_internal=True) + protocol = asyncio.StreamReaderProtocol(reader, loop=self.loop, + _asyncio_internal=True) transport, _ = self.loop.run_until_complete( self.loop.connect_read_pipe(lambda: protocol, pipe)) @@ -769,7 +807,7 @@ def test_streamreader_constructor(self): # asyncio issue #184: Ensure that StreamReaderProtocol constructor # retrieves the current loop if the loop parameter is not set - reader = asyncio.StreamReader() + reader = asyncio.StreamReader(_asyncio_internal=True) self.assertIs(reader._loop, self.loop) def test_streamreaderprotocol_constructor(self): @@ -779,7 +817,7 @@ def test_streamreaderprotocol_constructor(self): # asyncio issue #184: Ensure that StreamReaderProtocol constructor # retrieves the current loop if the loop parameter is not set reader = mock.Mock() - protocol = asyncio.StreamReaderProtocol(reader) + protocol = asyncio.StreamReaderProtocol(reader, _asyncio_internal=True) self.assertIs(protocol._loop, self.loop) def test_drain_raises(self): @@ -824,32 +862,38 @@ async def client(host, port): thread.join() def test___repr__(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) self.assertEqual("", repr(stream)) def test___repr__nondefault_limit(self): - stream = asyncio.StreamReader(loop=self.loop, limit=123) + stream = asyncio.StreamReader(loop=self.loop, limit=123, + _asyncio_internal=True) self.assertEqual("", repr(stream)) def test___repr__eof(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_eof() self.assertEqual("", repr(stream)) def test___repr__data(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream.feed_data(b'data') self.assertEqual("", repr(stream)) def test___repr__exception(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) exc = RuntimeError() stream.set_exception(exc) self.assertEqual("", repr(stream)) def test___repr__waiter(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream._waiter = asyncio.Future(loop=self.loop) self.assertRegex( repr(stream), @@ -860,7 +904,8 @@ def test___repr__waiter(self): self.assertEqual("", repr(stream)) def test___repr__transport(self): - stream = asyncio.StreamReader(loop=self.loop) + stream = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) stream._transport = mock.Mock() stream._transport.__repr__ = mock.Mock() stream._transport.__repr__.return_value = "" @@ -947,8 +992,10 @@ def test_del_stream_before_connection_made(self): self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) with test_utils.run_test_server() as httpd: - rd = asyncio.StreamReader(loop=self.loop) - pr = asyncio.StreamReaderProtocol(rd, loop=self.loop) + rd = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) + pr = asyncio.StreamReaderProtocol(rd, loop=self.loop, + _asyncio_internal=True) del rd gc.collect() tr, _ = self.loop.run_until_complete( @@ -1005,6 +1052,25 @@ def test_eof_feed_when_closing_writer(self): self.assertEqual(messages, []) + def test_stream_reader_create_warning(self): + with self.assertWarns(DeprecationWarning): + asyncio.StreamReader(loop=self.loop) + + def test_stream_reader_protocol_create_warning(self): + reader = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) + with self.assertWarns(DeprecationWarning): + asyncio.StreamReaderProtocol(reader, loop=self.loop) + + def test_stream_writer_create_warning(self): + reader = asyncio.StreamReader(loop=self.loop, + _asyncio_internal=True) + proto = asyncio.StreamReaderProtocol(reader, loop=self.loop, + _asyncio_internal=True) + with self.assertWarns(DeprecationWarning): + asyncio.StreamWriter('transport', proto, reader, self.loop) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index a5bdb8eca517d3..3908aabf5a1321 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -510,6 +510,18 @@ async def execute(): self.loop.run_until_complete(execute()) + def test_subprocess_protocol_create_warning(self): + with self.assertWarns(DeprecationWarning): + subprocess.SubprocessStreamProtocol(limit=10, loop=self.loop) + + def test_process_create_warning(self): + proto = subprocess.SubprocessStreamProtocol(limit=10, loop=self.loop, + _asyncio_internal=True) + transp = mock.Mock() + + with self.assertWarns(DeprecationWarning): + subprocess.Process(transp, proto, loop=self.loop) + if sys.platform != 'win32': # Unix diff --git a/Misc/NEWS.d/next/Library/2019-05-05-16-14-38.bpo-36806.rAzF-x.rst b/Misc/NEWS.d/next/Library/2019-05-05-16-14-38.bpo-36806.rAzF-x.rst new file mode 100644 index 00000000000000..7e3ff6cf0e1442 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-05-16-14-38.bpo-36806.rAzF-x.rst @@ -0,0 +1,2 @@ +Forbid creation of asyncio stream objects like StreamReader, StreamWriter, +Process, and their protocols outside of asyncio package. From 11a8832c98b3db78727312154dd1d3ba76d639ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lapeyre?= Date: Tue, 7 May 2019 12:48:36 +0200 Subject: [PATCH 194/212] bpo-31855: unittest.mock.mock_open() results now respects the argument of read([size]) (GH-11521) unittest.mock.mock_open() results now respects the argument of read([size]) Co-Authored-By: remilapeyre --- Lib/unittest/mock.py | 39 +++++++------------ Lib/unittest/test/testmock/testwith.py | 7 +++- .../2019-01-11-17-09-15.bpo-31855.PlhfsX.rst | 2 + 3 files changed, 22 insertions(+), 26 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-01-11-17-09-15.bpo-31855.PlhfsX.rst diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 351aba5d44d7f4..1e8057d5f5bb5f 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -25,6 +25,7 @@ __version__ = '1.0' +import io import inspect import pprint import sys @@ -2318,25 +2319,12 @@ def __init__(self, spec, spec_set=False, parent=None, file_spec = None -def _iterate_read_data(read_data): - # Helper for mock_open: - # Retrieve lines from read_data via a generator so that separate calls to - # readline, read, and readlines are properly interleaved - sep = b'\n' if isinstance(read_data, bytes) else '\n' - data_as_list = [l + sep for l in read_data.split(sep)] - - if data_as_list[-1] == sep: - # If the last line ended in a newline, the list comprehension will have an - # extra entry that's just a newline. Remove this. - data_as_list = data_as_list[:-1] - else: - # If there wasn't an extra newline by itself, then the file being - # emulated doesn't have a newline to end the last line remove the - # newline that our naive format() added - data_as_list[-1] = data_as_list[-1][:-1] - for line in data_as_list: - yield line +def _to_stream(read_data): + if isinstance(read_data, bytes): + return io.BytesIO(read_data) + else: + return io.StringIO(read_data) def mock_open(mock=None, read_data=''): @@ -2351,20 +2339,23 @@ def mock_open(mock=None, read_data=''): `read_data` is a string for the `read`, `readline` and `readlines` of the file handle to return. This is an empty string by default. """ + _read_data = _to_stream(read_data) + _state = [_read_data, None] + def _readlines_side_effect(*args, **kwargs): if handle.readlines.return_value is not None: return handle.readlines.return_value - return list(_state[0]) + return _state[0].readlines(*args, **kwargs) def _read_side_effect(*args, **kwargs): if handle.read.return_value is not None: return handle.read.return_value - return type(read_data)().join(_state[0]) + return _state[0].read(*args, **kwargs) - def _readline_side_effect(): + def _readline_side_effect(*args, **kwargs): yield from _iter_side_effect() while True: - yield type(read_data)() + yield _state[0].readline(*args, **kwargs) def _iter_side_effect(): if handle.readline.return_value is not None: @@ -2384,8 +2375,6 @@ def _iter_side_effect(): handle = MagicMock(spec=file_spec) handle.__enter__.return_value = handle - _state = [_iterate_read_data(read_data), None] - handle.write.return_value = None handle.read.return_value = None handle.readline.return_value = None @@ -2398,7 +2387,7 @@ def _iter_side_effect(): handle.__iter__.side_effect = _iter_side_effect def reset_data(*args, **kwargs): - _state[0] = _iterate_read_data(read_data) + _state[0] = _to_stream(read_data) if handle.readline.side_effect == _state[1]: # Only reset the side effect if the user hasn't overridden it. _state[1] = _readline_side_effect() diff --git a/Lib/unittest/test/testmock/testwith.py b/Lib/unittest/test/testmock/testwith.py index 37100b8c1834b3..5172c222d97a78 100644 --- a/Lib/unittest/test/testmock/testwith.py +++ b/Lib/unittest/test/testmock/testwith.py @@ -283,7 +283,12 @@ def test_mock_open_read_with_argument(self): # for mocks returned by mock_open some_data = 'foo\nbar\nbaz' mock = mock_open(read_data=some_data) - self.assertEqual(mock().read(10), some_data) + self.assertEqual(mock().read(10), some_data[:10]) + self.assertEqual(mock().read(10), some_data[:10]) + + f = mock() + self.assertEqual(f.read(10), some_data[:10]) + self.assertEqual(f.read(10), some_data[10:]) def test_interleaved_reads(self): diff --git a/Misc/NEWS.d/next/Library/2019-01-11-17-09-15.bpo-31855.PlhfsX.rst b/Misc/NEWS.d/next/Library/2019-01-11-17-09-15.bpo-31855.PlhfsX.rst new file mode 100644 index 00000000000000..0da9c4997e1aa1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-01-11-17-09-15.bpo-31855.PlhfsX.rst @@ -0,0 +1,2 @@ +:func:`unittest.mock.mock_open` results now respects the argument of read([size]). +Patch contributed by Rémi Lapeyre. From 14987d4dc86d1dceffdb05863c632ceb81545fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Tue, 7 May 2019 16:56:31 +0200 Subject: [PATCH 195/212] Post v3.8.0a4 --- Include/patchlevel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h index c0a1a6fb0d8bfc..da787f27cc88a7 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 4 /* Version as a string */ -#define PY_VERSION "3.8.0a4" +#define PY_VERSION "3.8.0a4+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. From 5765ecf79fcee987f2f97c246c64b494324dfd33 Mon Sep 17 00:00:00 2001 From: Edison A <20975616+SimiCode@users.noreply.github.com> Date: Tue, 7 May 2019 08:00:21 -0700 Subject: [PATCH 196/212] bpo-36783: Added C API Documentation for Time_FromTimeAndFold and PyDateTime_FromDateAndTimeAndFold (GH-13147) --- Doc/c-api/datetime.rst | 16 ++++++++++++++++ .../2019-05-07-02-30-51.bpo-36783.gpC8E2.rst | 2 ++ 2 files changed, 18 insertions(+) create mode 100644 Misc/NEWS.d/next/Documentation/2019-05-07-02-30-51.bpo-36783.gpC8E2.rst diff --git a/Doc/c-api/datetime.rst b/Doc/c-api/datetime.rst index 78724619ea3c52..b7949e235005c8 100644 --- a/Doc/c-api/datetime.rst +++ b/Doc/c-api/datetime.rst @@ -98,6 +98,22 @@ Macros to create objects: minute, second and microsecond. +.. c:function:: PyObject* PyDateTime_FromDateAndTimeAndFold(int year, int month, int day, int hour, int minute, int second, int usecond, int fold) + + Return a :class:`datetime.datetime` object with the specified year, month, day, hour, + minute, second, microsecond and fold. + + .. versionadded:: 3.6 + + +.. c:function:: PyObject* PyTime_FromTimeAndFold(int hour, int minute, int second, int usecond, int fold) + + Return a :class:`datetime.time` object with the specified hour, minute, second, + microsecond and fold. + + .. versionadded:: 3.6 + + .. c:function:: PyObject* PyTime_FromTime(int hour, int minute, int second, int usecond) Return a :class:`datetime.time` object with the specified hour, minute, second and diff --git a/Misc/NEWS.d/next/Documentation/2019-05-07-02-30-51.bpo-36783.gpC8E2.rst b/Misc/NEWS.d/next/Documentation/2019-05-07-02-30-51.bpo-36783.gpC8E2.rst new file mode 100644 index 00000000000000..d3cbf4f6e13e88 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-05-07-02-30-51.bpo-36783.gpC8E2.rst @@ -0,0 +1,2 @@ +Added C API Documentation for Time_FromTimeAndFold and PyDateTime_FromDateAndTimeAndFold as per PEP 495. +Patch by Edison Abahurire. \ No newline at end of file From e85ef7a7eacdef2f43e6bf2e67f335100e7ef2da Mon Sep 17 00:00:00 2001 From: Julien Palard Date: Tue, 7 May 2019 17:27:48 +0200 Subject: [PATCH 197/212] bpo-28795: Signal documentation: Fix misleading statement. (GH-13121) --- Doc/library/signal.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index ac6cad9aff8e97..01200b4df8803e 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -16,7 +16,8 @@ The :func:`signal.signal` function allows defining custom handlers to be executed when a signal is received. A small number of default handlers are installed: :const:`SIGPIPE` is ignored (so write errors on pipes and sockets can be reported as ordinary Python exceptions) and :const:`SIGINT` is -translated into a :exc:`KeyboardInterrupt` exception. +translated into a :exc:`KeyboardInterrupt` exception if the parent process +has not changed it. A handler for a particular signal, once set, remains installed until it is explicitly reset (Python emulates the BSD style interface regardless of the From 64aa6d2000665efb1a2eccae176df9520bf5f5e6 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Tue, 7 May 2019 12:18:20 -0400 Subject: [PATCH 198/212] bpo-36533: Reinit logging.Handler locks on fork(). (GH-12704) Instead of attempting to acquire and release them all across fork which was leading to deadlocks in some applications that had chained their own handlers while holding multiple locks. --- Lib/logging/__init__.py | 61 ++++++++----------- Lib/test/test_logging.py | 31 ++++++++-- .../2019-04-06-00-55-09.bpo-36533.kzMyRH.rst | 6 ++ 3 files changed, 58 insertions(+), 40 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-06-00-55-09.bpo-36533.kzMyRH.rst diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index e093982a0cdfbc..07a0c0c4ae980d 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -231,49 +231,38 @@ def _releaseLock(): # Prevent a held logging lock from blocking a child from logging. if not hasattr(os, 'register_at_fork'): # Windows and friends. - def _register_at_fork_acquire_release(instance): + def _register_at_fork_reinit_lock(instance): pass # no-op when os.register_at_fork does not exist. -else: # The os.register_at_fork API exists - os.register_at_fork(before=_acquireLock, - after_in_child=_releaseLock, - after_in_parent=_releaseLock) - - # A collection of instances with acquire and release methods (logging.Handler) - # to be called before and after fork. The weakref avoids us keeping discarded - # Handler instances alive forever in case an odd program creates and destroys - # many over its lifetime. - _at_fork_acquire_release_weakset = weakref.WeakSet() - - - def _register_at_fork_acquire_release(instance): - # We put the instance itself in a single WeakSet as we MUST have only - # one atomic weak ref. used by both before and after atfork calls to - # guarantee matched pairs of acquire and release calls. - _at_fork_acquire_release_weakset.add(instance) - +else: + # A collection of instances with a createLock method (logging.Handler) + # to be called in the child after forking. The weakref avoids us keeping + # discarded Handler instances alive. A set is used to avoid accumulating + # duplicate registrations as createLock() is responsible for registering + # a new Handler instance with this set in the first place. + _at_fork_reinit_lock_weakset = weakref.WeakSet() + + def _register_at_fork_reinit_lock(instance): + _acquireLock() + try: + _at_fork_reinit_lock_weakset.add(instance) + finally: + _releaseLock() - def _at_fork_weak_calls(method_name): - for instance in _at_fork_acquire_release_weakset: - method = getattr(instance, method_name) + def _after_at_fork_child_reinit_locks(): + # _acquireLock() was called in the parent before forking. + for handler in _at_fork_reinit_lock_weakset: try: - method() + handler.createLock() except Exception as err: # Similar to what PyErr_WriteUnraisable does. print("Ignoring exception from logging atfork", instance, - method_name, "method:", err, file=sys.stderr) - - - def _before_at_fork_weak_calls(): - _at_fork_weak_calls('acquire') + "._reinit_lock() method:", err, file=sys.stderr) + _releaseLock() # Acquired by os.register_at_fork(before=. - def _after_at_fork_weak_calls(): - _at_fork_weak_calls('release') - - - os.register_at_fork(before=_before_at_fork_weak_calls, - after_in_child=_after_at_fork_weak_calls, - after_in_parent=_after_at_fork_weak_calls) + os.register_at_fork(before=_acquireLock, + after_in_child=_after_at_fork_child_reinit_locks, + after_in_parent=_releaseLock) #--------------------------------------------------------------------------- @@ -900,7 +889,7 @@ def createLock(self): Acquire a thread lock for serializing access to the underlying I/O. """ self.lock = threading.RLock() - _register_at_fork_acquire_release(self) + _register_at_fork_reinit_lock(self) def acquire(self): """ diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 82cbedada47247..950217cec28806 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -668,10 +668,28 @@ def remove_loop(fname, tries): # register_at_fork mechanism is also present and used. @unittest.skipIf(not hasattr(os, 'fork'), 'Test requires os.fork().') def test_post_fork_child_no_deadlock(self): - """Ensure forked child logging locks are not held; bpo-6721.""" - refed_h = logging.Handler() + """Ensure child logging locks are not held; bpo-6721 & bpo-36533.""" + class _OurHandler(logging.Handler): + def __init__(self): + super().__init__() + self.sub_handler = logging.StreamHandler( + stream=open('/dev/null', 'wt')) + + def emit(self, record): + self.sub_handler.acquire() + try: + self.sub_handler.emit(record) + finally: + self.sub_handler.release() + + self.assertEqual(len(logging._handlers), 0) + refed_h = _OurHandler() refed_h.name = 'because we need at least one for this test' self.assertGreater(len(logging._handlers), 0) + self.assertGreater(len(logging._at_fork_reinit_lock_weakset), 1) + test_logger = logging.getLogger('test_post_fork_child_no_deadlock') + test_logger.addHandler(refed_h) + test_logger.setLevel(logging.DEBUG) locks_held__ready_to_fork = threading.Event() fork_happened__release_locks_and_end_thread = threading.Event() @@ -709,19 +727,24 @@ def lock_holder_thread_fn(): locks_held__ready_to_fork.wait() pid = os.fork() if pid == 0: # Child. - logging.error(r'Child process did not deadlock. \o/') - os._exit(0) + try: + test_logger.info(r'Child process did not deadlock. \o/') + finally: + os._exit(0) else: # Parent. + test_logger.info(r'Parent process returned from fork. \o/') fork_happened__release_locks_and_end_thread.set() lock_holder_thread.join() start_time = time.monotonic() while True: + test_logger.debug('Waiting for child process.') waited_pid, status = os.waitpid(pid, os.WNOHANG) if waited_pid == pid: break # child process exited. if time.monotonic() - start_time > 7: break # so long? implies child deadlock. time.sleep(0.05) + test_logger.debug('Done waiting.') if waited_pid != pid: os.kill(pid, signal.SIGKILL) waited_pid, status = os.waitpid(pid, 0) diff --git a/Misc/NEWS.d/next/Library/2019-04-06-00-55-09.bpo-36533.kzMyRH.rst b/Misc/NEWS.d/next/Library/2019-04-06-00-55-09.bpo-36533.kzMyRH.rst new file mode 100644 index 00000000000000..15c4222d48374d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-06-00-55-09.bpo-36533.kzMyRH.rst @@ -0,0 +1,6 @@ +Reinitialize logging.Handler locks in forked child processes instead of +attempting to acquire them all in the parent before forking only to be +released in the child process. The acquire/release pattern was leading to +deadlocks in code that has implemented any form of chained logging handlers +that depend upon one another as the lock acquision order cannot be +guaranteed. From 91cc01f40eec03ece2d6b04ad9ea786e77707d8d Mon Sep 17 00:00:00 2001 From: Julia Iliuk Date: Tue, 7 May 2019 10:05:20 -0700 Subject: [PATCH 199/212] bpo-11001: updated cookie docs (GH-13086) Used **spookylukey**'s patch from 2011-01-24 https://bugs.python.org/issue11001 --- Doc/library/http.cookies.rst | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index f3457a0cdc7bc4..17792b200599bd 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -55,8 +55,9 @@ in Cookie name (as :attr:`~Morsel.key`). .. class:: SimpleCookie([input]) This class derives from :class:`BaseCookie` and overrides :meth:`value_decode` - and :meth:`value_encode` to be the identity and :func:`str` respectively. - + and :meth:`value_encode`. SimpleCookie supports strings as cookie values. + When setting the value, SimpleCookie calls the builtin :func:`str()` to convert + the value to a string. Values received from HTTP are kept as strings. .. seealso:: @@ -76,15 +77,16 @@ Cookie Objects .. method:: BaseCookie.value_decode(val) - Return a decoded value from a string representation. Return value can be any - type. This method does nothing in :class:`BaseCookie` --- it exists so it can be - overridden. + Return a tuple ``(real_value, coded_value)`` from a string representation. + ``real_value`` can be any type. This method does no decoding in + :class:`BaseCookie` --- it exists so it can be overridden. .. method:: BaseCookie.value_encode(val) - Return an encoded value. *val* can be any type, but return value must be a - string. This method does nothing in :class:`BaseCookie` --- it exists so it can + Return a tuple ``(real_value, coded_value)``. *val* can be any type, but + ``coded_value`` will always be converted to a string. + This method does no encoding in :class:`BaseCookie` --- it exists so it can be overridden. In general, it should be the case that :meth:`value_encode` and From 63deaa5b70108ef441c57728322da6b4321db4fc Mon Sep 17 00:00:00 2001 From: Vincent Michel Date: Tue, 7 May 2019 19:18:49 +0200 Subject: [PATCH 200/212] bpo-31922: Do not connect UDP sockets when broadcast is allowed (GH-423) *Moved from python/asyncio#493.* This PR fixes issue python/asyncio#480, as explained in [this comment](https://github.com/python/asyncio/issues/480#issuecomment-278703828). The `_SelectorDatagramTransport.sendto` method has to be modified ~~so `_sock.sendto` is used in all cases (because it is tricky to reliably tell if the socket is connected or not). Could that be an issue for connected sockets?~~ *EDIT* ... so `_sock.send` is used only if `_sock` is connected. It also protects `socket.getsockname` against `OSError` in `_SelectorTransport`. This might happen on Windows if the socket is not connected (e.g. for UDP broadcasting). https://bugs.python.org/issue31922 --- Lib/asyncio/base_events.py | 3 ++- Lib/asyncio/selector_events.py | 17 +++++++++++------ Lib/test/test_asyncio/test_base_events.py | 17 +++++++++++++++++ Lib/test/test_asyncio/test_selector_events.py | 1 + .../2018-05-30-01-05-50.bpo-31922.fobsXJ.rst | 3 +++ 5 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-05-30-01-05-50.bpo-31922.fobsXJ.rst diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index c58906f8b4897f..9613ac2a114f0d 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -1306,7 +1306,8 @@ async def create_datagram_endpoint(self, protocol_factory, if local_addr: sock.bind(local_address) if remote_addr: - await self.sock_connect(sock, remote_address) + if not allow_broadcast: + await self.sock_connect(sock, remote_address) r_addr = remote_address except OSError as exc: if sock is not None: diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 93b6889509436c..29968214f8ed92 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -587,7 +587,10 @@ class _SelectorTransport(transports._FlowControlMixin, def __init__(self, loop, sock, protocol, extra=None, server=None): super().__init__(extra, loop) self._extra['socket'] = sock - self._extra['sockname'] = sock.getsockname() + try: + self._extra['sockname'] = sock.getsockname() + except OSError: + self._extra['sockname'] = None if 'peername' not in self._extra: try: self._extra['peername'] = sock.getpeername() @@ -976,9 +979,11 @@ def sendto(self, data, addr=None): if not data: return - if self._address and addr not in (None, self._address): - raise ValueError( - f'Invalid address: must be None or {self._address}') + if self._address: + if addr not in (None, self._address): + raise ValueError( + f'Invalid address: must be None or {self._address}') + addr = self._address if self._conn_lost and self._address: if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES: @@ -989,7 +994,7 @@ def sendto(self, data, addr=None): if not self._buffer: # Attempt to send it right away first. try: - if self._address: + if self._extra['peername']: self._sock.send(data) else: self._sock.sendto(data, addr) @@ -1012,7 +1017,7 @@ def _sendto_ready(self): while self._buffer: data, addr = self._buffer.popleft() try: - if self._address: + if self._extra['peername']: self._sock.send(data) else: self._sock.sendto(data, addr) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index c245c472996ec3..25420b2ff6fa7e 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1586,6 +1586,23 @@ def test_create_datagram_endpoint_connect_err(self): self.assertRaises( OSError, self.loop.run_until_complete, coro) + def test_create_datagram_endpoint_allow_broadcast(self): + protocol = MyDatagramProto(create_future=True, loop=self.loop) + self.loop.sock_connect = sock_connect = mock.Mock() + sock_connect.return_value = [] + + coro = self.loop.create_datagram_endpoint( + lambda: protocol, + remote_addr=('127.0.0.1', 0), + allow_broadcast=True) + + transport, _ = self.loop.run_until_complete(coro) + self.assertFalse(sock_connect.called) + + transport.close() + self.loop.run_until_complete(protocol.done) + self.assertEqual('CLOSED', protocol.state) + @patch_socket def test_create_datagram_endpoint_socket_err(self, m_socket): m_socket.getaddrinfo = socket.getaddrinfo diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index d0d171a9853a33..bf721b0005b000 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -1065,6 +1065,7 @@ def setUp(self): self.sock.fileno.return_value = 7 def datagram_transport(self, address=None): + self.sock.getpeername.side_effect = None if address else OSError transport = _SelectorDatagramTransport(self.loop, self.sock, self.protocol, address=address) diff --git a/Misc/NEWS.d/next/Library/2018-05-30-01-05-50.bpo-31922.fobsXJ.rst b/Misc/NEWS.d/next/Library/2018-05-30-01-05-50.bpo-31922.fobsXJ.rst new file mode 100644 index 00000000000000..df3881bffaaa38 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-30-01-05-50.bpo-31922.fobsXJ.rst @@ -0,0 +1,3 @@ +:meth:`asyncio.AbstractEventLoop.create_datagram_endpoint`: +Do not connect UDP socket when broadcast is allowed. +This allows to receive replies after a UDP broadcast. From f7bda5c5729a3cc69b32c2a3baf5c64dea666d33 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Tue, 7 May 2019 13:31:11 -0400 Subject: [PATCH 201/212] Don't import wait from connection, it shadows a name (GH-13112) (lint cleanup) This import causes an argument parameter to shadow the global import name. --- Lib/concurrent/futures/process.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index 21bf4a447f084c..d7e2478d9227b5 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -51,7 +51,7 @@ import queue from queue import Full import multiprocessing as mp -from multiprocessing.connection import wait +import multiprocessing.connection from multiprocessing.queues import Queue import threading import weakref @@ -352,7 +352,7 @@ def shutdown_worker(): # submitted, from the executor being shutdown/gc-ed, or from the # shutdown of the python interpreter. worker_sentinels = [p.sentinel for p in processes.values()] - ready = wait(readers + worker_sentinels) + ready = mp.connection.wait(readers + worker_sentinels) cause = None is_broken = True From b35acc5b3a0148c5fd4462968b310fb436726d5a Mon Sep 17 00:00:00 2001 From: Romain Picard Date: Tue, 7 May 2019 20:58:24 +0200 Subject: [PATCH 202/212] bpo-35125: remove inner callback on outer cancellation in asyncio shield (GH-10340) When the future returned by shield is cancelled, its completion callback of the inner future is not removed. This makes the callback list of inner inner future grow each time a shield is created and cancelled. This change unregisters the callback from the inner future when the outer future is cancelled. https://bugs.python.org/issue35125 --- Lib/asyncio/tasks.py | 10 ++++++++-- Lib/test/test_asyncio/test_tasks.py | 11 ++++++++++- .../Library/2019-02-15-17-18-50.bpo-35125.h0xk0f.rst | 1 + 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-02-15-17-18-50.bpo-35125.h0xk0f.rst diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index b007b74344edb5..211b9126b0114a 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -818,7 +818,7 @@ def shield(arg, *, loop=None): loop = futures._get_loop(inner) outer = loop.create_future() - def _done_callback(inner): + def _inner_done_callback(inner): if outer.cancelled(): if not inner.cancelled(): # Mark inner's result as retrieved. @@ -834,7 +834,13 @@ def _done_callback(inner): else: outer.set_result(inner.result()) - inner.add_done_callback(_done_callback) + + def _outer_done_callback(outer): + if not inner.done(): + inner.remove_done_callback(_inner_done_callback) + + inner.add_done_callback(_inner_done_callback) + outer.add_done_callback(_outer_done_callback) return outer diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index c4f6d703549ca2..fa9783f2ff2196 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1777,7 +1777,7 @@ def test_shield_exception(self): test_utils.run_briefly(self.loop) self.assertIs(outer.exception(), exc) - def test_shield_cancel(self): + def test_shield_cancel_inner(self): inner = self.new_future(self.loop) outer = asyncio.shield(inner) test_utils.run_briefly(self.loop) @@ -1785,6 +1785,15 @@ def test_shield_cancel(self): test_utils.run_briefly(self.loop) self.assertTrue(outer.cancelled()) + def test_shield_cancel_outer(self): + inner = self.new_future(self.loop) + outer = asyncio.shield(inner) + test_utils.run_briefly(self.loop) + outer.cancel() + test_utils.run_briefly(self.loop) + self.assertTrue(outer.cancelled()) + self.assertEqual(0, 0 if outer._callbacks is None else len(outer._callbacks)) + def test_shield_shortcut(self): fut = self.new_future(self.loop) fut.set_result(42) diff --git a/Misc/NEWS.d/next/Library/2019-02-15-17-18-50.bpo-35125.h0xk0f.rst b/Misc/NEWS.d/next/Library/2019-02-15-17-18-50.bpo-35125.h0xk0f.rst new file mode 100644 index 00000000000000..2e28a25d2415a2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-02-15-17-18-50.bpo-35125.h0xk0f.rst @@ -0,0 +1 @@ +Asyncio: Remove inner callback on outer cancellation in shield From e19a91e45fd54a56e39c2d12e6aaf4757030507f Mon Sep 17 00:00:00 2001 From: Adorilson Bezerra Date: Tue, 7 May 2019 17:20:58 -0300 Subject: [PATCH 203/212] Add a footnote about Cheese Shop in Doc/tutorial (GH-13103) --- Doc/tutorial/whatnow.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst index d876d0740d8065..3208201312b871 100644 --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -39,7 +39,7 @@ More Python resources: * https://docs.python.org: Fast access to Python's documentation. * https://pypi.org: The Python Package Index, previously also nicknamed - the Cheese Shop, is an index of user-created Python modules that are available + the Cheese Shop [#]_, is an index of user-created Python modules that are available for download. Once you begin releasing code, you can register it here so that others can find it. @@ -68,3 +68,9 @@ Before posting, be sure to check the list of :ref:`Frequently Asked Questions ` (also called the FAQ). The FAQ answers many of the questions that come up again and again, and may already contain the solution for your problem. + +.. rubric:: Footnotes + +.. [#] "Cheese Shop" is a Monty Python's sketch: a customer enters a cheese shop, + but whatever cheese he asks for, the clerk says it's missing. + From 1cc0ee7d9f6a2817918fafd24c18d8bb093a85d3 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Tue, 7 May 2019 16:53:19 -0400 Subject: [PATCH 204/212] bpo-36801: Fix waiting in StreamWriter.drain for closing SSL transport (GH-13098) https://bugs.python.org/issue36801 --- Lib/asyncio/streams.py | 21 ++++++++++------- Lib/asyncio/subprocess.py | 9 ++++++++ Lib/test/test_asyncio/test_streams.py | 23 +++++++++++++++++++ .../2019-05-05-09-45-44.bpo-36801.XrlFFs.rst | 1 + 4 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-05-05-09-45-44.bpo-36801.XrlFFs.rst diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index c9b1f32813d437..79adf028212f87 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -199,6 +199,9 @@ async def _drain_helper(self): self._drain_waiter = waiter await waiter + def _get_close_waiter(self, stream): + raise NotImplementedError + class StreamReaderProtocol(FlowControlMixin, protocols.Protocol): """Helper class to adapt between Protocol and StreamReader. @@ -315,6 +318,9 @@ def eof_received(self): return False return True + def _get_close_waiter(self, stream): + return self._closed + def __del__(self): # Prevent reports about unhandled exceptions. # Better than self._closed._log_traceback = False hack @@ -376,7 +382,7 @@ def is_closing(self): return self._transport.is_closing() async def wait_closed(self): - await self._protocol._closed + await self._protocol._get_close_waiter(self) def get_extra_info(self, name, default=None): return self._transport.get_extra_info(name, default) @@ -394,13 +400,12 @@ async def drain(self): if exc is not None: raise exc if self._transport.is_closing(): - # Yield to the event loop so connection_lost() may be - # called. Without this, _drain_helper() would return - # immediately, and code that calls - # write(...); await drain() - # in a loop would never call connection_lost(), so it - # would not see an error when the socket is closed. - await sleep(0, loop=self._loop) + # Wait for protocol.connection_lost() call + # Raise connection closing error if any, + # ConnectionResetError otherwise + fut = self._protocol._get_close_waiter(self) + await fut + raise ConnectionResetError('Connection lost') await self._protocol._drain_helper() async def aclose(self): diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py index fa58e1e8586239..d34b6118fdcf72 100644 --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -26,6 +26,7 @@ def __init__(self, limit, loop, *, _asyncio_internal=False): self._transport = None self._process_exited = False self._pipe_fds = [] + self._stdin_closed = self._loop.create_future() def __repr__(self): info = [self.__class__.__name__] @@ -80,6 +81,10 @@ def pipe_connection_lost(self, fd, exc): if pipe is not None: pipe.close() self.connection_lost(exc) + if exc is None: + self._stdin_closed.set_result(None) + else: + self._stdin_closed.set_exception(exc) return if fd == 1: reader = self.stdout @@ -106,6 +111,10 @@ def _maybe_close_transport(self): self._transport.close() self._transport = None + def _get_close_waiter(self, stream): + if stream is self.stdin: + return self._stdin_closed + class Process: def __init__(self, transport, protocol, loop, *, _asyncio_internal=False): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index c1cc9d7fa0e9a9..905141ca89c7ee 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -109,6 +109,29 @@ def test_open_unix_connection_no_loop_ssl(self): self._basetest_open_connection_no_loop_ssl(conn_fut) + @unittest.skipIf(ssl is None, 'No ssl module') + def test_drain_on_closed_writer_ssl(self): + + async def inner(httpd): + reader, writer = await asyncio.open_connection( + *httpd.address, + ssl=test_utils.dummy_ssl_context()) + + messages = [] + self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) + writer.write(b'GET / HTTP/1.0\r\n\r\n') + data = await reader.read() + self.assertTrue(data.endswith(b'\r\n\r\nTest message')) + + writer.close() + with self.assertRaises(ConnectionResetError): + await writer.drain() + + self.assertEqual(messages, []) + + with test_utils.run_test_server(use_ssl=True) as httpd: + self.loop.run_until_complete(inner(httpd)) + def _basetest_open_connection_error(self, open_connection_fut): messages = [] self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx)) diff --git a/Misc/NEWS.d/next/Library/2019-05-05-09-45-44.bpo-36801.XrlFFs.rst b/Misc/NEWS.d/next/Library/2019-05-05-09-45-44.bpo-36801.XrlFFs.rst new file mode 100644 index 00000000000000..43e51fe5ca94d5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-05-09-45-44.bpo-36801.XrlFFs.rst @@ -0,0 +1 @@ +Properly handle SSL connection closing in asyncio StreamWriter.drain() call. From 3918ad6b45da31e05265de5a455102276717c659 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Tue, 7 May 2019 17:03:50 -0400 Subject: [PATCH 205/212] bpo-36838: Suggest 'make venv' when missing Doc/ tools. (GH-13173) --- Doc/Makefile | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Doc/Makefile b/Doc/Makefile index 53877e61329089..cf1bb88b0b8ea4 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -48,11 +48,19 @@ build: @if [ -f ../Misc/NEWS ] ; then \ echo "Using existing Misc/NEWS file"; \ cp ../Misc/NEWS build/NEWS; \ - elif [ -d ../Misc/NEWS.d ]; then \ - echo "Building NEWS from Misc/NEWS.d with blurb"; \ - $(BLURB) merge -f build/NEWS; \ + elif $(BLURB) help >/dev/null 2>&1 && $(SPHINXBUILD) --version >/dev/null 2>&1; then \ + if [ -d ../Misc/NEWS.d ]; then \ + echo "Building NEWS from Misc/NEWS.d with blurb"; \ + $(BLURB) merge -f build/NEWS; \ + else \ + echo "Neither Misc/NEWS.d nor Misc/NEWS found; cannot build docs"; \ + exit 1; \ + fi \ else \ - echo "Neither Misc/NEWS.d nor Misc/NEWS found; cannot build docs"; \ + echo ""; \ + echo "Missing the required blurb or sphinx-build tools."; \ + echo "Please run 'make venv' to install local copies."; \ + echo ""; \ exit 1; \ fi $(SPHINXBUILD) $(ALLSPHINXOPTS) From ca87eebb22d202c33f3317cbf85059cadc64fa9f Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 7 May 2019 23:36:39 +0200 Subject: [PATCH 206/212] bpo-36015: Handle StreamHandler representaton of stream with an integer name (GH-11908) --- Lib/logging/__init__.py | 2 ++ Lib/test/test_logging.py | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 07a0c0c4ae980d..16812ec8d55678 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -1111,6 +1111,8 @@ def setStream(self, stream): def __repr__(self): level = getLevelName(self.level) name = getattr(self.stream, 'name', '') + # bpo-36015: name can be an int + name = str(name) if name: name += ' ' return '<%s %s(%s)>' % (self.__class__.__name__, name, level) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 950217cec28806..bc99c3adbe3416 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -760,6 +760,10 @@ class TestStreamHandler(logging.StreamHandler): def handleError(self, record): self.error_record = record +class StreamWithIntName(object): + level = logging.NOTSET + name = 2 + class StreamHandlerTest(BaseTest): def test_error_handling(self): h = TestStreamHandler(BadStream()) @@ -797,6 +801,10 @@ def test_stream_setting(self): actual = h.setStream(old) self.assertIsNone(actual) + def test_can_represent_stream_with_int_name(self): + h = logging.StreamHandler(StreamWithIntName()) + self.assertEqual(repr(h), '') + # -- The following section could be moved into a server_helper.py module # -- if it proves to be of wider utility than just test_logging From b1c3167c232c36ed3543ca351ff10c613639b5f5 Mon Sep 17 00:00:00 2001 From: Michael Blahay Date: Tue, 7 May 2019 17:41:06 -0400 Subject: [PATCH 207/212] bpo-27639: Correct return type for UserList slicing operation (#13169) * BPO-27639: Correct return type for UserList slicing operation Added logic to __getitem__ magic method for UserList to ensure that the return type matches that of self. --- Lib/collections/__init__.py | 6 +++++- Lib/test/test_userlist.py | 6 ++++++ .../2019-05-07-15-49-17.bpo-27639.b1Ah87.rst | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-05-07-15-49-17.bpo-27639.b1Ah87.rst diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index e6cafb320fabf7..706907ad4a282d 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -1085,7 +1085,11 @@ def __cast(self, other): return other.data if isinstance(other, UserList) else other def __contains__(self, item): return item in self.data def __len__(self): return len(self.data) - def __getitem__(self, i): return self.data[i] + def __getitem__(self, i): + if isinstance(i, slice): + return self.__class__(self.data[i]) + else: + return self.data[i] def __setitem__(self, i, item): self.data[i] = item def __delitem__(self, i): del self.data[i] def __add__(self, other): diff --git a/Lib/test/test_userlist.py b/Lib/test/test_userlist.py index 8de6c14e392f20..1ed67dac805967 100644 --- a/Lib/test/test_userlist.py +++ b/Lib/test/test_userlist.py @@ -17,6 +17,12 @@ def test_getslice(self): for j in range(-3, 6): self.assertEqual(u[i:j], l[i:j]) + def test_slice_type(self): + l = [0, 1, 2, 3, 4] + u = UserList(l) + self.assertIsInstance(u[:], u.__class__) + self.assertEqual(u[:],u) + def test_add_specials(self): u = UserList("spam") u2 = u + "eggs" diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-05-07-15-49-17.bpo-27639.b1Ah87.rst b/Misc/NEWS.d/next/Core and Builtins/2019-05-07-15-49-17.bpo-27639.b1Ah87.rst new file mode 100644 index 00000000000000..ae5b915969d3b5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-05-07-15-49-17.bpo-27639.b1Ah87.rst @@ -0,0 +1,2 @@ +Correct return type for UserList slicing operations. Patch by Michael Blahay, +Erick Cervantes, and vaultah From 70b80541bb044e8cb7037acaf97f64890fef418e Mon Sep 17 00:00:00 2001 From: Zhaorong Ma Date: Wed, 8 May 2019 09:44:01 -0400 Subject: [PATCH 208/212] Doc: Fix missing bracket (GH-13163) --- Doc/distutils/setupscript.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/distutils/setupscript.rst b/Doc/distutils/setupscript.rst index 54ed1aebc242d8..a65a26ac57facc 100644 --- a/Doc/distutils/setupscript.rst +++ b/Doc/distutils/setupscript.rst @@ -523,7 +523,7 @@ following way:: setup(..., data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']), - ('config', ['cfg/data.cfg']), + ('config', ['cfg/data.cfg'])], ) Each (*directory*, *files*) pair in the sequence specifies the installation From b2758ff9553d8bebe4e9dd1cb3996212473810e3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 8 May 2019 09:45:06 -0400 Subject: [PATCH 209/212] bpo-36832: add zipfile.Path (#13153) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * bpo-36832: add zipfile.Path * bpo-36832: add documentation for zipfile.Path * 📜🤖 Added by blurb_it. * Remove module reference from blurb. * Sort the imports * Update docstrings and docs per recommendations. * Rely on test.support.temp_dir * Signal that 'root' is the parameter. * Correct spelling of 'mod' * Convert docstring to comment for brevity. * Fix more errors in the docs --- Doc/library/zipfile.rst | 67 ++++++++ Lib/test/test_zipfile.py | 116 +++++++++++++- Lib/zipfile.py | 144 +++++++++++++++++- .../2019-05-07-15-00-45.bpo-36832.TExgqb.rst | 1 + 4 files changed, 320 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-05-07-15-00-45.bpo-36832.TExgqb.rst diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst index 4e9edff270143d..9db9697105d6b5 100644 --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -52,6 +52,15 @@ The module defines the following items: :ref:`zipfile-objects` for constructor details. +.. class:: Path + :noindex: + + A pathlib-compatible wrapper for zip files. See section + :ref:`path-objects` for details. + + .. versionadded:: 3.8 + + .. class:: PyZipFile :noindex: @@ -456,6 +465,64 @@ The following data attributes are also available: truncated. +.. _path-objects: + +Path Objects +------------ + +.. class:: Path(root, at='') + + Construct a Path object from a ``root`` zipfile (which may be a + :class:`ZipFile` instance or ``file`` suitable for passing to + the :class:`ZipFile` constructor). + + ``at`` specifies the location of this Path within the zipfile, + e.g. 'dir/file.txt', 'dir/', or ''. Defaults to the empty string, + indicating the root. + +Path objects expose the following features of :mod:`pathlib.Path` +objects: + +Path objects are traversable using the ``/`` operator. + +.. attribute:: Path.name + + The final path component. + +.. method:: Path.open(*, **) + + Invoke :meth:`ZipFile.open` on the current path. Accepts + the same arguments as :meth:`ZipFile.open`. + +.. method:: Path.listdir() + + Enumerate the children of the current directory. + +.. method:: Path.is_dir() + + Return ``True`` if the current context references a directory. + +.. method:: Path.is_file() + + Return ``True`` if the current context references a file. + +.. method:: Path.exists() + + Return ``True`` if the current context references a file or + directory in the zip file. + +.. method:: Path.read_text(*, **) + + Read the current file as unicode text. Positional and + keyword arguments are passed through to + :class:`io.TextIOWrapper` (except ``buffer``, which is + implied by the context). + +.. method:: Path.read_bytes() + + Read the current file as bytes. + + .. _pyzipfile-objects: PyZipFile Objects diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py index 14e1e08c5bfdcc..538d4ee55dfbe7 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -1,13 +1,15 @@ import contextlib +import importlib.util import io import os -import importlib.util import pathlib import posixpath -import time +import shutil import struct -import zipfile +import tempfile +import time import unittest +import zipfile from tempfile import TemporaryFile @@ -2392,5 +2394,113 @@ def test_extract_command(self): with open(path, 'rb') as f: self.assertEqual(f.read(), zf.read(zi)) + +# Poor man's technique to consume a (smallish) iterable. +consume = tuple + + +def add_dirs(zipfile): + """ + Given a writable zipfile, inject directory entries for + any directories implied by the presence of children. + """ + names = zipfile.namelist() + consume( + zipfile.writestr(name + "/", b"") + for name in map(posixpath.dirname, names) + if name and name + "/" not in names + ) + return zipfile + + +def build_abcde_files(): + """ + Create a zip file with this structure: + + . + ├── a.txt + └── b + ├── c.txt + └── d + └── e.txt + """ + data = io.BytesIO() + zf = zipfile.ZipFile(data, "w") + zf.writestr("a.txt", b"content of a") + zf.writestr("b/c.txt", b"content of c") + zf.writestr("b/d/e.txt", b"content of e") + zf.filename = "abcde.zip" + return zf + + +class TestPath(unittest.TestCase): + def setUp(self): + self.fixtures = contextlib.ExitStack() + self.addCleanup(self.fixtures.close) + + def zipfile_abcde(self): + with self.subTest(): + yield build_abcde_files() + with self.subTest(): + yield add_dirs(build_abcde_files()) + + def zipfile_ondisk(self): + tmpdir = pathlib.Path(self.fixtures.enter_context(temp_dir())) + for zipfile_abcde in self.zipfile_abcde(): + buffer = zipfile_abcde.fp + zipfile_abcde.close() + path = tmpdir / zipfile_abcde.filename + with path.open("wb") as strm: + strm.write(buffer.getvalue()) + yield path + + def test_iterdir_istype(self): + for zipfile_abcde in self.zipfile_abcde(): + root = zipfile.Path(zipfile_abcde) + assert root.is_dir() + a, b = root.iterdir() + assert a.is_file() + assert b.is_dir() + c, d = b.iterdir() + assert c.is_file() + e, = d.iterdir() + assert e.is_file() + + def test_open(self): + for zipfile_abcde in self.zipfile_abcde(): + root = zipfile.Path(zipfile_abcde) + a, b = root.iterdir() + with a.open() as strm: + data = strm.read() + assert data == b"content of a" + + def test_read(self): + for zipfile_abcde in self.zipfile_abcde(): + root = zipfile.Path(zipfile_abcde) + a, b = root.iterdir() + assert a.read_text() == "content of a" + assert a.read_bytes() == b"content of a" + + def test_traverse_truediv(self): + for zipfile_abcde in self.zipfile_abcde(): + root = zipfile.Path(zipfile_abcde) + a = root / "a" + assert a.is_file() + e = root / "b" / "d" / "e.txt" + assert e.read_text() == "content of e" + + def test_pathlike_construction(self): + """ + zipfile.Path should be constructable from a path-like object + """ + for zipfile_ondisk in self.zipfile_ondisk(): + pathlike = pathlib.Path(str(zipfile_ondisk)) + zipfile.Path(pathlike) + + def test_traverse_pathlike(self): + for zipfile_abcde in self.zipfile_abcde(): + root = zipfile.Path(zipfile_abcde) + root / pathlib.Path("a") + if __name__ == "__main__": unittest.main() diff --git a/Lib/zipfile.py b/Lib/zipfile.py index 2dc01647211799..62475c701f50a7 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -3,16 +3,18 @@ XXX references to utf-8 need further investigation. """ +import binascii +import functools +import importlib.util import io import os -import importlib.util -import sys -import time -import stat +import posixpath import shutil +import stat import struct -import binascii +import sys import threading +import time try: import zlib # We may need its compression method @@ -2102,6 +2104,138 @@ def _compile(file, optimize=-1): return (fname, archivename) +class Path: + """ + A pathlib-compatible interface for zip files. + + Consider a zip file with this structure:: + + . + ├── a.txt + └── b + ├── c.txt + └── d + └── e.txt + + >>> data = io.BytesIO() + >>> zf = ZipFile(data, 'w') + >>> zf.writestr('a.txt', 'content of a') + >>> zf.writestr('b/c.txt', 'content of c') + >>> zf.writestr('b/d/e.txt', 'content of e') + >>> zf.filename = 'abcde.zip' + + Path accepts the zipfile object itself or a filename + + >>> root = Path(zf) + + From there, several path operations are available. + + Directory iteration (including the zip file itself): + + >>> a, b = root.iterdir() + >>> a + Path('abcde.zip', 'a.txt') + >>> b + Path('abcde.zip', 'b/') + + name property: + + >>> b.name + 'b' + + join with divide operator: + + >>> c = b / 'c.txt' + >>> c + Path('abcde.zip', 'b/c.txt') + >>> c.name + 'c.txt' + + Read text: + + >>> c.read_text() + 'content of c' + + existence: + + >>> c.exists() + True + >>> (b / 'missing.txt').exists() + False + + Coersion to string: + + >>> str(c) + 'abcde.zip/b/c.txt' + """ + + __repr = "{self.__class__.__name__}({self.root.filename!r}, {self.at!r})" + + def __init__(self, root, at=""): + self.root = root if isinstance(root, ZipFile) else ZipFile(root) + self.at = at + + @property + def open(self): + return functools.partial(self.root.open, self.at) + + @property + def name(self): + return posixpath.basename(self.at.rstrip("/")) + + def read_text(self, *args, **kwargs): + with self.open() as strm: + return io.TextIOWrapper(strm, *args, **kwargs).read() + + def read_bytes(self): + with self.open() as strm: + return strm.read() + + def _is_child(self, path): + return posixpath.dirname(path.at.rstrip("/")) == self.at.rstrip("/") + + def _next(self, at): + return Path(self.root, at) + + def is_dir(self): + return not self.at or self.at.endswith("/") + + def is_file(self): + return not self.is_dir() + + def exists(self): + return self.at in self._names() + + def iterdir(self): + if not self.is_dir(): + raise ValueError("Can't listdir a file") + subs = map(self._next, self._names()) + return filter(self._is_child, subs) + + def __str__(self): + return posixpath.join(self.root.filename, self.at) + + def __repr__(self): + return self.__repr.format(self=self) + + def __truediv__(self, add): + next = posixpath.join(self.at, add) + next_dir = posixpath.join(self.at, add, "") + names = self._names() + return self._next(next_dir if next not in names and next_dir in names else next) + + @staticmethod + def _add_implied_dirs(names): + return names + [ + name + "/" + for name in map(posixpath.dirname, names) + if name and name + "/" not in names + ] + + def _names(self): + return self._add_implied_dirs(self.root.namelist()) + + def main(args=None): import argparse diff --git a/Misc/NEWS.d/next/Library/2019-05-07-15-00-45.bpo-36832.TExgqb.rst b/Misc/NEWS.d/next/Library/2019-05-07-15-00-45.bpo-36832.TExgqb.rst new file mode 100644 index 00000000000000..23577d9b5a829f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-07-15-00-45.bpo-36832.TExgqb.rst @@ -0,0 +1 @@ +Introducing ``zipfile.Path``, a pathlib-compatible wrapper for traversing zip files. From 1d4b16051f8550fd7dada3670a3e83ae13b99d3b Mon Sep 17 00:00:00 2001 From: Julien Palard Date: Wed, 8 May 2019 17:01:11 +0200 Subject: [PATCH 210/212] Doc: Be explicit that Pathlib resolve was strict before 3.6. (GH-11316) --- Doc/library/pathlib.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 7a4a20dc61182f..41aebc4f61c83c 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -976,7 +976,7 @@ call fails (for example because the path doesn't exist). is raised. .. versionadded:: 3.6 - The *strict* argument. + The *strict* argument (pre-3.6 behavior is strict). .. method:: Path.rglob(pattern) From 6d19b0407e469d7de77106b5d6bfb78bb52e4179 Mon Sep 17 00:00:00 2001 From: Michael Felt Date: Mon, 15 Apr 2019 13:36:05 +0000 Subject: [PATCH 211/212] example of what it could become --- Lib/test/support/__init__.py | 3 +++ Lib/test/test_c_locale_coercion.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 9e60d960ab12f4..8f44aee7277929 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -101,6 +101,8 @@ # network "HOST", "IPV6_ENABLED", "find_unused_port", "bind_port", "open_urlresource", "bind_unix_socket", + # platform + "is_aix", # processes 'temp_umask', "reap_children", # logging @@ -815,6 +817,7 @@ def dec(*args, **kwargs): requires_lzma = unittest.skipUnless(lzma, 'requires lzma') is_jython = sys.platform.startswith('java') +is_aix = platform.system() == 'AIX' is_android = hasattr(sys, 'getandroidapilevel') diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index 35272b5c15aca7..0685ed85d2431b 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -10,6 +10,7 @@ from collections import namedtuple from test import support +is_aix = support.is_aix from test.support.script_helper import ( run_python_until_end, interpreter_requires_environment, @@ -40,7 +41,7 @@ # TODO: Once https://bugs.python.org/issue30672 is addressed, we'll be # able to check this case unconditionally EXPECTED_C_LOCALE_EQUIVALENTS.append("POSIX") -elif sys.platform.startswith("aix"): +elif is_aix: # AIX uses iso8859-1 in the C locale, other *nix platforms use ASCII EXPECTED_C_LOCALE_STREAM_ENCODING = "iso8859-1" EXPECTED_C_LOCALE_FS_ENCODING = "iso8859-1" From 219b577c43cce66f6ffa73964c14e817a9c34fc9 Mon Sep 17 00:00:00 2001 From: Michael Felt Date: Mon, 15 Apr 2019 15:13:50 +0000 Subject: [PATCH 212/212] Add constants in Lib/test/support to signify platform during testing --- Doc/whatsnew/3.8.rst | 10 ++++ Lib/test/_test_multiprocessing.py | 35 ++++++------- Lib/test/datetimetester.py | 8 +-- Lib/test/eintrdata/eintr_tester.py | 10 ++-- Lib/test/libregrtest/main.py | 2 +- Lib/test/libregrtest/setup.py | 2 +- Lib/test/support/__init__.py | 50 +++++++++--------- Lib/test/support/script_helper.py | 4 +- Lib/test/test___all__.py | 3 +- Lib/test/test__osx_support.py | 3 +- Lib/test/test_asynchat.py | 6 +-- Lib/test/test_asyncio/test_events.py | 51 +++++++++---------- Lib/test/test_asyncio/test_proactor_events.py | 3 +- Lib/test/test_asyncio/test_sendfile.py | 7 +-- Lib/test/test_asyncio/test_sock_lowlevel.py | 2 +- Lib/test/test_asyncio/test_streams.py | 4 +- Lib/test/test_asyncio/test_subprocess.py | 15 +++--- Lib/test/test_asyncio/test_unix_events.py | 2 +- Lib/test/test_asyncio/test_windows_events.py | 3 +- Lib/test/test_asyncio/test_windows_utils.py | 4 +- Lib/test/test_asyncore.py | 3 +- Lib/test/test_c_locale_coercion.py | 15 +++--- Lib/test/test_cmath.py | 4 +- Lib/test/test_cmd_line.py | 12 ++--- Lib/test/test_cmd_line_script.py | 4 +- Lib/test/test_codecs.py | 6 +-- Lib/test/test_codeop.py | 8 +-- Lib/test/test_concurrent_futures.py | 5 +- Lib/test/test_decimal.py | 8 +-- Lib/test/test_email/test_utils.py | 4 +- Lib/test/test_exceptions.py | 7 ++- Lib/test/test_faulthandler.py | 22 +++----- Lib/test/test_fcntl.py | 4 +- Lib/test/test_fileio.py | 13 ++--- Lib/test/test_gdb.py | 4 +- Lib/test/test_genericpath.py | 6 +-- Lib/test/test_glob.py | 6 +-- Lib/test/test_httpservers.py | 9 ++-- Lib/test/test_imp.py | 4 +- Lib/test/test_import/__init__.py | 12 ++--- Lib/test/test_importlib/source/test_finder.py | 4 +- Lib/test/test_importlib/test_windows.py | 4 +- Lib/test/test_importlib/util.py | 2 +- Lib/test/test_io.py | 6 +-- Lib/test/test_largefile.py | 4 +- Lib/test/test_locale.py | 14 +++-- Lib/test/test_logging.py | 9 ++-- Lib/test/test_math.py | 4 +- Lib/test/test_mimetypes.py | 3 +- Lib/test/test_mmap.py | 13 ++--- Lib/test/test_multiprocessing_fork.py | 5 +- Lib/test/test_multiprocessing_forkserver.py | 2 +- Lib/test/test_ntpath.py | 6 +-- Lib/test/test_os.py | 49 +++++++++--------- Lib/test/test_osx_env.py | 5 +- Lib/test/test_pathlib.py | 5 +- Lib/test/test_platform.py | 9 ++-- Lib/test/test_posix.py | 7 +-- Lib/test/test_regrtest.py | 7 +-- Lib/test/test_resource.py | 3 +- Lib/test/test_select.py | 4 +- Lib/test/test_selectors.py | 6 +-- Lib/test/test_shutil.py | 9 ++-- Lib/test/test_signal.py | 19 +++---- Lib/test/test_site.py | 8 +-- Lib/test/test_smtplib.py | 4 +- Lib/test/test_socket.py | 33 ++++++------ Lib/test/test_ssl.py | 9 ++-- Lib/test/test_stat.py | 5 +- Lib/test/test_strftime.py | 5 +- Lib/test/test_strptime.py | 6 +-- Lib/test/test_subprocess.py | 34 ++++++------- Lib/test/test_sundry.py | 3 +- Lib/test/test_sys.py | 5 +- Lib/test/test_sysconfig.py | 17 +++---- Lib/test/test_tarfile.py | 12 ++--- Lib/test/test_tcl.py | 2 +- Lib/test/test_tempfile.py | 8 +-- Lib/test/test_threading.py | 4 +- Lib/test/test_threadsignals.py | 9 ++-- Lib/test/test_time.py | 5 +- Lib/test/test_tix.py | 2 +- Lib/test/test_tools/test_sundry.py | 2 +- Lib/test/test_unicode.py | 13 ++--- Lib/test/test_unicode_file_functions.py | 9 ++-- Lib/test/test_urllib.py | 2 +- Lib/test/test_urllib2.py | 3 +- Lib/test/test_utf8_mode.py | 6 +-- Lib/test/test_venv.py | 9 ++-- Lib/test/test_wait4.py | 4 +- Lib/test/test_winconsoleio.py | 3 +- Lib/test/test_zipapp.py | 8 ++- .../2019-04-15-14-48-48.bpo-36624.yjmwEK.rst | 4 ++ 93 files changed, 409 insertions(+), 404 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-04-15-14-48-48.bpo-36624.yjmwEK.rst diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index d6388f8faaba4f..631b5ef218753e 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -460,6 +460,16 @@ in a standardized and extensible format, and offers several other benefits. (Contributed by C.A.M. Gerlach in :issue:`36268`.) +test +---- + +The :mod:`test` module now uses ``CONSTANTS`` for the major platforms +(``AIX``, ``ANDROID``, ``LINUX``, ``JYTHON``, ``MACOS``, ``MS_WINDOWS``) +to standardize the style compared to the current practice of some constants +and different styles of sys.platform and platform.system(). +The constants are defined in `test.support`. +(Contributed by M. Felt in :issue:`36624`.) + tokenize -------- diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 836fde88cd266d..cd7ff6b7262d19 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -25,6 +25,7 @@ import test.support import test.support.script_helper from test import support +from test.support import LINUX, MACOS, MS_WINDOWS # Skip tests if _multiprocessing wasn't built. @@ -108,8 +109,6 @@ def join_process(process): HAVE_GETVALUE = not getattr(_multiprocessing, 'HAVE_BROKEN_SEM_GETVALUE', False) -WIN32 = (sys.platform == "win32") - from multiprocessing.connection import wait def wait_for_handle(handle, timeout): @@ -508,7 +507,7 @@ def test_many_processes(self): join_process(p) if os.name != 'nt': exitcodes = [-signal.SIGTERM] - if sys.platform == 'darwin': + if MACOS: # bpo-31510: On macOS, killing a freshly started process with # SIGTERM sometimes kills the process with SIGKILL. exitcodes.append(-signal.SIGKILL) @@ -1487,7 +1486,7 @@ def _test_wait_result(cls, c, pid): os.kill(pid, signal.SIGINT) def test_wait_result(self): - if isinstance(self, ProcessesMixin) and sys.platform != 'win32': + if isinstance(self, ProcessesMixin) and not MS_WINDOWS: pid = os.getpid() else: pid = None @@ -3096,8 +3095,7 @@ def test_fd_transfer(self): self.assertEqual(f.read(), b"foo") @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction") - @unittest.skipIf(sys.platform == "win32", - "test semantics don't make sense on Windows") + @unittest.skipIf(MS_WINDOWS, "test semantics don't make sense on Windows") @unittest.skipIf(MAXFD <= 256, "largest assignable fd number is too small") @unittest.skipUnless(hasattr(os, "dup2"), @@ -3133,7 +3131,7 @@ def _send_data_without_fd(self, conn): os.write(conn.fileno(), b"\0") @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction") - @unittest.skipIf(sys.platform == "win32", "doesn't make sense on Windows") + @unittest.skipIf(MS_WINDOWS, "doesn't make sense on Windows") def test_missing_fd_transfer(self): # Check that exception is raised when received data is not # accompanied by a file descriptor in ancillary data. @@ -3747,7 +3745,7 @@ def test_shared_memory_SharedMemoryManager_basics(self): self.assertGreaterEqual(len(doppleganger_shm0.buf), 32) held_name = lom[0].name smm1.shutdown() - if sys.platform != "win32": + if not MS_WINDOWS: # Calls to unlink() have no effect on Windows platform; shared # memory will only be released once final process exits. with self.assertRaises(FileNotFoundError): @@ -3758,7 +3756,7 @@ def test_shared_memory_SharedMemoryManager_basics(self): sl = smm2.ShareableList("howdy") shm = smm2.SharedMemory(size=128) held_name = sl.shm.name - if sys.platform != "win32": + if not MS_WINDOWS: with self.assertRaises(FileNotFoundError): # No longer there to be attached to again. absent_sl = shared_memory.ShareableList(name=held_name) @@ -4011,7 +4009,7 @@ def get_module_names(self): def test_import(self): modules = self.get_module_names() - if sys.platform == 'win32': + if MS_WINDOWS: modules.remove('multiprocessing.popen_fork') modules.remove('multiprocessing.popen_forkserver') modules.remove('multiprocessing.popen_spawn_posix') @@ -4144,7 +4142,7 @@ def record(*args): class TestInvalidHandle(unittest.TestCase): - @unittest.skipIf(WIN32, "skipped on Windows") + @unittest.skipIf(MS_WINDOWS, "skipped on Windows") def test_invalid_handles(self): conn = multiprocessing.connection.Connection(44977608) # check that poll() doesn't crash @@ -4470,12 +4468,12 @@ def test_neg_timeout(self): class TestInvalidFamily(unittest.TestCase): - @unittest.skipIf(WIN32, "skipped on Windows") + @unittest.skipIf(MS_WINDOWS, "skipped on Windows") def test_invalid_family(self): with self.assertRaises(ValueError): multiprocessing.connection.Listener(r'\\.\test') - @unittest.skipUnless(WIN32, "skipped on non-Windows platforms") + @unittest.skipUnless(MS_WINDOWS, "skipped on non-Windows platforms") def test_invalid_family_win32(self): with self.assertRaises(ValueError): multiprocessing.connection.Listener('/var/test.pipe') @@ -4601,7 +4599,7 @@ def test_lock(self): class TestCloseFds(unittest.TestCase): def get_high_socket_fd(self): - if WIN32: + if MS_WINDOWS: # The child process will not have any socket handles, so # calling socket.fromfd() should produce WSAENOTSOCK even # if there is a handle of the same number. @@ -4619,7 +4617,7 @@ def get_high_socket_fd(self): return fd def close(self, fd): - if WIN32: + if MS_WINDOWS: socket.socket(socket.AF_INET, socket.SOCK_STREAM, fileno=fd).close() else: os.close(fd) @@ -4782,7 +4780,7 @@ def test_set_get(self): def test_get_all(self): methods = multiprocessing.get_all_start_methods() - if sys.platform == 'win32': + if MS_WINDOWS: self.assertEqual(methods, ['spawn']) else: self.assertTrue(methods == ['fork', 'spawn'] or @@ -4801,8 +4799,7 @@ def test_preload_resources(self): self.fail("failed spawning forkserver or grandchild") -@unittest.skipIf(sys.platform == "win32", - "test semantics don't make sense on Windows") +@unittest.skipIf(MS_WINDOWS, "test semantics don't make sense on Windows") class TestSemaphoreTracker(unittest.TestCase): def test_semaphore_tracker(self): @@ -5420,7 +5417,7 @@ def setUpModule(): raise unittest.SkipTest(start_method + ' start method not supported') - if sys.platform.startswith("linux"): + if LINUX: try: lock = multiprocessing.RLock() except OSError: diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index af0047fafd8770..d05f782a8aa4b3 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -2,7 +2,7 @@ See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases """ -from test.support import is_resource_enabled +from test.support import is_resource_enabled, MS_WINDOWS import itertools import bisect @@ -2453,13 +2453,13 @@ def test_insane_utcfromtimestamp(self): self.assertRaises(OverflowError, self.theclass.utcfromtimestamp, insane) - @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps") + @unittest.skipIf(MS_WINDOWS, "Windows doesn't accept negative timestamps") def test_negative_float_fromtimestamp(self): # The result is tz-dependent; at least test that this doesn't # fail (like it did before bug 1646728 was fixed). self.theclass.fromtimestamp(-1.05) - @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps") + @unittest.skipIf(MS_WINDOWS, "Windows doesn't accept negative timestamps") def test_negative_float_utcfromtimestamp(self): d = self.theclass.utcfromtimestamp(-1.05) self.assertEqual(d, self.theclass(1969, 12, 31, 23, 59, 58, 950000)) @@ -5700,7 +5700,7 @@ class ZoneInfoTest(unittest.TestCase): zonename = 'America/New_York' def setUp(self): - if sys.platform == "win32": + if MS_WINDOWS: self.skipTest("Skipping zoneinfo tests on Windows") try: self.tz = ZoneInfo.fromname(self.zonename) diff --git a/Lib/test/eintrdata/eintr_tester.py b/Lib/test/eintrdata/eintr_tester.py index 404934ce97a2bf..e76d7ffec200ea 100644 --- a/Lib/test/eintrdata/eintr_tester.py +++ b/Lib/test/eintrdata/eintr_tester.py @@ -22,6 +22,7 @@ import unittest from test import support +from test.support import MACOS @contextlib.contextmanager def kill_on_error(proc): @@ -347,8 +348,7 @@ def python_open(self, path): fp = open(path, 'w') fp.close() - @unittest.skipIf(sys.platform == "darwin", - "hangs under macOS; see bpo-25234, bpo-35363") + @unittest.skipIf(MACOS, "hangs under macOS; see bpo-25234, bpo-35363") def test_open(self): self._test_open("fp = open(path, 'r')\nfp.close()", self.python_open) @@ -357,8 +357,7 @@ def os_open(self, path): fd = os.open(path, os.O_WRONLY) os.close(fd) - @unittest.skipIf(sys.platform == "darwin", - "hangs under macOS; see bpo-25234, bpo-35363") + @unittest.skipIf(MACOS, "hangs under macOS; see bpo-25234, bpo-35363") def test_os_open(self): self._test_open("fd = os.open(path, os.O_RDONLY)\nos.close(fd)", self.os_open) @@ -439,8 +438,7 @@ def test_select(self): self.stop_alarm() self.assertGreaterEqual(dt, self.sleep_time) - @unittest.skipIf(sys.platform == "darwin", - "poll may fail on macOS; see issue #28087") + @unittest.skipIf(MACOS, "poll may fail on macOS; see issue #28087") @unittest.skipUnless(hasattr(select, 'poll'), 'need select.poll') def test_poll(self): poller = select.poll() diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index c19ea44db9b287..b2b7d29c4efbdd 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -608,7 +608,7 @@ def _main(self, tests, kwargs): # If we're on windows and this is the parent runner (not a worker), # track the load average. - if sys.platform == 'win32' and (self.ns.worker_args is None): + if support.MS_WINDOWS and (self.ns.worker_args is None): from test.libregrtest.win_utils import WindowsLoadTracker try: diff --git a/Lib/test/libregrtest/setup.py b/Lib/test/libregrtest/setup.py index 9a6585af9d0dd6..b8c8a64fe0c281 100644 --- a/Lib/test/libregrtest/setup.py +++ b/Lib/test/libregrtest/setup.py @@ -64,7 +64,7 @@ def setup_tests(ns): # fix is to set the stack limit to 2048. # This approach may also be useful for other Unixy platforms that # suffer from small default stack limits. - if sys.platform == 'darwin': + if support.MACOS: try: import resource except ImportError: diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 8f44aee7277929..e17ac11ead0110 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -36,6 +36,14 @@ import urllib.error import warnings +ANDROID = hasattr(sys, 'getandroidapilevel') +JYTHON = sys.platform.startswith('java') + +AIX = platform.system() == 'AIX' +LINUX = platform.system() == 'Linux' +MACOS = platform.system() == 'Darwin' +MS_WINDOWS = platform.system() == 'Windows' + from .testresult import get_test_runner try: @@ -96,13 +104,14 @@ "check__all__", "skip_unless_bind_unix_socket", "ignore_warnings", # sys - "is_jython", "is_android", "check_impl_detail", "unix_shell", + "check_impl_detail", "unix_shell", + "ANDROID", "JYTHON", "setswitchinterval", # network "HOST", "IPV6_ENABLED", "find_unused_port", "bind_port", "open_urlresource", "bind_unix_socket", # platform - "is_aix", + "AIX", "LINUX", "MACOS", "MS_WINDOWS", # processes 'temp_umask', "reap_children", # logging @@ -336,7 +345,7 @@ def _force_run(path, func, *args): os.chmod(path, stat.S_IRWXU) return func(*args) -if sys.platform.startswith("win"): +if MS_WINDOWS: def _waitfor(func, pathname, waitall=False): # Perform the operation func(pathname) @@ -487,7 +496,7 @@ def _is_gui_available(): if hasattr(_is_gui_available, 'result'): return _is_gui_available.result reason = None - if sys.platform.startswith('win'): + if MS_WINDOWS: # if Python is running as a service (such as the buildbot service), # gui interaction may be disallowed import ctypes @@ -513,7 +522,7 @@ class USEROBJECTFLAGS(ctypes.Structure): raise ctypes.WinError() if not bool(uof.dwFlags & WSF_VISIBLE): reason = "gui not available (WSF_VISIBLE flag not set)" - elif sys.platform == 'darwin': + elif MACOS: # The Aqua Tk implementations on OS X can abort the process if # being called in an environment where a window server connection # cannot be made, for instance when invoked by a buildbot or ssh @@ -629,7 +638,7 @@ def requires_mac_ver(*min_version): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): - if sys.platform == 'darwin': + if MACOS: version_txt = platform.mac_ver()[0] try: version = tuple(map(int, version_txt.split('.'))) @@ -816,13 +825,8 @@ def dec(*args, **kwargs): requires_lzma = unittest.skipUnless(lzma, 'requires lzma') -is_jython = sys.platform.startswith('java') -is_aix = platform.system() == 'AIX' - -is_android = hasattr(sys, 'getandroidapilevel') - -if sys.platform != 'win32': - unix_shell = '/system/bin/sh' if is_android else '/bin/sh' +if not MS_WINDOWS: + unix_shell = '/system/bin/sh' if ANDROID else '/bin/sh' else: unix_shell = None @@ -891,7 +895,7 @@ def dec(*args, **kwargs): # TESTFN_UNICODE is a non-ascii filename TESTFN_UNICODE = TESTFN + "-\xe0\xf2\u0258\u0141\u011f" -if sys.platform == 'darwin': +if MACOS: # In Mac OS X's VFS API file names are, by definition, canonically # decomposed Unicode, encoded using UTF-8. See QA1173: # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html @@ -919,7 +923,7 @@ def dec(*args, **kwargs): % (TESTFN_UNENCODABLE, TESTFN_ENCODING)) TESTFN_UNENCODABLE = None # Mac OS X denies unencodable filenames (invalid utf-8) -elif sys.platform != 'darwin': +elif not MACOS: try: # ascii and utf-8 cannot encode the byte 0xff b'\xff'.decode(TESTFN_ENCODING) @@ -1628,7 +1632,7 @@ def gc_collect(): objects to disappear. """ gc.collect() - if is_jython: + if JYTHON: time.sleep(0.1) gc.collect() gc.collect() @@ -2092,7 +2096,7 @@ def _check_docstrings(): """Just used to check if docstrings are enabled""" MISSING_C_DOCSTRINGS = (check_impl_detail() and - sys.platform != 'win32' and + not MS_WINDOWS and not sysconfig.get_config_var('WITH_DOC_STRINGS')) HAVE_DOCSTRINGS = (_check_docstrings.__doc__ is not None and @@ -2664,7 +2668,7 @@ def __enter__(self): On UNIX, try to save the previous core file size limit, then set soft limit to 0. """ - if sys.platform.startswith('win'): + if MS_WINDOWS: # see http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621.aspx # GetErrorMode is not available on Windows XP and Windows Server 2003, # but SetErrorMode returns the previous value, so we can use that @@ -2702,7 +2706,7 @@ def __enter__(self): except (ValueError, OSError): pass - if sys.platform == 'darwin': + if MACOS: # Check if the 'Crash Reporter' on OSX was configured # in 'Developer' mode and warn that it will get triggered # when it is. @@ -2727,7 +2731,7 @@ def __exit__(self, *ignore_exc): if self.old_value is None: return - if sys.platform.startswith('win'): + if MS_WINDOWS: self._k32.SetErrorMode(self.old_value) if self.old_modes: @@ -2846,7 +2850,7 @@ def setswitchinterval(interval): # Setting a very low gil interval on the Android emulator causes python # to hang (issue #26939). minimum_interval = 1e-5 - if is_android and interval < minimum_interval: + if ANDROID and interval < minimum_interval: global _is_android_emulator if _is_android_emulator is None: _is_android_emulator = (subprocess.check_output( @@ -2875,7 +2879,7 @@ def disable_faulthandler(): def fd_count(): """Count the number of open file descriptors. """ - if sys.platform.startswith(('linux', 'freebsd')): + if LINUX or sys.platform.startswith('freebsd'): try: names = os.listdir("/proc/self/fd") # Substract one because listdir() opens internally a file @@ -2892,7 +2896,7 @@ def fd_count(): pass old_modes = None - if sys.platform == 'win32': + if MACOS: # bpo-25306, bpo-31009: Call CrtSetReportMode() to not kill the process # on invalid file descriptor if Python is compiled in debug mode try: diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py index 27a47f2c4e668c..02411b97a46e8c 100644 --- a/Lib/test/support/script_helper.py +++ b/Lib/test/support/script_helper.py @@ -11,7 +11,7 @@ import zipfile from importlib.util import source_from_cache -from test.support import make_legacy_pyc, strip_python_stderr +from test.support import make_legacy_pyc, strip_python_stderr, MS_WINDOWS # Cached result of the expensive test performed in the function below. @@ -105,7 +105,7 @@ def run_python_until_end(*args, **env_vars): # caller is responsible to pass the full environment. if env_vars.pop('__cleanenv', None): env = {} - if sys.platform == 'win32': + if MS_WINDOWS: # Windows requires at least the SYSTEMROOT environment variable to # start Python. env['SYSTEMROOT'] = os.environ['SYSTEMROOT'] diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py index f6e82eb64ab025..c9f29e18605195 100644 --- a/Lib/test/test___all__.py +++ b/Lib/test/test___all__.py @@ -1,5 +1,6 @@ import unittest from test import support +from test.support import JYTHON import os import sys @@ -67,7 +68,7 @@ def test_all(self): '__future__', ]) - if not sys.platform.startswith('java'): + if not JYTHON: # In case _socket fails to build, make this test fail more gracefully # than an AttributeError somewhere deep in CGIHTTPServer. import _socket diff --git a/Lib/test/test__osx_support.py b/Lib/test/test__osx_support.py index 388a2b1a84b17c..4b5897232c2627 100644 --- a/Lib/test/test__osx_support.py +++ b/Lib/test/test__osx_support.py @@ -9,10 +9,11 @@ import unittest import test.support +from test.support import MACOS import _osx_support -@unittest.skipUnless(sys.platform.startswith("darwin"), "requires OS X") +@unittest.skipUnless(MACOS, "requires OS X") class Test_OSXSupport(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_asynchat.py b/Lib/test/test_asynchat.py index 1d147c741961e3..5b3cd0b32f90a9 100644 --- a/Lib/test/test_asynchat.py +++ b/Lib/test/test_asynchat.py @@ -1,6 +1,7 @@ # test asynchat from test import support +from test.support import HOST, MACOS import asynchat import asyncore @@ -13,7 +14,6 @@ import unittest import unittest.mock -HOST = support.HOST SERVER_QUIT = b'QUIT\n' TIMEOUT = 3.0 @@ -77,9 +77,9 @@ def __init__(self, terminator, server_port): def handle_connect(self): pass - if sys.platform == 'darwin': + if MACOS: # select.poll returns a select.POLLHUP at the end of the tests - # on darwin, so just ignore it + # on macOS, so just ignore it def handle_expt(self): pass diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index b46b614e556eae..7859756acfce55 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -22,7 +22,10 @@ from unittest import mock import weakref -if sys.platform != 'win32': +from test import support +from test.support import AIX, MACOS, MS_WINDOWS + +if not MS_WINDOWS: import tty import asyncio @@ -33,7 +36,6 @@ from asyncio import proactor_events from asyncio import selector_events from test.test_asyncio import utils as test_utils -from test import support def tearDownModule(): @@ -42,9 +44,9 @@ def tearDownModule(): def broken_unix_getsockname(): """Return True if the platform is Mac OS 10.4 or older.""" - if sys.platform.startswith("aix"): + if AIX: return True - elif sys.platform != 'darwin': + elif not MACOS: return False version = platform.mac_ver()[0] version = tuple(map(int, version.split('.'))) @@ -710,7 +712,7 @@ def client(): @unittest.skipIf(ssl is None, 'No ssl module') def test_ssl_connect_accepted_socket(self): - if (sys.platform == 'win32' and + if (MS_WINDOWS and sys.version_info < (3, 5) and isinstance(self.loop, proactor_events.BaseProactorEventLoop) ): @@ -1252,7 +1254,7 @@ def datagram_received(self, data, addr): server.transport.close() def test_create_datagram_endpoint_sock(self): - if (sys.platform == 'win32' and + if (MS_WINDOWS and isinstance(self.loop, proactor_events.BaseProactorEventLoop)): raise unittest.SkipTest( 'UDP is not supported with proactor event loops') @@ -1294,8 +1296,7 @@ def test_internal_fds(self): self.assertIsNone(loop._csock) self.assertIsNone(loop._ssock) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") def test_read_pipe(self): proto = MyReadPipeProto(loop=self.loop) @@ -1328,8 +1329,7 @@ async def connect(): # extra info is available self.assertIsNotNone(proto.transport.get_extra_info('pipe')) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") def test_unclosed_pipe_transport(self): # This test reproduces the issue #314 on GitHub loop = self.create_event_loop() @@ -1362,8 +1362,7 @@ async def connect(): read_transport._pipe = None write_transport._pipe = None - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") def test_read_pty_output(self): proto = MyReadPipeProto(loop=self.loop) @@ -1397,8 +1396,7 @@ async def connect(): # extra info is available self.assertIsNotNone(proto.transport.get_extra_info('pipe')) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") def test_write_pipe(self): rpipe, wpipe = os.pipe() pipeobj = io.open(wpipe, 'wb', 1024) @@ -1436,8 +1434,7 @@ def reader(data): self.loop.run_until_complete(proto.done) self.assertEqual('CLOSED', proto.state) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") def test_write_pipe_disconnect_on_close(self): rsock, wsock = socket.socketpair() rsock.setblocking(False) @@ -1459,8 +1456,7 @@ def test_write_pipe_disconnect_on_close(self): self.loop.run_until_complete(proto.done) self.assertEqual('CLOSED', proto.state) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") # select, poll and kqueue don't support character devices (PTY) on Mac OS X # older than 10.6 (Snow Leopard) @support.requires_mac_ver(10, 6) @@ -1503,8 +1499,7 @@ def reader(data): self.loop.run_until_complete(proto.done) self.assertEqual('CLOSED', proto.state) - @unittest.skipUnless(sys.platform != 'win32', - "Don't support pipes for Windows") + @unittest.skipIf(MS_WINDOWS, "Don't support pipes for Windows") # select, poll and kqueue don't support character devices (PTY) on Mac OS X # older than 10.6 (Snow Leopard) @support.requires_mac_ver(10, 6) @@ -1711,14 +1706,14 @@ def test(): class SubprocessTestsMixin: def check_terminated(self, returncode): - if sys.platform == 'win32': + if MS_WINDOWS: self.assertIsInstance(returncode, int) # expect 1 but sometimes get 0 else: self.assertEqual(-signal.SIGTERM, returncode) def check_killed(self, returncode): - if sys.platform == 'win32': + if MS_WINDOWS: self.assertIsInstance(returncode, int) # expect 1 but sometimes get 0 else: @@ -1839,7 +1834,7 @@ def test_subprocess_terminate(self): self.check_terminated(proto.returncode) transp.close() - @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") + @unittest.skipIf(MS_WINDOWS, "Don't have SIGHUP") def test_subprocess_send_signal(self): # bpo-31034: Make sure that we get the default signal handler (killing # the process). The parent process may have decided to ignore SIGHUP, @@ -1925,7 +1920,7 @@ def test_subprocess_close_client_stream(self): self.loop.run_until_complete(proto.disconnects[1]) stdin.write(b'xxx') self.loop.run_until_complete(proto.got_data[2].wait()) - if sys.platform != 'win32': + if not MS_WINDOWS: self.assertEqual(b'ERR:BrokenPipeError', proto.data[2]) else: # After closing the read-end of a pipe, writing to the @@ -1982,7 +1977,7 @@ async def connect(cmd=None, **kwds): self.loop.run_until_complete(connect(shell=False)) -if sys.platform == 'win32': +if MS_WINDOWS: class SelectEventLoopTests(EventLoopTestsMixin, test_utils.TestCase): @@ -2601,14 +2596,14 @@ def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) - if sys.platform != 'win32': + if not MS_WINDOWS: watcher = asyncio.SafeChildWatcher() watcher.attach_loop(self.loop) asyncio.set_child_watcher(watcher) def tearDown(self): try: - if sys.platform != 'win32': + if not MS_WINDOWS: asyncio.set_child_watcher(None) super().tearDown() @@ -2626,7 +2621,7 @@ def tearDown(self): asyncio.get_running_loop = self.get_running_loop_saved asyncio.get_event_loop = self.get_event_loop_saved - if sys.platform != 'win32': + if not MS_WINDOWS: def test_get_event_loop_new_process(self): # Issue bpo-32126: The multiprocessing module used by diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 5952ccccce0e5d..fad2bfd6c281c5 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -865,8 +865,7 @@ def test_stop_serving(self): self.assertFalse(future2.cancel.called) -@unittest.skipIf(sys.platform != 'win32', - 'Proactor is supported on Windows only') +@unittest.skipUnless(support.MS_WINDOWS, 'Proactor is supported on Windows only') class ProactorEventLoopUnixSockSendfileTests(test_utils.TestCase): DATA = b"12345abcde" * 16 * 1024 # 160 KiB diff --git a/Lib/test/test_asyncio/test_sendfile.py b/Lib/test/test_asyncio/test_sendfile.py index f148fe27e6ad40..18afe1b6ff8a46 100644 --- a/Lib/test/test_asyncio/test_sendfile.py +++ b/Lib/test/test_asyncio/test_sendfile.py @@ -10,6 +10,7 @@ from asyncio import constants from unittest import mock from test import support +from test.support import MS_WINDOWS from test.test_asyncio import utils as test_utils try: @@ -281,7 +282,7 @@ def cleanup(): self.addCleanup(cleanup) return srv_proto, cli_proto - @unittest.skipIf(sys.platform == 'win32', "UDP sockets are not supported") + @unittest.skipIf(MS_WINDOWS, "UDP sockets are not supported") def test_sendfile_not_supported(self): tr, pr = self.run_loop( self.loop.create_datagram_endpoint( @@ -327,7 +328,7 @@ def sendfile_native(transp, file, offset, count): self.assertEqual(self.file.tell(), len(self.DATA)) def test_sendfile_force_unsupported_native(self): - if sys.platform == 'win32': + if MS_WINDOWS: if isinstance(self.loop, asyncio.ProactorEventLoop): self.skipTest("Fails on proactor event loop") srv_proto, cli_proto = self.prepare_sendfile() @@ -507,7 +508,7 @@ class SendfileTestsBase(SendfileMixin, SockSendfileMixin): pass -if sys.platform == 'win32': +if MS_WINDOWS: class SelectEventLoopTests(SendfileTestsBase, test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py index 7b40a765e4a01f..04f939c9bac203 100644 --- a/Lib/test/test_asyncio/test_sock_lowlevel.py +++ b/Lib/test/test_asyncio/test_sock_lowlevel.py @@ -296,7 +296,7 @@ def test_create_connection_sock(self): tr.close() -if sys.platform == 'win32': +if support.MS_WINDOWS: class SelectEventLoopTests(BaseSockTestsMixin, test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 905141ca89c7ee..7507f47587df5d 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -10,6 +10,8 @@ import unittest from unittest import mock from test import support +from test.support import MS_WINDOWS + try: import ssl except ImportError: @@ -783,7 +785,7 @@ async def client(path): self.assertEqual(messages, []) - @unittest.skipIf(sys.platform == 'win32', "Don't have pipes") + @unittest.skipIf(MS_WINDOWS, "Don't have pipes") def test_read_all_from_pipe_reader(self): # See asyncio issue 168. This test is derived from the example # subprocess_attach_read_pipe.py, but we configure the diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 3908aabf5a1321..ba5870034d40df 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -9,8 +9,9 @@ from asyncio import subprocess from test.test_asyncio import utils as test_utils from test import support +from test.support import MS_WINDOWS -if sys.platform != 'win32': +if not MS_WINDOWS: from asyncio import unix_events # Program blocking @@ -171,7 +172,7 @@ def test_kill(self): proc = self.loop.run_until_complete(create) proc.kill() returncode = self.loop.run_until_complete(proc.wait()) - if sys.platform == 'win32': + if MS_WINDOWS: self.assertIsInstance(returncode, int) # expect 1 but sometimes get 0 else: @@ -183,13 +184,13 @@ def test_terminate(self): proc = self.loop.run_until_complete(create) proc.terminate() returncode = self.loop.run_until_complete(proc.wait()) - if sys.platform == 'win32': + if MS_WINDOWS: self.assertIsInstance(returncode, int) # expect 1 but sometimes get 0 else: self.assertEqual(-signal.SIGTERM, returncode) - @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") + @unittest.skipIf(MS_WINDOWS, "Don't have SIGHUP") def test_send_signal(self): # bpo-31034: Make sure that we get the default signal handler (killing # the process). The parent process may have decided to ignore SIGHUP, @@ -464,14 +465,14 @@ async def kill_running(): # Unlike SafeChildWatcher, FastChildWatcher does not pop the # callbacks if waitpid() is called elsewhere. Let's clear them # manually to avoid a warning when the watcher is detached. - if (sys.platform != 'win32' and + if (not MS_WINDOWS and isinstance(self, SubprocessFastWatcherTests)): asyncio.get_child_watcher()._callbacks.clear() def test_popen_error(self): # Issue #24763: check that the subprocess transport is closed # when BaseSubprocessTransport fails - if sys.platform == 'win32': + if MS_WINDOWS: target = 'asyncio.windows_utils.Popen' else: target = 'subprocess.Popen' @@ -523,7 +524,7 @@ def test_process_create_warning(self): subprocess.Process(transp, proto, loop=self.loop) -if sys.platform != 'win32': +if not MS_WINDOWS: # Unix class SubprocessWatcherMixin(SubprocessMixin): diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 31e710037f76a3..bd7ba4c83da901 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -16,7 +16,7 @@ from unittest import mock from test import support -if sys.platform == 'win32': +if support.MS_WINDOWS: raise unittest.SkipTest('UNIX only') diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index 05f85159be0cd5..78de46d002c748 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -7,8 +7,9 @@ import threading import unittest from unittest import mock +from test.support import MS_WINDOWS -if sys.platform != 'win32': +if not MS_WINDOWS: raise unittest.SkipTest('Windows only') import _overlapped diff --git a/Lib/test/test_asyncio/test_windows_utils.py b/Lib/test/test_asyncio/test_windows_utils.py index 45c09bb4a2d3a0..5bf399a4298b5c 100644 --- a/Lib/test/test_asyncio/test_windows_utils.py +++ b/Lib/test/test_asyncio/test_windows_utils.py @@ -3,8 +3,9 @@ import sys import unittest import warnings +from test import support -if sys.platform != 'win32': +if not support.MS_WINDOWS: raise unittest.SkipTest('Windows only') import _overlapped @@ -12,7 +13,6 @@ import asyncio from asyncio import windows_utils -from test import support def tearDownModule(): diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py index 3fcedb58ec18a6..9516621390eab5 100644 --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -10,6 +10,7 @@ import threading from test import support +from test.support import MACOS from io import BytesIO if support.PGO: @@ -658,7 +659,7 @@ def test_handle_expt(self): if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX: self.skipTest("Not applicable to AF_UNIX sockets.") - if sys.platform == "darwin" and self.use_poll: + if MACOS and self.use_poll: self.skipTest("poll may fail on macOS; see issue #28087") class TestClient(BaseClient): diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index 0685ed85d2431b..8d3c0edf87a72e 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -10,7 +10,8 @@ from collections import namedtuple from test import support -is_aix = support.is_aix +from test.support import AIX, ANDROID, LINUX, MACOS + from test.support.script_helper import ( run_python_until_end, interpreter_requires_environment, @@ -30,8 +31,8 @@ TARGET_LOCALES = ["C.UTF-8", "C.utf8", "UTF-8"] # Apply some platform dependent overrides -if sys.platform.startswith("linux"): - if support.is_android: +if LINUX: + if ANDROID: # Android defaults to using UTF-8 for all system interfaces EXPECTED_C_LOCALE_STREAM_ENCODING = "utf-8" EXPECTED_C_LOCALE_FS_ENCODING = "utf-8" @@ -41,11 +42,11 @@ # TODO: Once https://bugs.python.org/issue30672 is addressed, we'll be # able to check this case unconditionally EXPECTED_C_LOCALE_EQUIVALENTS.append("POSIX") -elif is_aix: +elif AIX: # AIX uses iso8859-1 in the C locale, other *nix platforms use ASCII EXPECTED_C_LOCALE_STREAM_ENCODING = "iso8859-1" EXPECTED_C_LOCALE_FS_ENCODING = "iso8859-1" -elif sys.platform == "darwin": +elif MACOS: # FS encoding is UTF-8 on macOS EXPECTED_C_LOCALE_FS_ENCODING = "utf-8" elif sys.platform == "cygwin": @@ -79,7 +80,7 @@ # `locale.nl_langinfo(locale.CODESET)` works, as if it fails, the interpreter # will skip locale coercion for that particular target locale _check_nl_langinfo_CODESET = bool( - sys.platform not in ("darwin", "linux") and + not (MACOS or LINUX) and hasattr(locale, "nl_langinfo") and hasattr(locale, "CODESET") ) @@ -348,7 +349,7 @@ def _check_c_locale_coercion(self, # locale environment variables are undefined or empty. When # this code path is run with environ['LC_ALL'] == 'C', then # LEGACY_LOCALE_WARNING is printed. - if (support.is_android and + if (support.ANDROID and _expected_warnings == [CLI_COERCION_WARNING]): _expected_warnings = None self._check_child_encoding_details(base_var_dict, diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py index 43a074b4b66353..81a1991e0c1b93 100644 --- a/Lib/test/test_cmath.py +++ b/Lib/test/test_cmath.py @@ -1,4 +1,4 @@ -from test.support import requires_IEEE_754, cpython_only +from test.support import requires_IEEE_754, cpython_only, MACOS from test.test_math import parse_testfile, test_file import test.test_math as test_math import unittest @@ -339,7 +339,7 @@ def test_specific_values(self): SKIP_ON_TIGER = {'tan0064'} osx_version = None - if sys.platform == 'darwin': + if MACOS: version_txt = platform.mac_ver()[0] try: osx_version = tuple(map(int, version_txt.split('.'))) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index f7925eb795c71e..4db4cf6a616308 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -9,6 +9,7 @@ import tempfile import unittest from test import support +from test.support import MS_WINDOWS, MACOS, ANDROID from test.support.script_helper import ( spawn_python, kill_python, assert_python_ok, assert_python_failure, interpreter_requires_environment @@ -152,8 +153,7 @@ def test_non_ascii(self): # command line, but how subprocess does decode bytes to unicode. Python # doesn't decode the command line because Windows provides directly the # arguments as unicode (using wmain() instead of main()). - @unittest.skipIf(sys.platform == 'win32', - 'Windows has a native unicode API') + @unittest.skipIf(MS_WINDOWS, 'Windows has a native unicode API') def test_undecodable_code(self): undecodable = b"\xff" env = os.environ.copy() @@ -187,8 +187,7 @@ def test_undecodable_code(self): if not stdout.startswith(pattern): raise AssertionError("%a doesn't start with %a" % (stdout, pattern)) - @unittest.skipUnless((sys.platform == 'darwin' or - support.is_android), 'test specific to Mac OS X and Android') + @unittest.skipUnless((MACOS or ANDROID), 'test specific to Mac OS X and Android') def test_osx_android_utf8(self): def check_output(text): decoded = text.decode('utf-8', 'surrogateescape') @@ -331,7 +330,7 @@ def test_output_newline(self): print(4, file=sys.stderr)""" rc, out, err = assert_python_ok('-c', code) - if sys.platform == 'win32': + if MS_WINDOWS: self.assertEqual(b'1\r\n2\r\n', out) self.assertEqual(b'3\r\n4', err) else: @@ -729,8 +728,7 @@ def test_pythondevmode_env(self): self.assertEqual(proc.stdout.rstrip(), 'True') self.assertEqual(proc.returncode, 0, proc) - @unittest.skipUnless(sys.platform == 'win32', - 'bpo-32457 only applies on Windows') + @unittest.skipUnless(MS_WINDOWS, 'bpo-32457 only applies on Windows') def test_argv0_normalization(self): args = sys.executable, '-c', 'print(0)' prefix, exe = os.path.split(sys.executable) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index d138ca027c6848..7d9d2e64f11cbe 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -14,6 +14,7 @@ import textwrap from test import support +from test.support import MACOS, MS_WINDOWS from test.support.script_helper import ( make_pkg, make_script, make_zip_pkg, make_zip_script, assert_python_ok, assert_python_failure, spawn_python, kill_python) @@ -532,8 +533,7 @@ def test_non_ascii(self): # Mac OS X denies the creation of a file with an invalid UTF-8 name. # Windows allows creating a name with an arbitrary bytes name, but # Python cannot a undecodable bytes argument to a subprocess. - if (support.TESTFN_UNDECODABLE - and sys.platform not in ('win32', 'darwin')): + if (support.TESTFN_UNDECODABLE and not (MACOS or MS_WINDOWS)): name = os.fsdecode(support.TESTFN_UNDECODABLE) elif support.TESTFN_NONASCII: name = support.TESTFN_NONASCII diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 027a84e275e369..f908d2ea16a0df 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -875,8 +875,7 @@ def test_surrogatepass_handler(self): b"abc\xed\xa0z".decode(self.encoding, "surrogatepass") -@unittest.skipUnless(sys.platform == 'win32', - 'cp65001 is a Windows-only codec') +@unittest.skipUnless(support.MS_WINDOWS, 'cp65001 is a Windows-only codec') class CP65001Test(ReadTest, unittest.TestCase): encoding = "cp65001" @@ -2956,8 +2955,7 @@ def decode_to_bytes(*args, **kwds): -@unittest.skipUnless(sys.platform == 'win32', - 'code pages are specific to Windows') +@unittest.skipUnless(support.MS_WINDOWS, 'code pages are specific to Windows') class CodePageTest(unittest.TestCase): # CP_UTF8 is already tested by CP65001Test CP_UTF8 = 65001 diff --git a/Lib/test/test_codeop.py b/Lib/test/test_codeop.py index 98da26fa5dab13..71d9432ddd1d2b 100644 --- a/Lib/test/test_codeop.py +++ b/Lib/test/test_codeop.py @@ -3,12 +3,12 @@ Nick Mathewson """ import unittest -from test.support import is_jython +from test.support import JYTHON from codeop import compile_command, PyCF_DONT_IMPLY_DEDENT import io -if is_jython: +if JYTHON: import sys def unify_callables(d): @@ -21,7 +21,7 @@ class CodeopTests(unittest.TestCase): def assertValid(self, str, symbol='single'): '''succeed iff str is a valid piece of code''' - if is_jython: + if JYTHON: code = compile_command(str, "", symbol) self.assertTrue(code) if symbol == "single": @@ -60,7 +60,7 @@ def test_valid(self): av = self.assertValid # special case - if not is_jython: + if not JYTHON: self.assertEqual(compile_command(""), compile("pass", "", 'single', PyCF_DONT_IMPLY_DEDENT)) diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index 903afbd2a4f68a..4fc9e32e56e55a 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -5,6 +5,7 @@ # Skip tests if sem_open implementation is broken. test.support.import_module('multiprocessing.synchronize') +from test.support import MS_WINDOWS from test.support.script_helper import assert_python_ok import contextlib @@ -156,7 +157,7 @@ class ProcessPoolForkMixin(ExecutorMixin): ctx = "fork" def get_context(self): - if sys.platform == "win32": + if MS_WINDOWS: self.skipTest("require unix system") return super().get_context() @@ -171,7 +172,7 @@ class ProcessPoolForkserverMixin(ExecutorMixin): ctx = "forkserver" def get_context(self): - if sys.platform == "win32": + if MS_WINDOWS: self.skipTest("require unix system") return super().get_context() diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 1f37b5372a3e7e..56fd5418e7c626 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -35,7 +35,7 @@ from test.support import (run_unittest, run_doctest, is_resource_enabled, requires_IEEE_754, requires_docstrings) from test.support import (import_fresh_module, TestFailed, - run_with_locale, cpython_only) + run_with_locale, cpython_only, MS_WINDOWS) import random import inspect import threading @@ -4862,7 +4862,7 @@ def test_c_context_errors(self): for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'): self.assertRaises(OverflowError, setattr, c, attr, int_max+1) self.assertRaises(OverflowError, setattr, c, attr, -int_max-2) - if sys.platform != 'win32': + if not MS_WINDOWS: self.assertRaises(ValueError, setattr, c, attr, int_max) self.assertRaises(ValueError, setattr, c, attr, -int_max-1) @@ -4937,7 +4937,7 @@ def test_c_context_errors_extra(self): # OverflowError, general ValueError self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1) self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2) - if sys.platform != 'win32': + if not MS_WINDOWS: self.assertRaises(ValueError, setattr, c, '_allcr', int_max) self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1) @@ -4945,7 +4945,7 @@ def test_c_context_errors_extra(self): for attr in ('_flags', '_traps'): self.assertRaises(OverflowError, setattr, c, attr, int_max+1) self.assertRaises(OverflowError, setattr, c, attr, -int_max-2) - if sys.platform != 'win32': + if not MS_WINDOWS: self.assertRaises(TypeError, setattr, c, attr, int_max) self.assertRaises(TypeError, setattr, c, attr, -int_max-1) diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py index 4e3c3f3a195fc4..4fbdd47c2fa3cf 100644 --- a/Lib/test/test_email/test_utils.py +++ b/Lib/test/test_email/test_utils.py @@ -1,6 +1,7 @@ import datetime from email import utils import test.support +from test.support import MS_WINDOWS import time import unittest import sys @@ -124,8 +125,7 @@ def test_localtime_epoch_notz_daylight_false(self): self.assertEqual(t1, t2) # XXX: Need a more robust test for Olson's tzdata - @unittest.skipIf(sys.platform.startswith('win'), - "Windows does not use Olson's TZ database") + @unittest.skipIf(MS_WINDOWS, "Windows does not use Olson's TZ database") @unittest.skipUnless(os.path.exists('/usr/share/zoneinfo') or os.path.exists('/usr/lib/zoneinfo'), "Can't find the Olson's TZ database") diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 6ef529e2b015be..749654068f2c21 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -11,7 +11,7 @@ from test.support import (TESTFN, captured_stderr, check_impl_detail, check_warnings, cpython_only, gc_collect, run_unittest, no_tracing, unlink, import_module, script_helper, - SuppressCrashReport) + SuppressCrashReport, JYTHON, MS_WINDOWS) class NaiveException(Exception): def __init__(self, x): self.x = x @@ -270,7 +270,7 @@ def test_capi3(): self.assertRaises(SystemError, _testcapi.raise_exception, InvalidException, 1) - if not sys.platform.startswith('java'): + if not JYTHON: test_capi1() test_capi2() test_capi3() @@ -314,8 +314,7 @@ def test_WindowsError(self): self.assertEqual(w.filename, None) self.assertEqual(w.filename2, None) - @unittest.skipUnless(sys.platform == 'win32', - 'test specific to Windows') + @unittest.skipUnless(MS_WINDOWS, 'test specific to Windows') def test_windows_message(self): """Should fill in unknown error code in Windows error message""" ctypes = import_module('ctypes') diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index f0be91844ffa7c..f35fc0ff07a7c9 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -7,7 +7,7 @@ import sys import sysconfig from test import support -from test.support import script_helper, is_android +from test.support import script_helper, ANDROID, AIX, MS_WINDOWS import tempfile import threading import unittest @@ -19,7 +19,6 @@ _testcapi = None TIMEOUT = 0.5 -MS_WINDOWS = (os.name == 'nt') _cflags = sysconfig.get_config_var('CFLAGS') or '' _config_args = sysconfig.get_config_var('CONFIG_ARGS') or '' UB_SANITIZER = ( @@ -43,7 +42,7 @@ def expected_traceback(lineno1, lineno2, header, min_count=1): def skip_segfault_on_android(test): # Issue #32138: Raising SIGSEGV on Android may not cause a crash. - return unittest.skipIf(is_android, + return unittest.skipIf(ANDROID, 'raising SIGSEGV on Android is unreliable')(test) @contextmanager @@ -130,8 +129,7 @@ def check_windows_exception(self, code, line_number, name_regex, **kw): fatal_error = 'Windows fatal exception: %s' % name_regex self.check_error(code, line_number, fatal_error, **kw) - @unittest.skipIf(sys.platform.startswith('aix'), - "the first page of memory is a mapped read-only on AIX") + @unittest.skipIf(AIX, "the first page of memory is a mapped read-only on AIX") def test_read_null(self): if not MS_WINDOWS: self.check_fatal_error(""" @@ -182,7 +180,7 @@ def test_sigabrt(self): 3, 'Aborted') - @unittest.skipIf(sys.platform == 'win32', + @unittest.skipIf(MS_WINDOWS, "SIGFPE cannot be caught on Windows") def test_sigfpe(self): self.check_fatal_error(""" @@ -277,8 +275,7 @@ def test_enable_file(self): 'Segmentation fault', filename=filename) - @unittest.skipIf(sys.platform == "win32", - "subprocess doesn't support pass_fds on Windows") + @unittest.skipIf(MS_WINDOWS, "subprocess doesn't support pass_fds on Windows") @unittest.skipIf(UB_SANITIZER or MEMORY_SANITIZER, "sanitizer builds change crashing process output.") @skip_segfault_on_android @@ -434,8 +431,7 @@ def test_dump_traceback_file(self): with temporary_filename() as filename: self.check_dump_traceback(filename=filename) - @unittest.skipIf(sys.platform == "win32", - "subprocess doesn't support pass_fds on Windows") + @unittest.skipIf(MS_WINDOWS, "subprocess doesn't support pass_fds on Windows") def test_dump_traceback_fd(self): with tempfile.TemporaryFile('wb+') as fp: self.check_dump_traceback(fd=fp.fileno()) @@ -607,8 +603,7 @@ def test_dump_traceback_later_file(self): with temporary_filename() as filename: self.check_dump_traceback_later(filename=filename) - @unittest.skipIf(sys.platform == "win32", - "subprocess doesn't support pass_fds on Windows") + @unittest.skipIf(MS_WINDOWS, "subprocess doesn't support pass_fds on Windows") def test_dump_traceback_later_fd(self): with tempfile.TemporaryFile('wb+') as fp: self.check_dump_traceback_later(fd=fp.fileno()) @@ -709,8 +704,7 @@ def test_register_file(self): with temporary_filename() as filename: self.check_register(filename=filename) - @unittest.skipIf(sys.platform == "win32", - "subprocess doesn't support pass_fds on Windows") + @unittest.skipIf(MS_WINDOWS, "subprocess doesn't support pass_fds on Windows") def test_register_fd(self): with tempfile.TemporaryFile('wb+') as fp: self.check_register(fd=fp.fileno()) diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index 5d4abe388f7828..61148326e6e43d 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -6,7 +6,7 @@ import sys import unittest from test.support import (verbose, TESTFN, unlink, run_unittest, import_module, - cpython_only) + cpython_only, MACOS) # Skip test if no fcntl module. fcntl = import_module('fcntl') @@ -23,7 +23,7 @@ def get_lockdata(): start_len = "qq" if (sys.platform.startswith(('netbsd', 'freebsd', 'openbsd')) - or sys.platform == 'darwin'): + or MACOS): if struct.calcsize('l') == 8: off_t = 'l' pid_t = 'i' diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index 57a02656206ff4..bf85fb5845fb4b 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -10,7 +10,8 @@ from functools import wraps from test.support import (TESTFN, TESTFN_UNICODE, check_warnings, run_unittest, - make_bad_fd, cpython_only, swap_attr) + make_bad_fd, cpython_only, swap_attr, + AIX, MACOS, MS_WINDOWS) from collections import UserList import _io # C implementation of io @@ -371,7 +372,7 @@ def testAbles(self): self.assertEqual(f.isatty(), False) f.close() - if sys.platform != "win32": + if not MS_WINDOWS: try: f = self.FileIO("/dev/tty", "a") except OSError: @@ -382,9 +383,9 @@ def testAbles(self): else: self.assertEqual(f.readable(), False) self.assertEqual(f.writable(), True) - if sys.platform != "darwin" and \ - 'bsd' not in sys.platform and \ - not sys.platform.startswith(('sunos', 'aix')): + if not (AIX or MACOS) \ + and 'bsd' not in sys.platform \ + and not sys.platform.startswith('sunos'): # Somehow /dev/tty appears seekable on some BSDs self.assertEqual(f.seekable(), False) self.assertEqual(f.isatty(), True) @@ -464,7 +465,7 @@ def testConstructorHandlesNULChars(self): def testInvalidFd(self): self.assertRaises(ValueError, self.FileIO, -10) self.assertRaises(OSError, self.FileIO, make_bad_fd()) - if sys.platform == 'win32': + if MS_WINDOWS: import msvcrt self.assertRaises(OSError, msvcrt.get_osfhandle, make_bad_fd()) diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py index 4d1ce4ed96c06d..da0d6f2708042f 100644 --- a/Lib/test/test_gdb.py +++ b/Lib/test/test_gdb.py @@ -13,7 +13,7 @@ import unittest from test import support -from test.support import run_unittest, findfile, python_is_optimized +from test.support import run_unittest, findfile, python_is_optimized, MACOS def get_gdb_version(): try: @@ -48,7 +48,7 @@ def get_gdb_version(): if not sysconfig.is_python_build(): raise unittest.SkipTest("test_gdb only works on source builds at the moment.") -if 'Clang' in platform.python_compiler() and sys.platform == 'darwin': +if 'Clang' in platform.python_compiler() and MACOS: raise unittest.SkipTest("test_gdb doesn't work correctly when python is" " built with LLVM clang") diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py index 9d5ac44b6d06a7..ce44454318e55a 100644 --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -9,7 +9,7 @@ import warnings from test import support from test.support.script_helper import assert_python_ok -from test.support import FakePath +from test.support import FakePath, MACOS, MS_WINDOWS def create_file(filename, data=b'foo'): @@ -436,7 +436,7 @@ def test_abspath(self): self.assertIn(b"foo", self.pathmodule.abspath(b"foo")) # avoid UnicodeDecodeError on Windows - undecodable_path = b'' if sys.platform == 'win32' else b'f\xf2\xf2' + undecodable_path = b'' if MS_WINDOWS else b'f\xf2\xf2' # Abspath returns bytes when the arg is bytes with warnings.catch_warnings(): @@ -479,7 +479,7 @@ def test_nonascii_abspath(self): # UTF-8 name. Windows allows creating a directory with an # arbitrary bytes name, but fails to enter this directory # (when the bytes name is used). - and sys.platform not in ('win32', 'darwin')): + and not (MACOS or MS_WINDOWS)): name = support.TESTFN_UNDECODABLE elif support.TESTFN_NONASCII: name = support.TESTFN_NONASCII diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py index 767bd3764b8925..43dc720a1cd4dd 100644 --- a/Lib/test/test_glob.py +++ b/Lib/test/test_glob.py @@ -4,7 +4,7 @@ import sys import unittest -from test.support import (TESTFN, skip_unless_symlink, +from test.support import (TESTFN, skip_unless_symlink, MS_WINDOWS, can_symlink, create_empty_file, change_cwd) @@ -161,7 +161,7 @@ def test_glob_broken_symlinks(self): eq(self.glob('sym1'), [self.norm('sym1')]) eq(self.glob('sym2'), [self.norm('sym2')]) - @unittest.skipUnless(sys.platform == "win32", "Win32 specific test") + @unittest.skipUnless(MS_WINDOWS, "Win32 specific test") def test_glob_magic_in_drive(self): eq = self.assertSequencesEqual_noorder eq(glob.glob('*:'), []) @@ -186,7 +186,7 @@ def test_escape(self): check('[[_/*?*/_]]', '[[][[]_/[*][?][*]/_]]') check('/[[_/*?*/_]]/', '/[[][[]_/[*][?][*]/_]]/') - @unittest.skipUnless(sys.platform == "win32", "Win32 specific test") + @unittest.skipUnless(MS_WINDOWS, "Win32 specific test") def test_escape_windows(self): check = self.check_escape check('?:?', '?:[?]') diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 8357ee9145d7e5..abda3ad44cb93a 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -29,6 +29,7 @@ import unittest from test import support +from test.support import MACOS, MS_WINDOWS class NoLogRequestHandler: @@ -385,10 +386,8 @@ def close_conn(): reader.close() return body - @unittest.skipIf(sys.platform == 'darwin', - 'undecodable name cannot always be decoded on macOS') - @unittest.skipIf(sys.platform == 'win32', - 'undecodable name cannot be decoded on win32') + @unittest.skipIf(MACOS, 'undecodable name cannot always be decoded on macOS') + @unittest.skipIf(MS_WINDOWS, 'undecodable name cannot be decoded on win32') @unittest.skipUnless(support.TESTFN_UNDECODABLE, 'need support.TESTFN_UNDECODABLE') def test_undecodable_filename(self): @@ -397,7 +396,7 @@ def test_undecodable_filename(self): with open(os.path.join(self.tempdir, filename), 'wb') as f: f.write(support.TESTFN_UNDECODABLE) response = self.request(self.base_url + '/') - if sys.platform == 'darwin': + if MACOS: # On Mac OS the HFS+ filesystem replaces bytes that aren't valid # UTF-8 into a percent-encoded value. for name in os.listdir(self.tempdir): diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py index fe394dc50c56b1..2cbfabd8c2c3bc 100644 --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -5,7 +5,7 @@ import py_compile import sys from test import support -from test.support import script_helper +from test.support import script_helper, MACOS import unittest import warnings with warnings.catch_warnings(): @@ -136,7 +136,7 @@ def test_issue5604(self): 'cp1258' : b'\xc0', } - if sys.platform == 'darwin': + if MACOS: self.assertEqual(fs_encoding, 'utf-8') # Mac OS X uses the Normal Form D decomposition # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 109b01413b2d84..bdc3dbe167ff06 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -23,10 +23,10 @@ import test.support from test.support import ( - EnvironmentVarGuard, TESTFN, check_warnings, forget, is_jython, + EnvironmentVarGuard, TESTFN, check_warnings, forget, JYTHON, make_legacy_pyc, rmtree, run_unittest, swap_attr, swap_item, temp_umask, unlink, unload, create_empty_file, cpython_only, TESTFN_UNENCODABLE, - temp_dir, DirsOnSysPath) + temp_dir, DirsOnSysPath, MS_WINDOWS) from test.support import script_helper from test.test_importlib.util import uncache @@ -151,7 +151,7 @@ def test_import(self): def test_with_extension(ext): # The extension is normally ".py", perhaps ".pyw". source = TESTFN + ext - if is_jython: + if JYTHON: pyc = TESTFN + "$py.class" else: pyc = TESTFN + ".pyc" @@ -185,7 +185,7 @@ def test_with_extension(ext): sys.path.insert(0, os.curdir) try: test_with_extension(".py") - if sys.platform.startswith("win"): + if MS_WINDOWS: for ext in [".PY", ".Py", ".pY", ".pyw", ".PYW", ".pYw"]: test_with_extension(ext) finally: @@ -463,7 +463,7 @@ def run(): finally: del sys.path[0] - @unittest.skipUnless(sys.platform == "win32", "Windows-specific") + @unittest.skipUnless(MS_WINDOWS, "Windows-specific") def test_dll_dependency_import(self): from _winapi import GetModuleFileName dllname = GetModuleFileName(sys.dllhandle) @@ -711,7 +711,7 @@ def test_trailing_slash(self): unload("test_trailing_slash") # Regression test for http://bugs.python.org/issue3677. - @unittest.skipUnless(sys.platform == 'win32', 'Windows-specific') + @unittest.skipUnless(MS_WINDOWS, 'Windows-specific') def test_UNC_path(self): with open(os.path.join(self.path, 'test_unc_path.py'), 'w') as f: f.write("testdata = 'test_unc_path'") diff --git a/Lib/test/test_importlib/source/test_finder.py b/Lib/test/test_importlib/source/test_finder.py index f372b850dc7c15..bdad0c69cfa334 100644 --- a/Lib/test/test_importlib/source/test_finder.py +++ b/Lib/test/test_importlib/source/test_finder.py @@ -9,7 +9,7 @@ import stat import sys import tempfile -from test.support import make_legacy_pyc +from test.support import make_legacy_pyc, MS_WINDOWS import unittest import warnings @@ -153,7 +153,7 @@ def test_dir_removal_handling(self): found = self._find(finder, 'mod', loader_only=True) self.assertIsNone(found) - @unittest.skipUnless(sys.platform != 'win32', + @unittest.skipIf(MS_WINDOWS, 'os.chmod() does not support the needed arguments under Windows') def test_no_read_directory(self): # Issue #16730 diff --git a/Lib/test/test_importlib/test_windows.py b/Lib/test/test_importlib/test_windows.py index 005b685cc03cd9..115b7f842823ec 100644 --- a/Lib/test/test_importlib/test_windows.py +++ b/Lib/test/test_importlib/test_windows.py @@ -54,7 +54,7 @@ def setup_module(machinery, name, path=None): delete_registry_tree(HKEY_CURRENT_USER, key) -@unittest.skipUnless(sys.platform.startswith('win'), 'requires Windows') +@unittest.skipUnless(support.MS_WINDOWS, 'requires Windows') class WindowsRegistryFinderTests: # The module name is process-specific, allowing for # simultaneous runs of the same test on a single machine. @@ -86,7 +86,7 @@ def test_module_not_found(self): Source_WindowsRegistryFinderTests ) = test_util.test_both(WindowsRegistryFinderTests, machinery=machinery) -@unittest.skipUnless(sys.platform.startswith('win'), 'requires Windows') +@unittest.skipUnless(support.MS_WINDOWS, 'requires Windows') class WindowsExtensionSuffixTests: def test_tagged_suffix(self): suffixes = self.machinery.EXTENSION_SUFFIXES diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index 196ea1c9d4dda5..b3f3fd5e85345e 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -92,7 +92,7 @@ def test_both(test_class, base=None, **kwargs): CASE_INSENSITIVE_FS = True # Windows is the only OS that is *always* case-insensitive # (OS X *can* be case-sensitive). -if sys.platform not in ('win32', 'cygwin'): +if not (support.MS_WINDOWS or support.MACOS): changed_name = __file__.upper() if changed_name == __file__: changed_name = __file__.lower() diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 5406a2891bb251..dbdcaf165f8ae5 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -38,7 +38,7 @@ from itertools import cycle, count from test import support from test.support.script_helper import assert_python_ok, run_python_until_end -from test.support import FakePath +from test.support import FakePath, MACOS, MS_WINDOWS import codecs import io # C implementation of io @@ -500,7 +500,7 @@ class UnseekableWriter(self.MockUnseekableIO): else: self.assertRaises(OSError, obj.write, data) - if sys.platform.startswith("win") and test in ( + if MS_WINDOWS and test in ( pipe_reader, pipe_writer): # Pipes seem to appear as seekable on Windows continue @@ -596,7 +596,7 @@ def test_large_file_ops(self): # On Windows and Mac OSX this test consumes large resources; It takes # a long time to build the >2 GiB file and takes >2 GiB of disk space # therefore the resource must be enabled to run this test. - if sys.platform[:3] == 'win' or sys.platform == 'darwin': + if MACOS or MS_WINDOWS: support.requires( 'largefile', 'test requires %s bytes and a long time to run' % self.LARGE) diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py index 8870c721ab0efb..f278dc16cb2e22 100644 --- a/Lib/test/test_largefile.py +++ b/Lib/test/test_largefile.py @@ -5,7 +5,7 @@ import stat import sys import unittest -from test.support import TESTFN, requires, unlink, bigmemtest +from test.support import TESTFN, requires, unlink, bigmemtest, MACOS, MS_WINDOWS import io # C implementation of io import _pyio as pyio # Python implementation of io @@ -154,7 +154,7 @@ def setUpModule(): # takes a long time to build the >2 GiB file and takes >2 GiB of disk # space therefore the resource must be enabled to run this test. # If not, nothing after this line stanza will be executed. - if sys.platform[:3] == 'win' or sys.platform == 'darwin': + if MS_WINDOWS or MACOS: requires('largefile', 'test requires %s bytes and a long time to run' % str(size)) else: diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index e2c2178ae6cc30..27ae945d02ae89 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -1,4 +1,4 @@ -from test.support import verbose, is_android, check_warnings +from test.support import verbose, check_warnings, ANDROID, AIX, MACOS, MS_WINDOWS import unittest import locale import sys @@ -12,7 +12,7 @@ class BaseLocalizedTest(unittest.TestCase): @classmethod def setUpClass(cls): - if sys.platform == 'darwin': + if MACOS: import os tlocs = ("en_US.UTF-8", "en_US.ISO8859-1", "en_US") if int(os.uname().release.split('.')[0]) < 10: @@ -20,7 +20,7 @@ def setUpClass(cls): # haven't had time yet to verify if tests work on OSX 10.5 # (10.4 is known to be bad) raise unittest.SkipTest("Locale support on MacOSX is minimal") - elif sys.platform.startswith("win"): + elif MS_WINDOWS: tlocs = ("En", "English") else: tlocs = ("en_US.UTF-8", "en_US.ISO8859-1", @@ -365,18 +365,16 @@ def setUp(self): enc = codecs.lookup(locale.getpreferredencoding(False) or 'ascii').name if enc not in ('utf-8', 'iso8859-1', 'cp1252'): raise unittest.SkipTest('encoding not suitable') - if enc != 'iso8859-1' and (sys.platform == 'darwin' or is_android or + if enc != 'iso8859-1' and (MACOS or ANDROID or sys.platform.startswith('freebsd')): raise unittest.SkipTest('wcscoll/wcsxfrm have known bugs') BaseLocalizedTest.setUp(self) - @unittest.skipIf(sys.platform.startswith('aix'), - 'bpo-29972: broken test on AIX') + @unittest.skipIf(AIX, 'bpo-29972: broken test on AIX') def test_strcoll_with_diacritic(self): self.assertLess(locale.strcoll('à', 'b'), 0) - @unittest.skipIf(sys.platform.startswith('aix'), - 'bpo-29972: broken test on AIX') + @unittest.skipIf(AIX, 'bpo-29972: broken test on AIX') def test_strxfrm_with_diacritic(self): self.assertLess(locale.strxfrm('à'), locale.strxfrm('b')) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index bc99c3adbe3416..532d78bc8c92b2 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -42,6 +42,7 @@ import sys import tempfile from test.support.script_helper import assert_python_ok, assert_python_failure +from test.support import LINUX, MACOS, MS_WINDOWS from test import support import textwrap import threading @@ -543,7 +544,7 @@ def test_name(self): def test_builtin_handlers(self): # We can't actually *use* too many handlers in the tests, # but we can try instantiating them with various options - if sys.platform in ('linux', 'darwin'): + if LINUX or MACOS: for existing in (True, False): fd, fn = tempfile.mkstemp() os.close(fd) @@ -568,7 +569,7 @@ def test_builtin_handlers(self): h.close() if existing: os.unlink(fn) - if sys.platform == 'darwin': + if MACOS: sockname = '/var/run/syslog' else: sockname = '/dev/log' @@ -609,7 +610,7 @@ def test_path_objects(self): (logging.handlers.RotatingFileHandler, (pfn, 'a')), (logging.handlers.TimedRotatingFileHandler, (pfn, 'h')), ) - if sys.platform in ('linux', 'darwin'): + if LINUX or MACOS: cases += ((logging.handlers.WatchedFileHandler, (pfn, 'w')),) for cls, args in cases: h = cls(*args) @@ -617,7 +618,7 @@ def test_path_objects(self): h.close() os.unlink(fn) - @unittest.skipIf(os.name == 'nt', 'WatchedFileHandler not appropriate for Windows.') + @unittest.skipIf(MS_WINDOWS, 'WatchedFileHandler not appropriate for Windows.') def test_race(self): # Issue #14632 refers. def remove_loop(fname, tries): diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index cb05dee0e0fd3c..a764d2c42c6271 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1,7 +1,7 @@ # Python test set -- math module # XXXX Should not do tests around zero only -from test.support import run_unittest, verbose, requires_IEEE_754 +from test.support import run_unittest, verbose, requires_IEEE_754, MACOS from test import support import unittest import itertools @@ -1478,7 +1478,7 @@ def test_testfile(self): SKIP_ON_TIGER = {'tan0064'} osx_version = None - if sys.platform == 'darwin': + if MACOS: version_txt = platform.mac_ver()[0] try: osx_version = tuple(map(int, version_txt.split('.'))) diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py index c4b2fe2047a71d..e1896bdc638e18 100644 --- a/Lib/test/test_mimetypes.py +++ b/Lib/test/test_mimetypes.py @@ -7,6 +7,7 @@ from test import support from platform import win32_edition +from test.support import MS_WINDOWS # Tell it we don't know about external files: mimetypes.knownfiles = [] @@ -103,7 +104,7 @@ def test_keywords_args_api(self): type='image/jpg', strict=False), '.jpg') -@unittest.skipUnless(sys.platform.startswith("win"), "Windows only") +@unittest.skipUnless(MS_WINDOWS, "Windows only") class Win32MimeTypesTestCase(unittest.TestCase): def setUp(self): # ensure all entries actually come from the Windows registry diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index dd857a0632aeef..7ecb63c8a496b6 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -1,5 +1,6 @@ from test.support import (TESTFN, import_module, unlink, - requires, _2G, _4G, gc_collect, cpython_only) + requires, _2G, _4G, gc_collect, cpython_only, + LINUX, MACOS, MS_WINDOWS) import unittest import os import re @@ -184,14 +185,14 @@ def test_access_parameter(self): # CAUTION: This also changes the size of the file on disk, and # later tests assume that the length hasn't changed. We need to # repair that. - if sys.platform.startswith('win'): + if MS_WINDOWS: self.fail("Opening mmap with size+1 should work on Windows.") else: # we expect a ValueError on Unix, but not on Windows - if not sys.platform.startswith('win'): + if not MS_WINDOWS: self.fail("Opening mmap with size+1 should raise ValueError.") m.close() - if sys.platform.startswith('win'): + if MS_WINDOWS: # Repair damage from the resizing test. with open(TESTFN, 'r+b') as f: f.truncate(mapsize) @@ -734,7 +735,7 @@ def test_flush_return_value(self): mm.write(b'python') result = mm.flush() self.assertIsNone(result) - if sys.platform.startswith('linux'): + if LINUX: # 'offset' must be a multiple of mmap.PAGESIZE on Linux. # See bpo-34754 for details. self.assertRaises(OSError, mm.flush, 1, len(b'python')) @@ -749,7 +750,7 @@ def tearDown(self): unlink(TESTFN) def _make_test_file(self, num_zeroes, tail): - if sys.platform[:3] == 'win' or sys.platform == 'darwin': + if MACOS or MS_WINDOWS: requires('largefile', 'test requires %s bytes and a long time to run' % str(0x180000000)) f = open(TESTFN, 'w+b') diff --git a/Lib/test/test_multiprocessing_fork.py b/Lib/test/test_multiprocessing_fork.py index 5000edb7c5c299..378fd471817950 100644 --- a/Lib/test/test_multiprocessing_fork.py +++ b/Lib/test/test_multiprocessing_fork.py @@ -3,14 +3,15 @@ import sys from test import support +from test.support import MACOS, MS_WINDOWS if support.PGO: raise unittest.SkipTest("test is not helpful for PGO") -if sys.platform == "win32": +if MS_WINDOWS: raise unittest.SkipTest("fork is not available on Windows") -if sys.platform == 'darwin': +if MACOS: raise unittest.SkipTest("test may crash on macOS (bpo-33725)") test._test_multiprocessing.install_tests_in_module_dict(globals(), 'fork') diff --git a/Lib/test/test_multiprocessing_forkserver.py b/Lib/test/test_multiprocessing_forkserver.py index 6ad5faf9e8a329..884f434b56df1f 100644 --- a/Lib/test/test_multiprocessing_forkserver.py +++ b/Lib/test/test_multiprocessing_forkserver.py @@ -7,7 +7,7 @@ if support.PGO: raise unittest.SkipTest("test is not helpful for PGO") -if sys.platform == "win32": +if support.MS_WINDOWS: raise unittest.SkipTest("forkserver is not available on Windows") test._test_multiprocessing.install_tests_in_module_dict(globals(), 'forkserver') diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index fc2398c2d518ba..6f233047abad6d 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -3,7 +3,7 @@ import sys import unittest import warnings -from test.support import TestFailed, FakePath +from test.support import TestFailed, FakePath, MS_WINDOWS from test import support, test_genericpath from tempfile import TemporaryFile @@ -388,7 +388,7 @@ def test_sameopenfile(self): # Make sure different files are really different self.assertFalse(ntpath.sameopenfile(tf1.fileno(), tf2.fileno())) # Make sure invalid values don't cause issues on win32 - if sys.platform == "win32": + if MS_WINDOWS: with self.assertRaises(OSError): # Invalid file descriptors shouldn't display assert # dialogs (#4804) @@ -412,7 +412,7 @@ def test_ismount(self): with support.temp_dir() as d: self.assertFalse(ntpath.ismount(d)) - if sys.platform == "win32": + if MS_WINDOWS: # # Make sure the current folder isn't the root folder # (or any other volume root). The drive-relative diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index a2021b1eba068f..58ad6c62b009c9 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -29,6 +29,7 @@ import warnings from test import support from platform import win32_is_iot +from test.support import LINUX, MS_WINDOWS try: import resource @@ -181,8 +182,7 @@ def write_windows_console(self, *args): shell=True) self.assertEqual(retcode, 0) - @unittest.skipUnless(sys.platform == 'win32', - 'test specific to the Windows console') + @unittest.skipUnless(MS_WINDOWS, 'test specific to the Windows console') def test_write_windows_console(self): # Issue #11395: the Windows console returns an error (12: not enough # space error) on writing into stdout if stdout mode is binary and the @@ -381,7 +381,7 @@ def test_statvfs_result_pickle(self): unpickled = pickle.loads(p) self.assertEqual(result, unpickled) - @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") + @unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") def test_1686475(self): # Verify that an open file can be stat'ed try: @@ -391,7 +391,7 @@ def test_1686475(self): except OSError as e: self.fail("Could not stat pagefile.sys") - @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") + @unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") def test_15261(self): # Verify that stat'ing a closed fd does not cause crash @@ -410,8 +410,7 @@ def check_file_attributes(self, result): self.assertTrue(isinstance(result.st_file_attributes, int)) self.assertTrue(0 <= result.st_file_attributes <= 0xFFFFFFFF) - @unittest.skipUnless(sys.platform == "win32", - "st_file_attributes is Win32 specific") + @unittest.skipUnless(MS_WINDOWS, "st_file_attributes is Win32 specific") def test_file_attributes(self): # test file st_file_attributes (FILE_ATTRIBUTE_DIRECTORY not set) result = os.stat(self.fname) @@ -431,7 +430,7 @@ def test_file_attributes(self): result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY, stat.FILE_ATTRIBUTE_DIRECTORY) - @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") + @unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") def test_access_denied(self): # Default to FindFirstFile WIN32_FIND_DATA when access is # denied. See issue 28075. @@ -608,7 +607,7 @@ def set_time(filename): self._test_utime_current(set_time) def get_file_system(self, path): - if sys.platform == 'win32': + if MS_WINDOWS: root = os.path.splitdrive(os.path.abspath(path))[0] + '\\' import ctypes kernel32 = ctypes.windll.kernel32 @@ -809,7 +808,7 @@ def test_environb(self): # On OS X < 10.6, unsetenv() doesn't return a value (bpo-13415). @support.requires_mac_ver(10, 6) def test_unset_error(self): - if sys.platform == "win32": + if MS_WINDOWS: # an environment variable is limited to 32,767 characters key = 'x' * 50000 self.assertRaises(ValueError, os.environ.__delitem__, key) @@ -1611,7 +1610,7 @@ def test_execve_invalid_env(self): with self.assertRaises(ValueError): os.execve(args[0], args, newenv) - @unittest.skipUnless(sys.platform == "win32", "Win32-specific test") + @unittest.skipUnless(MS_WINDOWS, "Win32-specific test") def test_execve_with_empty_path(self): # bpo-32890: Check GetLastError() misuse try: @@ -1622,7 +1621,7 @@ def test_execve_with_empty_path(self): self.fail('No OSError raised') -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") class Win32ErrorTests(unittest.TestCase): def setUp(self): try: @@ -1795,7 +1794,7 @@ def test_unicode_name(self): self.file2 = self.file1 + "2" self._test_link(self.file1, self.file2) -@unittest.skipIf(sys.platform == "win32", "Posix specific tests") +@unittest.skipIf(MS_WINDOWS, "Posix specific tests") class PosixUidGidTests(unittest.TestCase): # uid_t and gid_t are 32-bit unsigned integers on Linux UID_OVERFLOW = (1 << 32) @@ -1863,7 +1862,7 @@ def test_setregid_neg1(self): sys.executable, '-c', 'import os,sys;os.setregid(-1,-1);sys.exit(0)']) -@unittest.skipIf(sys.platform == "win32", "Posix specific tests") +@unittest.skipIf(MS_WINDOWS, "Posix specific tests") class Pep383Tests(unittest.TestCase): def setUp(self): if support.TESTFN_UNENCODABLE: @@ -1935,7 +1934,7 @@ def test_stat(self): for fn in self.unicodefn: os.stat(os.path.join(self.dir, fn)) -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") class Win32KillTests(unittest.TestCase): def _kill(self, sig): # Start sys.executable as a subprocess and communicate from the @@ -2051,7 +2050,7 @@ def test_CTRL_BREAK_EVENT(self): self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT") -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") class Win32ListdirTests(unittest.TestCase): """Test listdir on Windows.""" @@ -2146,7 +2145,7 @@ def test_bytes(self): self.assertIsInstance(path, bytes) -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") @support.skip_unless_symlink class Win32SymlinkTests(unittest.TestCase): filelink = 'filelinktest' @@ -2306,7 +2305,7 @@ def test_buffer_overflow(self): except OSError: pass -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") class Win32JunctionTests(unittest.TestCase): junction = 'junctiontest' junction_target = os.path.dirname(os.path.abspath(__file__)) @@ -2336,7 +2335,7 @@ def test_unlink_removes_junction(self): os.unlink(self.junction) self.assertFalse(os.path.exists(self.junction)) -@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +@unittest.skipUnless(MS_WINDOWS, "Win32 specific tests") class Win32NtTests(unittest.TestCase): def test_getfinalpathname_handles(self): nt = support.import_module('nt') @@ -2440,7 +2439,7 @@ def test_bad_fd(self): # Return None when an fd doesn't actually exist. self.assertIsNone(os.device_encoding(123456)) - @unittest.skipUnless(os.isatty(0) and not win32_is_iot() and (sys.platform.startswith('win') or + @unittest.skipUnless(os.isatty(0) and not win32_is_iot() and (MS_WINDOWS or (hasattr(locale, 'nl_langinfo') and hasattr(locale, 'CODESET'))), 'test requires a tty and either Windows or nl_langinfo(CODESET)') def test_device_encoding(self): @@ -2771,7 +2770,7 @@ def handle_error(self): class TestSendfile(unittest.TestCase): DATA = b"12345abcde" * 16 * 1024 # 160 KiB - SUPPORT_HEADERS_TRAILERS = not sys.platform.startswith("linux") and \ + SUPPORT_HEADERS_TRAILERS = not LINUX and \ not sys.platform.startswith("solaris") and \ not sys.platform.startswith("sunos") requires_headers_trailers = unittest.skipUnless(SUPPORT_HEADERS_TRAILERS, @@ -3085,7 +3084,7 @@ def test_does_not_crash(self): try: size = os.get_terminal_size() except OSError as e: - if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY): + if MS_WINDOWS or e.errno in (errno.EINVAL, errno.ENOTTY): # Under win32 a generic OSError can be thrown if the # handle cannot be retrieved self.skipTest("failed to query terminal size") @@ -3111,7 +3110,7 @@ def test_stty_match(self): try: actual = os.get_terminal_size(sys.__stdin__.fileno()) except OSError as e: - if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY): + if MS_WINDOWS or e.errno in (errno.EINVAL, errno.ENOTTY): # Under win32 a generic OSError can be thrown if the # handle cannot be retrieved self.skipTest("failed to query terminal size") @@ -3152,7 +3151,7 @@ def test_oserror_filename(self): (self.filenames, os.stat,), (self.filenames, os.unlink,), ] - if sys.platform == "win32": + if MS_WINDOWS: funcs.extend(( (self.bytes_filenames, os.rename, b"dst"), (self.bytes_filenames, os.replace, b"dst"), @@ -3179,7 +3178,7 @@ def test_oserror_filename(self): if hasattr(os, "chroot"): funcs.append((self.filenames, os.chroot,)) if hasattr(os, "link"): - if sys.platform == "win32": + if MS_WINDOWS: funcs.append((self.bytes_filenames, os.link, b"dst")) funcs.append((self.unicode_filenames, os.link, "dst")) else: @@ -3194,7 +3193,7 @@ def test_oserror_filename(self): if hasattr(os, "lchmod"): funcs.append((self.filenames, os.lchmod, 0o777)) if hasattr(os, "readlink"): - if sys.platform == "win32": + if MS_WINDOWS: funcs.append((self.unicode_filenames, os.readlink,)) else: funcs.append((self.filenames, os.readlink,)) diff --git a/Lib/test/test_osx_env.py b/Lib/test/test_osx_env.py index 8a3bc5a46e547b..a4918bb0f6798b 100644 --- a/Lib/test/test_osx_env.py +++ b/Lib/test/test_osx_env.py @@ -2,14 +2,13 @@ Test suite for OS X interpreter environment variables. """ -from test.support import EnvironmentVarGuard +from test.support import EnvironmentVarGuard, MACOS import subprocess import sys import sysconfig import unittest -@unittest.skipUnless(sys.platform == 'darwin' and - sysconfig.get_config_var('WITH_NEXT_FRAMEWORK'), +@unittest.skipUnless(MACOS and sysconfig.get_config_var('WITH_NEXT_FRAMEWORK'), 'unnecessary on this platform') class OSXEnvironmentVariableTestCase(unittest.TestCase): def _check_sys(self, ev, cond, sv, val = sys.executable + 'dummy'): diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 990207b9c4e488..8047eef1a3f4f4 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -12,7 +12,7 @@ from unittest import mock from test import support -from test.support import TESTFN, FakePath +from test.support import TESTFN, FakePath, MACOS try: import grp, pwd @@ -2226,8 +2226,7 @@ def test_expanduser(self): self.assertEqual(p6.expanduser(), p6) self.assertRaises(RuntimeError, p7.expanduser) - @unittest.skipIf(sys.platform != "darwin", - "Bad file descriptor in /dev/fd affects only macOS") + @unittest.skipIf(MACOS, "Bad file descriptor in /dev/fd affects only macOS") def test_handling_bad_descriptor(self): try: file_descriptors = list(pathlib.Path('/dev/fd').rglob("*"))[3:] diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 9cf17726d92e0d..2839340bbf3879 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -8,6 +8,7 @@ from unittest import mock from test import support +from test.support import JYTHON, MACOS, MS_WINDOWS class PlatformTest(unittest.TestCase): def clear_caches(self): @@ -23,7 +24,7 @@ def test_architecture_via_symlink(self): # issue3762 # On Windows, the EXE needs to know where pythonXY.dll and *.pyd is at # so we add the directory to the path, PYTHONHOME and PYTHONPATH. env = None - if sys.platform == "win32": + if MS_WINDOWS: env = {k.upper(): os.environ[k] for k in os.environ} env["PATH"] = "{};{}".format( os.path.dirname(sys.executable), env.get("PATH", "")) @@ -189,7 +190,7 @@ def test_uname(self): self.assertEqual(res[4], res.machine) self.assertEqual(res[5], res.processor) - @unittest.skipUnless(sys.platform.startswith('win'), "windows only test") + @unittest.skipUnless(MS_WINDOWS, "windows only test") def test_uname_win32_ARCHITEW6432(self): # Issue 7860: make sure we get architecture from the correct variable # on 64 bit Windows: if PROCESSOR_ARCHITEW6432 exists we should be @@ -212,7 +213,7 @@ def test_uname_win32_ARCHITEW6432(self): def test_java_ver(self): res = platform.java_ver() - if sys.platform == 'java': + if JYTHON: self.assertTrue(all(res)) def test_win32_ver(self): @@ -251,7 +252,7 @@ def test_mac_ver(self): self.assertEqual(res[2], 'PowerPC') - @unittest.skipUnless(sys.platform == 'darwin', "OSX only test") + @unittest.skipUnless(MACOS, "OSX only test") def test_mac_ver_with_fork(self): # Issue7895: platform.mac_ver() crashes when using fork without exec # diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 843402930ffc0f..8a103b95fb812d 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1,6 +1,7 @@ "Test posix functions" from test import support +from test.support import MACOS from test.support.script_helper import assert_python_ok # Skip these tests if there is no posix module. @@ -1041,7 +1042,7 @@ def test_getgroups(self): raise unittest.SkipTest("need working 'id -G'") # Issues 16698: OS X ABIs prior to 10.6 have limits on getgroups() - if sys.platform == 'darwin': + if MACOS: import sysconfig dt = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') or '10.0' if tuple(int(n) for n in dt.split('.')[0:2]) < (10, 6): @@ -1285,7 +1286,7 @@ def test_sched_priority(self): self.assertIsInstance(hi, int) self.assertGreaterEqual(hi, lo) # OSX evidently just returns 15 without checking the argument. - if sys.platform != "darwin": + if not MACOS: self.assertRaises(OSError, posix.sched_get_priority_min, -23) self.assertRaises(OSError, posix.sched_get_priority_max, -23) @@ -1464,7 +1465,7 @@ def setUp(self): raise unittest.SkipTest("not enough privileges") if not hasattr(posix, 'getgroups'): raise unittest.SkipTest("need posix.getgroups") - if sys.platform == 'darwin': + if MACOS: raise unittest.SkipTest("getgroups(2) is broken on OSX") self.saved_groups = posix.getgroups() diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 9155522c273d88..b4e3ea7c2e5c28 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -19,6 +19,7 @@ from test import libregrtest from test import support from test.libregrtest import utils +from test.support import MS_WINDOWS Py_DEBUG = hasattr(sys, 'gettotalrefcount') @@ -548,7 +549,7 @@ def setUp(self): '--testdir=%s' % self.tmptestdir] if hasattr(faulthandler, 'dump_traceback_later'): self.regrtest_args.extend(('--timeout', '3600', '-j4')) - if sys.platform == 'win32': + if MS_WINDOWS: self.regrtest_args.append('-n') def check_output(self, output): @@ -611,7 +612,7 @@ def run_batch(self, *args): @unittest.skipUnless(sysconfig.is_python_build(), 'test.bat script is not installed') - @unittest.skipUnless(sys.platform == 'win32', 'Windows only') + @unittest.skipUnless(MS_WINDOWS, 'Windows only') def test_tools_buildbot_test(self): # Tools\buildbot\test.bat script = os.path.join(ROOT_DIR, 'Tools', 'buildbot', 'test.bat') @@ -622,7 +623,7 @@ def test_tools_buildbot_test(self): test_args.append('+d') # Release build, use python.exe self.run_batch(script, *test_args, *self.tests) - @unittest.skipUnless(sys.platform == 'win32', 'Windows only') + @unittest.skipUnless(MS_WINDOWS, 'Windows only') def test_pcbuild_rt(self): # PCbuild\rt.bat script = os.path.join(ROOT_DIR, r'PCbuild\rt.bat') diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index e5ece5284cf15b..df8d0f44f06b41 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -2,6 +2,7 @@ import sys import unittest from test import support +from test.support import LINUX import time resource = support.import_module('resource') @@ -135,7 +136,7 @@ def test_pagesize(self): self.assertIsInstance(pagesize, int) self.assertGreaterEqual(pagesize, 0) - @unittest.skipUnless(sys.platform == 'linux', 'test requires Linux') + @unittest.skipUnless(LINUX, 'test requires Linux') def test_linux_constants(self): for attr in ['MSGQUEUE', 'NICE', 'RTPRIO', 'RTTIME', 'SIGPENDING']: with contextlib.suppress(AttributeError): diff --git a/Lib/test/test_select.py b/Lib/test/test_select.py index 458998a62fdf5e..8250c21ae1468d 100644 --- a/Lib/test/test_select.py +++ b/Lib/test/test_select.py @@ -4,9 +4,9 @@ import sys import unittest from test import support +from test.support import MS_WINDOWS -@unittest.skipIf((sys.platform[:3]=='win'), - "can't easily test on this system") +@unittest.skipIf(MS_WINDOWS, "can't easily test on this system") class SelectTestCase(unittest.TestCase): class Nope: diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py index 31611224dc71e1..b43504135f2b25 100644 --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -6,6 +6,7 @@ import socket import sys from test import support +from test.support import MACOS, MS_WINDOWS from time import sleep import unittest import unittest.mock @@ -348,8 +349,7 @@ def test_selector(self): self.assertEqual(bufs, [MSG] * NUM_SOCKETS) - @unittest.skipIf(sys.platform == 'win32', - 'select.select() cannot be used with empty fd sets') + @unittest.skipIf(MS_WINDOWS, 'select.select() cannot be used with empty fd sets') def test_empty_select(self): # Issue #23009: Make sure EpollSelector.select() works when no FD is # registered. @@ -484,7 +484,7 @@ def test_above_fd_setsize(self): try: fds = s.select() except OSError as e: - if e.errno == errno.EINVAL and sys.platform == 'darwin': + if e.errno == errno.EINVAL and MACOS: # unexplainable errors on macOS don't need to fail the test self.skipTest("Invalid argument error calling poll()") raise diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index e709a5661bf3ef..eceb2f5a916619 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -30,11 +30,10 @@ posix = None from test import support -from test.support import TESTFN, FakePath +from test.support import TESTFN, FakePath, AIX, MACOS, MS_WINDOWS TESTFN2 = TESTFN + "2" -MACOS = sys.platform.startswith("darwin") -AIX = sys.platform[:3] == 'aix' + try: import grp import pwd @@ -1577,7 +1576,7 @@ def test_cwd(self): base_dir = os.path.dirname(self.dir) with support.change_cwd(path=self.dir): rv = shutil.which(self.file, path=base_dir) - if sys.platform == "win32": + if MS_WINDOWS: # Windows: current directory implicitly on PATH self.assertEqual(rv, os.path.join(self.curdir, self.file)) else: @@ -1605,7 +1604,7 @@ def test_nonexistent_file(self): rv = shutil.which("foo.exe", path=self.dir) self.assertIsNone(rv) - @unittest.skipUnless(sys.platform == "win32", + @unittest.skipUnless(MS_WINDOWS, "pathext check is Windows-only") def test_pathext_checking(self): # Ask for the file without the ".exe" extension, then ensure that diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 063b35ca230f59..8e49e14c4d3dbf 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -10,6 +10,7 @@ import time import unittest from test import support +from test.support import MS_WINDOWS from test.support.script_helper import assert_python_ok, spawn_python try: import _testcapi @@ -33,7 +34,7 @@ def test_enums(self): self.assertEqual(sys.platform, "win32") -@unittest.skipIf(sys.platform == "win32", "Not valid on Windows") +@unittest.skipIf(MS_WINDOWS, "Not valid on Windows") class PosixTests(unittest.TestCase): def trivial_signal_handler(self, *args): pass @@ -95,7 +96,7 @@ def test_keyboard_interrupt_exit_code(self): # to confirm that our process died via a SIGINT proved too complex. -@unittest.skipUnless(sys.platform == "win32", "Windows specific") +@unittest.skipUnless(MS_WINDOWS, "Windows specific") class WindowsSignalTests(unittest.TestCase): def test_valid_signals(self): @@ -201,7 +202,7 @@ def test_set_wakeup_fd_socket_result(self): # On Windows, files are always blocking and Windows does not provide a # function to test if a socket is in non-blocking mode. - @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX") + @unittest.skipIf(MS_WINDOWS, "tests specific to POSIX") def test_set_wakeup_fd_blocking(self): rfd, wfd = os.pipe() self.addCleanup(os.close, rfd) @@ -220,7 +221,7 @@ def test_set_wakeup_fd_blocking(self): signal.set_wakeup_fd(-1) -@unittest.skipIf(sys.platform == "win32", "Not valid on Windows") +@unittest.skipIf(MS_WINDOWS, "Not valid on Windows") class WakeupSignalTests(unittest.TestCase): @unittest.skipIf(_testcapi is None, 'need _testcapi') def check_wakeup(self, test_body, *signals, ordered=True): @@ -498,7 +499,7 @@ def test_warn_on_full_buffer(self): import sys import time import _testcapi - from test.support import captured_stderr + from test.support import captured_stderr, MS_WINDOWS signum = signal.SIGINT @@ -512,7 +513,7 @@ def handler(signum, frame): read, write = socket.socketpair() # Fill the socketpair buffer - if sys.platform == 'win32': + if MS_WINDOWS: # bpo-34130: On Windows, sometimes non-blocking send fails to fill # the full socketpair buffer, so use a timeout of 50 ms instead. write.settimeout(0.050) @@ -594,7 +595,7 @@ def handler(signum, frame): assert_python_ok('-c', code) -@unittest.skipIf(sys.platform == "win32", "Not valid on Windows") +@unittest.skipIf(MS_WINDOWS, "Not valid on Windows") class SiginterruptTest(unittest.TestCase): def readpipe_interrupted(self, interrupt): @@ -679,7 +680,7 @@ def test_siginterrupt_off(self): self.assertFalse(interrupted) -@unittest.skipIf(sys.platform == "win32", "Not valid on Windows") +@unittest.skipIf(MS_WINDOWS, "Not valid on Windows") class ItimerTest(unittest.TestCase): def setUp(self): self.hndl_called = False @@ -1250,7 +1251,7 @@ def test_sigint(self): with self.assertRaises(KeyboardInterrupt): signal.raise_signal(signal.SIGINT) - @unittest.skipIf(sys.platform != "win32", "Windows specific test") + @unittest.skipUnless(MS_WINDOWS, "Windows specific test") def test_invalid_argument(self): try: SIGHUP = 1 # not supported on win32 diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 41c4229919507b..4fbd21580669dc 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -8,7 +8,7 @@ import test.support from test import support from test.support import (captured_stderr, TESTFN, EnvironmentVarGuard, - change_cwd) + change_cwd, MACOS, MS_WINDOWS) import builtins import os import sys @@ -186,7 +186,7 @@ def test__getuserbase(self): self.assertEqual(site._getuserbase(), sysconfig._getuserbase()) def test_get_path(self): - if sys.platform == 'darwin' and sys._framework: + if MACOS and sys._framework: scheme = 'osx_framework_user' else: scheme = os.name + '_user' @@ -470,7 +470,7 @@ def test_setting_help(self): self.assertTrue(hasattr(builtins, "help")) def test_aliasing_mbcs(self): - if sys.platform == "win32": + if MS_WINDOWS: import locale if locale.getdefaultlocale()[1].startswith('cp'): for value in encodings.aliases.aliases.values(): @@ -559,7 +559,7 @@ def test_startup_interactivehook_isolated_explicit(self): self.assertTrue(r, "'__interactivehook__' not added by enablerlcompleter()") -@unittest.skipUnless(sys.platform == 'win32', "only supported on Windows") +@unittest.skipUnless(MS_WINDOWS, "only supported on Windows") class _pthFileTests(unittest.TestCase): def _create_underpth_exe(self, lines): diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index fdcf6f21925645..5fe3bc967f2908 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -19,12 +19,12 @@ import unittest from test import support, mock_socket -from test.support import HOST, HOSTv4, HOSTv6 +from test.support import HOST, HOSTv4, HOSTv6, MACOS from test.support import threading_setup, threading_cleanup, join_thread from unittest.mock import Mock -if sys.platform == 'darwin': +if MACOS: # select.poll returns a select.POLLHUP at the end of the tests # on darwin, so just ignore it def handle_expt(self): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 0094cecb79cca6..7314908e7f6c09 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1,5 +1,6 @@ import unittest from test import support +from test.support import AIX, LINUX, MACOS, MS_WINDOWS import errno import io @@ -40,7 +41,6 @@ MAIN_TIMEOUT = 60.0 VSOCKPORT = 1234 -AIX = platform.system() == "AIX" try: import _socket @@ -1048,7 +1048,7 @@ def testGetServBy(self): # I've ordered this by protocols that have both a tcp and udp # protocol, at least for modern Linuxes. if (sys.platform.startswith(('freebsd', 'netbsd', 'gnukfreebsd')) - or sys.platform in ('linux', 'darwin')): + or LINUX or MACOS): # avoid the 'echo' service on this platform, as there is an # assumption breaking non-standard port/protocol entry services = ('daytime', 'qotd', 'domain') @@ -1077,7 +1077,7 @@ def testGetServBy(self): eq(udpport, port) # Now make sure the lookup by port returns the same service name # Issue #26936: Android getservbyport() is broken. - if not support.is_android: + if not support.ANDROID: eq(socket.getservbyport(port2), service) eq(socket.getservbyport(port, 'tcp'), service) if udpport is not None: @@ -1162,7 +1162,7 @@ def testIPv6toString(self): except ImportError: self.skipTest('could not import needed symbols from socket') - if sys.platform == "win32": + if MS_WINDOWS: try: inet_pton(AF_INET6, '::') except OSError as e: @@ -1252,7 +1252,7 @@ def testStringToIPv6(self): except ImportError: self.skipTest('could not import needed symbols from socket') - if sys.platform == "win32": + if MS_WINDOWS: try: inet_ntop(AF_INET6, b'\x00' * 16) except OSError as e: @@ -1655,9 +1655,7 @@ def test_getaddrinfo_ipv6_scopeid_symbolic(self): self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, ifindex)) @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') - @unittest.skipUnless( - sys.platform == 'win32', - 'Numeric scope id does not work or undocumented') + @unittest.skipUnless(MS_WINDOWS, 'Numeric scope id does not work or undocumented') def test_getaddrinfo_ipv6_scopeid_numeric(self): # Also works on Linux and Mac OS X, but is not documented (?) # Windows, Linux and Max OS X allow nonexistent interface numbers here. @@ -1684,8 +1682,7 @@ def test_getnameinfo_ipv6_scopeid_symbolic(self): self.assertEqual(nameinfo, ('ff02::1de:c0:face:8d%' + test_interface, '1234')) @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') - @unittest.skipUnless( sys.platform == 'win32', - 'Numeric scope id does not work or undocumented') + @unittest.skipUnless(MS_WINDOWS, 'Numeric scope id does not work or undocumented') def test_getnameinfo_ipv6_scopeid_numeric(self): # Also works on Linux (undocumented), but does not work on Mac OS X # Windows and Linux allow nonexistent interface numbers here. @@ -2742,7 +2739,7 @@ def _testSendmsgTimeout(self): # Linux supports MSG_DONTWAIT when sending, but in general, it # only works when receiving. Could add other platforms if they # support it too. - @skipWithClientIf(sys.platform not in {"linux"}, + @skipWithClientIf(not LINUX, "MSG_DONTWAIT not known to work on this platform when " "sending") def testSendmsgDontWait(self): @@ -3259,7 +3256,7 @@ def testFDPassCMSG_LEN(self): def _testFDPassCMSG_LEN(self): self.createAndSendFDs(1) - @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(MACOS, "skipping, see issue #12958") @unittest.skipIf(AIX, "skipping, see issue #22397") @requireAttrs(socket, "CMSG_SPACE") def testFDPassSeparate(self): @@ -3270,7 +3267,7 @@ def testFDPassSeparate(self): maxcmsgs=2) @testFDPassSeparate.client_skip - @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(MACOS, "skipping, see issue #12958") @unittest.skipIf(AIX, "skipping, see issue #22397") def _testFDPassSeparate(self): fd0, fd1 = self.newFDs(2) @@ -3283,7 +3280,7 @@ def _testFDPassSeparate(self): array.array("i", [fd1]))]), len(MSG)) - @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(MACOS, "skipping, see issue #12958") @unittest.skipIf(AIX, "skipping, see issue #22397") @requireAttrs(socket, "CMSG_SPACE") def testFDPassSeparateMinSpace(self): @@ -3297,7 +3294,7 @@ def testFDPassSeparateMinSpace(self): maxcmsgs=2, ignoreflags=socket.MSG_CTRUNC) @testFDPassSeparateMinSpace.client_skip - @unittest.skipIf(sys.platform == "darwin", "skipping, see issue #12958") + @unittest.skipIf(MACOS, "skipping, see issue #12958") @unittest.skipIf(AIX, "skipping, see issue #22397") def _testFDPassSeparateMinSpace(self): fd0, fd1 = self.newFDs(2) @@ -3321,7 +3318,7 @@ def sendAncillaryIfPossible(self, msg, ancdata): nbytes = self.sendmsgToServer([msg]) self.assertEqual(nbytes, len(msg)) - @unittest.skipIf(sys.platform == "darwin", "see issue #24725") + @unittest.skipIf(MACOS, "see issue #24725") def testFDPassEmpty(self): # Try to pass an empty FD array. Can receive either no array # or an empty array. @@ -5021,7 +5018,7 @@ def test_setblocking_invalidfd(self): sock.setblocking(False) -@unittest.skipUnless(sys.platform == 'linux', 'Linux specific test') +@unittest.skipUnless(LINUX, 'Linux specific test') class TestLinuxAbstractNamespace(unittest.TestCase): UNIX_PATH_MAX = 108 @@ -6044,7 +6041,7 @@ def test_length_restriction(self): sock.bind(("type", "n" * 64)) -@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") +@unittest.skipUnless(MS_WINDOWS, "requires Windows") class TestMSWindowsTCPFlags(unittest.TestCase): knownTCPFlags = { # available since long time ago diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 5b53b8250f68a5..29984b0546fafd 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -3,6 +3,7 @@ import sys import unittest from test import support +from test.support import MS_WINDOWS import socket import select import time @@ -805,7 +806,7 @@ def test_get_default_verify_paths(self): self.assertEqual(paths.cafile, CERTFILE) self.assertEqual(paths.capath, CAPATH) - @unittest.skipUnless(sys.platform == "win32", "Windows specific") + @unittest.skipUnless(MS_WINDOWS, "Windows specific") def test_enum_certificates(self): self.assertTrue(ssl.enum_certificates("CA")) self.assertTrue(ssl.enum_certificates("ROOT")) @@ -830,7 +831,7 @@ def test_enum_certificates(self): serverAuth = "1.3.6.1.5.5.7.3.1" self.assertIn(serverAuth, trust_oids) - @unittest.skipUnless(sys.platform == "win32", "Windows specific") + @unittest.skipUnless(MS_WINDOWS, "Windows specific") def test_enum_crls(self): self.assertTrue(ssl.enum_crls("CA")) self.assertRaises(TypeError, ssl.enum_crls) @@ -1476,7 +1477,7 @@ def test_load_default_certs(self): self.assertRaises(TypeError, ctx.load_default_certs, None) self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH') - @unittest.skipIf(sys.platform == "win32", "not-Windows specific") + @unittest.skipIf(MS_WINDOWS, "not-Windows specific") @unittest.skipIf(IS_LIBRESSL, "LibreSSL doesn't support env vars") def test_load_default_certs_env(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) @@ -1486,7 +1487,7 @@ def test_load_default_certs_env(self): ctx.load_default_certs() self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0}) - @unittest.skipUnless(sys.platform == "win32", "Windows specific") + @unittest.skipUnless(MS_WINDOWS, "Windows specific") @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs") def test_load_default_certs_env_windows(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py index 17443bed0738b5..45abfeb02ba8e3 100644 --- a/Lib/test/test_stat.py +++ b/Lib/test/test_stat.py @@ -1,8 +1,7 @@ -import unittest import os import socket import sys -from test.support import (TESTFN, import_fresh_module, +from test.support import (TESTFN, import_fresh_module, MS_WINDOWS, skip_unless_bind_unix_socket) c_stat = import_fresh_module('stat', fresh=['_stat']) @@ -219,7 +218,7 @@ def test_module_attributes(self): self.assertTrue(callable(func)) self.assertEqual(func(0), 0) - @unittest.skipUnless(sys.platform == "win32", + @unittest.skipUnless(MS_WINDOWS, "FILE_ATTRIBUTE_* constants are Win32 specific") def test_file_attribute_constants(self): for key, value in sorted(self.file_attributes.items()): diff --git a/Lib/test/test_strftime.py b/Lib/test/test_strftime.py index ec305e54ff24f0..f06e72addece7b 100644 --- a/Lib/test/test_strftime.py +++ b/Lib/test/test_strftime.py @@ -6,6 +6,7 @@ import sys import re from test import support +from test.support import AIX, MS_WINDOWS import time import unittest @@ -187,8 +188,8 @@ class Y1900Tests(unittest.TestCase): def test_y_before_1900(self): # Issue #13674, #19634 t = (1899, 1, 1, 0, 0, 0, 0, 0, 0) - if (sys.platform == "win32" - or sys.platform.startswith(("aix", "sunos", "solaris"))): + if (MS_WINDOWS or AIX + or sys.platform.startswith(("sunos", "solaris"))): with self.assertRaises(ValueError): time.strftime("%y", t) else: diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 623da401eee4ff..64bf539efb3af6 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -7,6 +7,7 @@ import os import sys from test import support +from test.support import AIX from datetime import date as datetime_date import _strptime @@ -521,7 +522,7 @@ def test_day_of_week_calculation(self): "Calculation of day of the week failed; " "%s != %s" % (result.tm_wday, self.time_tuple.tm_wday)) - if support.is_android: + if support.ANDROID: # Issue #26929: strftime() on Android incorrectly formats %V or %G for # the last or the first incomplete week in a year. _ymd_excluded = ((1905, 1, 1), (1906, 12, 31), (2008, 12, 29), @@ -531,8 +532,7 @@ def test_day_of_week_calculation(self): _ymd_excluded = () _formats_excluded = () - @unittest.skipIf(sys.platform.startswith('aix'), - 'bpo-29972: broken test on AIX') + @unittest.skipIf(AIX, 'bpo-29972: broken test on AIX') def test_week_of_year_and_day_of_week_calculation(self): # Should be able to infer date if given year, week of year (%U or %W) # and day of the week diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index b0b6b06e92759e..fc2d76ecd044b1 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -18,7 +18,7 @@ import threading import gc import textwrap -from test.support import FakePath +from test.support import FakePath, MACOS, MS_WINDOWS try: import ctypes @@ -35,13 +35,11 @@ if support.PGO: raise unittest.SkipTest("test is not helpful for PGO") -mswindows = (sys.platform == "win32") - # # Depends on the following external programs: Python # -if mswindows: +if MS_WINDOWS: SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), ' 'os.O_BINARY);') else: @@ -314,7 +312,7 @@ def test_executable_takes_precedence(self): self._assert_python, pre_args, executable=NONEXISTING_CMD[0]) - @unittest.skipIf(mswindows, "executable argument replaces shell") + @unittest.skipIf(MS_WINDOWS, "executable argument replaces shell") def test_executable_replaces_shell(self): # Check that the executable argument replaces the default shell # when shell=True. @@ -363,7 +361,7 @@ def test_cwd_with_pathlike(self): temp_dir = self._normalize_cwd(temp_dir) self._assert_cwd(temp_dir, sys.executable, cwd=FakePath(temp_dir)) - @unittest.skipIf(mswindows, "pending resolution of issue #15533") + @unittest.skipIf(MS_WINDOWS, "pending resolution of issue #15533") def test_cwd_with_relative_arg(self): # Check that Popen looks for args[0] relative to cwd if args[0] # is relative. @@ -379,7 +377,7 @@ def test_cwd_with_relative_arg(self): python_dir = self._normalize_cwd(python_dir) self._assert_cwd(python_dir, rel_python, cwd=python_dir) - @unittest.skipIf(mswindows, "pending resolution of issue #15533") + @unittest.skipIf(MS_WINDOWS, "pending resolution of issue #15533") def test_cwd_with_relative_executable(self): # Check that Popen looks for executable relative to cwd if executable # is relative (and that executable takes precedence over args[0]). @@ -632,8 +630,7 @@ def test_env(self): # Windows requires at least the SYSTEMROOT environment variable to start # Python - @unittest.skipIf(sys.platform == 'win32', - 'cannot test an empty env on Windows') + @unittest.skipIf(MS_WINDOWS, 'cannot test an empty env on Windows') @unittest.skipIf(sysconfig.get_config_var('Py_ENABLE_SHARED') == 1, 'The Python shared library cannot be loaded ' 'with an empty environment.') @@ -1008,7 +1005,7 @@ def test_communicate_errors(self): def test_no_leaking(self): # Make sure we leak no resources - if not mswindows: + if not MS_WINDOWS: max_handles = 1026 # too much for most UNIX systems else: max_handles = 2050 # too much for (at least some) Windows setups @@ -1245,7 +1242,7 @@ def kill_proc_timer_thread(): t = threading.Timer(0.2, kill_proc_timer_thread) t.start() - if mswindows: + if MS_WINDOWS: expected_errorcode = 1 else: # Should be -9 because of the proc.kill() from the thread. @@ -1366,13 +1363,13 @@ def test_failed_child_execute_fd_leak(self): fds_after_exception = os.listdir(fd_directory) self.assertEqual(fds_before_popen, fds_after_exception) - @unittest.skipIf(mswindows, "behavior currently not supported on Windows") + @unittest.skipIf(MS_WINDOWS, "behavior currently not supported on Windows") def test_file_not_found_includes_filename(self): with self.assertRaises(FileNotFoundError) as c: subprocess.call(['/opt/nonexistent_binary', 'with', 'some', 'args']) self.assertEqual(c.exception.filename, '/opt/nonexistent_binary') - @unittest.skipIf(mswindows, "behavior currently not supported on Windows") + @unittest.skipIf(MS_WINDOWS, "behavior currently not supported on Windows") def test_file_not_found_with_bad_cwd(self): with self.assertRaises(FileNotFoundError) as c: subprocess.Popen(['exit', '0'], cwd='/some/nonexistent/directory') @@ -1506,7 +1503,7 @@ def test_stderr_with_capture_output_arg(self): self.assertIn('capture_output', c.exception.args[0]) -@unittest.skipIf(mswindows, "POSIX specific tests") +@unittest.skipIf(MS_WINDOWS, "POSIX specific tests") class POSIXProcessTestCase(BaseTestCase): def setUp(self): @@ -1793,8 +1790,7 @@ def raise_runtime_error(): if not enabled: gc.disable() - @unittest.skipIf( - sys.platform == 'darwin', 'setrlimit() seems to fail on OS X') + @unittest.skipIf(MACOS, 'setrlimit() seems to fail on OS X') def test_preexec_fork_failure(self): # The internal code did not preserve the previous exception when # re-enabling garbage collection @@ -2815,7 +2811,7 @@ def test_stopped(self): self.assertEqual(returncode, -3) -@unittest.skipUnless(mswindows, "Windows specific tests") +@unittest.skipUnless(MS_WINDOWS, "Windows specific tests") class Win32ProcessTestCase(BaseTestCase): def test_startupinfo(self): @@ -3147,7 +3143,7 @@ def test_getoutput(self): dir = tempfile.mkdtemp() name = os.path.join(dir, "foo") status, output = subprocess.getstatusoutput( - ("type " if mswindows else "cat ") + name) + ("type " if MS_WINDOWS else "cat ") + name) self.assertNotEqual(status, 0) finally: if dir is not None: @@ -3181,7 +3177,7 @@ def tearDown(self): ProcessTestCase.tearDown(self) -@unittest.skipUnless(mswindows, "Windows-specific tests") +@unittest.skipUnless(MS_WINDOWS, "Windows-specific tests") class CommandsWithSpaces (BaseTestCase): def setUp(self): diff --git a/Lib/test/test_sundry.py b/Lib/test/test_sundry.py index 2accad1aeebd4f..fe8a342e0a4631 100644 --- a/Lib/test/test_sundry.py +++ b/Lib/test/test_sundry.py @@ -1,7 +1,6 @@ """Do a minimal test of all the modules that aren't otherwise tested.""" import importlib import platform -import sys from test import support import unittest @@ -26,7 +25,7 @@ def test_untested_modules_can_be_imported(self): import distutils.unixccompiler import distutils.command.bdist_dumb - if sys.platform.startswith('win') and not platform.win32_is_iot(): + if support.MS_WINDOWS and not platform.win32_is_iot(): import distutils.command.bdist_msi import distutils.command.bdist import distutils.command.bdist_rpm diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index d1c7daad7bba48..d00f9b822a2a90 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1,4 +1,5 @@ import unittest, test.support +from test.support import MACOS, MS_WINDOWS from test.support.script_helper import assert_python_ok, assert_python_failure import sys, io, os import struct @@ -486,7 +487,7 @@ def test_attributes(self): self.assertTrue(vi > (1,0,0)) self.assertIsInstance(sys.float_repr_style, str) self.assertIn(sys.float_repr_style, ('short', 'legacy')) - if not sys.platform.startswith('win'): + if not MS_WINDOWS: self.assertIsInstance(sys.abiflags, str) def test_thread_info(self): @@ -647,7 +648,7 @@ def check_fsencoding(self, fs_encoding, expected=None): def test_getfilesystemencoding(self): fs_encoding = sys.getfilesystemencoding() - if sys.platform == 'darwin': + if MACOS: expected = 'utf-8' else: expected = None diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 1b1929885edd6b..1eca2f459f7127 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -6,7 +6,8 @@ from copy import copy from test.support import (import_module, TESTFN, unlink, check_warnings, - captured_stdout, skip_unless_symlink, change_cwd) + captured_stdout, skip_unless_symlink, change_cwd, + LINUX, MACOS, MS_WINDOWS) import sysconfig from sysconfig import (get_paths, get_platform, get_config_vars, @@ -236,7 +237,7 @@ def test_symlink(self): # On Windows, the EXE needs to know where pythonXY.dll is at so we have # to add the directory to the path. env = None - if sys.platform == "win32": + if MS_WINDOWS: env = {k.upper(): os.environ[k] for k in os.environ} env["PATH"] = "{};{}".format( os.path.dirname(sys.executable), env.get("PATH", "")) @@ -294,14 +295,14 @@ def test_main(self): _main() self.assertTrue(len(output.getvalue().split('\n')) > 0) - @unittest.skipIf(sys.platform == "win32", "Does not apply to Windows") + @unittest.skipIf(MS_WINDOWS, "Does not apply to Windows") def test_ldshared_value(self): ldflags = sysconfig.get_config_var('LDFLAGS') ldshared = sysconfig.get_config_var('LDSHARED') self.assertIn(ldflags, ldshared) - @unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX") + @unittest.skipUnless(MACOS, "test only relevant on MacOSX") def test_platform_in_subprocess(self): my_platform = sysconfig.get_platform() @@ -391,8 +392,7 @@ def test_SO_in_vars(self): self.assertIsNotNone(vars['SO']) self.assertEqual(vars['SO'], vars['EXT_SUFFIX']) - @unittest.skipUnless(sys.platform == 'linux' and - hasattr(sys.implementation, '_multiarch'), + @unittest.skipUnless(LINUX and hasattr(sys.implementation, '_multiarch'), 'multiarch-specific test') def test_triplet_in_ext_suffix(self): ctypes = import_module('ctypes') @@ -409,15 +409,14 @@ def test_triplet_in_ext_suffix(self): else: # 8 byte pointer size self.assertTrue(suffix.endswith('x86_64-linux-gnu.so'), suffix) - @unittest.skipUnless(sys.platform == 'darwin', 'OS X-specific test') + @unittest.skipUnless(MACOS, 'OS X-specific test') def test_osx_ext_suffix(self): suffix = sysconfig.get_config_var('EXT_SUFFIX') self.assertTrue(suffix.endswith('-darwin.so'), suffix) class MakefileTests(unittest.TestCase): - @unittest.skipIf(sys.platform.startswith('win'), - 'Test is not Windows compatible') + @unittest.skipIf(MS_WINDOWS, 'Test is not Windows compatible') def test_get_makefile_filename(self): makefile = sysconfig.get_makefile_filename() self.assertTrue(os.path.isfile(makefile), makefile) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 7e32cbccd6c56d..b2130c982970db 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -11,7 +11,7 @@ import tarfile from test import support -from test.support import script_helper +from test.support import script_helper, LINUX, MS_WINDOWS # Check for our compression modules. try: @@ -562,7 +562,7 @@ def test_extractall(self): tar.extractall(DIR, directories) for tarinfo in directories: path = os.path.join(DIR, tarinfo.name) - if sys.platform != "win32": + if not MS_WINDOWS: # Win32 has no support for fine grained permissions. self.assertEqual(tarinfo.mode & 0o777, os.stat(path).st_mode & 0o777) @@ -591,7 +591,7 @@ def test_extract_directory(self): tar.extract(tarinfo, path=DIR) extracted = os.path.join(DIR, dirtype) self.assertEqual(os.path.getmtime(extracted), tarinfo.mtime) - if sys.platform != "win32": + if not MS_WINDOWS: self.assertEqual(os.stat(extracted).st_mode & 0o777, 0o755) finally: support.rmtree(DIR) @@ -974,7 +974,7 @@ def _fs_supports_holes(): # # The function returns False if page size is larger than 4 KiB. # For example, ppc64 uses pages of 64 KiB. - if sys.platform.startswith("linux"): + if LINUX: # Linux evidentially has 512 byte st_blocks units. name = os.path.join(TEMPDIR, "sparse-test") with open(name, "wb") as fobj: @@ -1334,7 +1334,7 @@ def test_pathnames(self): self._test_pathname("foo" + os.sep + os.sep, "foo", dir=True) def test_abs_pathnames(self): - if sys.platform == "win32": + if MS_WINDOWS: self._test_pathname("C:\\foo", "foo") else: self._test_pathname("/foo", "foo") @@ -1404,7 +1404,7 @@ def test_stream_padding(self): self.assertEqual(data.count(b"\0"), tarfile.RECORDSIZE, "incorrect zero padding") - @unittest.skipUnless(sys.platform != "win32" and hasattr(os, "umask"), + @unittest.skipUnless(not MS_WINDOWS and hasattr(os, "umask"), "Missing umask implementation") def test_file_mode(self): # Test for issue #8464: Create files with correct diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py index 80f1668bcecab8..c12f694ba7b501 100644 --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -226,7 +226,7 @@ def testPackageRequireException(self): tcl = self.interp self.assertRaises(TclError,tcl.eval,'package require DNE') - @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows') + @unittest.skipUnless(support.MS_WINDOWS, 'Requires Windows') def testLoadWithUNC(self): # Build a UNC path from the regular path. # Something like diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 489141d6ad726a..9e1b86d259a08e 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -14,7 +14,7 @@ import unittest from test import support -from test.support import script_helper +from test.support import script_helper, MS_WINDOWS has_textmode = (tempfile._text_openflags != tempfile._bin_openflags) @@ -434,7 +434,7 @@ def test_file_mode(self): file = self.do_create() mode = stat.S_IMODE(os.stat(file.name).st_mode) expected = 0o600 - if sys.platform == 'win32': + if MS_WINDOWS: # There's no distinction among 'user', 'group' and 'world'; # replicate the 'user' bits. user = expected >> 6 @@ -468,7 +468,7 @@ def test_noinherit(self): # On Windows a spawn* /path/ with embedded spaces shouldn't be quoted, # but an arg with embedded spaces should be decorated with double # quotes on each end - if sys.platform == 'win32': + if MS_WINDOWS: decorated = '"%s"' % sys.executable tester = '"%s"' % tester else: @@ -739,7 +739,7 @@ def test_mode(self): mode = stat.S_IMODE(os.stat(dir).st_mode) mode &= 0o777 # Mask off sticky bits inherited from /tmp expected = 0o700 - if sys.platform == 'win32': + if MS_WINDOWS: # There's no distinction among 'user', 'group' and 'world'; # replicate the 'user' bits. user = expected >> 6 diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 2ddc77b266b542..ac67f824a77ad0 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -3,7 +3,7 @@ """ import test.support -from test.support import (verbose, import_module, cpython_only, +from test.support import (verbose, import_module, cpython_only, MACOS, requires_type_collecting) from test.support.script_helper import assert_python_ok, assert_python_failure @@ -970,7 +970,7 @@ def test_releasing_unacquired_lock(self): lock = threading.Lock() self.assertRaises(RuntimeError, lock.release) - @unittest.skipUnless(sys.platform == 'darwin' and test.support.python_is_optimized(), + @unittest.skipUnless(MACOS and test.support.python_is_optimized(), 'test macosx problem') def test_recursion_limit(self): # Issue 9670 diff --git a/Lib/test/test_threadsignals.py b/Lib/test/test_threadsignals.py index eeacd3698cb138..a1fd870eaf3106 100644 --- a/Lib/test/test_threadsignals.py +++ b/Lib/test/test_threadsignals.py @@ -5,10 +5,11 @@ import os import sys from test import support +from test.support import LINUX, MS_WINDOWS import _thread as thread import time -if (sys.platform[:3] == 'win'): +if MS_WINDOWS: raise unittest.SkipTest("Can't test signal on %s" % sys.platform) process_pid = os.getpid() @@ -78,8 +79,7 @@ def alarm_interrupt(self, sig, frame): @unittest.skipIf(USING_PTHREAD_COND, 'POSIX condition variables cannot be interrupted') - @unittest.skipIf(sys.platform.startswith('linux') and - not sys.thread_info.version, + @unittest.skipIf(LINUX and not sys.thread_info.version, 'Issue 34004: musl does not allow interruption of locks ' 'by signals.') # Issue #20564: sem_timedwait() cannot be interrupted on OpenBSD @@ -109,8 +109,7 @@ def test_lock_acquire_interruption(self): @unittest.skipIf(USING_PTHREAD_COND, 'POSIX condition variables cannot be interrupted') - @unittest.skipIf(sys.platform.startswith('linux') and - not sys.thread_info.version, + @unittest.skipIf(LINUX and not sys.thread_info.version, 'Issue 34004: musl does not allow interruption of locks ' 'by signals.') # Issue #20564: sem_timedwait() cannot be interrupted on OpenBSD diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 42799b2a21ca34..86c21cffb2b6bd 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -1,4 +1,5 @@ from test import support +from test.support import LINUX, MS_WINDOWS import decimal import enum import locale @@ -497,7 +498,7 @@ def test_process_time(self): def test_thread_time(self): if not hasattr(time, 'thread_time'): - if sys.platform.startswith(('linux', 'win')): + if LINUX or MS_WINDOWS: self.fail("time.thread_time() should be available on %r" % (sys.platform,)) else: @@ -946,7 +947,7 @@ def timeval_converter(ns): us = us_converter(ns) return divmod(us, SEC_TO_US) - if sys.platform == 'win32': + if MS_WINDOWS: from _testcapi import LONG_MIN, LONG_MAX # On Windows, timeval.tv_sec type is a C long diff --git a/Lib/test/test_tix.py b/Lib/test/test_tix.py index e6ea3d07444ce7..983a9ec62567db 100644 --- a/Lib/test/test_tix.py +++ b/Lib/test/test_tix.py @@ -17,7 +17,7 @@ def setUp(self): try: self.root = tix.Tk() except TclError: - if sys.platform.startswith('win'): + if support.MS_WINDOWS: self.fail('Tix should always be available on Windows') self.skipTest('Tix not available') else: diff --git a/Lib/test/test_tools/test_sundry.py b/Lib/test/test_tools/test_sundry.py index f5fed01491e3f6..7bad03256306a1 100644 --- a/Lib/test/test_tools/test_sundry.py +++ b/Lib/test/test_tools/test_sundry.py @@ -45,7 +45,7 @@ def test_sundry(self): # Unload all modules loaded in this test support.modules_cleanup(*old_modules) - @unittest.skipIf(sys.platform != "win32", "Windows-only test") + @unittest.skipUnless(support.MS_WINDOWS, "Windows-only test") def test_sundry_windows(self): for name in self.windows_only: import_tool(name) diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index 36b72e40c7e419..ab95a6412d7f2b 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -14,6 +14,7 @@ import unittest import warnings from test import support, string_tests +from test.support import JYTHON # Error handling (bad decoder return) def search_function(encoding): @@ -81,7 +82,7 @@ def test_literals(self): self.assertNotEqual(r"\u0020", " ") def test_ascii(self): - if not sys.platform.startswith('java'): + if not support.JYTHON: # Test basic sanity of repr() self.assertEqual(ascii('abc'), "'abc'") self.assertEqual(ascii('ab\\c'), "'ab\\\\c'") @@ -123,7 +124,7 @@ def __repr__(self): self.assertRaises(TypeError, ascii, WrongRepr()) def test_repr(self): - if not sys.platform.startswith('java'): + if not support.JYTHON: # Test basic sanity of repr() self.assertEqual(repr('abc'), "'abc'") self.assertEqual(repr('ab\\c'), "'ab\\\\c'") @@ -584,7 +585,7 @@ def test_islower(self): def test_isupper(self): super().test_isupper() - if not sys.platform.startswith('java'): + if not support.JYTHON: self.checkequalnofix(False, '\u1FFc', 'isupper') self.assertTrue('\u2167'.isupper()) self.assertFalse('\u2177'.isupper()) @@ -1344,7 +1345,7 @@ def test_formatting(self): self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", -1, -2, 3.5), 'abc, abc, -1, -2.000000, 3.50') self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", -1, -2, 3.57), 'abc, abc, -1, -2.000000, 3.57') self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", -1, -2, 1003.57), 'abc, abc, -1, -2.000000, 1003.57') - if not sys.platform.startswith('java'): + if not support.JYTHON: self.assertEqual("%r, %r" % (b"abc", "abc"), "b'abc', 'abc'") self.assertEqual("%r" % ("\u1234",), "'\u1234'") self.assertEqual("%a" % ("\u1234",), "'\\u1234'") @@ -1537,7 +1538,7 @@ def __str__(self): # unicode(obj, encoding, error) tests (this maps to # PyUnicode_FromEncodedObject() at C level) - if not sys.platform.startswith('java'): + if not support.JYTHON: self.assertRaises( TypeError, str, @@ -1551,7 +1552,7 @@ def __str__(self): 'strings are decoded to unicode' ) - if not sys.platform.startswith('java'): + if not support.JYTHON: self.assertEqual( str( memoryview(b'character buffers are decoded to unicode'), diff --git a/Lib/test/test_unicode_file_functions.py b/Lib/test/test_unicode_file_functions.py index 1cd0d621cd4b3a..d61090293a18af 100644 --- a/Lib/test/test_unicode_file_functions.py +++ b/Lib/test/test_unicode_file_functions.py @@ -6,6 +6,7 @@ import warnings from unicodedata import normalize from test import support +from test.support import MACOS, MS_WINDOWS filenames = [ '1_abc', @@ -27,7 +28,7 @@ # these normal forms. For example, HFS Plus uses a variant of Normal Form D # in which U+2000 through U+2FFF, U+F900 through U+FAFF, and U+2F800 through # U+2FAFF are not decomposed." -if sys.platform != 'darwin': +if not MACOS: filenames.extend([ # Specific code points: NFC(fn), NFD(fn), NFKC(fn) and NFKD(fn) all different '11_\u0385\u03d3\u03d4', @@ -103,7 +104,7 @@ def test_failures(self): self._apply_failure(os.remove, name) self._apply_failure(os.listdir, name) - if sys.platform == 'win32': + if MS_WINDOWS: # Windows is lunatic. Issue #13366. _listdir_failure = NotADirectoryError, FileNotFoundError else: @@ -121,7 +122,7 @@ def test_open(self): # NFD (a variant of Unicode NFD form). Normalize the filename to NFC, NFKC, # NFKD in Python is useless, because darwin will normalize it later and so # open(), os.stat(), etc. don't raise any exception. - @unittest.skipIf(sys.platform == 'darwin', 'irrelevant test on Mac OS X') + @unittest.skipIf(MACOS, 'irrelevant test on Mac OS X') def test_normalize(self): files = set(self.files) others = set() @@ -139,7 +140,7 @@ def test_normalize(self): # Skip the test on darwin, because darwin uses a normalization different # than Python NFD normalization: filenames are different even if we use # Python NFD normalization. - @unittest.skipIf(sys.platform == 'darwin', 'irrelevant test on Mac OS X') + @unittest.skipIf(MACOS, 'irrelevant test on Mac OS X') def test_listdir(self): sf0 = set(self.files) with warnings.catch_warnings(): diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index 7214492eca9d88..630445e7144ac3 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -1420,7 +1420,7 @@ def test_quoting(self): "url2pathname() failed; %s != %s" % (expect, result)) - @unittest.skipUnless(sys.platform == 'win32', + @unittest.skipUnless(support.MS_WINDOWS, 'test specific to the urllib.url2path function.') def test_ntpath(self): given = ('/C:/', '///C:/', '/C|//') diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py index c6d275e16b097f..2beddfecc3567a 100644 --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -1,6 +1,7 @@ import unittest from test import support from test import test_urllib +from test.support import MACOS import os import io @@ -1421,7 +1422,7 @@ def test_proxy_https_proxy_authorization(self): self.assertEqual(req.host, "proxy.example.com:3128") self.assertEqual(req.get_header("Proxy-authorization"), "FooBar") - @unittest.skipUnless(sys.platform == 'darwin', "only relevant for OSX") + @unittest.skipUnless(MACOS, "only relevant for OSX") def test_osx_proxy_bypass(self): bypass = { 'exclude_simple': False, diff --git a/Lib/test/test_utf8_mode.py b/Lib/test/test_utf8_mode.py index bdb93457cfc405..08b0a1808f5f18 100644 --- a/Lib/test/test_utf8_mode.py +++ b/Lib/test/test_utf8_mode.py @@ -7,10 +7,10 @@ import textwrap import unittest from test import support +from test.support import AIX, ANDROID, MACOS, MS_WINDOWS from test.support.script_helper import assert_python_ok, assert_python_failure -MS_WINDOWS = (sys.platform == 'win32') POSIX_LOCALES = ('C', 'POSIX') VXWORKS = (sys.platform == "vxworks") @@ -225,9 +225,9 @@ def check(utf8_opt, expected, **kw): with self.subTest(LC_ALL=loc): check('utf8', [arg_utf8], LC_ALL=loc) - if sys.platform == 'darwin' or support.is_android or VXWORKS: + if MACOS or ANDROID or VXWORKS: c_arg = arg_utf8 - elif sys.platform.startswith("aix"): + elif AIX: c_arg = arg.decode('iso-8859-1') else: c_arg = arg_ascii diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 6822d567e42b58..7d5630848e1989 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -14,7 +14,8 @@ import sys import tempfile from test.support import (captured_stdout, captured_stderr, requires_zlib, - can_symlink, EnvironmentVarGuard, rmtree) + can_symlink, EnvironmentVarGuard, rmtree, + MACOS, MS_WINDOWS) import threading import unittest import venv @@ -94,8 +95,8 @@ def test_defaults(self): self.isdir(*self.lib) # Issue 21197 p = self.get_env_file('lib64') - conditions = ((struct.calcsize('P') == 8) and (os.name == 'posix') and - (sys.platform != 'darwin')) + conditions = ((struct.calcsize('P') == 8) + and (os.name == 'posix') and not MACOS) if conditions: self.assertTrue(os.path.islink(p)) else: @@ -153,7 +154,7 @@ def test_prefixes(self): out, err = check_output(cmd) self.assertEqual(out.strip(), expected.encode()) - if sys.platform == 'win32': + if MS_WINDOWS: ENV_SUBDIRS = ( ('Scripts',), ('Include',), diff --git a/Lib/test/test_wait4.py b/Lib/test/test_wait4.py index 3e6a79df463cb4..15582f28d1f022 100644 --- a/Lib/test/test_wait4.py +++ b/Lib/test/test_wait4.py @@ -6,7 +6,7 @@ import sys import unittest from test.fork_wait import ForkWait -from test.support import reap_children, get_attribute +from test.support import reap_children, get_attribute, AIX # If either of these do not exist, skip this test. get_attribute(os, 'fork') @@ -16,7 +16,7 @@ class Wait4Test(ForkWait): def wait_impl(self, cpid): option = os.WNOHANG - if sys.platform.startswith('aix'): + if AIX: # Issue #11185: wait4 is broken on AIX and will always return 0 # with WNOHANG. option = 0 diff --git a/Lib/test/test_winconsoleio.py b/Lib/test/test_winconsoleio.py index a78fa4d7d919ff..894659887304cd 100644 --- a/Lib/test/test_winconsoleio.py +++ b/Lib/test/test_winconsoleio.py @@ -7,8 +7,9 @@ import tempfile import unittest from test import support +from test.support import MS_WINDOWS -if sys.platform != 'win32': +if not MS_WINDOWS: raise unittest.SkipTest("test only relevant on win32") from _testconsole import write_input diff --git a/Lib/test/test_zipapp.py b/Lib/test/test_zipapp.py index 73bddc79c17ab6..8119d29aa18a6a 100644 --- a/Lib/test/test_zipapp.py +++ b/Lib/test/test_zipapp.py @@ -8,7 +8,7 @@ import unittest import zipapp import zipfile -from test.support import requires_zlib +from test.support import requires_zlib, MS_WINDOWS from unittest.mock import patch @@ -299,8 +299,7 @@ def test_content_of_copied_archive(self): self.assertEqual(set(z.namelist()), {'__main__.py'}) # (Unix only) tests that archives with shebang lines are made executable - @unittest.skipIf(sys.platform == 'win32', - 'Windows does not support an executable bit') + @unittest.skipIf(MS_WINDOWS, 'Windows does not support an executable bit') def test_shebang_is_executable(self): # Test that an archive with a shebang line is made executable. source = self.tmpdir / 'source' @@ -310,8 +309,7 @@ def test_shebang_is_executable(self): zipapp.create_archive(str(source), str(target), interpreter='python') self.assertTrue(target.stat().st_mode & stat.S_IEXEC) - @unittest.skipIf(sys.platform == 'win32', - 'Windows does not support an executable bit') + @unittest.skipIf(MS_WINDOWS, 'Windows does not support an executable bit') def test_no_shebang_is_not_executable(self): # Test that an archive with no shebang line is not made executable. source = self.tmpdir / 'source' diff --git a/Misc/NEWS.d/next/Tests/2019-04-15-14-48-48.bpo-36624.yjmwEK.rst b/Misc/NEWS.d/next/Tests/2019-04-15-14-48-48.bpo-36624.yjmwEK.rst new file mode 100644 index 00000000000000..fb9014fb9f4e56 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-04-15-14-48-48.bpo-36624.yjmwEK.rst @@ -0,0 +1,4 @@ +Add constants in Lib/test/support to support platform determination. +From platform.system() determine AIX, LINUX, MACOS, WINDOWS. +From sys determine ANDROID (was is_android) and JYTHON (was is_jython). +Patch by M. Felt.

    FormatPacked as .zipPacked as .tar.bz2