From webhook-mailer at python.org Thu Aug 1 01:43:11 2019 From: webhook-mailer at python.org (Ronald Oussoren) Date: Thu, 01 Aug 2019 05:43:11 -0000 Subject: [Python-checkins] bpo-18049: Sync thread stack size to main thread size on macOS (GH-14748) Message-ID: https://github.com/python/cpython/commit/1a057bab0f18d6ad843ce321d1d77a4819497ae4 commit: 1a057bab0f18d6ad843ce321d1d77a4819497ae4 branch: master author: Ronald Oussoren committer: GitHub date: 2019-08-01T07:43:07+02:00 summary: bpo-18049: Sync thread stack size to main thread size on macOS (GH-14748) This changeset increases the default size of the stack for threads on macOS to the size of the stack of the main thread and reenables the relevant recursion test. files: A Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst M Lib/test/test_threading.py M Python/thread_pthread.h M configure M configure.ac diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index a99b8eca2be7..1466d25e9482 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1057,8 +1057,6 @@ 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(), - 'test macosx problem') def test_recursion_limit(self): # Issue 9670 # test that excessive recursion within a non-main thread causes diff --git a/Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst b/Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst new file mode 100644 index 000000000000..5af07cdb4119 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst @@ -0,0 +1,3 @@ +Increase the default stack size of threads from 5MB to 16MB on macOS, to +match the stack size of the main thread. This avoids crashes on deep recursion +in threads. diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index a36d16c19ead..994e35b2cc08 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -40,7 +40,8 @@ */ #if defined(__APPLE__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 #undef THREAD_STACK_SIZE -#define THREAD_STACK_SIZE 0x500000 +/* Note: This matches the value of -Wl,-stack_size in configure.ac */ +#define THREAD_STACK_SIZE 0x1000000 #endif #if defined(__FreeBSD__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 #undef THREAD_STACK_SIZE diff --git a/configure b/configure index 4cea98e36528..bffb849b797b 100755 --- a/configure +++ b/configure @@ -9542,6 +9542,8 @@ then # 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 + # Note: This matches the value of THREAD_STACK_SIZE in + # thread_pthread.h LINKFORSHARED="-Wl,-stack_size,1000000 $LINKFORSHARED" if test "$enable_framework" diff --git a/configure.ac b/configure.ac index b9759e12f89f..8566d4338469 100644 --- a/configure.ac +++ b/configure.ac @@ -2694,6 +2694,8 @@ then # 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 + # Note: This matches the value of THREAD_STACK_SIZE in + # thread_pthread.h LINKFORSHARED="-Wl,-stack_size,1000000 $LINKFORSHARED" if test "$enable_framework" From webhook-mailer at python.org Thu Aug 1 09:18:11 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 01 Aug 2019 13:18:11 -0000 Subject: [Python-checkins] bpo-36302: Sort list of sources (GH-12341) Message-ID: https://github.com/python/cpython/commit/0d30ae1a03102de07758650af9243fd31211325a commit: 0d30ae1a03102de07758650af9243fd31211325a branch: master author: Bernhard M. Wiedemann committer: Victor Stinner date: 2019-08-01T15:18:03+02:00 summary: bpo-36302: Sort list of sources (GH-12341) When building packages (e.g. for openSUSE Linux) (random) filesystem order of input files influences ordering of functions in the output .so files. Thus without the patch, builds (in disposable VMs) would usually differ. Without this patch, all callers have to be patched individually https://github.com/dugsong/libdnet/pull/42 https://github.com/sass/libsass-python/pull/212 https://github.com/tahoe-lafs/pycryptopp/pull/41 https://github.com/yt-project/yt/pull/2206 https://github.com/pyproj4/pyproj/pull/142 https://github.com/pytries/datrie/pull/49 https://github.com/Roche/pyreadstat/pull/37 but that is an infinite effort. See https://reproducible-builds.org/ for why this matters. files: A Misc/NEWS.d/next/Library/2019-03-21-19-23-46.bpo-36302.Yc591g.rst M Lib/distutils/command/build_ext.py diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py index 2d7cdf063f01..38bb8fd93c27 100644 --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py @@ -490,7 +490,8 @@ def build_extension(self, ext): "in 'ext_modules' option (extension '%s'), " "'sources' must be present and must be " "a list of source filenames" % ext.name) - sources = list(sources) + # sort to make the resulting .so file build reproducible + sources = sorted(sources) ext_path = self.get_ext_fullpath(ext.name) depends = sources + ext.depends diff --git a/Misc/NEWS.d/next/Library/2019-03-21-19-23-46.bpo-36302.Yc591g.rst b/Misc/NEWS.d/next/Library/2019-03-21-19-23-46.bpo-36302.Yc591g.rst new file mode 100644 index 000000000000..fe01b5915d5d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-03-21-19-23-46.bpo-36302.Yc591g.rst @@ -0,0 +1,2 @@ +distutils sorts source file lists so that Extension .so files +build more reproducibly by default From webhook-mailer at python.org Thu Aug 1 10:17:58 2019 From: webhook-mailer at python.org (Guido van Rossum) Date: Thu, 01 Aug 2019 14:17:58 -0000 Subject: [Python-checkins] bpo-37726: Prefer argparse over getopt in stdlib tutorial (#15052) Message-ID: https://github.com/python/cpython/commit/2491134029b195d3159a489e1803ee22a7839b41 commit: 2491134029b195d3159a489e1803ee22a7839b41 branch: master author: mental committer: Guido van Rossum date: 2019-08-01T07:17:30-07:00 summary: bpo-37726: Prefer argparse over getopt in stdlib tutorial (#15052) files: A Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst M Doc/tutorial/stdlib.rst diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst index e030f8f19b48..f32063e7f096 100644 --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -72,10 +72,21 @@ three`` at the command line:: >>> print(sys.argv) ['demo.py', 'one', 'two', 'three'] -The :mod:`getopt` module processes *sys.argv* using the conventions of the Unix -:func:`getopt` function. More powerful and flexible command line processing is -provided by the :mod:`argparse` module. - +The :mod:`argparse` module provides a mechanism to process command line arguments. +It should always be preferred over directly processing ``sys.argv`` manually. + +Take, for example, the below snippet of code:: + + >>> import argparse + >>> from getpass import getuser + >>> parser = argparse.ArgumentParser(description='An argparse example.') + >>> parser.add_argument('name', nargs='?', default=getuser(), help='The name of someone to greet.') + >>> parser.add_argument('--verbose', '-v', action='count') + >>> args = parser.parse_args() + >>> greeting = ["Hi", "Hello", "Greetings! its very nice to meet you"][args.verbose % 3] + >>> print(f'{greeting}, {args.name}') + >>> if not args.verbose: + >>> print('Try running this again with multiple "-v" flags!') .. _tut-stderr: diff --git a/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst b/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst new file mode 100644 index 000000000000..195e9755a43c --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst @@ -0,0 +1,2 @@ +Stop recommending getopt in the tutorial for command line argument parsing +and promote argparse. From webhook-mailer at python.org Thu Aug 1 10:35:05 2019 From: webhook-mailer at python.org (Guido van Rossum) Date: Thu, 01 Aug 2019 14:35:05 -0000 Subject: [Python-checkins] bpo-37726: Prefer argparse over getopt in stdlib tutorial (GH-15052) (#15070) Message-ID: https://github.com/python/cpython/commit/dcc53ebbff384076b0763c1f842966c189417071 commit: dcc53ebbff384076b0763c1f842966c189417071 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Guido van Rossum date: 2019-08-01T07:34:57-07:00 summary: bpo-37726: Prefer argparse over getopt in stdlib tutorial (GH-15052) (#15070) (cherry picked from commit 2491134029b195d3159a489e1803ee22a7839b41) Co-authored-by: mental files: A Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst M Doc/tutorial/stdlib.rst diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst index 82261a651348..20ad3563ca05 100644 --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -72,10 +72,21 @@ three`` at the command line:: >>> print(sys.argv) ['demo.py', 'one', 'two', 'three'] -The :mod:`getopt` module processes *sys.argv* using the conventions of the Unix -:func:`getopt` function. More powerful and flexible command line processing is -provided by the :mod:`argparse` module. - +The :mod:`argparse` module provides a mechanism to process command line arguments. +It should always be preferred over directly processing ``sys.argv`` manually. + +Take, for example, the below snippet of code:: + + >>> import argparse + >>> from getpass import getuser + >>> parser = argparse.ArgumentParser(description='An argparse example.') + >>> parser.add_argument('name', nargs='?', default=getuser(), help='The name of someone to greet.') + >>> parser.add_argument('--verbose', '-v', action='count') + >>> args = parser.parse_args() + >>> greeting = ["Hi", "Hello", "Greetings! its very nice to meet you"][args.verbose % 3] + >>> print(f'{greeting}, {args.name}') + >>> if not args.verbose: + >>> print('Try running this again with multiple "-v" flags!') .. _tut-stderr: diff --git a/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst b/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst new file mode 100644 index 000000000000..195e9755a43c --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst @@ -0,0 +1,2 @@ +Stop recommending getopt in the tutorial for command line argument parsing +and promote argparse. From webhook-mailer at python.org Thu Aug 1 10:35:24 2019 From: webhook-mailer at python.org (Guido van Rossum) Date: Thu, 01 Aug 2019 14:35:24 -0000 Subject: [Python-checkins] bpo-37726: Prefer argparse over getopt in stdlib tutorial (GH-15052) (#15069) Message-ID: https://github.com/python/cpython/commit/8990ac0ab0398bfb9c62031288030fe7c630c2c7 commit: 8990ac0ab0398bfb9c62031288030fe7c630c2c7 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Guido van Rossum date: 2019-08-01T07:35:20-07:00 summary: bpo-37726: Prefer argparse over getopt in stdlib tutorial (GH-15052) (#15069) (cherry picked from commit 2491134029b195d3159a489e1803ee22a7839b41) Co-authored-by: mental files: A Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst M Doc/tutorial/stdlib.rst diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst index f5ec8acf58ad..26f11950e79e 100644 --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -72,10 +72,21 @@ three`` at the command line:: >>> print(sys.argv) ['demo.py', 'one', 'two', 'three'] -The :mod:`getopt` module processes *sys.argv* using the conventions of the Unix -:func:`getopt` function. More powerful and flexible command line processing is -provided by the :mod:`argparse` module. - +The :mod:`argparse` module provides a mechanism to process command line arguments. +It should always be preferred over directly processing ``sys.argv`` manually. + +Take, for example, the below snippet of code:: + + >>> import argparse + >>> from getpass import getuser + >>> parser = argparse.ArgumentParser(description='An argparse example.') + >>> parser.add_argument('name', nargs='?', default=getuser(), help='The name of someone to greet.') + >>> parser.add_argument('--verbose', '-v', action='count') + >>> args = parser.parse_args() + >>> greeting = ["Hi", "Hello", "Greetings! its very nice to meet you"][args.verbose % 3] + >>> print(f'{greeting}, {args.name}') + >>> if not args.verbose: + >>> print('Try running this again with multiple "-v" flags!') .. _tut-stderr: diff --git a/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst b/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst new file mode 100644 index 000000000000..195e9755a43c --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst @@ -0,0 +1,2 @@ +Stop recommending getopt in the tutorial for command line argument parsing +and promote argparse. From webhook-mailer at python.org Thu Aug 1 10:39:01 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 01 Aug 2019 14:39:01 -0000 Subject: [Python-checkins] bpo-18049: Sync thread stack size to main thread size on macOS (GH-14748) Message-ID: https://github.com/python/cpython/commit/8399641c34d8136c3151fda6461cc4727a20b28e commit: 8399641c34d8136c3151fda6461cc4727a20b28e branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-01T07:38:57-07:00 summary: bpo-18049: Sync thread stack size to main thread size on macOS (GH-14748) This changeset increases the default size of the stack for threads on macOS to the size of the stack of the main thread and reenables the relevant recursion test. (cherry picked from commit 1a057bab0f18d6ad843ce321d1d77a4819497ae4) Co-authored-by: Ronald Oussoren files: A Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst M Lib/test/test_threading.py M Python/thread_pthread.h M configure M configure.ac diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 0a0a62bdf9bf..ac4e7a7e0f53 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1049,8 +1049,6 @@ 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(), - 'test macosx problem') def test_recursion_limit(self): # Issue 9670 # test that excessive recursion within a non-main thread causes diff --git a/Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst b/Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst new file mode 100644 index 000000000000..5af07cdb4119 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst @@ -0,0 +1,3 @@ +Increase the default stack size of threads from 5MB to 16MB on macOS, to +match the stack size of the main thread. This avoids crashes on deep recursion +in threads. diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index a36d16c19ead..994e35b2cc08 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -40,7 +40,8 @@ */ #if defined(__APPLE__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 #undef THREAD_STACK_SIZE -#define THREAD_STACK_SIZE 0x500000 +/* Note: This matches the value of -Wl,-stack_size in configure.ac */ +#define THREAD_STACK_SIZE 0x1000000 #endif #if defined(__FreeBSD__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 #undef THREAD_STACK_SIZE diff --git a/configure b/configure index cb5f130d38e0..3cd9b8866c72 100755 --- a/configure +++ b/configure @@ -9542,6 +9542,8 @@ then # 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 + # Note: This matches the value of THREAD_STACK_SIZE in + # thread_pthread.h LINKFORSHARED="-Wl,-stack_size,1000000 $LINKFORSHARED" if test "$enable_framework" diff --git a/configure.ac b/configure.ac index b31ed242f1a8..a2088897fc13 100644 --- a/configure.ac +++ b/configure.ac @@ -2694,6 +2694,8 @@ then # 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 + # Note: This matches the value of THREAD_STACK_SIZE in + # thread_pthread.h LINKFORSHARED="-Wl,-stack_size,1000000 $LINKFORSHARED" if test "$enable_framework" From webhook-mailer at python.org Thu Aug 1 12:36:51 2019 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 01 Aug 2019 16:36:51 -0000 Subject: [Python-checkins] bpo-37461: Fix infinite loop in parsing of specially crafted email headers (GH-14794) (GH-14817) Message-ID: https://github.com/python/cpython/commit/1789bbdd3e03023951a39933ef12dee0a03be616 commit: 1789bbdd3e03023951a39933ef12dee0a03be616 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2019-08-01T12:36:46-04:00 summary: bpo-37461: Fix infinite loop in parsing of specially crafted email headers (GH-14794) (GH-14817) Some crafted email header would cause the get_parameter method to run in an infinite loop causing a DoS attack surface when parsing those headers. This patch fixes that by making sure the DQUOTE character is handled to prevent going into an infinite loop. (cherry picked from commit a4a994bd3e619cbaff97610a1cee8ffa87c672f5) Co-authored-by: Abhilash Raj files: A Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst M Lib/email/_header_value_parser.py M Lib/test/test_email/test__header_value_parser.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index e3c343dffb42..737951e4b1b1 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2366,6 +2366,9 @@ def get_parameter(value): while value: if value[0] in WSP: token, value = get_fws(value) + elif value[0] == '"': + token = ValueTerminal('"', 'DQUOTE') + value = value[1:] else: token, value = get_qcontent(value) v.append(token) diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index 676732bb3d02..a2c900fa7fd2 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -2601,6 +2601,13 @@ def mime_parameters_as_value(self, # Defects are apparent missing *0*, and two 'out of sequence'. [errors.InvalidHeaderDefect]*3), + # bpo-37461: Check that we don't go into an infinite loop. + 'extra_dquote': ( + 'r*="\'a\'\\"', + ' r="\\""', + 'r*=\'a\'"', + [('r', '"')], + [errors.InvalidHeaderDefect]*2), } @parameterize diff --git a/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst b/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst new file mode 100644 index 000000000000..4bfd350c0b40 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst @@ -0,0 +1,2 @@ +Fix an inifite loop when parsing specially crafted email headers. Patch by +Abhilash Raj. From webhook-mailer at python.org Fri Aug 2 00:57:31 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 02 Aug 2019 04:57:31 -0000 Subject: [Python-checkins] bpo-16970: Adding error message for invalid args (GH-14844) Message-ID: https://github.com/python/cpython/commit/4b3e97592376d5f8a3b75192b399a2da1be642cb commit: 4b3e97592376d5f8a3b75192b399a2da1be642cb branch: master author: tmblweed committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-01T21:57:13-07:00 summary: bpo-16970: Adding error message for invalid args (GH-14844) BPO -16970: Adding error message for invalid args Applied the patch argparse-v2 patch issue 16970, ran patch check and the test suite, test_argparse with 0 errors https://bugs.python.org/issue16970 files: A Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst M Lib/argparse.py M Lib/test/test_argparse.py M Misc/ACKS diff --git a/Lib/argparse.py b/Lib/argparse.py index e45b67b67704..a300828f9e3d 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -593,7 +593,10 @@ def _format_args(self, action, default_metavar): elif action.nargs == SUPPRESS: result = '' else: - formats = ['%s' for _ in range(action.nargs)] + try: + formats = ['%s' for _ in range(action.nargs)] + except TypeError: + raise ValueError("invalid nargs value") from None result = ' '.join(formats) % get_metavar(action.nargs) return result @@ -850,7 +853,7 @@ def __init__(self, help=None, metavar=None): if nargs == 0: - raise ValueError('nargs for store actions must be > 0; if you ' + raise ValueError('nargs for store actions must be != 0; if you ' 'have nothing to store, actions such as store ' 'true or store const may be more appropriate') if const is not None and nargs != OPTIONAL: @@ -942,7 +945,7 @@ def __init__(self, help=None, metavar=None): if nargs == 0: - raise ValueError('nargs for append actions must be > 0; if arg ' + raise ValueError('nargs for append actions must be != 0; if arg ' 'strings are not supplying the value to append, ' 'the append const action may be more appropriate') if const is not None and nargs != OPTIONAL: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 5128dc5e1be4..d6d16090eb02 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4263,7 +4263,6 @@ class TestHelpSubparsersWithHelpOrdering(HelpTestCase): class TestHelpMetavarTypeFormatter(HelpTestCase): - """""" def custom_type(string): return string @@ -5150,6 +5149,35 @@ def test_nargs_3_metavar_length2(self): def test_nargs_3_metavar_length3(self): self.do_test_no_exception(nargs=3, metavar=("1", "2", "3")) + +class TestInvalidNargs(TestCase): + + EXPECTED_INVALID_MESSAGE = "invalid nargs value" + EXPECTED_RANGE_MESSAGE = ("nargs for store actions must be != 0; if you " + "have nothing to store, actions such as store " + "true or store const may be more appropriate") + + def do_test_range_exception(self, nargs): + parser = argparse.ArgumentParser() + with self.assertRaises(ValueError) as cm: + parser.add_argument("--foo", nargs=nargs) + self.assertEqual(cm.exception.args[0], self.EXPECTED_RANGE_MESSAGE) + + def do_test_invalid_exception(self, nargs): + parser = argparse.ArgumentParser() + with self.assertRaises(ValueError) as cm: + parser.add_argument("--foo", nargs=nargs) + self.assertEqual(cm.exception.args[0], self.EXPECTED_INVALID_MESSAGE) + + # Unit tests for different values of nargs + + def test_nargs_alphabetic(self): + self.do_test_invalid_exception(nargs='a') + self.do_test_invalid_exception(nargs="abcd") + + def test_nargs_zero(self): + self.do_test_range_exception(nargs=0) + # ============================ # from argparse import * tests # ============================ diff --git a/Misc/ACKS b/Misc/ACKS index 6463b535e17c..82fc51c98c40 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1878,3 +1878,4 @@ Edison Abahurire Geoff Shannon Batuhan Taskaya Aleksandr Balezin +Robert Leenders diff --git a/Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst b/Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst new file mode 100644 index 000000000000..7285b8176032 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst @@ -0,0 +1,2 @@ +Adding a value error when an invalid value in passed to nargs +Patch by Robert Leenders From webhook-mailer at python.org Fri Aug 2 01:16:49 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 02 Aug 2019 05:16:49 -0000 Subject: [Python-checkins] bpo-16970: Adding error message for invalid args (GH-14844) Message-ID: https://github.com/python/cpython/commit/1cc70322c99b80c123f9ff23a415d3da28b4ec74 commit: 1cc70322c99b80c123f9ff23a415d3da28b4ec74 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-01T22:16:44-07:00 summary: bpo-16970: Adding error message for invalid args (GH-14844) BPO -16970: Adding error message for invalid args Applied the patch argparse-v2 patch issue 16970, ran patch check and the test suite, test_argparse with 0 errors https://bugs.python.org/issue16970 (cherry picked from commit 4b3e97592376d5f8a3b75192b399a2da1be642cb) Co-authored-by: tmblweed files: A Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst M Lib/argparse.py M Lib/test/test_argparse.py M Misc/ACKS diff --git a/Lib/argparse.py b/Lib/argparse.py index 5820d0d8ca99..6f0b37c1c5ea 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -593,7 +593,10 @@ def _format_args(self, action, default_metavar): elif action.nargs == SUPPRESS: result = '' else: - formats = ['%s' for _ in range(action.nargs)] + try: + formats = ['%s' for _ in range(action.nargs)] + except TypeError: + raise ValueError("invalid nargs value") from None result = ' '.join(formats) % get_metavar(action.nargs) return result @@ -850,7 +853,7 @@ def __init__(self, help=None, metavar=None): if nargs == 0: - raise ValueError('nargs for store actions must be > 0; if you ' + raise ValueError('nargs for store actions must be != 0; if you ' 'have nothing to store, actions such as store ' 'true or store const may be more appropriate') if const is not None and nargs != OPTIONAL: @@ -942,7 +945,7 @@ def __init__(self, help=None, metavar=None): if nargs == 0: - raise ValueError('nargs for append actions must be > 0; if arg ' + raise ValueError('nargs for append actions must be != 0; if arg ' 'strings are not supplying the value to append, ' 'the append const action may be more appropriate') if const is not None and nargs != OPTIONAL: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 5128dc5e1be4..d6d16090eb02 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4263,7 +4263,6 @@ class TestHelpSubparsersWithHelpOrdering(HelpTestCase): class TestHelpMetavarTypeFormatter(HelpTestCase): - """""" def custom_type(string): return string @@ -5150,6 +5149,35 @@ def test_nargs_3_metavar_length2(self): def test_nargs_3_metavar_length3(self): self.do_test_no_exception(nargs=3, metavar=("1", "2", "3")) + +class TestInvalidNargs(TestCase): + + EXPECTED_INVALID_MESSAGE = "invalid nargs value" + EXPECTED_RANGE_MESSAGE = ("nargs for store actions must be != 0; if you " + "have nothing to store, actions such as store " + "true or store const may be more appropriate") + + def do_test_range_exception(self, nargs): + parser = argparse.ArgumentParser() + with self.assertRaises(ValueError) as cm: + parser.add_argument("--foo", nargs=nargs) + self.assertEqual(cm.exception.args[0], self.EXPECTED_RANGE_MESSAGE) + + def do_test_invalid_exception(self, nargs): + parser = argparse.ArgumentParser() + with self.assertRaises(ValueError) as cm: + parser.add_argument("--foo", nargs=nargs) + self.assertEqual(cm.exception.args[0], self.EXPECTED_INVALID_MESSAGE) + + # Unit tests for different values of nargs + + def test_nargs_alphabetic(self): + self.do_test_invalid_exception(nargs='a') + self.do_test_invalid_exception(nargs="abcd") + + def test_nargs_zero(self): + self.do_test_range_exception(nargs=0) + # ============================ # from argparse import * tests # ============================ diff --git a/Misc/ACKS b/Misc/ACKS index ad2e0a1996aa..3e53429bf237 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1872,3 +1872,4 @@ Edison Abahurire Geoff Shannon Batuhan Taskaya Aleksandr Balezin +Robert Leenders diff --git a/Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst b/Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst new file mode 100644 index 000000000000..7285b8176032 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst @@ -0,0 +1,2 @@ +Adding a value error when an invalid value in passed to nargs +Patch by Robert Leenders From webhook-mailer at python.org Fri Aug 2 03:25:53 2019 From: webhook-mailer at python.org (Inada Naoki) Date: Fri, 02 Aug 2019 07:25:53 -0000 Subject: [Python-checkins] bpo-37729: gc: write stats at once (GH-15050) Message-ID: https://github.com/python/cpython/commit/bf8162c8c45338470bbe487c8769bba20bde66c2 commit: bf8162c8c45338470bbe487c8769bba20bde66c2 branch: master author: Inada Naoki committer: GitHub date: 2019-08-02T16:25:29+09:00 summary: bpo-37729: gc: write stats at once (GH-15050) gc used several PySys_WriteStderr() calls to write stats. It caused stats mixed up when stderr is shared by multiple processes like this: gc: collecting generation 2... gc: objects in each generation: 0 0gc: collecting generation 2... gc: objects in each generation: 0 0 126077 126077 gc: objects in permanent generation: 0 gc: objects in permanent generation: 0 gc: done, 112575 unreachable, 0 uncollectablegc: done, 112575 unreachable, 0 uncollectable, 0.2223s elapsed , 0.2344s elapsed files: M Modules/gcmodule.c diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 2ee765140b92..7586cd3e0515 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -962,6 +962,25 @@ clear_freelists(void) (void)PyContext_ClearFreeList(); } +// Show stats for objects in each gennerations. +static void +show_stats_each_generations(struct _gc_runtime_state *state) +{ + char buf[100]; + size_t pos = 0; + + for (int i = 0; i < NUM_GENERATIONS && pos < sizeof(buf); i++) { + pos += PyOS_snprintf(buf+pos, sizeof(buf)-pos, + " %"PY_FORMAT_SIZE_T"d", + gc_list_size(GEN_HEAD(state, i))); + } + + PySys_FormatStderr( + "gc: objects in each generation:%s\n" + "gc: objects in permanent generation: %zd\n", + buf, gc_list_size(&state->permanent_generation.head)); +} + /* This is the main function. Read this to understand how the * collection process works. */ static Py_ssize_t @@ -979,17 +998,9 @@ collect(struct _gc_runtime_state *state, int generation, _PyTime_t t1 = 0; /* initialize to prevent a compiler warning */ 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(state, i))); - PySys_WriteStderr("\ngc: objects in permanent generation: %zd", - gc_list_size(&state->permanent_generation.head)); + PySys_WriteStderr("gc: collecting generation %d...\n", generation); + show_stats_each_generations(state); t1 = _PyTime_GetMonotonicClock(); - - PySys_WriteStderr("\n"); } if (PyDTrace_GC_START_ENABLED()) @@ -1103,16 +1114,10 @@ collect(struct _gc_runtime_state *state, int generation, debug_cycle("uncollectable", FROM_GC(gc)); } if (state->debug & DEBUG_STATS) { - _PyTime_t t2 = _PyTime_GetMonotonicClock(); - - if (m == 0 && n == 0) - PySys_WriteStderr("gc: done"); - else - PySys_FormatStderr( - "gc: done, %zd unreachable, %zd uncollectable", - n+m, n); - PySys_WriteStderr(", %.4fs elapsed\n", - _PyTime_AsSecondsDouble(t2 - t1)); + double d = _PyTime_AsSecondsDouble(_PyTime_GetMonotonicClock() - t1); + PySys_FormatStderr( + "gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n", + n+m, n, d); } /* Append instances in the uncollectable set to a Python From webhook-mailer at python.org Fri Aug 2 11:50:31 2019 From: webhook-mailer at python.org (Eric Snow) Date: Fri, 02 Aug 2019 15:50:31 -0000 Subject: [Python-checkins] bpo-36487: Make C-API docs clear about what the main interpreter is. (gh-12666) Message-ID: https://github.com/python/cpython/commit/854d0a4b98b13629252e21edaf2b785b429e5135 commit: 854d0a4b98b13629252e21edaf2b785b429e5135 branch: master author: Joannah Nanjekye <33177550+nanjekyejoannah at users.noreply.github.com> committer: Eric Snow date: 2019-08-02T09:50:22-06:00 summary: bpo-36487: Make C-API docs clear about what the main interpreter is. (gh-12666) files: A Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst M Doc/c-api/init.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index a0ac4d21d139..4985a1d867e2 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -1141,10 +1141,18 @@ Sub-interpreter support While in most uses, you will only embed a single Python interpreter, there are cases where you need to create several independent interpreters in the -same process and perhaps even in the same thread. Sub-interpreters allow -you to do that. You can switch between sub-interpreters using the -:c:func:`PyThreadState_Swap` function. You can create and destroy them -using the following functions: +same process and perhaps even in the same thread. Sub-interpreters allow +you to do that. + +The "main" interpreter is the first one created when the runtime initializes. +It is usually the only Python interpreter in a process. Unlike sub-interpreters, +the main interpreter has unique process-global responsibilities like signal +handling. It is also responsible for execution during runtime initialization and +is usually the active interpreter during runtime finalization. The +:c:func:`PyInterpreterState_Main` funtion returns a pointer to its state. + +You can switch between sub-interpreters using the :c:func:`PyThreadState_Swap` +function. You can create and destroy them using the following functions: .. c:function:: PyThreadState* Py_NewInterpreter() diff --git a/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst b/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst new file mode 100755 index 000000000000..c8eb05b6c79c --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst @@ -0,0 +1 @@ +Make C-API docs clear about what the "main" interpreter is. \ No newline at end of file From webhook-mailer at python.org Fri Aug 2 11:53:05 2019 From: webhook-mailer at python.org (Vinay Sajip) Date: Fri, 02 Aug 2019 15:53:05 -0000 Subject: [Python-checkins] =?utf-8?q?bpo-37742=3A_Return_the_root_logger_?= =?utf-8?b?d2hlbiBsb2dnaW5nLmdldExvZ2dlcigncm9vdCcpIGlzIGPigKYgKCMxNTA3?= =?utf-8?q?7=29?= Message-ID: https://github.com/python/cpython/commit/cb65b3a4f484ce71dcb76a918af98c7015513025 commit: cb65b3a4f484ce71dcb76a918af98c7015513025 branch: master author: Vinay Sajip committer: GitHub date: 2019-08-02T16:53:00+01:00 summary: bpo-37742: Return the root logger when logging.getLogger('root') is c? (#15077) * bpo-37742: Return the root logger when logging.getLogger('root') is called. * Added type check guard on logger name in logging.getLogger() and refined a test. files: A Misc/NEWS.d/next/Library/2019-08-02-14-01-25.bpo-37742.f4Xn9S.rst M Lib/logging/__init__.py M Lib/test/test_logging.py diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 645e0b3c3a67..62a87a71b1a3 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -2024,10 +2024,9 @@ def getLogger(name=None): If no name is specified, return the root logger. """ - if name: - return Logger.manager.getLogger(name) - else: + if not name or isinstance(name, str) and name == root.name: return root + return Logger.manager.getLogger(name) def critical(msg, *args, **kwargs): """ diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 6507d79742a4..dca744c59092 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -4856,6 +4856,7 @@ def test_root_logger_aliases(self): self.assertIs(root, logging.root) self.assertIs(root, logging.getLogger(None)) self.assertIs(root, logging.getLogger('')) + self.assertIs(root, logging.getLogger('root')) self.assertIs(root, logging.getLogger('foo').root) self.assertIs(root, logging.getLogger('foo.bar').root) self.assertIs(root, logging.getLogger('foo').parent) diff --git a/Misc/NEWS.d/next/Library/2019-08-02-14-01-25.bpo-37742.f4Xn9S.rst b/Misc/NEWS.d/next/Library/2019-08-02-14-01-25.bpo-37742.f4Xn9S.rst new file mode 100644 index 000000000000..300ced3fec6b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-02-14-01-25.bpo-37742.f4Xn9S.rst @@ -0,0 +1,5 @@ +The logging.getLogger() API now returns the root logger when passed the name +'root', whereas previously it returned a non-root logger named 'root'. This +could affect cases where user code explicitly wants a non-root logger named +'root', or instantiates a logger using logging.getLogger(__name__) in some +top-level module called 'root.py'. From webhook-mailer at python.org Fri Aug 2 13:49:42 2019 From: webhook-mailer at python.org (Eric Snow) Date: Fri, 02 Aug 2019 17:49:42 -0000 Subject: [Python-checkins] bpo-36487: Make C-API docs clear about what the main interpreter is. (gh-15080) Message-ID: https://github.com/python/cpython/commit/375f35be0688da0fc0f27afc4faea76590d7c24d commit: 375f35be0688da0fc0f27afc4faea76590d7c24d branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Eric Snow date: 2019-08-02T11:49:38-06:00 summary: bpo-36487: Make C-API docs clear about what the main interpreter is. (gh-15080) (cherry picked from commit 854d0a4b98b13629252e21edaf2b785b429e5135) (gh-12666) Co-authored-by: Joannah Nanjekye <33177550+nanjekyejoannah at users.noreply.github.com> files: A Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst M Doc/c-api/init.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index a0ac4d21d139..4985a1d867e2 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -1141,10 +1141,18 @@ Sub-interpreter support While in most uses, you will only embed a single Python interpreter, there are cases where you need to create several independent interpreters in the -same process and perhaps even in the same thread. Sub-interpreters allow -you to do that. You can switch between sub-interpreters using the -:c:func:`PyThreadState_Swap` function. You can create and destroy them -using the following functions: +same process and perhaps even in the same thread. Sub-interpreters allow +you to do that. + +The "main" interpreter is the first one created when the runtime initializes. +It is usually the only Python interpreter in a process. Unlike sub-interpreters, +the main interpreter has unique process-global responsibilities like signal +handling. It is also responsible for execution during runtime initialization and +is usually the active interpreter during runtime finalization. The +:c:func:`PyInterpreterState_Main` funtion returns a pointer to its state. + +You can switch between sub-interpreters using the :c:func:`PyThreadState_Swap` +function. You can create and destroy them using the following functions: .. c:function:: PyThreadState* Py_NewInterpreter() diff --git a/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst b/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst new file mode 100755 index 000000000000..c8eb05b6c79c --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst @@ -0,0 +1 @@ +Make C-API docs clear about what the "main" interpreter is. \ No newline at end of file From webhook-mailer at python.org Fri Aug 2 16:30:02 2019 From: webhook-mailer at python.org (Steve Dower) Date: Fri, 02 Aug 2019 20:30:02 -0000 Subject: [Python-checkins] bpo-36590: Add Bluetooth RFCOMM and support for Windows. (GH-12767) Message-ID: https://github.com/python/cpython/commit/8fbece135d7615e836a845ca39223097046c8b8b commit: 8fbece135d7615e836a845ca39223097046c8b8b branch: master author: Greg Bowser committer: Steve Dower date: 2019-08-02T13:29:52-07:00 summary: bpo-36590: Add Bluetooth RFCOMM and support for Windows. (GH-12767) Support for RFCOMM, L2CAP, HCI, SCO is based on the BTPROTO_* macros being defined. Winsock only supports RFCOMM, even though it has a BTHPROTO_L2CAP macro. L2CAP support would build on windows, but not necessarily work. This also adds some basic unittests for constants (all of which existed prior to this commit, just not on windows) and creating sockets. pair: Nate Duarte files: A Misc/NEWS.d/next/Windows/2019-04-10-21-13-26.bpo-36590.ZTaKcu.rst M Lib/test/test_socket.py M Modules/socketmodule.c M Modules/socketmodule.h diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 11b2a38ad76d..ce816cd603ec 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -114,6 +114,19 @@ def _have_socket_vsock(): return ret +def _have_socket_bluetooth(): + """Check whether AF_BLUETOOTH sockets are supported on this host.""" + try: + # RFCOMM is supported by all platforms with bluetooth support. Windows + # does not support omitting the protocol. + s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM) + except (AttributeError, OSError): + return False + else: + s.close() + return True + + @contextlib.contextmanager def socket_setdefaulttimeout(timeout): old_timeout = socket.getdefaulttimeout() @@ -138,6 +151,8 @@ def socket_setdefaulttimeout(timeout): HAVE_SOCKET_UDPLITE = hasattr(socket, "IPPROTO_UDPLITE") +HAVE_SOCKET_BLUETOOTH = _have_socket_bluetooth() + # Size in bytes of the int type SIZEOF_INT = array.array("i").itemsize @@ -2257,6 +2272,45 @@ def testSocketBufferSize(self): socket.SO_VM_SOCKETS_BUFFER_MIN_SIZE)) + at unittest.skipUnless(HAVE_SOCKET_BLUETOOTH, + 'Bluetooth sockets required for this test.') +class BasicBluetoothTest(unittest.TestCase): + + def testBluetoothConstants(self): + socket.BDADDR_ANY + socket.BDADDR_LOCAL + socket.AF_BLUETOOTH + socket.BTPROTO_RFCOMM + + if sys.platform != "win32": + socket.BTPROTO_HCI + socket.SOL_HCI + socket.BTPROTO_L2CAP + + if not sys.platform.startswith("freebsd"): + socket.BTPROTO_SCO + + def testCreateRfcommSocket(self): + with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM) as s: + pass + + @unittest.skipIf(sys.platform == "win32", "windows does not support L2CAP sockets") + def testCreateL2capSocket(self): + with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP) as s: + pass + + @unittest.skipIf(sys.platform == "win32", "windows does not support HCI sockets") + def testCreateHciSocket(self): + with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI) as s: + pass + + @unittest.skipIf(sys.platform == "win32" or sys.platform.startswith("freebsd"), + "windows and freebsd do not support SCO sockets") + def testCreateScoSocket(self): + with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_SCO) as s: + pass + + class BasicTCPTest(SocketConnectedTest): def __init__(self, methodName='runTest'): @@ -6416,6 +6470,7 @@ def test_main(): BasicVSOCKTest, ThreadedVSOCKSocketStreamTest, ]) + tests.append(BasicBluetoothTest) tests.extend([ CmsgMacroTests, SendmsgUDPTest, diff --git a/Misc/NEWS.d/next/Windows/2019-04-10-21-13-26.bpo-36590.ZTaKcu.rst b/Misc/NEWS.d/next/Windows/2019-04-10-21-13-26.bpo-36590.ZTaKcu.rst new file mode 100644 index 000000000000..6a186bbeed74 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-04-10-21-13-26.bpo-36590.ZTaKcu.rst @@ -0,0 +1 @@ +Add native Bluetooth RFCOMM support to socket module. \ No newline at end of file diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c old mode 100644 new mode 100755 index 99e350b4333b..f220c2636319 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -520,6 +520,15 @@ remove_unusable_flags(PyObject *m) #endif #endif +#ifdef MS_WINDOWS +#define sockaddr_rc SOCKADDR_BTH_REDEF + +#define USE_BLUETOOTH 1 +#define AF_BLUETOOTH AF_BTH +#define BTPROTO_RFCOMM BTHPROTO_RFCOMM +#define _BT_RC_MEMB(sa, memb) ((sa)->memb) +#endif + /* Convert "sock_addr_t *" to "struct sockaddr *". */ #define SAS2SA(x) (&((x)->sa)) @@ -1256,12 +1265,23 @@ setbdaddr(const char *name, bdaddr_t *bdaddr) n = sscanf(name, "%X:%X:%X:%X:%X:%X%c", &b5, &b4, &b3, &b2, &b1, &b0, &ch); if (n == 6 && (b0 | b1 | b2 | b3 | b4 | b5) < 256) { + +#ifdef MS_WINDOWS + *bdaddr = (ULONGLONG)(b0 & 0xFF); + *bdaddr |= ((ULONGLONG)(b1 & 0xFF) << 8); + *bdaddr |= ((ULONGLONG)(b2 & 0xFF) << 16); + *bdaddr |= ((ULONGLONG)(b3 & 0xFF) << 24); + *bdaddr |= ((ULONGLONG)(b4 & 0xFF) << 32); + *bdaddr |= ((ULONGLONG)(b5 & 0xFF) << 40); +#else bdaddr->b[0] = b0; bdaddr->b[1] = b1; bdaddr->b[2] = b2; bdaddr->b[3] = b3; bdaddr->b[4] = b4; bdaddr->b[5] = b5; +#endif + return 6; } else { PyErr_SetString(PyExc_OSError, "bad bluetooth address"); @@ -1278,9 +1298,23 @@ makebdaddr(bdaddr_t *bdaddr) { char buf[(6 * 2) + 5 + 1]; +#ifdef MS_WINDOWS + int i; + unsigned int octets[6]; + + for (i = 0; i < 6; ++i) { + octets[i] = ((*bdaddr) >> (8 * i)) & 0xFF; + } + + sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", + octets[5], octets[4], octets[3], + octets[2], octets[1], octets[0]); +#else sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); +#endif + return PyUnicode_FromString(buf); } #endif @@ -1378,6 +1412,7 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) case AF_BLUETOOTH: switch (proto) { +#ifdef BTPROTO_L2CAP case BTPROTO_L2CAP: { struct sockaddr_l2 *a = (struct sockaddr_l2 *) addr; @@ -1392,6 +1427,8 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) return ret; } +#endif /* BTPROTO_L2CAP */ + case BTPROTO_RFCOMM: { struct sockaddr_rc *a = (struct sockaddr_rc *) addr; @@ -1406,6 +1443,7 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) return ret; } +#ifdef BTPROTO_HCI case BTPROTO_HCI: { struct sockaddr_hci *a = (struct sockaddr_hci *) addr; @@ -1425,6 +1463,7 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) return makebdaddr(&_BT_SCO_MEMB(a, bdaddr)); } #endif /* !__FreeBSD__ */ +#endif /* BTPROTO_HCI */ default: PyErr_SetString(PyExc_ValueError, @@ -1879,6 +1918,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, case AF_BLUETOOTH: { switch (s->sock_proto) { +#ifdef BTPROTO_L2CAP case BTPROTO_L2CAP: { struct sockaddr_l2 *addr; @@ -1899,6 +1939,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, *len_ret = sizeof *addr; return 1; } +#endif /* BTPROTO_L2CAP */ case BTPROTO_RFCOMM: { struct sockaddr_rc *addr; @@ -1918,6 +1959,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, *len_ret = sizeof *addr; return 1; } +#ifdef BTPROTO_HCI case BTPROTO_HCI: { struct sockaddr_hci *addr = (struct sockaddr_hci *)addr_ret; @@ -1964,6 +2006,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, return 1; } #endif /* !__FreeBSD__ */ +#endif /* BTPROTO_HCI */ default: PyErr_Format(PyExc_OSError, "%s(): unknown Bluetooth protocol", caller); @@ -2385,12 +2428,15 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret) switch(s->sock_proto) { +#ifdef BTPROTO_L2CAP case BTPROTO_L2CAP: *len_ret = sizeof (struct sockaddr_l2); return 1; +#endif /* BTPROTO_L2CAP */ case BTPROTO_RFCOMM: *len_ret = sizeof (struct sockaddr_rc); return 1; +#ifdef BTPROTO_HCI case BTPROTO_HCI: *len_ret = sizeof (struct sockaddr_hci); return 1; @@ -2399,6 +2445,7 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret) *len_ret = sizeof (struct sockaddr_sco); return 1; #endif /* !__FreeBSD__ */ +#endif /* BTPROTO_HCI */ default: PyErr_SetString(PyExc_OSError, "getsockaddrlen: " "unknown BT protocol"); @@ -7273,23 +7320,29 @@ PyInit__socket(void) #ifdef USE_BLUETOOTH PyModule_AddIntMacro(m, AF_BLUETOOTH); +#ifdef BTPROTO_L2CAP PyModule_AddIntMacro(m, BTPROTO_L2CAP); +#endif /* BTPROTO_L2CAP */ +#ifdef BTPROTO_HCI PyModule_AddIntMacro(m, BTPROTO_HCI); PyModule_AddIntMacro(m, SOL_HCI); #if !defined(__NetBSD__) && !defined(__DragonFly__) PyModule_AddIntMacro(m, HCI_FILTER); -#endif #if !defined(__FreeBSD__) -#if !defined(__NetBSD__) && !defined(__DragonFly__) PyModule_AddIntMacro(m, HCI_TIME_STAMP); -#endif PyModule_AddIntMacro(m, HCI_DATA_DIR); - PyModule_AddIntMacro(m, BTPROTO_SCO); -#endif +#endif /* !__FreeBSD__ */ +#endif /* !__NetBSD__ && !__DragonFly__ */ +#endif /* BTPROTO_HCI */ +#ifdef BTPROTO_RFCOMM PyModule_AddIntMacro(m, BTPROTO_RFCOMM); +#endif /* BTPROTO_RFCOMM */ PyModule_AddStringConstant(m, "BDADDR_ANY", "00:00:00:00:00:00"); PyModule_AddStringConstant(m, "BDADDR_LOCAL", "00:00:00:FF:FF:FF"); -#endif +#ifdef BTPROTO_SCO + PyModule_AddIntMacro(m, BTPROTO_SCO); +#endif /* BTPROTO_SCO */ +#endif /* USE_BLUETOOTH */ #ifdef AF_CAN /* Controller Area Network */ diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h old mode 100644 new mode 100755 index dff1f8f4e9ce..3d95fe709ac7 --- a/Modules/socketmodule.h +++ b/Modules/socketmodule.h @@ -14,6 +14,47 @@ #else /* MS_WINDOWS */ # include + +/* + * If Windows has bluetooth support, include bluetooth constants. + */ +#ifdef AF_BTH +# include +# include + +/* + * The current implementation assumes the bdaddr in the sockaddr structs + * will be a bdaddr_t. We treat this as an opaque type: on *nix systems, it + * will be a struct with a single member (an array of six bytes). On windows, + * we typedef this to ULONGLONG to match the Windows definition. + */ +typedef ULONGLONG bdaddr_t; + +/* + * Redefine SOCKADDR_BTH to provide names compatible with _BT_RC_MEMB() macros. + */ +struct SOCKADDR_BTH_REDEF { + union { + USHORT addressFamily; + USHORT family; + }; + + union { + ULONGLONG btAddr; + bdaddr_t bdaddr; + }; + + GUID serviceClassId; + + union { + ULONG port; + ULONG channel; + }; + +}; +# include +#endif + /* Windows 'supports' CMSG_LEN, but does not follow the POSIX standard * interface at all, so there is no point including the code that * attempts to use it. @@ -199,6 +240,8 @@ typedef union sock_addr { struct sockaddr_rc bt_rc; struct sockaddr_sco bt_sco; struct sockaddr_hci bt_hci; +#elif defined(MS_WINDOWS) + struct SOCKADDR_BTH_REDEF bt_rc; #endif #ifdef HAVE_NETPACKET_PACKET_H struct sockaddr_ll ll; From webhook-mailer at python.org Fri Aug 2 18:20:18 2019 From: webhook-mailer at python.org (Steve Dower) Date: Fri, 02 Aug 2019 22:20:18 -0000 Subject: [Python-checkins] bpo-20523: pdb searches for .pdbrc in ~ instead of $HOME (GH-11847) Message-ID: https://github.com/python/cpython/commit/7ea9a85f132b32347fcbd2cbe1b553a2e9890b56 commit: 7ea9a85f132b32347fcbd2cbe1b553a2e9890b56 branch: master author: Timothy Hopper committer: Steve Dower date: 2019-08-02T15:20:14-07:00 summary: bpo-20523: pdb searches for .pdbrc in ~ instead of $HOME (GH-11847) Previously pdb checked the $HOME environmental variable to find the user .pdbrc. If $HOME is not set, the user .pdbrc would not be found. Change pdb to use `os.path.expanduser('~')` to determine the user's home directory. Thus, if $HOME is not set (as in tox or on Windows), os.path.expanduser('~') falls back on other techniques for locating the user's home directory. This follows pip's implementation for loading .piprc. Co-authored-by: Dan Lidral-Porter files: A Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst M Lib/pdb.py M Lib/test/test_pdb.py diff --git a/Lib/pdb.py b/Lib/pdb.py index 5e62f392d932..69fd8bd6efb0 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -160,16 +160,14 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, self.allow_kbdint = False self.nosigint = nosigint - # Read $HOME/.pdbrc and ./.pdbrc + # Read ~/.pdbrc and ./.pdbrc self.rcLines = [] if readrc: - if 'HOME' in os.environ: - envHome = os.environ['HOME'] - try: - with open(os.path.join(envHome, ".pdbrc")) as rcFile: - self.rcLines.extend(rcFile) - except OSError: - pass + try: + with open(os.path.expanduser('~/.pdbrc')) as rcFile: + self.rcLines.extend(rcFile) + except OSError: + pass try: with open(".pdbrc") as rcFile: self.rcLines.extend(rcFile) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 1e464df28340..646bdb16e53b 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -1377,6 +1377,19 @@ def test_readrc_kwarg(self): if save_home is not None: os.environ['HOME'] = save_home + def test_readrc_homedir(self): + save_home = os.environ.pop("HOME", None) + with support.temp_dir() as temp_dir, patch("os.path.expanduser"): + rc_path = os.path.join(temp_dir, ".pdbrc") + os.path.expanduser.return_value = rc_path + try: + with open(rc_path, "w") as f: + f.write("invalid") + self.assertEqual(pdb.Pdb().rcLines[0], "invalid") + finally: + if save_home is not None: + os.environ["HOME"] = save_home + def test_header(self): stdout = StringIO() header = 'Nobody expects... blah, blah, blah' diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst b/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst new file mode 100644 index 000000000000..91397c243b9f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst @@ -0,0 +1,2 @@ +``pdb.Pdb`` supports ~/.pdbrc in Windows 7. Patch by Tim Hopper and Dan +Lidral-Porter. \ No newline at end of file From webhook-mailer at python.org Fri Aug 2 18:40:19 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 02 Aug 2019 22:40:19 -0000 Subject: [Python-checkins] bpo-20523: pdb searches for .pdbrc in ~ instead of $HOME (GH-11847) Message-ID: https://github.com/python/cpython/commit/1ff7dd681c7f3e31524bfada6d6d2786d4e37704 commit: 1ff7dd681c7f3e31524bfada6d6d2786d4e37704 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-02T15:40:14-07:00 summary: bpo-20523: pdb searches for .pdbrc in ~ instead of $HOME (GH-11847) Previously pdb checked the $HOME environmental variable to find the user .pdbrc. If $HOME is not set, the user .pdbrc would not be found. Change pdb to use `os.path.expanduser('~')` to determine the user's home directory. Thus, if $HOME is not set (as in tox or on Windows), os.path.expanduser('~') falls back on other techniques for locating the user's home directory. This follows pip's implementation for loading .piprc. Co-authored-by: Dan Lidral-Porter (cherry picked from commit 7ea9a85f132b32347fcbd2cbe1b553a2e9890b56) Co-authored-by: Timothy Hopper files: A Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst M Lib/pdb.py M Lib/test/test_pdb.py diff --git a/Lib/pdb.py b/Lib/pdb.py index 59b23dfc8bea..11d763994458 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -159,16 +159,14 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, self.allow_kbdint = False self.nosigint = nosigint - # Read $HOME/.pdbrc and ./.pdbrc + # Read ~/.pdbrc and ./.pdbrc self.rcLines = [] if readrc: - if 'HOME' in os.environ: - envHome = os.environ['HOME'] - try: - with open(os.path.join(envHome, ".pdbrc")) as rcFile: - self.rcLines.extend(rcFile) - except OSError: - pass + try: + with open(os.path.expanduser('~/.pdbrc')) as rcFile: + self.rcLines.extend(rcFile) + except OSError: + pass try: with open(".pdbrc") as rcFile: self.rcLines.extend(rcFile) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index de6c651b370a..63909e21f246 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -1350,6 +1350,19 @@ def test_readrc_kwarg(self): if save_home is not None: os.environ['HOME'] = save_home + def test_readrc_homedir(self): + save_home = os.environ.pop("HOME", None) + with support.temp_dir() as temp_dir, patch("os.path.expanduser"): + rc_path = os.path.join(temp_dir, ".pdbrc") + os.path.expanduser.return_value = rc_path + try: + with open(rc_path, "w") as f: + f.write("invalid") + self.assertEqual(pdb.Pdb().rcLines[0], "invalid") + finally: + if save_home is not None: + os.environ["HOME"] = save_home + def test_header(self): stdout = StringIO() header = 'Nobody expects... blah, blah, blah' diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst b/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst new file mode 100644 index 000000000000..91397c243b9f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst @@ -0,0 +1,2 @@ +``pdb.Pdb`` supports ~/.pdbrc in Windows 7. Patch by Tim Hopper and Dan +Lidral-Porter. \ No newline at end of file From webhook-mailer at python.org Fri Aug 2 18:42:54 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 02 Aug 2019 22:42:54 -0000 Subject: [Python-checkins] bpo-20523: pdb searches for .pdbrc in ~ instead of $HOME (GH-11847) Message-ID: https://github.com/python/cpython/commit/79af3bd1d170ed6a72a5c126e862590cdbf192d7 commit: 79af3bd1d170ed6a72a5c126e862590cdbf192d7 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-02T15:42:50-07:00 summary: bpo-20523: pdb searches for .pdbrc in ~ instead of $HOME (GH-11847) Previously pdb checked the $HOME environmental variable to find the user .pdbrc. If $HOME is not set, the user .pdbrc would not be found. Change pdb to use `os.path.expanduser('~')` to determine the user's home directory. Thus, if $HOME is not set (as in tox or on Windows), os.path.expanduser('~') falls back on other techniques for locating the user's home directory. This follows pip's implementation for loading .piprc. Co-authored-by: Dan Lidral-Porter (cherry picked from commit 7ea9a85f132b32347fcbd2cbe1b553a2e9890b56) Co-authored-by: Timothy Hopper files: A Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst M Lib/pdb.py M Lib/test/test_pdb.py diff --git a/Lib/pdb.py b/Lib/pdb.py index 5e62f392d932..69fd8bd6efb0 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -160,16 +160,14 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, self.allow_kbdint = False self.nosigint = nosigint - # Read $HOME/.pdbrc and ./.pdbrc + # Read ~/.pdbrc and ./.pdbrc self.rcLines = [] if readrc: - if 'HOME' in os.environ: - envHome = os.environ['HOME'] - try: - with open(os.path.join(envHome, ".pdbrc")) as rcFile: - self.rcLines.extend(rcFile) - except OSError: - pass + try: + with open(os.path.expanduser('~/.pdbrc')) as rcFile: + self.rcLines.extend(rcFile) + except OSError: + pass try: with open(".pdbrc") as rcFile: self.rcLines.extend(rcFile) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index d03f1b284300..16d245a5602a 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -1377,6 +1377,19 @@ def test_readrc_kwarg(self): if save_home is not None: os.environ['HOME'] = save_home + def test_readrc_homedir(self): + save_home = os.environ.pop("HOME", None) + with support.temp_dir() as temp_dir, patch("os.path.expanduser"): + rc_path = os.path.join(temp_dir, ".pdbrc") + os.path.expanduser.return_value = rc_path + try: + with open(rc_path, "w") as f: + f.write("invalid") + self.assertEqual(pdb.Pdb().rcLines[0], "invalid") + finally: + if save_home is not None: + os.environ["HOME"] = save_home + def test_header(self): stdout = StringIO() header = 'Nobody expects... blah, blah, blah' diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst b/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst new file mode 100644 index 000000000000..91397c243b9f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst @@ -0,0 +1,2 @@ +``pdb.Pdb`` supports ~/.pdbrc in Windows 7. Patch by Tim Hopper and Dan +Lidral-Porter. \ No newline at end of file From webhook-mailer at python.org Fri Aug 2 18:44:28 2019 From: webhook-mailer at python.org (Steve Dower) Date: Fri, 02 Aug 2019 22:44:28 -0000 Subject: [Python-checkins] bpo-30974: Change os.path.samefile docstring to match docs (GH-7337) Message-ID: https://github.com/python/cpython/commit/8e568ef266a2805f9a6042003723d9c050830461 commit: 8e568ef266a2805f9a6042003723d9c050830461 branch: master author: Timo Furrer committer: Steve Dower date: 2019-08-02T15:44:25-07:00 summary: bpo-30974: Change os.path.samefile docstring to match docs (GH-7337) files: M Lib/genericpath.py diff --git a/Lib/genericpath.py b/Lib/genericpath.py index 5dd703d736c5..db11f67d54cc 100644 --- a/Lib/genericpath.py +++ b/Lib/genericpath.py @@ -92,7 +92,11 @@ def samestat(s1, s2): # Are two filenames really pointing to the same file? def samefile(f1, f2): - """Test whether two pathnames reference the same actual file""" + """Test whether two pathnames reference the same actual file or directory + + This is determined by the device number and i-node number and + raises an exception if an os.stat() call on either pathname fails. + """ s1 = os.stat(f1) s2 = os.stat(f2) return samestat(s1, s2) From webhook-mailer at python.org Fri Aug 2 19:04:57 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 02 Aug 2019 23:04:57 -0000 Subject: [Python-checkins] bpo-30974: Change os.path.samefile docstring to match docs (GH-7337) Message-ID: https://github.com/python/cpython/commit/6b833901fe9053937c289c6371bb731c9aceb58e commit: 6b833901fe9053937c289c6371bb731c9aceb58e branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-02T16:04:53-07:00 summary: bpo-30974: Change os.path.samefile docstring to match docs (GH-7337) (cherry picked from commit 8e568ef266a2805f9a6042003723d9c050830461) Co-authored-by: Timo Furrer files: M Lib/genericpath.py diff --git a/Lib/genericpath.py b/Lib/genericpath.py index 5dd703d736c5..db11f67d54cc 100644 --- a/Lib/genericpath.py +++ b/Lib/genericpath.py @@ -92,7 +92,11 @@ def samestat(s1, s2): # Are two filenames really pointing to the same file? def samefile(f1, f2): - """Test whether two pathnames reference the same actual file""" + """Test whether two pathnames reference the same actual file or directory + + This is determined by the device number and i-node number and + raises an exception if an os.stat() call on either pathname fails. + """ s1 = os.stat(f1) s2 = os.stat(f2) return samestat(s1, s2) From webhook-mailer at python.org Fri Aug 2 19:11:37 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 02 Aug 2019 23:11:37 -0000 Subject: [Python-checkins] bpo-30974: Change os.path.samefile docstring to match docs (GH-7337) Message-ID: https://github.com/python/cpython/commit/a49f203e052c6fb1244d4e55c3fccc439dda0e2e commit: a49f203e052c6fb1244d4e55c3fccc439dda0e2e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-02T16:11:33-07:00 summary: bpo-30974: Change os.path.samefile docstring to match docs (GH-7337) (cherry picked from commit 8e568ef266a2805f9a6042003723d9c050830461) Co-authored-by: Timo Furrer files: M Lib/genericpath.py diff --git a/Lib/genericpath.py b/Lib/genericpath.py index 303b3b349a9f..85f4a57582f2 100644 --- a/Lib/genericpath.py +++ b/Lib/genericpath.py @@ -92,7 +92,11 @@ def samestat(s1, s2): # Are two filenames really pointing to the same file? def samefile(f1, f2): - """Test whether two pathnames reference the same actual file""" + """Test whether two pathnames reference the same actual file or directory + + This is determined by the device number and i-node number and + raises an exception if an os.stat() call on either pathname fails. + """ s1 = os.stat(f1) s2 = os.stat(f2) return samestat(s1, s2) From webhook-mailer at python.org Sat Aug 3 01:46:06 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 03 Aug 2019 05:46:06 -0000 Subject: [Python-checkins] bpo-37444: Update differing exception between builtins and importlib (GH-14869) Message-ID: https://github.com/python/cpython/commit/c5fa44944ee0a31a12b9a70776c7cb56c4dc39a2 commit: c5fa44944ee0a31a12b9a70776c7cb56c4dc39a2 branch: master author: Ngalim Siregar committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-02T22:46:02-07:00 summary: bpo-37444: Update differing exception between builtins and importlib (GH-14869) Imports now raise `TypeError` instead of `ValueError` for relative import failures. This makes things consistent between `builtins.__import__` and `importlib.__import__` as well as using a more natural import for the failure. https://bugs.python.org/issue37444 Automerge-Triggered-By: @brettcannon files: A Misc/NEWS.d/next/Core and Builtins/2019-07-20-22-34-42.bpo-37444.UOd3Xs.rst M Doc/library/importlib.rst M Doc/whatsnew/3.9.rst M Lib/importlib/_bootstrap.py M Lib/importlib/util.py M Lib/test/test_importlib/import_/test_relative_imports.py M Lib/test/test_importlib/test_util.py M Python/import.c M Python/importlib.h diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 65a685022e92..8be6172d4c76 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -1433,13 +1433,18 @@ an :term:`importer`. ``importlib.util.resolve_name('sys', __package__)`` without doing a check to see if the **package** argument is needed. - :exc:`ValueError` is raised if **name** is a relative module name but - package is a false value (e.g. ``None`` or the empty string). - :exc:`ValueError` is also raised a relative name would escape its containing + :exc:`ImportError` is raised if **name** is a relative module name but + **package** is a false value (e.g. ``None`` or the empty string). + :exc:`ImportError` is also raised a relative name would escape its containing package (e.g. requesting ``..bacon`` from within the ``spam`` package). .. versionadded:: 3.3 + .. versionchanged:: 3.9 + To improve consistency with import statements, raise + :exc:`ImportError` instead of :exc:`ValueError` for invalid relative + import attempts. + .. function:: find_spec(name, package=None) Find the :term:`spec ` for a module, optionally relative to diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 273fd2b50d59..61d9e745e87c 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -75,6 +75,12 @@ New Features Other Language Changes ====================== +* :func:`builtins.__import__` now raises :exc:`ImportError` instead of + :exc:`ValueError` as used to occur when a relative import went past + its top-level package. + (Contributed by Ngalim Siregar in :issue:`37444`.) + + * Python now gets the absolute path of the script filename specified on the command line (ex: ``python3 script.py``): the ``__file__`` attribute of the ``__main__`` module, ``sys.argv[0]`` and ``sys.path[0]`` become an @@ -118,6 +124,13 @@ pprint :mod:`pprint` can now pretty-print :class:`types.SimpleNamespace`. (Contributed by Carl Bordum Hansen in :issue:`37376`.) +importlib +--------- + +To improve consistency with import statements, :func:`importlib.util.resolve_name` +now raises :exc:`ImportError` instead of :exc:`ValueError` for invalid relative +import attempts. +(Contributed by Ngalim Siregar in :issue:`37444`.) Optimizations ============= @@ -180,4 +193,11 @@ Porting to Python 3.9 This section lists previously described changes and other bugfixes that may require changes to your code. +Changes in the Python API +------------------------- +* :func:`builtins.__import__` and :func:`importlib.util.resolve_name` now raise + :exc:`ImportError` where it previously raised :exc:`ValueError`. Callers + catching the specific exception type and supporting both Python 3.9 and + earlier versions will need to catch both: + ``except (ImportError, ValueError):`` diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 32deef10af9b..5e2f520c0ef8 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -873,7 +873,7 @@ def _resolve_name(name, package, level): """Resolve a relative module name to an absolute one.""" bits = package.rsplit('.', level - 1) if len(bits) < level: - raise ValueError('attempted relative import beyond top-level package') + raise ImportError('attempted relative import beyond top-level package') base = bits[0] return '{}.{}'.format(base, name) if name else base diff --git a/Lib/importlib/util.py b/Lib/importlib/util.py index 201e0f4cb89d..269a6fa930aa 100644 --- a/Lib/importlib/util.py +++ b/Lib/importlib/util.py @@ -29,8 +29,8 @@ def resolve_name(name, package): if not name.startswith('.'): return name elif not package: - raise ValueError(f'no package specified for {repr(name)} ' - '(required for relative module names)') + raise ImportError(f'no package specified for {repr(name)} ' + '(required for relative module names)') level = 0 for character in name: if character != '.': diff --git a/Lib/test/test_importlib/import_/test_relative_imports.py b/Lib/test/test_importlib/import_/test_relative_imports.py index 8a95a32109d2..586a9bf4bc12 100644 --- a/Lib/test/test_importlib/import_/test_relative_imports.py +++ b/Lib/test/test_importlib/import_/test_relative_imports.py @@ -156,7 +156,7 @@ def test_too_high_from_package(self): {'__name__': 'pkg', '__path__': ['blah']}) def callback(global_): self.__import__('pkg') - with self.assertRaises(ValueError): + with self.assertRaises(ImportError): self.__import__('', global_, fromlist=['top_level'], level=2) self.relative_import_test(create, globals_, callback) @@ -167,7 +167,7 @@ def test_too_high_from_module(self): globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.module'} def callback(global_): self.__import__('pkg') - with self.assertRaises(ValueError): + with self.assertRaises(ImportError): self.__import__('', global_, fromlist=['top_level'], level=2) self.relative_import_test(create, globals_, callback) diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py index 0350a5a5cc05..8489c198728a 100644 --- a/Lib/test/test_importlib/test_util.py +++ b/Lib/test/test_importlib/test_util.py @@ -375,7 +375,7 @@ def test_absolute_within_package(self): def test_no_package(self): # .bacon in '' - with self.assertRaises(ValueError): + with self.assertRaises(ImportError): self.util.resolve_name('.bacon', '') def test_in_package(self): @@ -390,7 +390,7 @@ def test_other_package(self): def test_escape(self): # ..bacon in spam - with self.assertRaises(ValueError): + with self.assertRaises(ImportError): self.util.resolve_name('..bacon', 'spam') @@ -518,7 +518,7 @@ def test_find_relative_module_missing_package(self): with util.temp_module(name, pkg=True) as pkg_dir: fullname, _ = util.submodule(name, subname, pkg_dir) relname = '.' + subname - with self.assertRaises(ValueError): + with self.assertRaises(ImportError): self.util.find_spec(relname) self.assertNotIn(name, sorted(sys.modules)) self.assertNotIn(fullname, sorted(sys.modules)) diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-07-20-22-34-42.bpo-37444.UOd3Xs.rst b/Misc/NEWS.d/next/Core and Builtins/2019-07-20-22-34-42.bpo-37444.UOd3Xs.rst new file mode 100644 index 000000000000..67c68071a839 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-07-20-22-34-42.bpo-37444.UOd3Xs.rst @@ -0,0 +1 @@ +Update differing exception between :meth:`builtins.__import__` and :meth:`importlib.__import__`. diff --git a/Python/import.c b/Python/import.c index 9f5ec284ae15..41c2f34f12c6 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1671,7 +1671,7 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level goto error; } else if (last_dot == -1) { - _PyErr_SetString(tstate, PyExc_ValueError, + _PyErr_SetString(tstate, PyExc_ImportError, "attempted relative import beyond top-level " "package"); goto error; diff --git a/Python/importlib.h b/Python/importlib.h index a285a31e2065..a6952af22b4f 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -1351,89 +1351,89 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,188,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,116,1,124,1,124,3,131,2, - 83,0,114,13,0,0,0,41,2,114,167,0,0,0,114,91, - 0,0,0,41,4,218,6,102,105,110,100,101,114,114,17,0, - 0,0,114,164,0,0,0,114,109,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,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, - 190,0,0,0,99,3,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,190,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,191,0, - 0,0,90,9,105,115,95,114,101,108,111,97,100,114,189,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,195,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,185, - 0,0,0,114,79,0,0,0,169,3,114,17,0,0,0,114, - 186,0,0,0,114,187,0,0,0,114,10,0,0,0,114,10, + 108,105,116,218,3,108,101,110,114,79,0,0,0,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,187,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,116,1,124,1,124,3,131,2,83,0,114,13,0,0,0, + 41,2,114,167,0,0,0,114,91,0,0,0,41,4,218,6, + 102,105,110,100,101,114,114,17,0,0,0,114,164,0,0,0, + 114,109,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,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,189,0,0,0,99,3,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,189,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,190,0,0,0,90,9,105,115,95, + 114,101,108,111,97,100,114,188,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,194,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,218,10,86,97,108,117,101,69,114, + 114,111,114,114,79,0,0,0,169,3,114,17,0,0,0,114, + 185,0,0,0,114,186,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, @@ -1462,7 +1462,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,195,0,0,0,114,159,0,0,0,114,5,0,0,0, + 114,114,194,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, @@ -1520,7 +1520,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,200,0, - 0,0,114,188,0,0,0,114,207,0,0,0,218,11,95,103, + 0,0,114,187,0,0,0,114,207,0,0,0,218,11,95,103, 99,100,95,105,109,112,111,114,116,114,199,0,0,0,114,10, 0,0,0,114,10,0,0,0,114,11,0,0,0,114,208,0, 0,0,234,3,0,0,115,8,0,0,0,0,9,12,1,8, @@ -1561,8 +1561,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,209,0,0,0, - 114,182,0,0,0,78,41,16,114,196,0,0,0,114,197,0, - 0,0,114,1,0,0,0,114,198,0,0,0,114,14,0,0, + 114,182,0,0,0,78,41,16,114,195,0,0,0,114,196,0, + 0,0,114,1,0,0,0,114,197,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,212,0,0,0,114,45,0, 0,0,114,67,0,0,0,114,203,0,0,0,114,17,0,0, @@ -1609,9 +1609,9 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,192,0,0,0,114,193,0,0, - 0,114,194,0,0,0,114,129,0,0,0,41,3,218,7,103, - 108,111,98,97,108,115,114,186,0,0,0,114,95,0,0,0, + 0,0,114,130,0,0,0,114,191,0,0,0,114,192,0,0, + 0,114,193,0,0,0,114,129,0,0,0,41,3,218,7,103, + 108,111,98,97,108,115,114,185,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, @@ -1666,8 +1666,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 111,110,114,184,0,0,0,114,15,0,0,0,114,92,0,0, 0,114,1,0,0,0,114,4,0,0,0,114,213,0,0,0, 41,9,114,17,0,0,0,114,218,0,0,0,218,6,108,111, - 99,97,108,115,114,214,0,0,0,114,187,0,0,0,114,96, - 0,0,0,90,8,103,108,111,98,97,108,115,95,114,186,0, + 99,97,108,115,114,214,0,0,0,114,186,0,0,0,114,96, + 0,0,0,90,8,103,108,111,98,97,108,115,95,114,185,0, 0,0,90,7,99,117,116,95,111,102,102,114,10,0,0,0, 114,10,0,0,0,114,11,0,0,0,218,10,95,95,105,109, 112,111,114,116,95,95,57,4,0,0,115,30,0,0,0,0, @@ -1713,10 +1713,10 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,192,0,0,0,114,64,0, + 32,41,3,114,23,0,0,0,114,191,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,196,0,0,0,114,78,0,0,0,114,160,0,0,0,114, + 114,195,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,223,0,0,0,114,5,0, 0,0,41,10,218,10,115,121,115,95,109,111,100,117,108,101, @@ -1738,7 +1738,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,227,0, - 0,0,114,15,0,0,0,114,191,0,0,0,114,120,0,0, + 0,0,114,15,0,0,0,114,190,0,0,0,114,120,0,0, 0,114,160,0,0,0,114,173,0,0,0,41,2,114,225,0, 0,0,114,226,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, @@ -1771,7 +1771,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 114,148,0,0,0,114,152,0,0,0,114,107,0,0,0,114, 93,0,0,0,114,158,0,0,0,114,159,0,0,0,114,94, 0,0,0,114,160,0,0,0,114,173,0,0,0,114,178,0, - 0,0,114,188,0,0,0,114,190,0,0,0,114,195,0,0, + 0,0,114,187,0,0,0,114,189,0,0,0,114,194,0,0, 0,114,200,0,0,0,90,15,95,69,82,82,95,77,83,71, 95,80,82,69,70,73,88,114,202,0,0,0,114,205,0,0, 0,218,6,111,98,106,101,99,116,114,206,0,0,0,114,207, From webhook-mailer at python.org Sat Aug 3 02:12:31 2019 From: webhook-mailer at python.org (Ronald Oussoren) Date: Sat, 03 Aug 2019 06:12:31 -0000 Subject: [Python-checkins] bpo-18049: Define THREAD_STACK_SIZE for AIX to pass default recursion limit test (GH-15081) Message-ID: https://github.com/python/cpython/commit/9670ce76b83bde950020f8d89c4d27168aaaf912 commit: 9670ce76b83bde950020f8d89c4d27168aaaf912 branch: master author: Michael Felt committer: Ronald Oussoren date: 2019-08-03T08:12:26+02:00 summary: bpo-18049: Define THREAD_STACK_SIZE for AIX to pass default recursion limit test (GH-15081) * Define THREAD_STACK_SIZE for AIX to pass default recursion limit test files: A Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst M Python/thread_pthread.h diff --git a/Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst b/Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst new file mode 100644 index 000000000000..36a4de384cc0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst @@ -0,0 +1,3 @@ +Add definition of THREAD_STACK_SIZE for AIX in Python/thread_pthread.h +The default thread stacksize caused crashes with the default recursion limit +Patch by M Felt diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 994e35b2cc08..5678b05ced36 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -47,6 +47,10 @@ #undef THREAD_STACK_SIZE #define THREAD_STACK_SIZE 0x400000 #endif +#if defined(_AIX) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 +#undef THREAD_STACK_SIZE +#define THREAD_STACK_SIZE 0x200000 +#endif /* for safety, ensure a viable minimum stacksize */ #define THREAD_STACK_MIN 0x8000 /* 32 KiB */ #else /* !_POSIX_THREAD_ATTR_STACKSIZE */ From webhook-mailer at python.org Sat Aug 3 14:16:39 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 03 Aug 2019 18:16:39 -0000 Subject: [Python-checkins] Correct description of HTTP status code 308. (GH-15078) Message-ID: https://github.com/python/cpython/commit/5c72badd06a962fe0018ceb9916f3ae66314ea8e commit: 5c72badd06a962fe0018ceb9916f3ae66314ea8e branch: master author: Florian Wendelborn <1133858+FlorianWendelborn at users.noreply.github.com> committer: Benjamin Peterson date: 2019-08-03T11:16:34-07:00 summary: Correct description of HTTP status code 308. (GH-15078) Permanent redirect was explained as a temporary redirect. files: M Lib/http/__init__.py diff --git a/Lib/http/__init__.py b/Lib/http/__init__.py index aed94a585046..e14a1eb074c5 100644 --- a/Lib/http/__init__.py +++ b/Lib/http/__init__.py @@ -59,7 +59,7 @@ def __new__(cls, value, phrase, description=''): TEMPORARY_REDIRECT = (307, 'Temporary Redirect', 'Object moved temporarily -- see URI list') PERMANENT_REDIRECT = (308, 'Permanent Redirect', - 'Object moved temporarily -- see URI list') + 'Object moved permanently -- see URI list') # client error BAD_REQUEST = (400, 'Bad Request', From webhook-mailer at python.org Sat Aug 3 14:39:50 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 03 Aug 2019 18:39:50 -0000 Subject: [Python-checkins] Correct description of HTTP status code 308. (GH-15098) Message-ID: https://github.com/python/cpython/commit/4e402d37eb4009140421365acbeff78104b108e0 commit: 4e402d37eb4009140421365acbeff78104b108e0 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2019-08-03T11:39:46-07:00 summary: Correct description of HTTP status code 308. (GH-15098) Permanent redirect was explained as a temporary redirect. (cherry picked from commit 5c72badd06a962fe0018ceb9916f3ae66314ea8e) Co-authored-by: Florian Wendelborn <1133858+FlorianWendelborn at users.noreply.github.com> files: M Lib/http/__init__.py diff --git a/Lib/http/__init__.py b/Lib/http/__init__.py index aed94a585046..e14a1eb074c5 100644 --- a/Lib/http/__init__.py +++ b/Lib/http/__init__.py @@ -59,7 +59,7 @@ def __new__(cls, value, phrase, description=''): TEMPORARY_REDIRECT = (307, 'Temporary Redirect', 'Object moved temporarily -- see URI list') PERMANENT_REDIRECT = (308, 'Permanent Redirect', - 'Object moved temporarily -- see URI list') + 'Object moved permanently -- see URI list') # client error BAD_REQUEST = (400, 'Bad Request', From webhook-mailer at python.org Sat Aug 3 14:40:13 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 03 Aug 2019 18:40:13 -0000 Subject: [Python-checkins] Correct description of HTTP status code 308. (GH-15097) Message-ID: https://github.com/python/cpython/commit/0bb8f22abd81751eab1125132cdaa31b2083c735 commit: 0bb8f22abd81751eab1125132cdaa31b2083c735 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2019-08-03T11:40:09-07:00 summary: Correct description of HTTP status code 308. (GH-15097) Permanent redirect was explained as a temporary redirect. (cherry picked from commit 5c72badd06a962fe0018ceb9916f3ae66314ea8e) Co-authored-by: Florian Wendelborn <1133858+FlorianWendelborn at users.noreply.github.com> files: M Lib/http/__init__.py diff --git a/Lib/http/__init__.py b/Lib/http/__init__.py index aed94a585046..e14a1eb074c5 100644 --- a/Lib/http/__init__.py +++ b/Lib/http/__init__.py @@ -59,7 +59,7 @@ def __new__(cls, value, phrase, description=''): TEMPORARY_REDIRECT = (307, 'Temporary Redirect', 'Object moved temporarily -- see URI list') PERMANENT_REDIRECT = (308, 'Permanent Redirect', - 'Object moved temporarily -- see URI list') + 'Object moved permanently -- see URI list') # client error BAD_REQUEST = (400, 'Bad Request', From webhook-mailer at python.org Sun Aug 4 05:38:50 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 04 Aug 2019 09:38:50 -0000 Subject: [Python-checkins] bpo-37685: Fixed comparisons of datetime.timedelta and datetime.timezone. (GH-14996) Message-ID: https://github.com/python/cpython/commit/17e52649c0e7e9389f1cc2444a53f059e24e6bca commit: 17e52649c0e7e9389f1cc2444a53f059e24e6bca branch: master author: Serhiy Storchaka committer: GitHub date: 2019-08-04T12:38:46+03:00 summary: bpo-37685: Fixed comparisons of datetime.timedelta and datetime.timezone. (GH-14996) There was a discrepancy between the Python and C implementations. Add singletons ALWAYS_EQ, LARGEST and SMALLEST in test.support to test mixed type comparison. files: A Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst M Doc/library/test.rst M Lib/datetime.py M Lib/test/datetimetester.py M Lib/test/support/__init__.py M Lib/test/test_ipaddress.py M Modules/_datetimemodule.c diff --git a/Doc/library/test.rst b/Doc/library/test.rst index 7d62a94d839b..da6a85d340be 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -356,11 +356,28 @@ The :mod:`test.support` module defines the following constants: Check for presence of docstrings. + .. data:: TEST_HTTP_URL Define the URL of a dedicated HTTP server for the network tests. +.. data:: ALWAYS_EQ + + Object that is equal to anything. Used to test mixed type comparison. + + +.. data:: LARGEST + + Object that is greater than anything (except itself). + Used to test mixed type comparison. + + +.. data:: SMALLEST + + Object that is less than anything (except itself). + Used to test mixed type comparison. + The :mod:`test.support` module defines the following functions: diff --git a/Lib/datetime.py b/Lib/datetime.py index e35ee0554c1f..d4c7a1ff9004 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -739,25 +739,25 @@ def __le__(self, other): if isinstance(other, timedelta): return self._cmp(other) <= 0 else: - _cmperror(self, other) + return NotImplemented def __lt__(self, other): if isinstance(other, timedelta): return self._cmp(other) < 0 else: - _cmperror(self, other) + return NotImplemented def __ge__(self, other): if isinstance(other, timedelta): return self._cmp(other) >= 0 else: - _cmperror(self, other) + return NotImplemented def __gt__(self, other): if isinstance(other, timedelta): return self._cmp(other) > 0 else: - _cmperror(self, other) + return NotImplemented def _cmp(self, other): assert isinstance(other, timedelta) @@ -1316,25 +1316,25 @@ def __le__(self, other): if isinstance(other, time): return self._cmp(other) <= 0 else: - _cmperror(self, other) + return NotImplemented def __lt__(self, other): if isinstance(other, time): return self._cmp(other) < 0 else: - _cmperror(self, other) + return NotImplemented def __ge__(self, other): if isinstance(other, time): return self._cmp(other) >= 0 else: - _cmperror(self, other) + return NotImplemented def __gt__(self, other): if isinstance(other, time): return self._cmp(other) > 0 else: - _cmperror(self, other) + return NotImplemented def _cmp(self, other, allow_mixed=False): assert isinstance(other, time) @@ -2210,9 +2210,9 @@ def __getinitargs__(self): return (self._offset, self._name) def __eq__(self, other): - if type(other) != timezone: - return False - return self._offset == other._offset + if isinstance(other, timezone): + return self._offset == other._offset + return NotImplemented def __hash__(self): return hash(self._offset) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 37ddd4b1a8bc..99b620ce2f41 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -2,11 +2,8 @@ See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases """ -from test.support import is_resource_enabled - import itertools import bisect - import copy import decimal import sys @@ -22,6 +19,7 @@ from operator import lt, le, gt, ge, eq, ne, truediv, floordiv, mod from test import support +from test.support import is_resource_enabled, ALWAYS_EQ, LARGEST, SMALLEST import datetime as datetime_module from datetime import MINYEAR, MAXYEAR @@ -54,18 +52,6 @@ NAN = float("nan") -class ComparesEqualClass(object): - """ - A class that is always equal to whatever you compare it to. - """ - - def __eq__(self, other): - return True - - def __ne__(self, other): - return False - - ############################################################################# # module tests @@ -353,6 +339,18 @@ def test_comparison(self): self.assertTrue(timezone(ZERO) != None) self.assertFalse(timezone(ZERO) == None) + tz = timezone(ZERO) + self.assertTrue(tz == ALWAYS_EQ) + self.assertFalse(tz != ALWAYS_EQ) + self.assertTrue(tz < LARGEST) + self.assertFalse(tz > LARGEST) + self.assertTrue(tz <= LARGEST) + self.assertFalse(tz >= LARGEST) + self.assertFalse(tz < SMALLEST) + self.assertTrue(tz > SMALLEST) + self.assertFalse(tz <= SMALLEST) + self.assertTrue(tz >= SMALLEST) + def test_aware_datetime(self): # test that timezone instances can be used by datetime t = datetime(1, 1, 1) @@ -414,10 +412,21 @@ def test_harmless_mixed_comparison(self): # Comparison to objects of unsupported types should return # NotImplemented which falls back to the right hand side's __eq__ - # method. In this case, ComparesEqualClass.__eq__ always returns True. - # ComparesEqualClass.__ne__ always returns False. - self.assertTrue(me == ComparesEqualClass()) - self.assertFalse(me != ComparesEqualClass()) + # method. In this case, ALWAYS_EQ.__eq__ always returns True. + # ALWAYS_EQ.__ne__ always returns False. + self.assertTrue(me == ALWAYS_EQ) + self.assertFalse(me != ALWAYS_EQ) + + # If the other class explicitly defines ordering + # relative to our class, it is allowed to do so + self.assertTrue(me < LARGEST) + self.assertFalse(me > LARGEST) + self.assertTrue(me <= LARGEST) + self.assertFalse(me >= LARGEST) + self.assertFalse(me < SMALLEST) + self.assertTrue(me > SMALLEST) + self.assertFalse(me <= SMALLEST) + self.assertTrue(me >= SMALLEST) def test_harmful_mixed_comparison(self): me = self.theclass(1, 1, 1) @@ -1582,29 +1591,6 @@ class SomeClass: self.assertRaises(TypeError, lambda: our < their) self.assertRaises(TypeError, lambda: their < our) - # However, if the other class explicitly defines ordering - # relative to our class, it is allowed to do so - - class LargerThanAnything: - def __lt__(self, other): - return False - def __le__(self, other): - return isinstance(other, LargerThanAnything) - def __eq__(self, other): - return isinstance(other, LargerThanAnything) - def __gt__(self, other): - return not isinstance(other, LargerThanAnything) - def __ge__(self, other): - return True - - their = LargerThanAnything() - self.assertEqual(our == their, False) - self.assertEqual(their == our, False) - self.assertEqual(our != their, True) - self.assertEqual(their != our, True) - self.assertEqual(our < their, True) - self.assertEqual(their < our, False) - def test_bool(self): # All dates are considered true. self.assertTrue(self.theclass.min) @@ -3781,8 +3767,8 @@ def test_replace(self): self.assertRaises(ValueError, base.replace, microsecond=1000000) def test_mixed_compare(self): - t1 = time(1, 2, 3) - t2 = time(1, 2, 3) + t1 = self.theclass(1, 2, 3) + t2 = self.theclass(1, 2, 3) self.assertEqual(t1, t2) t2 = t2.replace(tzinfo=None) self.assertEqual(t1, t2) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index dbbbdb0ee339..c82037eea523 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -113,6 +113,7 @@ "run_with_locale", "swap_item", "swap_attr", "Matcher", "set_memlimit", "SuppressCrashReport", "sortdict", "run_with_tz", "PGO", "missing_compiler_executable", "fd_count", + "ALWAYS_EQ", "LARGEST", "SMALLEST" ] class Error(Exception): @@ -3103,6 +3104,41 @@ def __fspath__(self): return self.path +class _ALWAYS_EQ: + """ + Object that is equal to anything. + """ + def __eq__(self, other): + return True + def __ne__(self, other): + return False + +ALWAYS_EQ = _ALWAYS_EQ() + + at functools.total_ordering +class _LARGEST: + """ + Object that is greater than anything (except itself). + """ + def __eq__(self, other): + return isinstance(other, _LARGEST) + def __lt__(self, other): + return False + +LARGEST = _LARGEST() + + at functools.total_ordering +class _SMALLEST: + """ + Object that is less than anything (except itself). + """ + def __eq__(self, other): + return isinstance(other, _SMALLEST) + def __gt__(self, other): + return False + +SMALLEST = _SMALLEST() + def maybe_get_event_loop_policy(): """Return the global event loop policy if one is set, else return None.""" return asyncio.events._event_loop_policy diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 9e17ea0c7aac..de77111705b6 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -12,6 +12,7 @@ import pickle import ipaddress import weakref +from test.support import LARGEST, SMALLEST class BaseTestCase(unittest.TestCase): @@ -673,20 +674,6 @@ def test_ip_network(self): self.assertFactoryError(ipaddress.ip_network, "network") - at functools.total_ordering -class LargestObject: - def __eq__(self, other): - return isinstance(other, LargestObject) - def __lt__(self, other): - return False - - at functools.total_ordering -class SmallestObject: - def __eq__(self, other): - return isinstance(other, SmallestObject) - def __gt__(self, other): - return False - class ComparisonTests(unittest.TestCase): v4addr = ipaddress.IPv4Address(1) @@ -775,8 +762,6 @@ def test_mixed_type_ordering(self): def test_foreign_type_ordering(self): other = object() - smallest = SmallestObject() - largest = LargestObject() for obj in self.objects: with self.assertRaises(TypeError): obj < other @@ -786,14 +771,14 @@ def test_foreign_type_ordering(self): obj <= other with self.assertRaises(TypeError): obj >= other - self.assertTrue(obj < largest) - self.assertFalse(obj > largest) - self.assertTrue(obj <= largest) - self.assertFalse(obj >= largest) - self.assertFalse(obj < smallest) - self.assertTrue(obj > smallest) - self.assertFalse(obj <= smallest) - self.assertTrue(obj >= smallest) + self.assertTrue(obj < LARGEST) + self.assertFalse(obj > LARGEST) + self.assertTrue(obj <= LARGEST) + self.assertFalse(obj >= LARGEST) + self.assertFalse(obj < SMALLEST) + self.assertTrue(obj > SMALLEST) + self.assertFalse(obj <= SMALLEST) + self.assertTrue(obj >= SMALLEST) def test_mixed_type_key(self): # with get_mixed_type_key, you can sort addresses and network. diff --git a/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst b/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst new file mode 100644 index 000000000000..ba60057e6fb6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst @@ -0,0 +1,2 @@ +Fixed comparisons of :class:`datetime.timedelta` and +:class:`datetime.timezone`. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 19d3d7e848f5..b55922cd961a 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3741,11 +3741,8 @@ timezone_richcompare(PyDateTime_TimeZone *self, { if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED; - if (Py_TYPE(other) != &PyDateTime_TimeZoneType) { - if (op == Py_EQ) - Py_RETURN_FALSE; - else - Py_RETURN_TRUE; + if (!PyTZInfo_Check(other)) { + Py_RETURN_NOTIMPLEMENTED; } return delta_richcompare(self->offset, other->offset, op); } From webhook-mailer at python.org Sun Aug 4 06:02:01 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 04 Aug 2019 10:02:01 -0000 Subject: [Python-checkins] bpo-37685: Fixed comparisons of datetime.timedelta and datetime.timezone. (GH-14996) Message-ID: https://github.com/python/cpython/commit/dde944f9df8dea28c07935ebd6de06db7e575c12 commit: dde944f9df8dea28c07935ebd6de06db7e575c12 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-04T03:01:55-07:00 summary: bpo-37685: Fixed comparisons of datetime.timedelta and datetime.timezone. (GH-14996) There was a discrepancy between the Python and C implementations. Add singletons ALWAYS_EQ, LARGEST and SMALLEST in test.support to test mixed type comparison. (cherry picked from commit 17e52649c0e7e9389f1cc2444a53f059e24e6bca) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst M Doc/library/test.rst M Lib/datetime.py M Lib/test/datetimetester.py M Lib/test/support/__init__.py M Lib/test/test_ipaddress.py M Modules/_datetimemodule.c diff --git a/Doc/library/test.rst b/Doc/library/test.rst index 7d62a94d839b..da6a85d340be 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -356,11 +356,28 @@ The :mod:`test.support` module defines the following constants: Check for presence of docstrings. + .. data:: TEST_HTTP_URL Define the URL of a dedicated HTTP server for the network tests. +.. data:: ALWAYS_EQ + + Object that is equal to anything. Used to test mixed type comparison. + + +.. data:: LARGEST + + Object that is greater than anything (except itself). + Used to test mixed type comparison. + + +.. data:: SMALLEST + + Object that is less than anything (except itself). + Used to test mixed type comparison. + The :mod:`test.support` module defines the following functions: diff --git a/Lib/datetime.py b/Lib/datetime.py index e35ee0554c1f..d4c7a1ff9004 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -739,25 +739,25 @@ def __le__(self, other): if isinstance(other, timedelta): return self._cmp(other) <= 0 else: - _cmperror(self, other) + return NotImplemented def __lt__(self, other): if isinstance(other, timedelta): return self._cmp(other) < 0 else: - _cmperror(self, other) + return NotImplemented def __ge__(self, other): if isinstance(other, timedelta): return self._cmp(other) >= 0 else: - _cmperror(self, other) + return NotImplemented def __gt__(self, other): if isinstance(other, timedelta): return self._cmp(other) > 0 else: - _cmperror(self, other) + return NotImplemented def _cmp(self, other): assert isinstance(other, timedelta) @@ -1316,25 +1316,25 @@ def __le__(self, other): if isinstance(other, time): return self._cmp(other) <= 0 else: - _cmperror(self, other) + return NotImplemented def __lt__(self, other): if isinstance(other, time): return self._cmp(other) < 0 else: - _cmperror(self, other) + return NotImplemented def __ge__(self, other): if isinstance(other, time): return self._cmp(other) >= 0 else: - _cmperror(self, other) + return NotImplemented def __gt__(self, other): if isinstance(other, time): return self._cmp(other) > 0 else: - _cmperror(self, other) + return NotImplemented def _cmp(self, other, allow_mixed=False): assert isinstance(other, time) @@ -2210,9 +2210,9 @@ def __getinitargs__(self): return (self._offset, self._name) def __eq__(self, other): - if type(other) != timezone: - return False - return self._offset == other._offset + if isinstance(other, timezone): + return self._offset == other._offset + return NotImplemented def __hash__(self): return hash(self._offset) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 37ddd4b1a8bc..99b620ce2f41 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -2,11 +2,8 @@ See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases """ -from test.support import is_resource_enabled - import itertools import bisect - import copy import decimal import sys @@ -22,6 +19,7 @@ from operator import lt, le, gt, ge, eq, ne, truediv, floordiv, mod from test import support +from test.support import is_resource_enabled, ALWAYS_EQ, LARGEST, SMALLEST import datetime as datetime_module from datetime import MINYEAR, MAXYEAR @@ -54,18 +52,6 @@ NAN = float("nan") -class ComparesEqualClass(object): - """ - A class that is always equal to whatever you compare it to. - """ - - def __eq__(self, other): - return True - - def __ne__(self, other): - return False - - ############################################################################# # module tests @@ -353,6 +339,18 @@ def test_comparison(self): self.assertTrue(timezone(ZERO) != None) self.assertFalse(timezone(ZERO) == None) + tz = timezone(ZERO) + self.assertTrue(tz == ALWAYS_EQ) + self.assertFalse(tz != ALWAYS_EQ) + self.assertTrue(tz < LARGEST) + self.assertFalse(tz > LARGEST) + self.assertTrue(tz <= LARGEST) + self.assertFalse(tz >= LARGEST) + self.assertFalse(tz < SMALLEST) + self.assertTrue(tz > SMALLEST) + self.assertFalse(tz <= SMALLEST) + self.assertTrue(tz >= SMALLEST) + def test_aware_datetime(self): # test that timezone instances can be used by datetime t = datetime(1, 1, 1) @@ -414,10 +412,21 @@ def test_harmless_mixed_comparison(self): # Comparison to objects of unsupported types should return # NotImplemented which falls back to the right hand side's __eq__ - # method. In this case, ComparesEqualClass.__eq__ always returns True. - # ComparesEqualClass.__ne__ always returns False. - self.assertTrue(me == ComparesEqualClass()) - self.assertFalse(me != ComparesEqualClass()) + # method. In this case, ALWAYS_EQ.__eq__ always returns True. + # ALWAYS_EQ.__ne__ always returns False. + self.assertTrue(me == ALWAYS_EQ) + self.assertFalse(me != ALWAYS_EQ) + + # If the other class explicitly defines ordering + # relative to our class, it is allowed to do so + self.assertTrue(me < LARGEST) + self.assertFalse(me > LARGEST) + self.assertTrue(me <= LARGEST) + self.assertFalse(me >= LARGEST) + self.assertFalse(me < SMALLEST) + self.assertTrue(me > SMALLEST) + self.assertFalse(me <= SMALLEST) + self.assertTrue(me >= SMALLEST) def test_harmful_mixed_comparison(self): me = self.theclass(1, 1, 1) @@ -1582,29 +1591,6 @@ class SomeClass: self.assertRaises(TypeError, lambda: our < their) self.assertRaises(TypeError, lambda: their < our) - # However, if the other class explicitly defines ordering - # relative to our class, it is allowed to do so - - class LargerThanAnything: - def __lt__(self, other): - return False - def __le__(self, other): - return isinstance(other, LargerThanAnything) - def __eq__(self, other): - return isinstance(other, LargerThanAnything) - def __gt__(self, other): - return not isinstance(other, LargerThanAnything) - def __ge__(self, other): - return True - - their = LargerThanAnything() - self.assertEqual(our == their, False) - self.assertEqual(their == our, False) - self.assertEqual(our != their, True) - self.assertEqual(their != our, True) - self.assertEqual(our < their, True) - self.assertEqual(their < our, False) - def test_bool(self): # All dates are considered true. self.assertTrue(self.theclass.min) @@ -3781,8 +3767,8 @@ def test_replace(self): self.assertRaises(ValueError, base.replace, microsecond=1000000) def test_mixed_compare(self): - t1 = time(1, 2, 3) - t2 = time(1, 2, 3) + t1 = self.theclass(1, 2, 3) + t2 = self.theclass(1, 2, 3) self.assertEqual(t1, t2) t2 = t2.replace(tzinfo=None) self.assertEqual(t1, t2) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index b88eb5804a96..e73c65bb9f34 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -113,6 +113,7 @@ "run_with_locale", "swap_item", "swap_attr", "Matcher", "set_memlimit", "SuppressCrashReport", "sortdict", "run_with_tz", "PGO", "missing_compiler_executable", "fd_count", + "ALWAYS_EQ", "LARGEST", "SMALLEST" ] class Error(Exception): @@ -3101,6 +3102,41 @@ def __fspath__(self): return self.path +class _ALWAYS_EQ: + """ + Object that is equal to anything. + """ + def __eq__(self, other): + return True + def __ne__(self, other): + return False + +ALWAYS_EQ = _ALWAYS_EQ() + + at functools.total_ordering +class _LARGEST: + """ + Object that is greater than anything (except itself). + """ + def __eq__(self, other): + return isinstance(other, _LARGEST) + def __lt__(self, other): + return False + +LARGEST = _LARGEST() + + at functools.total_ordering +class _SMALLEST: + """ + Object that is less than anything (except itself). + """ + def __eq__(self, other): + return isinstance(other, _SMALLEST) + def __gt__(self, other): + return False + +SMALLEST = _SMALLEST() + def maybe_get_event_loop_policy(): """Return the global event loop policy if one is set, else return None.""" return asyncio.events._event_loop_policy diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 9e17ea0c7aac..de77111705b6 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -12,6 +12,7 @@ import pickle import ipaddress import weakref +from test.support import LARGEST, SMALLEST class BaseTestCase(unittest.TestCase): @@ -673,20 +674,6 @@ def test_ip_network(self): self.assertFactoryError(ipaddress.ip_network, "network") - at functools.total_ordering -class LargestObject: - def __eq__(self, other): - return isinstance(other, LargestObject) - def __lt__(self, other): - return False - - at functools.total_ordering -class SmallestObject: - def __eq__(self, other): - return isinstance(other, SmallestObject) - def __gt__(self, other): - return False - class ComparisonTests(unittest.TestCase): v4addr = ipaddress.IPv4Address(1) @@ -775,8 +762,6 @@ def test_mixed_type_ordering(self): def test_foreign_type_ordering(self): other = object() - smallest = SmallestObject() - largest = LargestObject() for obj in self.objects: with self.assertRaises(TypeError): obj < other @@ -786,14 +771,14 @@ def test_foreign_type_ordering(self): obj <= other with self.assertRaises(TypeError): obj >= other - self.assertTrue(obj < largest) - self.assertFalse(obj > largest) - self.assertTrue(obj <= largest) - self.assertFalse(obj >= largest) - self.assertFalse(obj < smallest) - self.assertTrue(obj > smallest) - self.assertFalse(obj <= smallest) - self.assertTrue(obj >= smallest) + self.assertTrue(obj < LARGEST) + self.assertFalse(obj > LARGEST) + self.assertTrue(obj <= LARGEST) + self.assertFalse(obj >= LARGEST) + self.assertFalse(obj < SMALLEST) + self.assertTrue(obj > SMALLEST) + self.assertFalse(obj <= SMALLEST) + self.assertTrue(obj >= SMALLEST) def test_mixed_type_key(self): # with get_mixed_type_key, you can sort addresses and network. diff --git a/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst b/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst new file mode 100644 index 000000000000..ba60057e6fb6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst @@ -0,0 +1,2 @@ +Fixed comparisons of :class:`datetime.timedelta` and +:class:`datetime.timezone`. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 4d3562cbe64f..80ecfc3fff0b 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3744,11 +3744,8 @@ timezone_richcompare(PyDateTime_TimeZone *self, { if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED; - if (Py_TYPE(other) != &PyDateTime_TimeZoneType) { - if (op == Py_EQ) - Py_RETURN_FALSE; - else - Py_RETURN_TRUE; + if (!PyTZInfo_Check(other)) { + Py_RETURN_NOTIMPLEMENTED; } return delta_richcompare(self->offset, other->offset, op); } From webhook-mailer at python.org Sun Aug 4 07:12:52 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 04 Aug 2019 11:12:52 -0000 Subject: [Python-checkins] bpo-37648: Fixed minor inconsistency in some __contains__. (GH-14904) Message-ID: https://github.com/python/cpython/commit/18b711c5a7f90d88fb74748f18fa8ef49d8486c7 commit: 18b711c5a7f90d88fb74748f18fa8ef49d8486c7 branch: master author: Serhiy Storchaka committer: GitHub date: 2019-08-04T14:12:48+03:00 summary: bpo-37648: Fixed minor inconsistency in some __contains__. (GH-14904) The collection's item is now always at the left and the needle is on the right of ==. files: A Misc/NEWS.d/next/Core and Builtins/2019-07-22-11-05-05.bpo-37648.6TY2L-.rst M Doc/library/test.rst M Lib/test/list_tests.py M Lib/test/seq_tests.py M Lib/test/support/__init__.py M Lib/test/test_iter.py M Modules/_asynciomodule.c M Modules/_ssl.c M Objects/abstract.c M Objects/dictobject.c M Objects/listobject.c M Objects/tupleobject.c diff --git a/Doc/library/test.rst b/Doc/library/test.rst index da6a85d340be..6eef5c65499a 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -367,6 +367,12 @@ The :mod:`test.support` module defines the following constants: Object that is equal to anything. Used to test mixed type comparison. +.. data:: NEVER_EQ + + Object that is not equal to anything (even to :data:`ALWAYS_EQ`). + Used to test mixed type comparison. + + .. data:: LARGEST Object that is greater than anything (except itself). diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py index 40316de220fa..44bc2ae6573c 100644 --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -7,6 +7,7 @@ from functools import cmp_to_key from test import support, seq_tests +from test.support import ALWAYS_EQ, NEVER_EQ class CommonTest(seq_tests.CommonTest): @@ -329,6 +330,20 @@ def test_remove(self): self.assertRaises(TypeError, a.remove) + a = self.type2test([1, 2]) + self.assertRaises(ValueError, a.remove, NEVER_EQ) + self.assertEqual(a, [1, 2]) + a.remove(ALWAYS_EQ) + self.assertEqual(a, [2]) + a = self.type2test([ALWAYS_EQ]) + a.remove(1) + self.assertEqual(a, []) + a = self.type2test([ALWAYS_EQ]) + a.remove(NEVER_EQ) + self.assertEqual(a, []) + a = self.type2test([NEVER_EQ]) + self.assertRaises(ValueError, a.remove, ALWAYS_EQ) + class BadExc(Exception): pass diff --git a/Lib/test/seq_tests.py b/Lib/test/seq_tests.py index 65b110ef7818..1d9ad588987f 100644 --- a/Lib/test/seq_tests.py +++ b/Lib/test/seq_tests.py @@ -6,6 +6,7 @@ import sys import pickle from test import support +from test.support import ALWAYS_EQ, NEVER_EQ # Various iterables # This is used for checking the constructor (here and in test_deque.py) @@ -221,15 +222,15 @@ def test_contains(self): self.assertRaises(TypeError, u.__contains__) def test_contains_fake(self): - class AllEq: - # Sequences must use rich comparison against each item - # (unless "is" is true, or an earlier item answered) - # So instances of AllEq must be found in all non-empty sequences. - def __eq__(self, other): - return True - __hash__ = None # Can't meet hash invariant requirements - self.assertNotIn(AllEq(), self.type2test([])) - self.assertIn(AllEq(), self.type2test([1])) + # Sequences must use rich comparison against each item + # (unless "is" is true, or an earlier item answered) + # So ALWAYS_EQ must be found in all non-empty sequences. + self.assertNotIn(ALWAYS_EQ, self.type2test([])) + self.assertIn(ALWAYS_EQ, self.type2test([1])) + self.assertIn(1, self.type2test([ALWAYS_EQ])) + self.assertNotIn(NEVER_EQ, self.type2test([])) + self.assertNotIn(ALWAYS_EQ, self.type2test([NEVER_EQ])) + self.assertIn(NEVER_EQ, self.type2test([ALWAYS_EQ])) def test_contains_order(self): # Sequences must test in-order. If a rich comparison has side @@ -350,6 +351,11 @@ def test_count(self): self.assertEqual(a.count(1), 3) self.assertEqual(a.count(3), 0) + self.assertEqual(a.count(ALWAYS_EQ), 9) + self.assertEqual(self.type2test([ALWAYS_EQ, ALWAYS_EQ]).count(1), 2) + self.assertEqual(self.type2test([ALWAYS_EQ, ALWAYS_EQ]).count(NEVER_EQ), 2) + self.assertEqual(self.type2test([NEVER_EQ, NEVER_EQ]).count(ALWAYS_EQ), 0) + self.assertRaises(TypeError, a.count) class BadExc(Exception): @@ -378,6 +384,11 @@ def test_index(self): self.assertEqual(u.index(0, 3, 4), 3) self.assertRaises(ValueError, u.index, 2, 0, -10) + self.assertEqual(u.index(ALWAYS_EQ), 0) + self.assertEqual(self.type2test([ALWAYS_EQ, ALWAYS_EQ]).index(1), 0) + self.assertEqual(self.type2test([ALWAYS_EQ, ALWAYS_EQ]).index(NEVER_EQ), 0) + self.assertRaises(ValueError, self.type2test([NEVER_EQ, NEVER_EQ]).index, ALWAYS_EQ) + self.assertRaises(TypeError, u.index) class BadExc(Exception): diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index c82037eea523..d34f2efaed53 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -113,7 +113,7 @@ "run_with_locale", "swap_item", "swap_attr", "Matcher", "set_memlimit", "SuppressCrashReport", "sortdict", "run_with_tz", "PGO", "missing_compiler_executable", "fd_count", - "ALWAYS_EQ", "LARGEST", "SMALLEST" + "ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST" ] class Error(Exception): @@ -3115,6 +3115,17 @@ def __ne__(self, other): ALWAYS_EQ = _ALWAYS_EQ() +class _NEVER_EQ: + """ + Object that is not equal to anything. + """ + def __eq__(self, other): + return False + def __ne__(self, other): + return True + +NEVER_EQ = _NEVER_EQ() + @functools.total_ordering class _LARGEST: """ diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py index 542b28419e2c..6aceda23e9bd 100644 --- a/Lib/test/test_iter.py +++ b/Lib/test/test_iter.py @@ -3,7 +3,7 @@ import sys import unittest from test.support import run_unittest, TESTFN, unlink, cpython_only -from test.support import check_free_after_iterating +from test.support import check_free_after_iterating, ALWAYS_EQ, NEVER_EQ import pickle import collections.abc @@ -41,6 +41,14 @@ def __init__(self, n): def __iter__(self): return BasicIterClass(self.n) +class IteratorProxyClass: + def __init__(self, i): + self.i = i + def __next__(self): + return next(self.i) + def __iter__(self): + return self + class SequenceClass: def __init__(self, n): self.n = n @@ -50,6 +58,12 @@ def __getitem__(self, i): else: raise IndexError +class SequenceProxyClass: + def __init__(self, s): + self.s = s + def __getitem__(self, i): + return self.s[i] + class UnlimitedSequenceClass: def __getitem__(self, i): return i @@ -635,6 +649,13 @@ def test_in_and_not_in(self): for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5: self.assertNotIn(i, sc5) + self.assertIn(ALWAYS_EQ, IteratorProxyClass(iter([1]))) + self.assertIn(ALWAYS_EQ, SequenceProxyClass([1])) + self.assertNotIn(ALWAYS_EQ, IteratorProxyClass(iter([NEVER_EQ]))) + self.assertNotIn(ALWAYS_EQ, SequenceProxyClass([NEVER_EQ])) + self.assertIn(NEVER_EQ, IteratorProxyClass(iter([ALWAYS_EQ]))) + self.assertIn(NEVER_EQ, SequenceProxyClass([ALWAYS_EQ])) + self.assertRaises(TypeError, lambda: 3 in 12) self.assertRaises(TypeError, lambda: 3 not in map) diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-07-22-11-05-05.bpo-37648.6TY2L-.rst b/Misc/NEWS.d/next/Core and Builtins/2019-07-22-11-05-05.bpo-37648.6TY2L-.rst new file mode 100644 index 000000000000..3c11d3d6008e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-07-22-11-05-05.bpo-37648.6TY2L-.rst @@ -0,0 +1,3 @@ +Fixed minor inconsistency in :meth:`list.__contains__`, +:meth:`tuple.__contains__` and a few other places. The collection's item is +now always at the left and the needle is on the right of ``==``. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index e9e6c5682d62..4d503a418a2e 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -937,7 +937,7 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn) ENSURE_FUTURE_ALIVE(self) if (self->fut_callback0 != NULL) { - int cmp = PyObject_RichCompareBool(fn, self->fut_callback0, Py_EQ); + int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ); if (cmp == -1) { return NULL; } @@ -962,7 +962,7 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn) if (len == 1) { PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0); int cmp = PyObject_RichCompareBool( - fn, PyTuple_GET_ITEM(cb_tup, 0), Py_EQ); + PyTuple_GET_ITEM(cb_tup, 0), fn, Py_EQ); if (cmp == -1) { return NULL; } @@ -984,7 +984,7 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn) int ret; PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i); Py_INCREF(item); - ret = PyObject_RichCompareBool(fn, PyTuple_GET_ITEM(item, 0), Py_EQ); + ret = PyObject_RichCompareBool(PyTuple_GET_ITEM(item, 0), fn, Py_EQ); if (ret == 0) { if (j < len) { PyList_SET_ITEM(newlist, j, item); diff --git a/Modules/_ssl.c b/Modules/_ssl.c index da30cbb758e2..3d54b844fe07 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -5600,8 +5600,7 @@ list_contains(PyListObject *a, PyObject *el) int cmp; for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i) - cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i), - Py_EQ); + cmp = PyObject_RichCompareBool(PyList_GET_ITEM(a, i), el, Py_EQ); return cmp; } diff --git a/Objects/abstract.c b/Objects/abstract.c index db1c3064db6f..f93d73fa7571 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2016,7 +2016,7 @@ _PySequence_IterSearch(PyObject *seq, PyObject *obj, int operation) break; } - cmp = PyObject_RichCompareBool(obj, item, Py_EQ); + cmp = PyObject_RichCompareBool(item, obj, Py_EQ); Py_DECREF(item); if (cmp < 0) goto Fail; diff --git a/Objects/dictobject.c b/Objects/dictobject.c index b6205d93ca14..f168ad5d2f00 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -4392,7 +4392,7 @@ dictitems_contains(_PyDictViewObject *dv, PyObject *obj) return 0; } Py_INCREF(found); - result = PyObject_RichCompareBool(value, found, Py_EQ); + result = PyObject_RichCompareBool(found, value, Py_EQ); Py_DECREF(found); return result; } diff --git a/Objects/listobject.c b/Objects/listobject.c index d012ab933a9e..cea9b24a3b2f 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -449,8 +449,7 @@ list_contains(PyListObject *a, PyObject *el) int cmp; for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i) - cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i), - Py_EQ); + cmp = PyObject_RichCompareBool(PyList_GET_ITEM(a, i), el, Py_EQ); return cmp; } diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index fc2d2742dd2c..aeaf845d74cf 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -403,8 +403,7 @@ tuplecontains(PyTupleObject *a, PyObject *el) int cmp; for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i) - cmp = PyObject_RichCompareBool(el, PyTuple_GET_ITEM(a, i), - Py_EQ); + cmp = PyObject_RichCompareBool(PyTuple_GET_ITEM(a, i), el, Py_EQ); return cmp; } From webhook-mailer at python.org Sun Aug 4 08:28:26 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 04 Aug 2019 12:28:26 -0000 Subject: [Python-checkins] [3.7] bpo-37685: Fixed comparisons of datetime.timedelta and datetime.timezone. (GH-14996) (GH-15104) Message-ID: https://github.com/python/cpython/commit/6ed20e54e4c110e9adcfb70aba85310625e3edb4 commit: 6ed20e54e4c110e9adcfb70aba85310625e3edb4 branch: 3.7 author: Serhiy Storchaka committer: GitHub date: 2019-08-04T15:28:21+03:00 summary: [3.7] bpo-37685: Fixed comparisons of datetime.timedelta and datetime.timezone. (GH-14996) (GH-15104) There was a discrepancy between the Python and C implementations. Add singletons ALWAYS_EQ, LARGEST and SMALLEST in test.support to test mixed type comparison. (cherry picked from commit 17e52649c0e7e9389f1cc2444a53f059e24e6bca) files: A Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst M Doc/library/test.rst M Lib/datetime.py M Lib/test/datetimetester.py M Lib/test/support/__init__.py M Lib/test/test_ipaddress.py M Modules/_datetimemodule.c diff --git a/Doc/library/test.rst b/Doc/library/test.rst index de79cdfc5fa9..e93ef450f022 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -356,11 +356,28 @@ The :mod:`test.support` module defines the following constants: Check for presence of docstrings. + .. data:: TEST_HTTP_URL Define the URL of a dedicated HTTP server for the network tests. +.. data:: ALWAYS_EQ + + Object that is equal to anything. Used to test mixed type comparison. + + +.. data:: LARGEST + + Object that is greater than anything (except itself). + Used to test mixed type comparison. + + +.. data:: SMALLEST + + Object that is less than anything (except itself). + Used to test mixed type comparison. + The :mod:`test.support` module defines the following functions: diff --git a/Lib/datetime.py b/Lib/datetime.py index 03beb055a00b..0485b0523e8d 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -724,25 +724,25 @@ def __le__(self, other): if isinstance(other, timedelta): return self._cmp(other) <= 0 else: - _cmperror(self, other) + return NotImplemented def __lt__(self, other): if isinstance(other, timedelta): return self._cmp(other) < 0 else: - _cmperror(self, other) + return NotImplemented def __ge__(self, other): if isinstance(other, timedelta): return self._cmp(other) >= 0 else: - _cmperror(self, other) + return NotImplemented def __gt__(self, other): if isinstance(other, timedelta): return self._cmp(other) > 0 else: - _cmperror(self, other) + return NotImplemented def _cmp(self, other): assert isinstance(other, timedelta) @@ -1267,25 +1267,25 @@ def __le__(self, other): if isinstance(other, time): return self._cmp(other) <= 0 else: - _cmperror(self, other) + return NotImplemented def __lt__(self, other): if isinstance(other, time): return self._cmp(other) < 0 else: - _cmperror(self, other) + return NotImplemented def __ge__(self, other): if isinstance(other, time): return self._cmp(other) >= 0 else: - _cmperror(self, other) + return NotImplemented def __gt__(self, other): if isinstance(other, time): return self._cmp(other) > 0 else: - _cmperror(self, other) + return NotImplemented def _cmp(self, other, allow_mixed=False): assert isinstance(other, time) @@ -2167,9 +2167,9 @@ def __getinitargs__(self): return (self._offset, self._name) def __eq__(self, other): - if type(other) != timezone: - return False - return self._offset == other._offset + if isinstance(other, timezone): + return self._offset == other._offset + return NotImplemented def __hash__(self): return hash(self._offset) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 581441738658..8a5716979716 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -2,11 +2,8 @@ See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases """ -from test.support import is_resource_enabled - import itertools import bisect - import copy import decimal import sys @@ -22,6 +19,7 @@ from operator import lt, le, gt, ge, eq, ne, truediv, floordiv, mod from test import support +from test.support import is_resource_enabled, ALWAYS_EQ, LARGEST, SMALLEST import datetime as datetime_module from datetime import MINYEAR, MAXYEAR @@ -54,18 +52,6 @@ NAN = float("nan") -class ComparesEqualClass(object): - """ - A class that is always equal to whatever you compare it to. - """ - - def __eq__(self, other): - return True - - def __ne__(self, other): - return False - - ############################################################################# # module tests @@ -353,6 +339,18 @@ def test_comparison(self): self.assertTrue(timezone(ZERO) != None) self.assertFalse(timezone(ZERO) == None) + tz = timezone(ZERO) + self.assertTrue(tz == ALWAYS_EQ) + self.assertFalse(tz != ALWAYS_EQ) + self.assertTrue(tz < LARGEST) + self.assertFalse(tz > LARGEST) + self.assertTrue(tz <= LARGEST) + self.assertFalse(tz >= LARGEST) + self.assertFalse(tz < SMALLEST) + self.assertTrue(tz > SMALLEST) + self.assertFalse(tz <= SMALLEST) + self.assertTrue(tz >= SMALLEST) + def test_aware_datetime(self): # test that timezone instances can be used by datetime t = datetime(1, 1, 1) @@ -414,10 +412,21 @@ def test_harmless_mixed_comparison(self): # Comparison to objects of unsupported types should return # NotImplemented which falls back to the right hand side's __eq__ - # method. In this case, ComparesEqualClass.__eq__ always returns True. - # ComparesEqualClass.__ne__ always returns False. - self.assertTrue(me == ComparesEqualClass()) - self.assertFalse(me != ComparesEqualClass()) + # method. In this case, ALWAYS_EQ.__eq__ always returns True. + # ALWAYS_EQ.__ne__ always returns False. + self.assertTrue(me == ALWAYS_EQ) + self.assertFalse(me != ALWAYS_EQ) + + # If the other class explicitly defines ordering + # relative to our class, it is allowed to do so + self.assertTrue(me < LARGEST) + self.assertFalse(me > LARGEST) + self.assertTrue(me <= LARGEST) + self.assertFalse(me >= LARGEST) + self.assertFalse(me < SMALLEST) + self.assertTrue(me > SMALLEST) + self.assertFalse(me <= SMALLEST) + self.assertTrue(me >= SMALLEST) def test_harmful_mixed_comparison(self): me = self.theclass(1, 1, 1) @@ -1544,29 +1553,6 @@ class SomeClass: self.assertRaises(TypeError, lambda: our < their) self.assertRaises(TypeError, lambda: their < our) - # However, if the other class explicitly defines ordering - # relative to our class, it is allowed to do so - - class LargerThanAnything: - def __lt__(self, other): - return False - def __le__(self, other): - return isinstance(other, LargerThanAnything) - def __eq__(self, other): - return isinstance(other, LargerThanAnything) - def __gt__(self, other): - return not isinstance(other, LargerThanAnything) - def __ge__(self, other): - return True - - their = LargerThanAnything() - self.assertEqual(our == their, False) - self.assertEqual(their == our, False) - self.assertEqual(our != their, True) - self.assertEqual(their != our, True) - self.assertEqual(our < their, True) - self.assertEqual(their < our, False) - def test_bool(self): # All dates are considered true. self.assertTrue(self.theclass.min) @@ -3642,8 +3628,8 @@ def test_replace(self): self.assertRaises(ValueError, base.replace, microsecond=1000000) def test_mixed_compare(self): - t1 = time(1, 2, 3) - t2 = time(1, 2, 3) + t1 = self.theclass(1, 2, 3) + t2 = self.theclass(1, 2, 3) self.assertEqual(t1, t2) t2 = t2.replace(tzinfo=None) self.assertEqual(t1, t2) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 6e40a143c274..bf1f0d2120ac 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -109,6 +109,7 @@ "run_with_locale", "swap_item", "swap_attr", "Matcher", "set_memlimit", "SuppressCrashReport", "sortdict", "run_with_tz", "PGO", "missing_compiler_executable", "fd_count", + "ALWAYS_EQ", "LARGEST", "SMALLEST" ] class Error(Exception): @@ -2919,3 +2920,39 @@ def __fspath__(self): raise self.path else: return self.path + + +class _ALWAYS_EQ: + """ + Object that is equal to anything. + """ + def __eq__(self, other): + return True + def __ne__(self, other): + return False + +ALWAYS_EQ = _ALWAYS_EQ() + + at functools.total_ordering +class _LARGEST: + """ + Object that is greater than anything (except itself). + """ + def __eq__(self, other): + return isinstance(other, _LARGEST) + def __lt__(self, other): + return False + +LARGEST = _LARGEST() + + at functools.total_ordering +class _SMALLEST: + """ + Object that is less than anything (except itself). + """ + def __eq__(self, other): + return isinstance(other, _SMALLEST) + def __gt__(self, other): + return False + +SMALLEST = _SMALLEST() diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index a2326db0af86..455b893fb126 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -12,6 +12,7 @@ import pickle import ipaddress import weakref +from test.support import LARGEST, SMALLEST class BaseTestCase(unittest.TestCase): @@ -679,20 +680,6 @@ def test_ip_network(self): self.assertFactoryError(ipaddress.ip_network, "network") - at functools.total_ordering -class LargestObject: - def __eq__(self, other): - return isinstance(other, LargestObject) - def __lt__(self, other): - return False - - at functools.total_ordering -class SmallestObject: - def __eq__(self, other): - return isinstance(other, SmallestObject) - def __gt__(self, other): - return False - class ComparisonTests(unittest.TestCase): v4addr = ipaddress.IPv4Address(1) @@ -781,8 +768,6 @@ def test_mixed_type_ordering(self): def test_foreign_type_ordering(self): other = object() - smallest = SmallestObject() - largest = LargestObject() for obj in self.objects: with self.assertRaises(TypeError): obj < other @@ -792,14 +777,14 @@ def test_foreign_type_ordering(self): obj <= other with self.assertRaises(TypeError): obj >= other - self.assertTrue(obj < largest) - self.assertFalse(obj > largest) - self.assertTrue(obj <= largest) - self.assertFalse(obj >= largest) - self.assertFalse(obj < smallest) - self.assertTrue(obj > smallest) - self.assertFalse(obj <= smallest) - self.assertTrue(obj >= smallest) + self.assertTrue(obj < LARGEST) + self.assertFalse(obj > LARGEST) + self.assertTrue(obj <= LARGEST) + self.assertFalse(obj >= LARGEST) + self.assertFalse(obj < SMALLEST) + self.assertTrue(obj > SMALLEST) + self.assertFalse(obj <= SMALLEST) + self.assertTrue(obj >= SMALLEST) def test_mixed_type_key(self): # with get_mixed_type_key, you can sort addresses and network. diff --git a/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst b/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst new file mode 100644 index 000000000000..ba60057e6fb6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst @@ -0,0 +1,2 @@ +Fixed comparisons of :class:`datetime.timedelta` and +:class:`datetime.timezone`. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 9405b4610dfc..aa759b115f0e 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3644,11 +3644,8 @@ timezone_richcompare(PyDateTime_TimeZone *self, { if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED; - if (Py_TYPE(other) != &PyDateTime_TimeZoneType) { - if (op == Py_EQ) - Py_RETURN_FALSE; - else - Py_RETURN_TRUE; + if (!PyTZInfo_Check(other)) { + Py_RETURN_NOTIMPLEMENTED; } return delta_richcompare(self->offset, other->offset, op); } From webhook-mailer at python.org Sun Aug 4 09:43:39 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 04 Aug 2019 13:43:39 -0000 Subject: [Python-checkins] bpo-37730: Fix usage of NotImplemented instead of NotImplementedError in docs. (GH-15062) Message-ID: https://github.com/python/cpython/commit/dd5f8abb54923bf2efea51b7a553ca1fca9cad68 commit: dd5f8abb54923bf2efea51b7a553ca1fca9cad68 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-04T06:43:30-07:00 summary: bpo-37730: Fix usage of NotImplemented instead of NotImplementedError in docs. (GH-15062) (cherry picked from commit ed5e8e06cbf766e89d6c58a882ee024abb5b2ed7) Co-authored-by: David H files: M Doc/library/winreg.rst M PC/clinic/winreg.c.h M PC/winreg.c diff --git a/Doc/library/winreg.rst b/Doc/library/winreg.rst index e9c026102273..cb67f2f39d76 100644 --- a/Doc/library/winreg.rst +++ b/Doc/library/winreg.rst @@ -456,7 +456,7 @@ This module offers the following functions: *key* is an already open key, or one of the predefined :ref:`HKEY_* constants `. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit operating + Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating system. If the key is not on the reflection list, the function succeeds but has no @@ -471,7 +471,7 @@ This module offers the following functions: *key* is an already open key, or one of the predefined :ref:`HKEY_* constants `. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit operating + Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating system. Restoring reflection for a key does not affect reflection of any subkeys. @@ -486,7 +486,7 @@ This module offers the following functions: Returns ``True`` if reflection is disabled. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit + Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating system. diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h index 50210250ed19..b7af1855ac54 100644 --- a/PC/clinic/winreg.c.h +++ b/PC/clinic/winreg.c.h @@ -1029,7 +1029,7 @@ PyDoc_STRVAR(winreg_DisableReflectionKey__doc__, " key\n" " An already open key, or any one of the predefined HKEY_* constants.\n" "\n" -"Will generally raise NotImplemented if executed on a 32bit OS.\n" +"Will generally raise NotImplementedError if executed on a 32bit OS.\n" "\n" "If the key is not on the reflection list, the function succeeds but has\n" "no effect. Disabling reflection for a key does not affect reflection\n" @@ -1065,7 +1065,7 @@ PyDoc_STRVAR(winreg_EnableReflectionKey__doc__, " key\n" " An already open key, or any one of the predefined HKEY_* constants.\n" "\n" -"Will generally raise NotImplemented if executed on a 32bit OS.\n" +"Will generally raise NotImplementedError if executed on a 32bit OS.\n" "Restoring reflection for a key does not affect reflection of any\n" "subkeys."); @@ -1099,7 +1099,7 @@ PyDoc_STRVAR(winreg_QueryReflectionKey__doc__, " key\n" " An already open key, or any one of the predefined HKEY_* constants.\n" "\n" -"Will generally raise NotImplemented if executed on a 32bit OS."); +"Will generally raise NotImplementedError if executed on a 32bit OS."); #define WINREG_QUERYREFLECTIONKEY_METHODDEF \ {"QueryReflectionKey", (PyCFunction)winreg_QueryReflectionKey, METH_O, winreg_QueryReflectionKey__doc__}, @@ -1121,4 +1121,4 @@ winreg_QueryReflectionKey(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=1204d20c543b5b4a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=015afbbd690eb59d input=a9049054013a1b77]*/ diff --git a/PC/winreg.c b/PC/winreg.c index 5f5fc85d2250..d0df7ef0ad47 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1702,7 +1702,7 @@ winreg.DisableReflectionKey Disables registry reflection for 32bit processes running on a 64bit OS. -Will generally raise NotImplemented if executed on a 32bit OS. +Will generally raise NotImplementedError if executed on a 32bit OS. If the key is not on the reflection list, the function succeeds but has no effect. Disabling reflection for a key does not affect reflection @@ -1711,7 +1711,7 @@ of any subkeys. static PyObject * winreg_DisableReflectionKey_impl(PyObject *module, HKEY key) -/*[clinic end generated code: output=830cce504cc764b4 input=a6c9e5ca5410193c]*/ +/*[clinic end generated code: output=830cce504cc764b4 input=70bece2dee02e073]*/ { HMODULE hMod; typedef LONG (WINAPI *RDRKFunc)(HKEY); @@ -1749,14 +1749,14 @@ winreg.EnableReflectionKey Restores registry reflection for the specified disabled key. -Will generally raise NotImplemented if executed on a 32bit OS. +Will generally raise NotImplementedError if executed on a 32bit OS. Restoring reflection for a key does not affect reflection of any subkeys. [clinic start generated code]*/ static PyObject * winreg_EnableReflectionKey_impl(PyObject *module, HKEY key) -/*[clinic end generated code: output=86fa1385fdd9ce57 input=7748abbacd1e166a]*/ +/*[clinic end generated code: output=86fa1385fdd9ce57 input=eeae770c6eb9f559]*/ { HMODULE hMod; typedef LONG (WINAPI *RERKFunc)(HKEY); @@ -1794,12 +1794,12 @@ winreg.QueryReflectionKey Returns the reflection state for the specified key as a bool. -Will generally raise NotImplemented if executed on a 32bit OS. +Will generally raise NotImplementedError if executed on a 32bit OS. [clinic start generated code]*/ static PyObject * winreg_QueryReflectionKey_impl(PyObject *module, HKEY key) -/*[clinic end generated code: output=4e774af288c3ebb9 input=9f325eacb5a65d88]*/ +/*[clinic end generated code: output=4e774af288c3ebb9 input=a98fa51d55ade186]*/ { HMODULE hMod; typedef LONG (WINAPI *RQRKFunc)(HKEY, BOOL *); From webhook-mailer at python.org Sun Aug 4 10:06:59 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 04 Aug 2019 14:06:59 -0000 Subject: [Python-checkins] [3.7] bpo-37730: Fix usage of NotImplemented instead of NotImplementedError in docs. (GH-15062). (GH-15106) Message-ID: https://github.com/python/cpython/commit/8cd630578451a062dcf46fbb21274520ae36c399 commit: 8cd630578451a062dcf46fbb21274520ae36c399 branch: 3.7 author: Serhiy Storchaka committer: GitHub date: 2019-08-04T17:06:51+03:00 summary: [3.7] bpo-37730: Fix usage of NotImplemented instead of NotImplementedError in docs. (GH-15062). (GH-15106) (cherry picked from commit ed5e8e06cbf766e89d6c58a882ee024abb5b2ed7) Co-authored-by: David H files: M Doc/library/winreg.rst M PC/clinic/winreg.c.h M PC/winreg.c diff --git a/Doc/library/winreg.rst b/Doc/library/winreg.rst index e9c026102273..cb67f2f39d76 100644 --- a/Doc/library/winreg.rst +++ b/Doc/library/winreg.rst @@ -456,7 +456,7 @@ This module offers the following functions: *key* is an already open key, or one of the predefined :ref:`HKEY_* constants `. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit operating + Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating system. If the key is not on the reflection list, the function succeeds but has no @@ -471,7 +471,7 @@ This module offers the following functions: *key* is an already open key, or one of the predefined :ref:`HKEY_* constants `. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit operating + Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating system. Restoring reflection for a key does not affect reflection of any subkeys. @@ -486,7 +486,7 @@ This module offers the following functions: Returns ``True`` if reflection is disabled. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit + Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating system. diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h index 6a5f613808c2..e9df3675b146 100644 --- a/PC/clinic/winreg.c.h +++ b/PC/clinic/winreg.c.h @@ -1003,7 +1003,7 @@ PyDoc_STRVAR(winreg_DisableReflectionKey__doc__, " key\n" " An already open key, or any one of the predefined HKEY_* constants.\n" "\n" -"Will generally raise NotImplemented if executed on a 32bit OS.\n" +"Will generally raise NotImplementedError if executed on a 32bit OS.\n" "\n" "If the key is not on the reflection list, the function succeeds but has\n" "no effect. Disabling reflection for a key does not affect reflection\n" @@ -1039,7 +1039,7 @@ PyDoc_STRVAR(winreg_EnableReflectionKey__doc__, " key\n" " An already open key, or any one of the predefined HKEY_* constants.\n" "\n" -"Will generally raise NotImplemented if executed on a 32bit OS.\n" +"Will generally raise NotImplementedError if executed on a 32bit OS.\n" "Restoring reflection for a key does not affect reflection of any\n" "subkeys."); @@ -1073,7 +1073,7 @@ PyDoc_STRVAR(winreg_QueryReflectionKey__doc__, " key\n" " An already open key, or any one of the predefined HKEY_* constants.\n" "\n" -"Will generally raise NotImplemented if executed on a 32bit OS."); +"Will generally raise NotImplementedError if executed on a 32bit OS."); #define WINREG_QUERYREFLECTIONKEY_METHODDEF \ {"QueryReflectionKey", (PyCFunction)winreg_QueryReflectionKey, METH_O, winreg_QueryReflectionKey__doc__}, @@ -1095,4 +1095,4 @@ winreg_QueryReflectionKey(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=60c92ffc7438f8cf input=a9049054013a1b77]*/ +/*[clinic end generated code: output=696f627d310ac599 input=a9049054013a1b77]*/ diff --git a/PC/winreg.c b/PC/winreg.c index 1021609e582f..5f18876895c3 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1697,7 +1697,7 @@ winreg.DisableReflectionKey Disables registry reflection for 32bit processes running on a 64bit OS. -Will generally raise NotImplemented if executed on a 32bit OS. +Will generally raise NotImplementedError if executed on a 32bit OS. If the key is not on the reflection list, the function succeeds but has no effect. Disabling reflection for a key does not affect reflection @@ -1706,7 +1706,7 @@ of any subkeys. static PyObject * winreg_DisableReflectionKey_impl(PyObject *module, HKEY key) -/*[clinic end generated code: output=830cce504cc764b4 input=a6c9e5ca5410193c]*/ +/*[clinic end generated code: output=830cce504cc764b4 input=70bece2dee02e073]*/ { HMODULE hMod; typedef LONG (WINAPI *RDRKFunc)(HKEY); @@ -1742,14 +1742,14 @@ winreg.EnableReflectionKey Restores registry reflection for the specified disabled key. -Will generally raise NotImplemented if executed on a 32bit OS. +Will generally raise NotImplementedError if executed on a 32bit OS. Restoring reflection for a key does not affect reflection of any subkeys. [clinic start generated code]*/ static PyObject * winreg_EnableReflectionKey_impl(PyObject *module, HKEY key) -/*[clinic end generated code: output=86fa1385fdd9ce57 input=7748abbacd1e166a]*/ +/*[clinic end generated code: output=86fa1385fdd9ce57 input=eeae770c6eb9f559]*/ { HMODULE hMod; typedef LONG (WINAPI *RERKFunc)(HKEY); @@ -1785,12 +1785,12 @@ winreg.QueryReflectionKey Returns the reflection state for the specified key as a bool. -Will generally raise NotImplemented if executed on a 32bit OS. +Will generally raise NotImplementedError if executed on a 32bit OS. [clinic start generated code]*/ static PyObject * winreg_QueryReflectionKey_impl(PyObject *module, HKEY key) -/*[clinic end generated code: output=4e774af288c3ebb9 input=9f325eacb5a65d88]*/ +/*[clinic end generated code: output=4e774af288c3ebb9 input=a98fa51d55ade186]*/ { HMODULE hMod; typedef LONG (WINAPI *RQRKFunc)(HKEY, BOOL *); From webhook-mailer at python.org Sun Aug 4 12:25:34 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 04 Aug 2019 16:25:34 -0000 Subject: [Python-checkins] bpo-37706: IDLE - fix sidebar code bug and drag tests (GH-15103) Message-ID: https://github.com/python/cpython/commit/86f1a18abfee5939452f468d80de998918e2afd2 commit: 86f1a18abfee5939452f468d80de998918e2afd2 branch: master author: Tal Einat committer: Terry Jan Reedy date: 2019-08-04T12:25:27-04:00 summary: bpo-37706: IDLE - fix sidebar code bug and drag tests (GH-15103) Convert mouse y to line number in the sidebar rather than the text. files: M Lib/idlelib/idle_test/htest.py M Lib/idlelib/idle_test/test_sidebar.py M Lib/idlelib/sidebar.py diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py index 6990af519b1f..1373b7642a6e 100644 --- a/Lib/idlelib/idle_test/htest.py +++ b/Lib/idlelib/idle_test/htest.py @@ -210,13 +210,20 @@ def _wrapper(parent): # htest # 'file': 'sidebar', 'kwds': {}, 'msg': textwrap.dedent("""\ - Click on the line numbers and drag down below the edge of the + 1. Click on the line numbers and drag down below the edge of the window, moving the mouse a bit and then leaving it there for a while. The text and line numbers should gradually scroll down, with the selection updated continuously. - Do the same as above, dragging to above the window. The text and line + + 2. With the lines still selected, click on a line number above the + selected lines. Only the line whose number was clicked should be + selected. + + 3. Repeat step #1, dragging to above the window. The text and line numbers should gradually scroll up, with the selection updated - continuously."""), + continuously. + + 4. Repeat step #2, clicking a line number below the selection."""), } _multi_call_spec = { diff --git a/Lib/idlelib/idle_test/test_sidebar.py b/Lib/idlelib/idle_test/test_sidebar.py index 07e8f2e96b90..0f5b4c712232 100644 --- a/Lib/idlelib/idle_test/test_sidebar.py +++ b/Lib/idlelib/idle_test/test_sidebar.py @@ -240,7 +240,6 @@ def get_width(): self.assert_sidebar_n_lines(1) self.assertEqual(get_width(), 1) - @unittest.skipIf(platform == 'darwin', 'test tk version dependent') def test_click_selection(self): self.linenumber.show_sidebar() self.text.insert('1.0', 'one\ntwo\nthree\nfour\n') @@ -254,44 +253,47 @@ def test_click_selection(self): self.assertEqual(self.get_selection(), ('2.0', '3.0')) - @unittest.skipIf(platform == 'darwin', 'test tk version dependent') - def test_drag_selection_down(self): - self.linenumber.show_sidebar() - self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n') - self.root.update() + def simulate_drag(self, start_line, end_line): + start_x, start_y = self.get_line_screen_position(start_line) + end_x, end_y = self.get_line_screen_position(end_line) - # Drag from the second line to the fourth line. - start_x, start_y = self.get_line_screen_position(2) - end_x, end_y = self.get_line_screen_position(4) self.linenumber.sidebar_text.event_generate('', x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=end_x, y=end_y) + self.root.update() + + def lerp(a, b, steps): + """linearly interpolate from a to b (inclusive) in equal steps""" + last_step = steps - 1 + for i in range(steps): + yield ((last_step - i) / last_step) * a + (i / last_step) * b + + for x, y in zip( + map(int, lerp(start_x, end_x, steps=11)), + map(int, lerp(start_y, end_y, steps=11)), + ): + self.linenumber.sidebar_text.event_generate('', x=x, y=y) + self.root.update() + self.linenumber.sidebar_text.event_generate('', x=end_x, y=end_y) self.root.update() + + def test_drag_selection_down(self): + self.linenumber.show_sidebar() + self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n') + self.root.update() + + # Drag from the second line to the fourth line. + self.simulate_drag(2, 4) self.assertEqual(self.get_selection(), ('2.0', '5.0')) - @unittest.skipIf(platform == 'darwin', 'test tk version dependent') def test_drag_selection_up(self): self.linenumber.show_sidebar() self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n') self.root.update() # Drag from the fourth line to the second line. - start_x, start_y = self.get_line_screen_position(4) - end_x, end_y = self.get_line_screen_position(2) - self.linenumber.sidebar_text.event_generate('', - x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=end_x, y=end_y) - self.linenumber.sidebar_text.event_generate('', - x=end_x, y=end_y) - self.root.update() + self.simulate_drag(4, 2) self.assertEqual(self.get_selection(), ('2.0', '5.0')) def test_scroll(self): diff --git a/Lib/idlelib/sidebar.py b/Lib/idlelib/sidebar.py index 76964a4cdfbe..41c09684a202 100644 --- a/Lib/idlelib/sidebar.py +++ b/Lib/idlelib/sidebar.py @@ -204,10 +204,19 @@ def bind_mouse_event(event_name, target_event_name): bind_mouse_event(event_name, target_event_name=f'') + # This is set by b1_mousedown_handler() and read by + # drag_update_selection_and_insert_mark(), to know where dragging + # began. start_line = None + # These are set by b1_motion_handler() and read by selection_handler(). + # last_y is passed this way since the mouse Y-coordinate is not + # available on selection event objects. last_yview is passed this way + # to recognize scrolling while the mouse isn't moving. + last_y = last_yview = None + def b1_mousedown_handler(event): # select the entire line - lineno = self.editwin.getlineno(f"@0,{event.y}") + lineno = int(float(self.sidebar_text.index(f"@0,{event.y}"))) self.text.tag_remove("sel", "1.0", "end") self.text.tag_add("sel", f"{lineno}.0", f"{lineno+1}.0") self.text.mark_set("insert", f"{lineno+1}.0") @@ -217,15 +226,20 @@ def b1_mousedown_handler(event): start_line = lineno self.sidebar_text.bind('', b1_mousedown_handler) - # These are set by b1_motion_handler() and read by selection_handler(); - # see below. last_y is passed this way since the mouse Y-coordinate - # is not available on selection event objects. last_yview is passed - # this way to recognize scrolling while the mouse isn't moving. - last_y = last_yview = None + def b1_mouseup_handler(event): + # On mouse up, we're no longer dragging. Set the shared persistent + # variables to None to represent this. + nonlocal start_line + nonlocal last_y + nonlocal last_yview + start_line = None + last_y = None + last_yview = None + self.sidebar_text.bind('', b1_mouseup_handler) def drag_update_selection_and_insert_mark(y_coord): """Helper function for drag and selection event handlers.""" - lineno = self.editwin.getlineno(f"@0,{y_coord}") + lineno = int(float(self.sidebar_text.index(f"@0,{y_coord}"))) a, b = sorted([start_line, lineno]) self.text.tag_remove("sel", "1.0", "end") self.text.tag_add("sel", f"{a}.0", f"{b+1}.0") @@ -253,6 +267,9 @@ def b1_drag_handler(event, *args): # while the mouse isn't moving, leading to the above fix not scrolling # properly. def selection_handler(event): + if last_yview is None: + # This logic is only needed while dragging. + return yview = self.sidebar_text.yview() if yview != last_yview: self.text.yview_moveto(yview[0]) From webhook-mailer at python.org Sun Aug 4 12:44:00 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 04 Aug 2019 16:44:00 -0000 Subject: [Python-checkins] bpo-37706: IDLE - fix sidebar code bug and drag tests (GH-15103) Message-ID: https://github.com/python/cpython/commit/1d2b4dba6ccbeb90ef797034b775c0f1ed17d1a0 commit: 1d2b4dba6ccbeb90ef797034b775c0f1ed17d1a0 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-04T09:43:56-07:00 summary: bpo-37706: IDLE - fix sidebar code bug and drag tests (GH-15103) Convert mouse y to line number in the sidebar rather than the text. (cherry picked from commit 86f1a18abfee5939452f468d80de998918e2afd2) Co-authored-by: Tal Einat files: M Lib/idlelib/idle_test/htest.py M Lib/idlelib/idle_test/test_sidebar.py M Lib/idlelib/sidebar.py diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py index 6990af519b1f..1373b7642a6e 100644 --- a/Lib/idlelib/idle_test/htest.py +++ b/Lib/idlelib/idle_test/htest.py @@ -210,13 +210,20 @@ def _wrapper(parent): # htest # 'file': 'sidebar', 'kwds': {}, 'msg': textwrap.dedent("""\ - Click on the line numbers and drag down below the edge of the + 1. Click on the line numbers and drag down below the edge of the window, moving the mouse a bit and then leaving it there for a while. The text and line numbers should gradually scroll down, with the selection updated continuously. - Do the same as above, dragging to above the window. The text and line + + 2. With the lines still selected, click on a line number above the + selected lines. Only the line whose number was clicked should be + selected. + + 3. Repeat step #1, dragging to above the window. The text and line numbers should gradually scroll up, with the selection updated - continuously."""), + continuously. + + 4. Repeat step #2, clicking a line number below the selection."""), } _multi_call_spec = { diff --git a/Lib/idlelib/idle_test/test_sidebar.py b/Lib/idlelib/idle_test/test_sidebar.py index 07e8f2e96b90..0f5b4c712232 100644 --- a/Lib/idlelib/idle_test/test_sidebar.py +++ b/Lib/idlelib/idle_test/test_sidebar.py @@ -240,7 +240,6 @@ def get_width(): self.assert_sidebar_n_lines(1) self.assertEqual(get_width(), 1) - @unittest.skipIf(platform == 'darwin', 'test tk version dependent') def test_click_selection(self): self.linenumber.show_sidebar() self.text.insert('1.0', 'one\ntwo\nthree\nfour\n') @@ -254,44 +253,47 @@ def test_click_selection(self): self.assertEqual(self.get_selection(), ('2.0', '3.0')) - @unittest.skipIf(platform == 'darwin', 'test tk version dependent') - def test_drag_selection_down(self): - self.linenumber.show_sidebar() - self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n') - self.root.update() + def simulate_drag(self, start_line, end_line): + start_x, start_y = self.get_line_screen_position(start_line) + end_x, end_y = self.get_line_screen_position(end_line) - # Drag from the second line to the fourth line. - start_x, start_y = self.get_line_screen_position(2) - end_x, end_y = self.get_line_screen_position(4) self.linenumber.sidebar_text.event_generate('', x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=end_x, y=end_y) + self.root.update() + + def lerp(a, b, steps): + """linearly interpolate from a to b (inclusive) in equal steps""" + last_step = steps - 1 + for i in range(steps): + yield ((last_step - i) / last_step) * a + (i / last_step) * b + + for x, y in zip( + map(int, lerp(start_x, end_x, steps=11)), + map(int, lerp(start_y, end_y, steps=11)), + ): + self.linenumber.sidebar_text.event_generate('', x=x, y=y) + self.root.update() + self.linenumber.sidebar_text.event_generate('', x=end_x, y=end_y) self.root.update() + + def test_drag_selection_down(self): + self.linenumber.show_sidebar() + self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n') + self.root.update() + + # Drag from the second line to the fourth line. + self.simulate_drag(2, 4) self.assertEqual(self.get_selection(), ('2.0', '5.0')) - @unittest.skipIf(platform == 'darwin', 'test tk version dependent') def test_drag_selection_up(self): self.linenumber.show_sidebar() self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n') self.root.update() # Drag from the fourth line to the second line. - start_x, start_y = self.get_line_screen_position(4) - end_x, end_y = self.get_line_screen_position(2) - self.linenumber.sidebar_text.event_generate('', - x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=end_x, y=end_y) - self.linenumber.sidebar_text.event_generate('', - x=end_x, y=end_y) - self.root.update() + self.simulate_drag(4, 2) self.assertEqual(self.get_selection(), ('2.0', '5.0')) def test_scroll(self): diff --git a/Lib/idlelib/sidebar.py b/Lib/idlelib/sidebar.py index 76964a4cdfbe..41c09684a202 100644 --- a/Lib/idlelib/sidebar.py +++ b/Lib/idlelib/sidebar.py @@ -204,10 +204,19 @@ def bind_mouse_event(event_name, target_event_name): bind_mouse_event(event_name, target_event_name=f'') + # This is set by b1_mousedown_handler() and read by + # drag_update_selection_and_insert_mark(), to know where dragging + # began. start_line = None + # These are set by b1_motion_handler() and read by selection_handler(). + # last_y is passed this way since the mouse Y-coordinate is not + # available on selection event objects. last_yview is passed this way + # to recognize scrolling while the mouse isn't moving. + last_y = last_yview = None + def b1_mousedown_handler(event): # select the entire line - lineno = self.editwin.getlineno(f"@0,{event.y}") + lineno = int(float(self.sidebar_text.index(f"@0,{event.y}"))) self.text.tag_remove("sel", "1.0", "end") self.text.tag_add("sel", f"{lineno}.0", f"{lineno+1}.0") self.text.mark_set("insert", f"{lineno+1}.0") @@ -217,15 +226,20 @@ def b1_mousedown_handler(event): start_line = lineno self.sidebar_text.bind('', b1_mousedown_handler) - # These are set by b1_motion_handler() and read by selection_handler(); - # see below. last_y is passed this way since the mouse Y-coordinate - # is not available on selection event objects. last_yview is passed - # this way to recognize scrolling while the mouse isn't moving. - last_y = last_yview = None + def b1_mouseup_handler(event): + # On mouse up, we're no longer dragging. Set the shared persistent + # variables to None to represent this. + nonlocal start_line + nonlocal last_y + nonlocal last_yview + start_line = None + last_y = None + last_yview = None + self.sidebar_text.bind('', b1_mouseup_handler) def drag_update_selection_and_insert_mark(y_coord): """Helper function for drag and selection event handlers.""" - lineno = self.editwin.getlineno(f"@0,{y_coord}") + lineno = int(float(self.sidebar_text.index(f"@0,{y_coord}"))) a, b = sorted([start_line, lineno]) self.text.tag_remove("sel", "1.0", "end") self.text.tag_add("sel", f"{a}.0", f"{b+1}.0") @@ -253,6 +267,9 @@ def b1_drag_handler(event, *args): # while the mouse isn't moving, leading to the above fix not scrolling # properly. def selection_handler(event): + if last_yview is None: + # This logic is only needed while dragging. + return yview = self.sidebar_text.yview() if yview != last_yview: self.text.yview_moveto(yview[0]) From webhook-mailer at python.org Sun Aug 4 12:47:15 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 04 Aug 2019 16:47:15 -0000 Subject: [Python-checkins] bpo-37706: IDLE - fix sidebar code bug and drag tests (GH-15103) Message-ID: https://github.com/python/cpython/commit/9e0c48a002c144d910a46a74b76b02179502b9aa commit: 9e0c48a002c144d910a46a74b76b02179502b9aa branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-04T09:47:11-07:00 summary: bpo-37706: IDLE - fix sidebar code bug and drag tests (GH-15103) Convert mouse y to line number in the sidebar rather than the text. (cherry picked from commit 86f1a18abfee5939452f468d80de998918e2afd2) Co-authored-by: Tal Einat files: M Lib/idlelib/idle_test/htest.py M Lib/idlelib/idle_test/test_sidebar.py M Lib/idlelib/sidebar.py diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py index 6990af519b1f..1373b7642a6e 100644 --- a/Lib/idlelib/idle_test/htest.py +++ b/Lib/idlelib/idle_test/htest.py @@ -210,13 +210,20 @@ def _wrapper(parent): # htest # 'file': 'sidebar', 'kwds': {}, 'msg': textwrap.dedent("""\ - Click on the line numbers and drag down below the edge of the + 1. Click on the line numbers and drag down below the edge of the window, moving the mouse a bit and then leaving it there for a while. The text and line numbers should gradually scroll down, with the selection updated continuously. - Do the same as above, dragging to above the window. The text and line + + 2. With the lines still selected, click on a line number above the + selected lines. Only the line whose number was clicked should be + selected. + + 3. Repeat step #1, dragging to above the window. The text and line numbers should gradually scroll up, with the selection updated - continuously."""), + continuously. + + 4. Repeat step #2, clicking a line number below the selection."""), } _multi_call_spec = { diff --git a/Lib/idlelib/idle_test/test_sidebar.py b/Lib/idlelib/idle_test/test_sidebar.py index 07e8f2e96b90..0f5b4c712232 100644 --- a/Lib/idlelib/idle_test/test_sidebar.py +++ b/Lib/idlelib/idle_test/test_sidebar.py @@ -240,7 +240,6 @@ def get_width(): self.assert_sidebar_n_lines(1) self.assertEqual(get_width(), 1) - @unittest.skipIf(platform == 'darwin', 'test tk version dependent') def test_click_selection(self): self.linenumber.show_sidebar() self.text.insert('1.0', 'one\ntwo\nthree\nfour\n') @@ -254,44 +253,47 @@ def test_click_selection(self): self.assertEqual(self.get_selection(), ('2.0', '3.0')) - @unittest.skipIf(platform == 'darwin', 'test tk version dependent') - def test_drag_selection_down(self): - self.linenumber.show_sidebar() - self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n') - self.root.update() + def simulate_drag(self, start_line, end_line): + start_x, start_y = self.get_line_screen_position(start_line) + end_x, end_y = self.get_line_screen_position(end_line) - # Drag from the second line to the fourth line. - start_x, start_y = self.get_line_screen_position(2) - end_x, end_y = self.get_line_screen_position(4) self.linenumber.sidebar_text.event_generate('', x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=end_x, y=end_y) + self.root.update() + + def lerp(a, b, steps): + """linearly interpolate from a to b (inclusive) in equal steps""" + last_step = steps - 1 + for i in range(steps): + yield ((last_step - i) / last_step) * a + (i / last_step) * b + + for x, y in zip( + map(int, lerp(start_x, end_x, steps=11)), + map(int, lerp(start_y, end_y, steps=11)), + ): + self.linenumber.sidebar_text.event_generate('', x=x, y=y) + self.root.update() + self.linenumber.sidebar_text.event_generate('', x=end_x, y=end_y) self.root.update() + + def test_drag_selection_down(self): + self.linenumber.show_sidebar() + self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n') + self.root.update() + + # Drag from the second line to the fourth line. + self.simulate_drag(2, 4) self.assertEqual(self.get_selection(), ('2.0', '5.0')) - @unittest.skipIf(platform == 'darwin', 'test tk version dependent') def test_drag_selection_up(self): self.linenumber.show_sidebar() self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n') self.root.update() # Drag from the fourth line to the second line. - start_x, start_y = self.get_line_screen_position(4) - end_x, end_y = self.get_line_screen_position(2) - self.linenumber.sidebar_text.event_generate('', - x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=start_x, y=start_y) - self.linenumber.sidebar_text.event_generate('', - x=end_x, y=end_y) - self.linenumber.sidebar_text.event_generate('', - x=end_x, y=end_y) - self.root.update() + self.simulate_drag(4, 2) self.assertEqual(self.get_selection(), ('2.0', '5.0')) def test_scroll(self): diff --git a/Lib/idlelib/sidebar.py b/Lib/idlelib/sidebar.py index 76964a4cdfbe..41c09684a202 100644 --- a/Lib/idlelib/sidebar.py +++ b/Lib/idlelib/sidebar.py @@ -204,10 +204,19 @@ def bind_mouse_event(event_name, target_event_name): bind_mouse_event(event_name, target_event_name=f'') + # This is set by b1_mousedown_handler() and read by + # drag_update_selection_and_insert_mark(), to know where dragging + # began. start_line = None + # These are set by b1_motion_handler() and read by selection_handler(). + # last_y is passed this way since the mouse Y-coordinate is not + # available on selection event objects. last_yview is passed this way + # to recognize scrolling while the mouse isn't moving. + last_y = last_yview = None + def b1_mousedown_handler(event): # select the entire line - lineno = self.editwin.getlineno(f"@0,{event.y}") + lineno = int(float(self.sidebar_text.index(f"@0,{event.y}"))) self.text.tag_remove("sel", "1.0", "end") self.text.tag_add("sel", f"{lineno}.0", f"{lineno+1}.0") self.text.mark_set("insert", f"{lineno+1}.0") @@ -217,15 +226,20 @@ def b1_mousedown_handler(event): start_line = lineno self.sidebar_text.bind('', b1_mousedown_handler) - # These are set by b1_motion_handler() and read by selection_handler(); - # see below. last_y is passed this way since the mouse Y-coordinate - # is not available on selection event objects. last_yview is passed - # this way to recognize scrolling while the mouse isn't moving. - last_y = last_yview = None + def b1_mouseup_handler(event): + # On mouse up, we're no longer dragging. Set the shared persistent + # variables to None to represent this. + nonlocal start_line + nonlocal last_y + nonlocal last_yview + start_line = None + last_y = None + last_yview = None + self.sidebar_text.bind('', b1_mouseup_handler) def drag_update_selection_and_insert_mark(y_coord): """Helper function for drag and selection event handlers.""" - lineno = self.editwin.getlineno(f"@0,{y_coord}") + lineno = int(float(self.sidebar_text.index(f"@0,{y_coord}"))) a, b = sorted([start_line, lineno]) self.text.tag_remove("sel", "1.0", "end") self.text.tag_add("sel", f"{a}.0", f"{b+1}.0") @@ -253,6 +267,9 @@ def b1_drag_handler(event, *args): # while the mouse isn't moving, leading to the above fix not scrolling # properly. def selection_handler(event): + if last_yview is None: + # This logic is only needed while dragging. + return yview = self.sidebar_text.yview() if yview != last_yview: self.text.yview_moveto(yview[0]) From webhook-mailer at python.org Sun Aug 4 14:52:09 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 04 Aug 2019 18:52:09 -0000 Subject: [Python-checkins] bpo-36324: Update comments to include the target hash sums (GH-15110) Message-ID: https://github.com/python/cpython/commit/8183bb8150edcac6a7525bfb7708d08837ecb095 commit: 8183bb8150edcac6a7525bfb7708d08837ecb095 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-04T11:52:04-07:00 summary: bpo-36324: Update comments to include the target hash sums (GH-15110) files: M Lib/statistics.py diff --git a/Lib/statistics.py b/Lib/statistics.py index 8a6be7c75901..77291dd62cb9 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -892,6 +892,7 @@ def inv_cdf(self, p): q = p - 0.5 if fabs(q) <= 0.425: r = 0.180625 - q * q + # Hash sum: 55.88319_28806_14901_4439 num = (((((((2.50908_09287_30122_6727e+3 * r + 3.34305_75583_58812_8105e+4) * r + 6.72657_70927_00870_0853e+4) * r + @@ -914,6 +915,7 @@ def inv_cdf(self, p): r = sqrt(-log(r)) if r <= 5.0: r = r - 1.6 + # Hash sum: 49.33206_50330_16102_89036 num = (((((((7.74545_01427_83414_07640e-4 * r + 2.27238_44989_26918_45833e-2) * r + 2.41780_72517_74506_11770e-1) * r + @@ -932,6 +934,7 @@ def inv_cdf(self, p): 1.0) else: r = r - 5.0 + # Hash sum: 47.52583_31754_92896_71629 num = (((((((2.01033_43992_92288_13265e-7 * r + 2.71155_55687_43487_57815e-5) * r + 1.24266_09473_88078_43860e-3) * r + From webhook-mailer at python.org Sun Aug 4 15:16:23 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 04 Aug 2019 19:16:23 -0000 Subject: [Python-checkins] bpo-36324: Update comments to include the target hash sums (GH-15110) (GH-15112) Message-ID: https://github.com/python/cpython/commit/d7d607c000a28432f87d24d2a5a9315c51017041 commit: d7d607c000a28432f87d24d2a5a9315c51017041 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-04T12:16:19-07:00 summary: bpo-36324: Update comments to include the target hash sums (GH-15110) (GH-15112) (cherry picked from commit 8183bb8150edcac6a7525bfb7708d08837ecb095) Co-authored-by: Raymond Hettinger files: M Lib/statistics.py diff --git a/Lib/statistics.py b/Lib/statistics.py index 8a6be7c75901..77291dd62cb9 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -892,6 +892,7 @@ def inv_cdf(self, p): q = p - 0.5 if fabs(q) <= 0.425: r = 0.180625 - q * q + # Hash sum: 55.88319_28806_14901_4439 num = (((((((2.50908_09287_30122_6727e+3 * r + 3.34305_75583_58812_8105e+4) * r + 6.72657_70927_00870_0853e+4) * r + @@ -914,6 +915,7 @@ def inv_cdf(self, p): r = sqrt(-log(r)) if r <= 5.0: r = r - 1.6 + # Hash sum: 49.33206_50330_16102_89036 num = (((((((7.74545_01427_83414_07640e-4 * r + 2.27238_44989_26918_45833e-2) * r + 2.41780_72517_74506_11770e-1) * r + @@ -932,6 +934,7 @@ def inv_cdf(self, p): 1.0) else: r = r - 5.0 + # Hash sum: 47.52583_31754_92896_71629 num = (((((((2.01033_43992_92288_13265e-7 * r + 2.71155_55687_43487_57815e-5) * r + 1.24266_09473_88078_43860e-3) * r + From webhook-mailer at python.org Sun Aug 4 15:26:40 2019 From: webhook-mailer at python.org (Tal Einat) Date: Sun, 04 Aug 2019 19:26:40 -0000 Subject: [Python-checkins] [3.7] bpo-34621: backwards-compatible pickle UUID with is_safe=unknown (GH-14834) Message-ID: https://github.com/python/cpython/commit/a2ea9448c677706d6318eaa71101f08df7604eb9 commit: a2ea9448c677706d6318eaa71101f08df7604eb9 branch: 3.7 author: Tal Einat committer: GitHub date: 2019-08-04T22:26:32+03:00 summary: [3.7] bpo-34621: backwards-compatible pickle UUID with is_safe=unknown (GH-14834) This is a fix for a bug introduced in the original implementation of this for 3.7. files: A Misc/NEWS.d/next/Library/2019-08-04-22-06-54.bpo-34621.E2EWkw.rst M Lib/uuid.py diff --git a/Lib/uuid.py b/Lib/uuid.py index 26faa1accd09..b1abfe315d56 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -205,12 +205,14 @@ def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None, self.__dict__['is_safe'] = is_safe def __getstate__(self): - state = self.__dict__ + state = self.__dict__.copy() if self.is_safe != SafeUUID.unknown: # is_safe is a SafeUUID instance. Return just its value, so that # it can be un-pickled in older Python versions without SafeUUID. - state = state.copy() state['is_safe'] = self.is_safe.value + else: + # omit is_safe when it is "unknown" + del state['is_safe'] return state def __setstate__(self, state): diff --git a/Misc/NEWS.d/next/Library/2019-08-04-22-06-54.bpo-34621.E2EWkw.rst b/Misc/NEWS.d/next/Library/2019-08-04-22-06-54.bpo-34621.E2EWkw.rst new file mode 100644 index 000000000000..1128a2fb4459 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-04-22-06-54.bpo-34621.E2EWkw.rst @@ -0,0 +1,2 @@ +Fixed unpickle-ability in older Python versions (<3.7) of UUID objects with +``is_safe`` set to ``SafeUUID.unknown``. From webhook-mailer at python.org Sun Aug 4 16:14:07 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 04 Aug 2019 20:14:07 -0000 Subject: [Python-checkins] bpo-28292: Mark calendar.py helper functions as private. (GH-15113) Message-ID: https://github.com/python/cpython/commit/b1c8ec010fb4eb2654ca994e95144c8f2fea07fb commit: b1c8ec010fb4eb2654ca994e95144c8f2fea07fb branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-04T13:14:03-07:00 summary: bpo-28292: Mark calendar.py helper functions as private. (GH-15113) files: A Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst M Lib/calendar.py diff --git a/Lib/calendar.py b/Lib/calendar.py index 3828c43ed279..7550d52c0a94 100644 --- a/Lib/calendar.py +++ b/Lib/calendar.py @@ -127,18 +127,18 @@ def monthrange(year, month): return day1, ndays -def monthlen(year, month): +def _monthlen(year, month): return mdays[month] + (month == February and isleap(year)) -def prevmonth(year, month): +def _prevmonth(year, month): if month == 1: return year-1, 12 else: return year, month-1 -def nextmonth(year, month): +def _nextmonth(year, month): if month == 12: return year+1, 1 else: @@ -207,13 +207,13 @@ def itermonthdays3(self, year, month): day1, ndays = monthrange(year, month) days_before = (day1 - self.firstweekday) % 7 days_after = (self.firstweekday - day1 - ndays) % 7 - y, m = prevmonth(year, month) - end = monthlen(y, m) + 1 + y, m = _prevmonth(year, month) + end = _monthlen(y, m) + 1 for d in range(end-days_before, end): yield y, m, d for d in range(1, ndays + 1): yield year, month, d - y, m = nextmonth(year, month) + y, m = _nextmonth(year, month) for d in range(1, days_after + 1): yield y, m, d diff --git a/Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst b/Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst new file mode 100644 index 000000000000..478a1b03c195 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst @@ -0,0 +1,3 @@ +Mark calendar.py helper functions as being private. The follows PEP 8 +guidance to maintain the style conventions in the module and it addresses a +known case of user confusion. From webhook-mailer at python.org Sun Aug 4 16:35:00 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 04 Aug 2019 20:35:00 -0000 Subject: [Python-checkins] bpo-28292: Mark calendar.py helper functions as private. (GH-15113) (GH-15116) Message-ID: https://github.com/python/cpython/commit/0c16f6b307f7607e29b98b8fbb99cbca28f91a48 commit: 0c16f6b307f7607e29b98b8fbb99cbca28f91a48 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-04T13:34:56-07:00 summary: bpo-28292: Mark calendar.py helper functions as private. (GH-15113) (GH-15116) (cherry picked from commit b1c8ec010fb4eb2654ca994e95144c8f2fea07fb) Co-authored-by: Raymond Hettinger files: A Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst M Lib/calendar.py diff --git a/Lib/calendar.py b/Lib/calendar.py index 3828c43ed279..7550d52c0a94 100644 --- a/Lib/calendar.py +++ b/Lib/calendar.py @@ -127,18 +127,18 @@ def monthrange(year, month): return day1, ndays -def monthlen(year, month): +def _monthlen(year, month): return mdays[month] + (month == February and isleap(year)) -def prevmonth(year, month): +def _prevmonth(year, month): if month == 1: return year-1, 12 else: return year, month-1 -def nextmonth(year, month): +def _nextmonth(year, month): if month == 12: return year+1, 1 else: @@ -207,13 +207,13 @@ def itermonthdays3(self, year, month): day1, ndays = monthrange(year, month) days_before = (day1 - self.firstweekday) % 7 days_after = (self.firstweekday - day1 - ndays) % 7 - y, m = prevmonth(year, month) - end = monthlen(y, m) + 1 + y, m = _prevmonth(year, month) + end = _monthlen(y, m) + 1 for d in range(end-days_before, end): yield y, m, d for d in range(1, ndays + 1): yield year, month, d - y, m = nextmonth(year, month) + y, m = _nextmonth(year, month) for d in range(1, days_after + 1): yield y, m, d diff --git a/Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst b/Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst new file mode 100644 index 000000000000..478a1b03c195 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst @@ -0,0 +1,3 @@ +Mark calendar.py helper functions as being private. The follows PEP 8 +guidance to maintain the style conventions in the module and it addresses a +known case of user confusion. From webhook-mailer at python.org Sun Aug 4 16:36:02 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 04 Aug 2019 20:36:02 -0000 Subject: [Python-checkins] Update itertools docs (GH-15114) Message-ID: https://github.com/python/cpython/commit/adf02b36b3f3745ad4ee380d88f2f6011f54fc22 commit: adf02b36b3f3745ad4ee380d88f2f6011f54fc22 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-04T13:35:58-07:00 summary: Update itertools docs (GH-15114) * Remove suggestion that is less relevant now that global lookups are much faster * Add link for installing the recipes files: M Doc/library/itertools.rst diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index b3a0a5f5192d..a3f403a5b40b 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -691,6 +691,12 @@ Itertools Recipes This section shows recipes for creating an extended toolset using the existing itertools as building blocks. +Substantially all of these recipes and many, many others can be installed from +the `more-itertools project `_ found +on the Python Package Index:: + + pip install more-itertools + The extended tools offer the same high performance as the underlying toolset. The superior memory performance is kept by processing elements one at a time rather than bringing the whole iterable into memory all at once. Code volume is @@ -913,9 +919,3 @@ which incur interpreter overhead. result.append(pool[-1-n]) return tuple(result) -Note, many of the above recipes can be optimized by replacing global lookups -with local variables defined as default values. For example, the -*dotproduct* recipe can be written as:: - - def dotproduct(vec1, vec2, sum=sum, map=map, mul=operator.mul): - return sum(map(mul, vec1, vec2)) From webhook-mailer at python.org Sun Aug 4 16:45:19 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 04 Aug 2019 20:45:19 -0000 Subject: [Python-checkins] bpo-37748: Re-order the Run menu. (GH-15115) Message-ID: https://github.com/python/cpython/commit/14070299cdc0faf36975f0cc2d51824a9abf3db0 commit: 14070299cdc0faf36975f0cc2d51824a9abf3db0 branch: master author: Terry Jan Reedy committer: GitHub date: 2019-08-04T16:45:15-04:00 summary: bpo-37748: Re-order the Run menu. (GH-15115) Put the most common choice, Run Module, at the top. files: A Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst M Doc/library/idle.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/help.html M Lib/idlelib/mainmenu.py diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index 5975e3bb5806..0bd248c22b18 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -207,20 +207,6 @@ Strip trailing whitespace Run menu (Editor window only) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. _python-shell: - -Python Shell - Open or wake up the Python Shell window. - -.. _check-module: - -Check Module - Check the syntax of the module currently open in the Editor window. If the - module has not been saved IDLE will either prompt the user to save or - autosave, as selected in the General tab of the Idle Settings dialog. If - there is a syntax error, the approximate location is indicated in the - Editor window. - .. _run-module: Run Module @@ -239,6 +225,20 @@ Run... Customized settings. *Command Line Arguments* extend :data:`sys.argv` as if passed on a command line. The module can be run in the Shell without restarting. +.. _check-module: + +Check Module + Check the syntax of the module currently open in the Editor window. If the + module has not been saved IDLE will either prompt the user to save or + autosave, as selected in the General tab of the Idle Settings dialog. If + there is a syntax error, the approximate location is indicated in the + Editor window. + +.. _python-shell: + +Python Shell + Open or wake up the Python Shell window. + Shell menu (Shell window only) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -295,8 +295,8 @@ Configure IDLE menu. For more details, see :ref:`Setting preferences ` under Help and preferences. - Most configuration options apply to all windows or all future windows. - The option items below only apply to the active window. +Most configuration options apply to all windows or all future windows. +The option items below only apply to the active window. Show/Hide Code Context (Editor Window only) Open a pane at the top of the edit window which shows the block context diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index e3e92bd75f09..0fff7003b9d6 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,9 @@ Released on 2019-10-20? ====================================== +bpo-37748: Reorder the Run menu. Put the most common choice, +Run Module, at the top. + bpo-37692: Improve highlight config sample with example shell interaction and better labels for shell elements. diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 49068df7a8b9..91e66a4b9117 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -210,16 +210,6 @@

Edit menu (Shell and Editor)

Run menu (Editor window only)?

-
-
Python Shell
Open or wake up the Python Shell window.
-
-
-
Check Module
Check the syntax of the module currently open in the Editor window. If the -module has not been saved IDLE will either prompt the user to save or -autosave, as selected in the General tab of the Idle Settings dialog. If -there is a syntax error, the approximate location is indicated in the -Editor window.
-
Run Module
Do Check Module. If no error, restart the shell to clean the environment, then execute the module. Output is displayed in the Shell @@ -234,6 +224,16 @@

Edit menu (Shell and Editor)sys.argv as if passed on a command line. The module can be run in the Shell without restarting.

+
+
Check Module
Check the syntax of the module currently open in the Editor window. If the +module has not been saved IDLE will either prompt the user to save or +autosave, as selected in the General tab of the Idle Settings dialog. If +there is a syntax error, the approximate location is indicated in the +Editor window.
+
+
+
Python Shell
Open or wake up the Python Shell window.
+

Shell menu (Shell window only)?

@@ -268,23 +268,26 @@

Options menu (Shell and Editor)
Configure IDLE
Open a configuration dialog and change preferences for the following: fonts, indentation, keybindings, text color themes, startup windows and -size, additional help sources, and extensions. On macOS, open the +size, additional help sources, and extensions. On macOS, open the configuration dialog by selecting Preferences in the application -menu. For more, see -Setting preferences under Help and preferences. -Most configuration options apply to all windows or all future windows. -The option items below only apply to the active window.
+menu. For more details, see +Setting preferences under Help and preferences. + +

Most configuration options apply to all windows or all future windows. +The option items below only apply to the active window.

+
Show/Hide Code Context (Editor Window only)
Open a pane at the top of the edit window which shows the block context of the code which has scrolled above the top of the window. See -Code Context in the Editing and Navigation section below.
-
Line Numbers (Editor Window only)
Open a column to the left of the edit window which shows the linenumber -of each line of text. The default is off unless configured on -(see Setting preferences).
+Code Context in the Editing and Navigation section +below. +
Show/Hide Line Numbers (Editor Window only)
Open a column to the left of the edit window which shows the number +of each line of text. The default is off, which may be changed in the +preferences (see Setting preferences).
Zoom/Restore Height
Toggles the window between normal size and maximum height. The initial size defaults to 40 lines by 80 chars unless changed on the General tab of the Configure IDLE dialog. The maximum height for a screen is determined by momentarily maximizing a window the first time one is zoomed on the screen. -Changing screen settings may invalidate the saved height. This toogle has +Changing screen settings may invalidate the saved height. This toggle has no effect when a window is maximized.

@@ -900,7 +903,7 @@

Navigation



- Last updated on Jul 23, 2019. + Last updated on Aug 04, 2019. Found a bug?
diff --git a/Lib/idlelib/mainmenu.py b/Lib/idlelib/mainmenu.py index fc51fb1b5d34..74edce234838 100644 --- a/Lib/idlelib/mainmenu.py +++ b/Lib/idlelib/mainmenu.py @@ -73,10 +73,10 @@ ]), ('run', [ - ('Python Shell', '<>'), - ('C_heck Module', '<>'), ('R_un Module', '<>'), ('Run... _Customized', '<>'), + ('C_heck Module', '<>'), + ('Python Shell', '<>'), ]), ('shell', [ diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst new file mode 100644 index 000000000000..fc1d6b6bb357 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst @@ -0,0 +1 @@ +Reorder the Run menu. Put the most common choice, Run Module, at the top. From webhook-mailer at python.org Sun Aug 4 16:53:03 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 04 Aug 2019 20:53:03 -0000 Subject: [Python-checkins] Update itertools docs (GH-15114) (GH-15118) Message-ID: https://github.com/python/cpython/commit/fc6e3bc1cdaabac89382b45459f9b3f84d929afd commit: fc6e3bc1cdaabac89382b45459f9b3f84d929afd branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-04T13:52:59-07:00 summary: Update itertools docs (GH-15114) (GH-15118) * Remove suggestion that is less relevant now that global lookups are much faster * Add link for installing the recipes (cherry picked from commit adf02b36b3f3745ad4ee380d88f2f6011f54fc22) Co-authored-by: Raymond Hettinger files: M Doc/library/itertools.rst diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index b3a0a5f5192d..a3f403a5b40b 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -691,6 +691,12 @@ Itertools Recipes This section shows recipes for creating an extended toolset using the existing itertools as building blocks. +Substantially all of these recipes and many, many others can be installed from +the `more-itertools project `_ found +on the Python Package Index:: + + pip install more-itertools + The extended tools offer the same high performance as the underlying toolset. The superior memory performance is kept by processing elements one at a time rather than bringing the whole iterable into memory all at once. Code volume is @@ -913,9 +919,3 @@ which incur interpreter overhead. result.append(pool[-1-n]) return tuple(result) -Note, many of the above recipes can be optimized by replacing global lookups -with local variables defined as default values. For example, the -*dotproduct* recipe can be written as:: - - def dotproduct(vec1, vec2, sum=sum, map=map, mul=operator.mul): - return sum(map(mul, vec1, vec2)) From webhook-mailer at python.org Sun Aug 4 17:04:53 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 04 Aug 2019 21:04:53 -0000 Subject: [Python-checkins] bpo-37748: Re-order the Run menu. (GH-15115) Message-ID: https://github.com/python/cpython/commit/9c95fc752c1465202df67fa894ef326c8ebb8cac commit: 9c95fc752c1465202df67fa894ef326c8ebb8cac branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-04T14:04:49-07:00 summary: bpo-37748: Re-order the Run menu. (GH-15115) Put the most common choice, Run Module, at the top. (cherry picked from commit 14070299cdc0faf36975f0cc2d51824a9abf3db0) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst M Doc/library/idle.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/help.html M Lib/idlelib/mainmenu.py diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index 5975e3bb5806..0bd248c22b18 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -207,20 +207,6 @@ Strip trailing whitespace Run menu (Editor window only) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. _python-shell: - -Python Shell - Open or wake up the Python Shell window. - -.. _check-module: - -Check Module - Check the syntax of the module currently open in the Editor window. If the - module has not been saved IDLE will either prompt the user to save or - autosave, as selected in the General tab of the Idle Settings dialog. If - there is a syntax error, the approximate location is indicated in the - Editor window. - .. _run-module: Run Module @@ -239,6 +225,20 @@ Run... Customized settings. *Command Line Arguments* extend :data:`sys.argv` as if passed on a command line. The module can be run in the Shell without restarting. +.. _check-module: + +Check Module + Check the syntax of the module currently open in the Editor window. If the + module has not been saved IDLE will either prompt the user to save or + autosave, as selected in the General tab of the Idle Settings dialog. If + there is a syntax error, the approximate location is indicated in the + Editor window. + +.. _python-shell: + +Python Shell + Open or wake up the Python Shell window. + Shell menu (Shell window only) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -295,8 +295,8 @@ Configure IDLE menu. For more details, see :ref:`Setting preferences ` under Help and preferences. - Most configuration options apply to all windows or all future windows. - The option items below only apply to the active window. +Most configuration options apply to all windows or all future windows. +The option items below only apply to the active window. Show/Hide Code Context (Editor Window only) Open a pane at the top of the edit window which shows the block context diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index e3e92bd75f09..0fff7003b9d6 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,9 @@ Released on 2019-10-20? ====================================== +bpo-37748: Reorder the Run menu. Put the most common choice, +Run Module, at the top. + bpo-37692: Improve highlight config sample with example shell interaction and better labels for shell elements. diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 49068df7a8b9..91e66a4b9117 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -210,16 +210,6 @@

Edit menu (Shell and Editor)

Run menu (Editor window only)?

-
-
Python Shell
Open or wake up the Python Shell window.
-
-
-
Check Module
Check the syntax of the module currently open in the Editor window. If the -module has not been saved IDLE will either prompt the user to save or -autosave, as selected in the General tab of the Idle Settings dialog. If -there is a syntax error, the approximate location is indicated in the -Editor window.
-
Run Module
Do Check Module. If no error, restart the shell to clean the environment, then execute the module. Output is displayed in the Shell @@ -234,6 +224,16 @@

Edit menu (Shell and Editor)sys.argv as if passed on a command line. The module can be run in the Shell without restarting.

+
+
Check Module
Check the syntax of the module currently open in the Editor window. If the +module has not been saved IDLE will either prompt the user to save or +autosave, as selected in the General tab of the Idle Settings dialog. If +there is a syntax error, the approximate location is indicated in the +Editor window.
+
+
+
Python Shell
Open or wake up the Python Shell window.
+

Shell menu (Shell window only)?

@@ -268,23 +268,26 @@

Options menu (Shell and Editor)
Configure IDLE
Open a configuration dialog and change preferences for the following: fonts, indentation, keybindings, text color themes, startup windows and -size, additional help sources, and extensions. On macOS, open the +size, additional help sources, and extensions. On macOS, open the configuration dialog by selecting Preferences in the application -menu. For more, see -Setting preferences under Help and preferences. -Most configuration options apply to all windows or all future windows. -The option items below only apply to the active window.
+menu. For more details, see +Setting preferences under Help and preferences. + +

Most configuration options apply to all windows or all future windows. +The option items below only apply to the active window.

+
Show/Hide Code Context (Editor Window only)
Open a pane at the top of the edit window which shows the block context of the code which has scrolled above the top of the window. See -Code Context in the Editing and Navigation section below.
-
Line Numbers (Editor Window only)
Open a column to the left of the edit window which shows the linenumber -of each line of text. The default is off unless configured on -(see Setting preferences).
+Code Context in the Editing and Navigation section +below. +
Show/Hide Line Numbers (Editor Window only)
Open a column to the left of the edit window which shows the number +of each line of text. The default is off, which may be changed in the +preferences (see Setting preferences).
Zoom/Restore Height
Toggles the window between normal size and maximum height. The initial size defaults to 40 lines by 80 chars unless changed on the General tab of the Configure IDLE dialog. The maximum height for a screen is determined by momentarily maximizing a window the first time one is zoomed on the screen. -Changing screen settings may invalidate the saved height. This toogle has +Changing screen settings may invalidate the saved height. This toggle has no effect when a window is maximized.

@@ -900,7 +903,7 @@

Navigation



- Last updated on Jul 23, 2019. + Last updated on Aug 04, 2019. Found a bug?
diff --git a/Lib/idlelib/mainmenu.py b/Lib/idlelib/mainmenu.py index fc51fb1b5d34..74edce234838 100644 --- a/Lib/idlelib/mainmenu.py +++ b/Lib/idlelib/mainmenu.py @@ -73,10 +73,10 @@ ]), ('run', [ - ('Python Shell', '<>'), - ('C_heck Module', '<>'), ('R_un Module', '<>'), ('Run... _Customized', '<>'), + ('C_heck Module', '<>'), + ('Python Shell', '<>'), ]), ('shell', [ diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst new file mode 100644 index 000000000000..fc1d6b6bb357 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst @@ -0,0 +1 @@ +Reorder the Run menu. Put the most common choice, Run Module, at the top. From webhook-mailer at python.org Sun Aug 4 17:07:29 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 04 Aug 2019 21:07:29 -0000 Subject: [Python-checkins] bpo-37748: Re-order the Run menu. (GH-15115) Message-ID: https://github.com/python/cpython/commit/a96f0367d4c84ed42f8dc80c88c10f334498f36c commit: a96f0367d4c84ed42f8dc80c88c10f334498f36c branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-04T14:07:26-07:00 summary: bpo-37748: Re-order the Run menu. (GH-15115) Put the most common choice, Run Module, at the top. (cherry picked from commit 14070299cdc0faf36975f0cc2d51824a9abf3db0) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst M Doc/library/idle.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/help.html M Lib/idlelib/mainmenu.py diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index 5975e3bb5806..0bd248c22b18 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -207,20 +207,6 @@ Strip trailing whitespace Run menu (Editor window only) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. _python-shell: - -Python Shell - Open or wake up the Python Shell window. - -.. _check-module: - -Check Module - Check the syntax of the module currently open in the Editor window. If the - module has not been saved IDLE will either prompt the user to save or - autosave, as selected in the General tab of the Idle Settings dialog. If - there is a syntax error, the approximate location is indicated in the - Editor window. - .. _run-module: Run Module @@ -239,6 +225,20 @@ Run... Customized settings. *Command Line Arguments* extend :data:`sys.argv` as if passed on a command line. The module can be run in the Shell without restarting. +.. _check-module: + +Check Module + Check the syntax of the module currently open in the Editor window. If the + module has not been saved IDLE will either prompt the user to save or + autosave, as selected in the General tab of the Idle Settings dialog. If + there is a syntax error, the approximate location is indicated in the + Editor window. + +.. _python-shell: + +Python Shell + Open or wake up the Python Shell window. + Shell menu (Shell window only) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -295,8 +295,8 @@ Configure IDLE menu. For more details, see :ref:`Setting preferences ` under Help and preferences. - Most configuration options apply to all windows or all future windows. - The option items below only apply to the active window. +Most configuration options apply to all windows or all future windows. +The option items below only apply to the active window. Show/Hide Code Context (Editor Window only) Open a pane at the top of the edit window which shows the block context diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index cf545dcc6745..d4a00027f858 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,9 @@ Released on 2019-09-30? ====================================== +bpo-37748: Reorder the Run menu. Put the most common choice, +Run Module, at the top. + bpo-37692: Improve highlight config sample with example shell interaction and better labels for shell elements. diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 49068df7a8b9..91e66a4b9117 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -210,16 +210,6 @@

Edit menu (Shell and Editor)

Run menu (Editor window only)?

-
-
Python Shell
Open or wake up the Python Shell window.
-
-
-
Check Module
Check the syntax of the module currently open in the Editor window. If the -module has not been saved IDLE will either prompt the user to save or -autosave, as selected in the General tab of the Idle Settings dialog. If -there is a syntax error, the approximate location is indicated in the -Editor window.
-
Run Module
Do Check Module. If no error, restart the shell to clean the environment, then execute the module. Output is displayed in the Shell @@ -234,6 +224,16 @@

Edit menu (Shell and Editor)sys.argv as if passed on a command line. The module can be run in the Shell without restarting.

+
+
Check Module
Check the syntax of the module currently open in the Editor window. If the +module has not been saved IDLE will either prompt the user to save or +autosave, as selected in the General tab of the Idle Settings dialog. If +there is a syntax error, the approximate location is indicated in the +Editor window.
+
+
+
Python Shell
Open or wake up the Python Shell window.
+

Shell menu (Shell window only)?

@@ -268,23 +268,26 @@

Options menu (Shell and Editor)
Configure IDLE
Open a configuration dialog and change preferences for the following: fonts, indentation, keybindings, text color themes, startup windows and -size, additional help sources, and extensions. On macOS, open the +size, additional help sources, and extensions. On macOS, open the configuration dialog by selecting Preferences in the application -menu. For more, see -Setting preferences under Help and preferences. -Most configuration options apply to all windows or all future windows. -The option items below only apply to the active window.
+menu. For more details, see +Setting preferences under Help and preferences. + +

Most configuration options apply to all windows or all future windows. +The option items below only apply to the active window.

+
Show/Hide Code Context (Editor Window only)
Open a pane at the top of the edit window which shows the block context of the code which has scrolled above the top of the window. See -Code Context in the Editing and Navigation section below.
-
Line Numbers (Editor Window only)
Open a column to the left of the edit window which shows the linenumber -of each line of text. The default is off unless configured on -(see Setting preferences).
+Code Context in the Editing and Navigation section +below. +
Show/Hide Line Numbers (Editor Window only)
Open a column to the left of the edit window which shows the number +of each line of text. The default is off, which may be changed in the +preferences (see Setting preferences).
Zoom/Restore Height
Toggles the window between normal size and maximum height. The initial size defaults to 40 lines by 80 chars unless changed on the General tab of the Configure IDLE dialog. The maximum height for a screen is determined by momentarily maximizing a window the first time one is zoomed on the screen. -Changing screen settings may invalidate the saved height. This toogle has +Changing screen settings may invalidate the saved height. This toggle has no effect when a window is maximized.

@@ -900,7 +903,7 @@

Navigation



- Last updated on Jul 23, 2019. + Last updated on Aug 04, 2019. Found a bug?
diff --git a/Lib/idlelib/mainmenu.py b/Lib/idlelib/mainmenu.py index fc51fb1b5d34..74edce234838 100644 --- a/Lib/idlelib/mainmenu.py +++ b/Lib/idlelib/mainmenu.py @@ -73,10 +73,10 @@ ]), ('run', [ - ('Python Shell', '<>'), - ('C_heck Module', '<>'), ('R_un Module', '<>'), ('Run... _Customized', '<>'), + ('C_heck Module', '<>'), + ('Python Shell', '<>'), ]), ('shell', [ diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst new file mode 100644 index 000000000000..fc1d6b6bb357 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst @@ -0,0 +1 @@ +Reorder the Run menu. Put the most common choice, Run Module, at the top. From webhook-mailer at python.org Sun Aug 4 17:23:40 2019 From: webhook-mailer at python.org (Steve Dower) Date: Sun, 04 Aug 2019 21:23:40 -0000 Subject: [Python-checkins] Adds Tim Hopper and Dan Lidral-Porter to ACKS (GH-15101) Message-ID: https://github.com/python/cpython/commit/d748a8085568cc57613ab2b437f7b6c1b6d76ae3 commit: d748a8085568cc57613ab2b437f7b6c1b6d76ae3 branch: master author: Timothy Hopper committer: Steve Dower date: 2019-08-04T14:23:29-07:00 summary: Adds Tim Hopper and Dan Lidral-Porter to ACKS (GH-15101) Tim and Dan were authors for GH-11847 files: M Misc/ACKS diff --git a/Misc/ACKS b/Misc/ACKS index 82fc51c98c40..8c834b43120b 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1879,3 +1879,5 @@ Geoff Shannon Batuhan Taskaya Aleksandr Balezin Robert Leenders +Tim Hopper +Dan Lidral-Porter From webhook-mailer at python.org Sun Aug 4 19:49:02 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 04 Aug 2019 23:49:02 -0000 Subject: [Python-checkins] bpo-36419: IDLE - Refactor autocompete and improve testing. (#15121) Message-ID: https://github.com/python/cpython/commit/1213123005d9f94bb5027c0a5256ea4d3e97b61d commit: 1213123005d9f94bb5027c0a5256ea4d3e97b61d branch: master author: Terry Jan Reedy committer: GitHub date: 2019-08-04T19:48:52-04:00 summary: bpo-36419: IDLE - Refactor autocompete and improve testing. (#15121) files: A Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst M Lib/idlelib/autocomplete.py M Lib/idlelib/autocomplete_w.py M Lib/idlelib/idle_test/test_autocomplete.py diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index e20b757d8710..c623d45a1534 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -8,42 +8,45 @@ import string import sys -# These constants represent the two different types of completions. -# They must be defined here so autocomple_w can import them. -COMPLETE_ATTRIBUTES, COMPLETE_FILES = range(1, 2+1) - +# Two types of completions; defined here for autocomplete_w import below. +ATTRS, FILES = 0, 1 from idlelib import autocomplete_w from idlelib.config import idleConf from idlelib.hyperparser import HyperParser +# Tuples passed to open_completions. +# EvalFunc, Complete, WantWin, Mode +FORCE = True, False, True, None # Control-Space. +TAB = False, True, True, None # Tab. +TRY_A = False, False, False, ATTRS # '.' for attributes. +TRY_F = False, False, False, FILES # '/' in quotes for file name. + # This string includes all chars that may be in an identifier. # TODO Update this here and elsewhere. ID_CHARS = string.ascii_letters + string.digits + "_" -SEPS = os.sep -if os.altsep: # e.g. '/' on Windows... - SEPS += os.altsep - +SEPS = f"{os.sep}{os.altsep if os.altsep else ''}" +TRIGGERS = f".{SEPS}" class AutoComplete: def __init__(self, editwin=None): self.editwin = editwin - if editwin is not None: # not in subprocess or test + if editwin is not None: # not in subprocess or no-gui test self.text = editwin.text - self.autocompletewindow = None - # id of delayed call, and the index of the text insert when - # the delayed call was issued. If _delayed_completion_id is - # None, there is no delayed call. - self._delayed_completion_id = None - self._delayed_completion_index = None + self.autocompletewindow = None + # id of delayed call, and the index of the text insert when + # the delayed call was issued. If _delayed_completion_id is + # None, there is no delayed call. + self._delayed_completion_id = None + self._delayed_completion_index = None @classmethod def reload(cls): cls.popupwait = idleConf.GetOption( "extensions", "AutoComplete", "popupwait", type="int", default=0) - def _make_autocomplete_window(self): + def _make_autocomplete_window(self): # Makes mocking easier. return autocomplete_w.AutoCompleteWindow(self.text) def _remove_autocomplete_window(self, event=None): @@ -52,30 +55,12 @@ def _remove_autocomplete_window(self, event=None): self.autocompletewindow = None def force_open_completions_event(self, event): - """Happens when the user really wants to open a completion list, even - if a function call is needed. - """ - self.open_completions(True, False, True) + "(^space) Open completion list, even if a function call is needed." + self.open_completions(FORCE) return "break" - def try_open_completions_event(self, event): - """Happens when it would be nice to open a completion list, but not - really necessary, for example after a dot, so function - calls won't be made. - """ - lastchar = self.text.get("insert-1c") - if lastchar == ".": - self._open_completions_later(False, False, False, - COMPLETE_ATTRIBUTES) - elif lastchar in SEPS: - self._open_completions_later(False, False, False, - COMPLETE_FILES) - def autocomplete_event(self, event): - """Happens when the user wants to complete his word, and if necessary, - open a completion list after that (if there is more than one - completion) - """ + "(tab) Complete word or open list if multiple options." if hasattr(event, "mc_state") and event.mc_state or\ not self.text.get("insert linestart", "insert").strip(): # A modifier was pressed along with the tab or @@ -85,34 +70,34 @@ def autocomplete_event(self, event): self.autocompletewindow.complete() return "break" else: - opened = self.open_completions(False, True, True) + opened = self.open_completions(TAB) return "break" if opened else None - def _open_completions_later(self, *args): - self._delayed_completion_index = self.text.index("insert") - if self._delayed_completion_id is not None: - self.text.after_cancel(self._delayed_completion_id) - self._delayed_completion_id = \ - self.text.after(self.popupwait, self._delayed_open_completions, - *args) - - def _delayed_open_completions(self, *args): + def try_open_completions_event(self, event=None): + "(./) Open completion list after pause with no movement." + lastchar = self.text.get("insert-1c") + if lastchar in TRIGGERS: + args = TRY_A if lastchar == "." else TRY_F + self._delayed_completion_index = self.text.index("insert") + if self._delayed_completion_id is not None: + self.text.after_cancel(self._delayed_completion_id) + self._delayed_completion_id = self.text.after( + self.popupwait, self._delayed_open_completions, args) + + def _delayed_open_completions(self, args): + "Call open_completions if index unchanged." self._delayed_completion_id = None if self.text.index("insert") == self._delayed_completion_index: - self.open_completions(*args) + self.open_completions(args) - def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): + def open_completions(self, args): """Find the completions and create the AutoCompleteWindow. Return True if successful (no syntax error or so found). If complete is True, then if there's nothing to complete and no start of completion, won't open completions and return False. If mode is given, will open a completion list only in this mode. - - Action Function Eval Complete WantWin Mode - ^space force_open_completions True, False, True no - . or / try_open_completions False, False, False yes - tab autocomplete False, True, True no """ + evalfuncs, complete, wantwin, mode = args # Cancel another delayed call, if it exists. if self._delayed_completion_id is not None: self.text.after_cancel(self._delayed_completion_id) @@ -121,14 +106,14 @@ def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): hp = HyperParser(self.editwin, "insert") curline = self.text.get("insert linestart", "insert") i = j = len(curline) - if hp.is_in_string() and (not mode or mode==COMPLETE_FILES): + if hp.is_in_string() and (not mode or mode==FILES): # Find the beginning of the string. # fetch_completions will look at the file system to determine # whether the string value constitutes an actual file name # XXX could consider raw strings here and unescape the string # value if it's not raw. self._remove_autocomplete_window() - mode = COMPLETE_FILES + mode = FILES # Find last separator or string start while i and curline[i-1] not in "'\"" + SEPS: i -= 1 @@ -138,17 +123,17 @@ def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): while i and curline[i-1] not in "'\"": i -= 1 comp_what = curline[i:j] - elif hp.is_in_code() and (not mode or mode==COMPLETE_ATTRIBUTES): + elif hp.is_in_code() and (not mode or mode==ATTRS): self._remove_autocomplete_window() - mode = COMPLETE_ATTRIBUTES + mode = ATTRS while i and (curline[i-1] in ID_CHARS or ord(curline[i-1]) > 127): i -= 1 comp_start = curline[i:j] - if i and curline[i-1] == '.': + if i and curline[i-1] == '.': # Need object with attributes. hp.set_index("insert-%dc" % (len(curline)-(i-1))) comp_what = hp.get_expression() - if not comp_what or \ - (not evalfuncs and comp_what.find('(') != -1): + if (not comp_what or + (not evalfuncs and comp_what.find('(') != -1)): return None else: comp_what = "" @@ -163,7 +148,7 @@ def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): self.autocompletewindow = self._make_autocomplete_window() return not self.autocompletewindow.show_window( comp_lists, "insert-%dc" % len(comp_start), - complete, mode, userWantsWin) + complete, mode, wantwin) def fetch_completions(self, what, mode): """Return a pair of lists of completions for something. The first list @@ -185,7 +170,7 @@ def fetch_completions(self, what, mode): return rpcclt.remotecall("exec", "get_the_completion_list", (what, mode), {}) else: - if mode == COMPLETE_ATTRIBUTES: + if mode == ATTRS: if what == "": namespace = {**__main__.__builtins__.__dict__, **__main__.__dict__} @@ -207,7 +192,7 @@ def fetch_completions(self, what, mode): except: return [], [] - elif mode == COMPLETE_FILES: + elif mode == FILES: if what == "": what = "." try: diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index c24962527736..c69ab4a36836 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -6,7 +6,7 @@ from tkinter import * from tkinter.ttk import Frame, Scrollbar -from idlelib.autocomplete import COMPLETE_FILES, COMPLETE_ATTRIBUTES +from idlelib.autocomplete import FILES, ATTRS from idlelib.multicall import MC_SHIFT HIDE_VIRTUAL_EVENT_NAME = "<>" @@ -39,8 +39,7 @@ def __init__(self, widget): self.completions = None # A list with more completions, or None self.morecompletions = None - # The completion mode. Either autocomplete.COMPLETE_ATTRIBUTES or - # autocomplete.COMPLETE_FILES + # The completion mode, either autocomplete.ATTRS or .FILES. self.mode = None # The current completion start, on the text box (a string) self.start = None @@ -73,8 +72,8 @@ def _change_start(self, newstart): def _binary_search(self, s): """Find the first index in self.completions where completions[i] is - greater or equal to s, or the last index if there is no such - one.""" + greater or equal to s, or the last index if there is no such. + """ i = 0; j = len(self.completions) while j > i: m = (i + j) // 2 @@ -87,7 +86,8 @@ def _binary_search(self, s): def _complete_string(self, s): """Assuming that s is the prefix of a string in self.completions, return the longest string which is a prefix of all the strings which - s is a prefix of them. If s is not a prefix of a string, return s.""" + s is a prefix of them. If s is not a prefix of a string, return s. + """ first = self._binary_search(s) if self.completions[first][:len(s)] != s: # There is not even one completion which s is a prefix of. @@ -116,8 +116,10 @@ def _complete_string(self, s): return first_comp[:i] def _selection_changed(self): - """Should be called when the selection of the Listbox has changed. - Updates the Listbox display and calls _change_start.""" + """Call when the selection of the Listbox has changed. + + Updates the Listbox display and calls _change_start. + """ cursel = int(self.listbox.curselection()[0]) self.listbox.see(cursel) @@ -153,8 +155,10 @@ def _selection_changed(self): def show_window(self, comp_lists, index, complete, mode, userWantsWin): """Show the autocomplete list, bind events. - If complete is True, complete the text, and if there is exactly one - matching completion, don't open a list.""" + + If complete is True, complete the text, and if there is exactly + one matching completion, don't open a list. + """ # Handle the start we already have self.completions, self.morecompletions = comp_lists self.mode = mode @@ -300,7 +304,7 @@ def keypress_event(self, event): if keysym != "Tab": self.lastkey_was_tab = False if (len(keysym) == 1 or keysym in ("underscore", "BackSpace") - or (self.mode == COMPLETE_FILES and keysym in + or (self.mode == FILES and keysym in ("period", "minus"))) \ and not (state & ~MC_SHIFT): # Normal editing of text @@ -329,10 +333,10 @@ def keypress_event(self, event): self.hide_window() return 'break' - elif (self.mode == COMPLETE_ATTRIBUTES and keysym in + elif (self.mode == ATTRS and keysym in ("period", "space", "parenleft", "parenright", "bracketleft", "bracketright")) or \ - (self.mode == COMPLETE_FILES and keysym in + (self.mode == FILES and keysym in ("slash", "backslash", "quotedbl", "apostrophe")) \ and not (state & ~MC_SHIFT): # If start is a prefix of the selection, but is not '' when @@ -340,7 +344,7 @@ def keypress_event(self, event): # selected completion. Anyway, close the list. cursel = int(self.listbox.curselection()[0]) if self.completions[cursel][:len(self.start)] == self.start \ - and (self.mode == COMPLETE_ATTRIBUTES or self.start): + and (self.mode == ATTRS or self.start): self._change_start(self.completions[cursel]) self.hide_window() return None diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py index 6181b29ec250..2c478cd5c2a1 100644 --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -1,4 +1,4 @@ -"Test autocomplete, coverage 87%." +"Test autocomplete, coverage 93%." import unittest from unittest.mock import Mock, patch @@ -45,127 +45,177 @@ def setUp(self): def test_init(self): self.assertEqual(self.autocomplete.editwin, self.editor) + self.assertEqual(self.autocomplete.text, self.text) def test_make_autocomplete_window(self): testwin = self.autocomplete._make_autocomplete_window() self.assertIsInstance(testwin, acw.AutoCompleteWindow) def test_remove_autocomplete_window(self): - self.autocomplete.autocompletewindow = ( - self.autocomplete._make_autocomplete_window()) - self.autocomplete._remove_autocomplete_window() - self.assertIsNone(self.autocomplete.autocompletewindow) + acp = self.autocomplete + acp.autocompletewindow = m = Mock() + acp._remove_autocomplete_window() + m.hide_window.assert_called_once() + self.assertIsNone(acp.autocompletewindow) def test_force_open_completions_event(self): - # Test that force_open_completions_event calls _open_completions. - o_cs = Func() - self.autocomplete.open_completions = o_cs - self.autocomplete.force_open_completions_event('event') - self.assertEqual(o_cs.args, (True, False, True)) - - def test_try_open_completions_event(self): - Equal = self.assertEqual - autocomplete = self.autocomplete - trycompletions = self.autocomplete.try_open_completions_event - o_c_l = Func() - autocomplete._open_completions_later = o_c_l - - # _open_completions_later should not be called with no text in editor. - trycompletions('event') - Equal(o_c_l.args, None) - - # _open_completions_later should be called with COMPLETE_ATTRIBUTES (1). - self.text.insert('1.0', 're.') - trycompletions('event') - Equal(o_c_l.args, (False, False, False, 1)) - - # _open_completions_later should be called with COMPLETE_FILES (2). - self.text.delete('1.0', 'end') - self.text.insert('1.0', '"./Lib/') - trycompletions('event') - Equal(o_c_l.args, (False, False, False, 2)) + # Call _open_completions and break. + acp = self.autocomplete + open_c = Func() + acp.open_completions = open_c + self.assertEqual(acp.force_open_completions_event('event'), 'break') + self.assertEqual(open_c.args[0], ac.FORCE) def test_autocomplete_event(self): Equal = self.assertEqual - autocomplete = self.autocomplete + acp = self.autocomplete - # Test that the autocomplete event is ignored if user is pressing a - # modifier key in addition to the tab key. + # Result of autocomplete event: If modified tab, None. ev = Event(mc_state=True) - self.assertIsNone(autocomplete.autocomplete_event(ev)) + self.assertIsNone(acp.autocomplete_event(ev)) del ev.mc_state - # Test that tab after whitespace is ignored. + # If tab after whitespace, None. self.text.insert('1.0', ' """Docstring.\n ') - self.assertIsNone(autocomplete.autocomplete_event(ev)) + self.assertIsNone(acp.autocomplete_event(ev)) self.text.delete('1.0', 'end') - # If autocomplete window is open, complete() method is called. + # If active autocomplete window, complete() and 'break'. self.text.insert('1.0', 're.') - # This must call autocomplete._make_autocomplete_window(). - Equal(self.autocomplete.autocomplete_event(ev), 'break') - - # If autocomplete window is not active or does not exist, - # open_completions is called. Return depends on its return. - autocomplete._remove_autocomplete_window() - o_cs = Func() # .result = None. - autocomplete.open_completions = o_cs - Equal(self.autocomplete.autocomplete_event(ev), None) - Equal(o_cs.args, (False, True, True)) - o_cs.result = True - Equal(self.autocomplete.autocomplete_event(ev), 'break') - Equal(o_cs.args, (False, True, True)) - - def test_open_completions_later(self): - # Test that autocomplete._delayed_completion_id is set. + acp.autocompletewindow = mock = Mock() + mock.is_active = Mock(return_value=True) + Equal(acp.autocomplete_event(ev), 'break') + mock.complete.assert_called_once() + acp.autocompletewindow = None + + # If no active autocomplete window, open_completions(), None/break. + open_c = Func(result=False) + acp.open_completions = open_c + Equal(acp.autocomplete_event(ev), None) + Equal(open_c.args[0], ac.TAB) + open_c.result = True + Equal(acp.autocomplete_event(ev), 'break') + Equal(open_c.args[0], ac.TAB) + + def test_try_open_completions_event(self): + Equal = self.assertEqual + text = self.text acp = self.autocomplete + trycompletions = acp.try_open_completions_event + after = Func(result='after1') + acp.text.after = after + + # If no text or trigger, after not called. + trycompletions() + Equal(after.called, 0) + text.insert('1.0', 're') + trycompletions() + Equal(after.called, 0) + + # Attribute needed, no existing callback. + text.insert('insert', ' re.') acp._delayed_completion_id = None - acp._open_completions_later(False, False, False, ac.COMPLETE_ATTRIBUTES) + trycompletions() + Equal(acp._delayed_completion_index, text.index('insert')) + Equal(after.args, + (acp.popupwait, acp._delayed_open_completions, ac.TRY_A)) cb1 = acp._delayed_completion_id - self.assertTrue(cb1.startswith('after')) - - # Test that cb1 is cancelled and cb2 is new. - acp._open_completions_later(False, False, False, ac.COMPLETE_FILES) - self.assertNotIn(cb1, self.root.tk.call('after', 'info')) - cb2 = acp._delayed_completion_id - self.assertTrue(cb2.startswith('after') and cb2 != cb1) - self.text.after_cancel(cb2) + Equal(cb1, 'after1') + + # File needed, existing callback cancelled. + text.insert('insert', ' "./Lib/') + after.result = 'after2' + cancel = Func() + acp.text.after_cancel = cancel + trycompletions() + Equal(acp._delayed_completion_index, text.index('insert')) + Equal(cancel.args, (cb1,)) + Equal(after.args, + (acp.popupwait, acp._delayed_open_completions, ac.TRY_F)) + Equal(acp._delayed_completion_id, 'after2') def test_delayed_open_completions(self): - # Test that autocomplete._delayed_completion_id set to None - # and that open_completions is not called if the index is not - # equal to _delayed_completion_index. + Equal = self.assertEqual acp = self.autocomplete - acp.open_completions = Func() + open_c = Func() + acp.open_completions = open_c + self.text.insert('1.0', '"dict.') + + # Set autocomplete._delayed_completion_id to None. + # Text index changed, don't call open_completions. acp._delayed_completion_id = 'after' acp._delayed_completion_index = self.text.index('insert+1c') - acp._delayed_open_completions(1, 2, 3) + acp._delayed_open_completions('dummy') self.assertIsNone(acp._delayed_completion_id) - self.assertEqual(acp.open_completions.called, 0) + Equal(open_c.called, 0) - # Test that open_completions is called if indexes match. + # Text index unchanged, call open_completions. acp._delayed_completion_index = self.text.index('insert') - acp._delayed_open_completions(1, 2, 3, ac.COMPLETE_FILES) - self.assertEqual(acp.open_completions.args, (1, 2, 3, 2)) + acp._delayed_open_completions((1, 2, 3, ac.FILES)) + self.assertEqual(open_c.args[0], (1, 2, 3, ac.FILES)) + + def test_oc_cancel_comment(self): + none = self.assertIsNone + acp = self.autocomplete + + # Comment is in neither code or string. + acp._delayed_completion_id = 'after' + after = Func(result='after') + acp.text.after_cancel = after + self.text.insert(1.0, '# comment') + none(acp.open_completions(ac.TAB)) # From 'else' after 'elif'. + none(acp._delayed_completion_id) + + def test_oc_no_list(self): + acp = self.autocomplete + fetch = Func(result=([],[])) + acp.fetch_completions = fetch + self.text.insert('1.0', 'object') + self.assertIsNone(acp.open_completions(ac.TAB)) + self.text.insert('insert', '.') + self.assertIsNone(acp.open_completions(ac.TAB)) + self.assertEqual(fetch.called, 2) + + + def test_open_completions_none(self): + # Test other two None returns. + none = self.assertIsNone + acp = self.autocomplete + + # No object for attributes or need call not allowed. + self.text.insert(1.0, '.') + none(acp.open_completions(ac.TAB)) + self.text.insert('insert', ' int().') + none(acp.open_completions(ac.TAB)) + + # Blank or quote trigger 'if complete ...'. + self.text.delete(1.0, 'end') + self.assertFalse(acp.open_completions(ac.TAB)) + self.text.insert('1.0', '"') + self.assertFalse(acp.open_completions(ac.TAB)) + self.text.delete('1.0', 'end') + + class dummy_acw(): + __init__ = Func() + show_window = Func(result=False) + hide_window = Func() def test_open_completions(self): - # Test completions of files and attributes as well as non-completion - # of errors. - self.text.insert('1.0', 'pr') - self.assertTrue(self.autocomplete.open_completions(False, True, True)) + # Test completions of files and attributes. + acp = self.autocomplete + fetch = Func(result=(['tem'],['tem', '_tem'])) + acp.fetch_completions = fetch + def make_acw(): return self.dummy_acw() + acp._make_autocomplete_window = make_acw + + self.text.insert('1.0', 'int.') + acp.open_completions(ac.TAB) + self.assertIsInstance(acp.autocompletewindow, self.dummy_acw) self.text.delete('1.0', 'end') # Test files. self.text.insert('1.0', '"t') - #self.assertTrue(self.autocomplete.open_completions(False, True, True)) - self.text.delete('1.0', 'end') - - # Test with blank will fail. - self.assertFalse(self.autocomplete.open_completions(False, True, True)) - - # Test with only string quote will fail. - self.text.insert('1.0', '"') - self.assertFalse(self.autocomplete.open_completions(False, True, True)) + self.assertTrue(acp.open_completions(ac.TAB)) self.text.delete('1.0', 'end') def test_fetch_completions(self): @@ -174,21 +224,21 @@ def test_fetch_completions(self): # a small list containing non-private variables. # For file completion, a large list containing all files in the path, # and a small list containing files that do not start with '.'. - autocomplete = self.autocomplete - small, large = self.autocomplete.fetch_completions( - '', ac.COMPLETE_ATTRIBUTES) + acp = self.autocomplete + small, large = acp.fetch_completions( + '', ac.ATTRS) if __main__.__file__ != ac.__file__: self.assertNotIn('AutoComplete', small) # See issue 36405. # Test attributes - s, b = autocomplete.fetch_completions('', ac.COMPLETE_ATTRIBUTES) + s, b = acp.fetch_completions('', ac.ATTRS) self.assertLess(len(small), len(large)) self.assertTrue(all(filter(lambda x: x.startswith('_'), s))) self.assertTrue(any(filter(lambda x: x.startswith('_'), b))) # Test smalll should respect to __all__. with patch.dict('__main__.__dict__', {'__all__': ['a', 'b']}): - s, b = autocomplete.fetch_completions('', ac.COMPLETE_ATTRIBUTES) + s, b = acp.fetch_completions('', ac.ATTRS) self.assertEqual(s, ['a', 'b']) self.assertIn('__name__', b) # From __main__.__dict__ self.assertIn('sum', b) # From __main__.__builtins__.__dict__ @@ -197,7 +247,7 @@ def test_fetch_completions(self): mock = Mock() mock._private = Mock() with patch.dict('__main__.__dict__', {'foo': mock}): - s, b = autocomplete.fetch_completions('foo', ac.COMPLETE_ATTRIBUTES) + s, b = acp.fetch_completions('foo', ac.ATTRS) self.assertNotIn('_private', s) self.assertIn('_private', b) self.assertEqual(s, [i for i in sorted(dir(mock)) if i[:1] != '_']) @@ -211,36 +261,36 @@ def _listdir(path): return ['monty', 'python', '.hidden'] with patch.object(os, 'listdir', _listdir): - s, b = autocomplete.fetch_completions('', ac.COMPLETE_FILES) + s, b = acp.fetch_completions('', ac.FILES) self.assertEqual(s, ['bar', 'foo']) self.assertEqual(b, ['.hidden', 'bar', 'foo']) - s, b = autocomplete.fetch_completions('~', ac.COMPLETE_FILES) + s, b = acp.fetch_completions('~', ac.FILES) self.assertEqual(s, ['monty', 'python']) self.assertEqual(b, ['.hidden', 'monty', 'python']) def test_get_entity(self): # Test that a name is in the namespace of sys.modules and # __main__.__dict__. - autocomplete = self.autocomplete + acp = self.autocomplete Equal = self.assertEqual - Equal(self.autocomplete.get_entity('int'), int) + Equal(acp.get_entity('int'), int) # Test name from sys.modules. mock = Mock() with patch.dict('sys.modules', {'tempfile': mock}): - Equal(autocomplete.get_entity('tempfile'), mock) + Equal(acp.get_entity('tempfile'), mock) # Test name from __main__.__dict__. di = {'foo': 10, 'bar': 20} with patch.dict('__main__.__dict__', {'d': di}): - Equal(autocomplete.get_entity('d'), di) + Equal(acp.get_entity('d'), di) # Test name not in namespace. with patch.dict('__main__.__dict__', {}): with self.assertRaises(NameError): - autocomplete.get_entity('not_exist') + acp.get_entity('not_exist') if __name__ == '__main__': diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst new file mode 100644 index 000000000000..a44fd3b59b4f --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst @@ -0,0 +1 @@ +IDLE - Refactor autocompete and improve testing. From webhook-mailer at python.org Sun Aug 4 20:08:20 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 05 Aug 2019 00:08:20 -0000 Subject: [Python-checkins] bpo-36419: IDLE - Refactor autocompete and improve testing. (GH-15121) Message-ID: https://github.com/python/cpython/commit/5349f8cd784220fc6599830c56d3f0614de2b8cb commit: 5349f8cd784220fc6599830c56d3f0614de2b8cb branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-04T17:08:16-07:00 summary: bpo-36419: IDLE - Refactor autocompete and improve testing. (GH-15121) (cherry picked from commit 1213123005d9f94bb5027c0a5256ea4d3e97b61d) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst M Lib/idlelib/autocomplete.py M Lib/idlelib/autocomplete_w.py M Lib/idlelib/idle_test/test_autocomplete.py diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index e20b757d8710..c623d45a1534 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -8,42 +8,45 @@ import string import sys -# These constants represent the two different types of completions. -# They must be defined here so autocomple_w can import them. -COMPLETE_ATTRIBUTES, COMPLETE_FILES = range(1, 2+1) - +# Two types of completions; defined here for autocomplete_w import below. +ATTRS, FILES = 0, 1 from idlelib import autocomplete_w from idlelib.config import idleConf from idlelib.hyperparser import HyperParser +# Tuples passed to open_completions. +# EvalFunc, Complete, WantWin, Mode +FORCE = True, False, True, None # Control-Space. +TAB = False, True, True, None # Tab. +TRY_A = False, False, False, ATTRS # '.' for attributes. +TRY_F = False, False, False, FILES # '/' in quotes for file name. + # This string includes all chars that may be in an identifier. # TODO Update this here and elsewhere. ID_CHARS = string.ascii_letters + string.digits + "_" -SEPS = os.sep -if os.altsep: # e.g. '/' on Windows... - SEPS += os.altsep - +SEPS = f"{os.sep}{os.altsep if os.altsep else ''}" +TRIGGERS = f".{SEPS}" class AutoComplete: def __init__(self, editwin=None): self.editwin = editwin - if editwin is not None: # not in subprocess or test + if editwin is not None: # not in subprocess or no-gui test self.text = editwin.text - self.autocompletewindow = None - # id of delayed call, and the index of the text insert when - # the delayed call was issued. If _delayed_completion_id is - # None, there is no delayed call. - self._delayed_completion_id = None - self._delayed_completion_index = None + self.autocompletewindow = None + # id of delayed call, and the index of the text insert when + # the delayed call was issued. If _delayed_completion_id is + # None, there is no delayed call. + self._delayed_completion_id = None + self._delayed_completion_index = None @classmethod def reload(cls): cls.popupwait = idleConf.GetOption( "extensions", "AutoComplete", "popupwait", type="int", default=0) - def _make_autocomplete_window(self): + def _make_autocomplete_window(self): # Makes mocking easier. return autocomplete_w.AutoCompleteWindow(self.text) def _remove_autocomplete_window(self, event=None): @@ -52,30 +55,12 @@ def _remove_autocomplete_window(self, event=None): self.autocompletewindow = None def force_open_completions_event(self, event): - """Happens when the user really wants to open a completion list, even - if a function call is needed. - """ - self.open_completions(True, False, True) + "(^space) Open completion list, even if a function call is needed." + self.open_completions(FORCE) return "break" - def try_open_completions_event(self, event): - """Happens when it would be nice to open a completion list, but not - really necessary, for example after a dot, so function - calls won't be made. - """ - lastchar = self.text.get("insert-1c") - if lastchar == ".": - self._open_completions_later(False, False, False, - COMPLETE_ATTRIBUTES) - elif lastchar in SEPS: - self._open_completions_later(False, False, False, - COMPLETE_FILES) - def autocomplete_event(self, event): - """Happens when the user wants to complete his word, and if necessary, - open a completion list after that (if there is more than one - completion) - """ + "(tab) Complete word or open list if multiple options." if hasattr(event, "mc_state") and event.mc_state or\ not self.text.get("insert linestart", "insert").strip(): # A modifier was pressed along with the tab or @@ -85,34 +70,34 @@ def autocomplete_event(self, event): self.autocompletewindow.complete() return "break" else: - opened = self.open_completions(False, True, True) + opened = self.open_completions(TAB) return "break" if opened else None - def _open_completions_later(self, *args): - self._delayed_completion_index = self.text.index("insert") - if self._delayed_completion_id is not None: - self.text.after_cancel(self._delayed_completion_id) - self._delayed_completion_id = \ - self.text.after(self.popupwait, self._delayed_open_completions, - *args) - - def _delayed_open_completions(self, *args): + def try_open_completions_event(self, event=None): + "(./) Open completion list after pause with no movement." + lastchar = self.text.get("insert-1c") + if lastchar in TRIGGERS: + args = TRY_A if lastchar == "." else TRY_F + self._delayed_completion_index = self.text.index("insert") + if self._delayed_completion_id is not None: + self.text.after_cancel(self._delayed_completion_id) + self._delayed_completion_id = self.text.after( + self.popupwait, self._delayed_open_completions, args) + + def _delayed_open_completions(self, args): + "Call open_completions if index unchanged." self._delayed_completion_id = None if self.text.index("insert") == self._delayed_completion_index: - self.open_completions(*args) + self.open_completions(args) - def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): + def open_completions(self, args): """Find the completions and create the AutoCompleteWindow. Return True if successful (no syntax error or so found). If complete is True, then if there's nothing to complete and no start of completion, won't open completions and return False. If mode is given, will open a completion list only in this mode. - - Action Function Eval Complete WantWin Mode - ^space force_open_completions True, False, True no - . or / try_open_completions False, False, False yes - tab autocomplete False, True, True no """ + evalfuncs, complete, wantwin, mode = args # Cancel another delayed call, if it exists. if self._delayed_completion_id is not None: self.text.after_cancel(self._delayed_completion_id) @@ -121,14 +106,14 @@ def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): hp = HyperParser(self.editwin, "insert") curline = self.text.get("insert linestart", "insert") i = j = len(curline) - if hp.is_in_string() and (not mode or mode==COMPLETE_FILES): + if hp.is_in_string() and (not mode or mode==FILES): # Find the beginning of the string. # fetch_completions will look at the file system to determine # whether the string value constitutes an actual file name # XXX could consider raw strings here and unescape the string # value if it's not raw. self._remove_autocomplete_window() - mode = COMPLETE_FILES + mode = FILES # Find last separator or string start while i and curline[i-1] not in "'\"" + SEPS: i -= 1 @@ -138,17 +123,17 @@ def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): while i and curline[i-1] not in "'\"": i -= 1 comp_what = curline[i:j] - elif hp.is_in_code() and (not mode or mode==COMPLETE_ATTRIBUTES): + elif hp.is_in_code() and (not mode or mode==ATTRS): self._remove_autocomplete_window() - mode = COMPLETE_ATTRIBUTES + mode = ATTRS while i and (curline[i-1] in ID_CHARS or ord(curline[i-1]) > 127): i -= 1 comp_start = curline[i:j] - if i and curline[i-1] == '.': + if i and curline[i-1] == '.': # Need object with attributes. hp.set_index("insert-%dc" % (len(curline)-(i-1))) comp_what = hp.get_expression() - if not comp_what or \ - (not evalfuncs and comp_what.find('(') != -1): + if (not comp_what or + (not evalfuncs and comp_what.find('(') != -1)): return None else: comp_what = "" @@ -163,7 +148,7 @@ def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): self.autocompletewindow = self._make_autocomplete_window() return not self.autocompletewindow.show_window( comp_lists, "insert-%dc" % len(comp_start), - complete, mode, userWantsWin) + complete, mode, wantwin) def fetch_completions(self, what, mode): """Return a pair of lists of completions for something. The first list @@ -185,7 +170,7 @@ def fetch_completions(self, what, mode): return rpcclt.remotecall("exec", "get_the_completion_list", (what, mode), {}) else: - if mode == COMPLETE_ATTRIBUTES: + if mode == ATTRS: if what == "": namespace = {**__main__.__builtins__.__dict__, **__main__.__dict__} @@ -207,7 +192,7 @@ def fetch_completions(self, what, mode): except: return [], [] - elif mode == COMPLETE_FILES: + elif mode == FILES: if what == "": what = "." try: diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index c24962527736..c69ab4a36836 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -6,7 +6,7 @@ from tkinter import * from tkinter.ttk import Frame, Scrollbar -from idlelib.autocomplete import COMPLETE_FILES, COMPLETE_ATTRIBUTES +from idlelib.autocomplete import FILES, ATTRS from idlelib.multicall import MC_SHIFT HIDE_VIRTUAL_EVENT_NAME = "<>" @@ -39,8 +39,7 @@ def __init__(self, widget): self.completions = None # A list with more completions, or None self.morecompletions = None - # The completion mode. Either autocomplete.COMPLETE_ATTRIBUTES or - # autocomplete.COMPLETE_FILES + # The completion mode, either autocomplete.ATTRS or .FILES. self.mode = None # The current completion start, on the text box (a string) self.start = None @@ -73,8 +72,8 @@ def _change_start(self, newstart): def _binary_search(self, s): """Find the first index in self.completions where completions[i] is - greater or equal to s, or the last index if there is no such - one.""" + greater or equal to s, or the last index if there is no such. + """ i = 0; j = len(self.completions) while j > i: m = (i + j) // 2 @@ -87,7 +86,8 @@ def _binary_search(self, s): def _complete_string(self, s): """Assuming that s is the prefix of a string in self.completions, return the longest string which is a prefix of all the strings which - s is a prefix of them. If s is not a prefix of a string, return s.""" + s is a prefix of them. If s is not a prefix of a string, return s. + """ first = self._binary_search(s) if self.completions[first][:len(s)] != s: # There is not even one completion which s is a prefix of. @@ -116,8 +116,10 @@ def _complete_string(self, s): return first_comp[:i] def _selection_changed(self): - """Should be called when the selection of the Listbox has changed. - Updates the Listbox display and calls _change_start.""" + """Call when the selection of the Listbox has changed. + + Updates the Listbox display and calls _change_start. + """ cursel = int(self.listbox.curselection()[0]) self.listbox.see(cursel) @@ -153,8 +155,10 @@ def _selection_changed(self): def show_window(self, comp_lists, index, complete, mode, userWantsWin): """Show the autocomplete list, bind events. - If complete is True, complete the text, and if there is exactly one - matching completion, don't open a list.""" + + If complete is True, complete the text, and if there is exactly + one matching completion, don't open a list. + """ # Handle the start we already have self.completions, self.morecompletions = comp_lists self.mode = mode @@ -300,7 +304,7 @@ def keypress_event(self, event): if keysym != "Tab": self.lastkey_was_tab = False if (len(keysym) == 1 or keysym in ("underscore", "BackSpace") - or (self.mode == COMPLETE_FILES and keysym in + or (self.mode == FILES and keysym in ("period", "minus"))) \ and not (state & ~MC_SHIFT): # Normal editing of text @@ -329,10 +333,10 @@ def keypress_event(self, event): self.hide_window() return 'break' - elif (self.mode == COMPLETE_ATTRIBUTES and keysym in + elif (self.mode == ATTRS and keysym in ("period", "space", "parenleft", "parenright", "bracketleft", "bracketright")) or \ - (self.mode == COMPLETE_FILES and keysym in + (self.mode == FILES and keysym in ("slash", "backslash", "quotedbl", "apostrophe")) \ and not (state & ~MC_SHIFT): # If start is a prefix of the selection, but is not '' when @@ -340,7 +344,7 @@ def keypress_event(self, event): # selected completion. Anyway, close the list. cursel = int(self.listbox.curselection()[0]) if self.completions[cursel][:len(self.start)] == self.start \ - and (self.mode == COMPLETE_ATTRIBUTES or self.start): + and (self.mode == ATTRS or self.start): self._change_start(self.completions[cursel]) self.hide_window() return None diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py index 6181b29ec250..2c478cd5c2a1 100644 --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -1,4 +1,4 @@ -"Test autocomplete, coverage 87%." +"Test autocomplete, coverage 93%." import unittest from unittest.mock import Mock, patch @@ -45,127 +45,177 @@ def setUp(self): def test_init(self): self.assertEqual(self.autocomplete.editwin, self.editor) + self.assertEqual(self.autocomplete.text, self.text) def test_make_autocomplete_window(self): testwin = self.autocomplete._make_autocomplete_window() self.assertIsInstance(testwin, acw.AutoCompleteWindow) def test_remove_autocomplete_window(self): - self.autocomplete.autocompletewindow = ( - self.autocomplete._make_autocomplete_window()) - self.autocomplete._remove_autocomplete_window() - self.assertIsNone(self.autocomplete.autocompletewindow) + acp = self.autocomplete + acp.autocompletewindow = m = Mock() + acp._remove_autocomplete_window() + m.hide_window.assert_called_once() + self.assertIsNone(acp.autocompletewindow) def test_force_open_completions_event(self): - # Test that force_open_completions_event calls _open_completions. - o_cs = Func() - self.autocomplete.open_completions = o_cs - self.autocomplete.force_open_completions_event('event') - self.assertEqual(o_cs.args, (True, False, True)) - - def test_try_open_completions_event(self): - Equal = self.assertEqual - autocomplete = self.autocomplete - trycompletions = self.autocomplete.try_open_completions_event - o_c_l = Func() - autocomplete._open_completions_later = o_c_l - - # _open_completions_later should not be called with no text in editor. - trycompletions('event') - Equal(o_c_l.args, None) - - # _open_completions_later should be called with COMPLETE_ATTRIBUTES (1). - self.text.insert('1.0', 're.') - trycompletions('event') - Equal(o_c_l.args, (False, False, False, 1)) - - # _open_completions_later should be called with COMPLETE_FILES (2). - self.text.delete('1.0', 'end') - self.text.insert('1.0', '"./Lib/') - trycompletions('event') - Equal(o_c_l.args, (False, False, False, 2)) + # Call _open_completions and break. + acp = self.autocomplete + open_c = Func() + acp.open_completions = open_c + self.assertEqual(acp.force_open_completions_event('event'), 'break') + self.assertEqual(open_c.args[0], ac.FORCE) def test_autocomplete_event(self): Equal = self.assertEqual - autocomplete = self.autocomplete + acp = self.autocomplete - # Test that the autocomplete event is ignored if user is pressing a - # modifier key in addition to the tab key. + # Result of autocomplete event: If modified tab, None. ev = Event(mc_state=True) - self.assertIsNone(autocomplete.autocomplete_event(ev)) + self.assertIsNone(acp.autocomplete_event(ev)) del ev.mc_state - # Test that tab after whitespace is ignored. + # If tab after whitespace, None. self.text.insert('1.0', ' """Docstring.\n ') - self.assertIsNone(autocomplete.autocomplete_event(ev)) + self.assertIsNone(acp.autocomplete_event(ev)) self.text.delete('1.0', 'end') - # If autocomplete window is open, complete() method is called. + # If active autocomplete window, complete() and 'break'. self.text.insert('1.0', 're.') - # This must call autocomplete._make_autocomplete_window(). - Equal(self.autocomplete.autocomplete_event(ev), 'break') - - # If autocomplete window is not active or does not exist, - # open_completions is called. Return depends on its return. - autocomplete._remove_autocomplete_window() - o_cs = Func() # .result = None. - autocomplete.open_completions = o_cs - Equal(self.autocomplete.autocomplete_event(ev), None) - Equal(o_cs.args, (False, True, True)) - o_cs.result = True - Equal(self.autocomplete.autocomplete_event(ev), 'break') - Equal(o_cs.args, (False, True, True)) - - def test_open_completions_later(self): - # Test that autocomplete._delayed_completion_id is set. + acp.autocompletewindow = mock = Mock() + mock.is_active = Mock(return_value=True) + Equal(acp.autocomplete_event(ev), 'break') + mock.complete.assert_called_once() + acp.autocompletewindow = None + + # If no active autocomplete window, open_completions(), None/break. + open_c = Func(result=False) + acp.open_completions = open_c + Equal(acp.autocomplete_event(ev), None) + Equal(open_c.args[0], ac.TAB) + open_c.result = True + Equal(acp.autocomplete_event(ev), 'break') + Equal(open_c.args[0], ac.TAB) + + def test_try_open_completions_event(self): + Equal = self.assertEqual + text = self.text acp = self.autocomplete + trycompletions = acp.try_open_completions_event + after = Func(result='after1') + acp.text.after = after + + # If no text or trigger, after not called. + trycompletions() + Equal(after.called, 0) + text.insert('1.0', 're') + trycompletions() + Equal(after.called, 0) + + # Attribute needed, no existing callback. + text.insert('insert', ' re.') acp._delayed_completion_id = None - acp._open_completions_later(False, False, False, ac.COMPLETE_ATTRIBUTES) + trycompletions() + Equal(acp._delayed_completion_index, text.index('insert')) + Equal(after.args, + (acp.popupwait, acp._delayed_open_completions, ac.TRY_A)) cb1 = acp._delayed_completion_id - self.assertTrue(cb1.startswith('after')) - - # Test that cb1 is cancelled and cb2 is new. - acp._open_completions_later(False, False, False, ac.COMPLETE_FILES) - self.assertNotIn(cb1, self.root.tk.call('after', 'info')) - cb2 = acp._delayed_completion_id - self.assertTrue(cb2.startswith('after') and cb2 != cb1) - self.text.after_cancel(cb2) + Equal(cb1, 'after1') + + # File needed, existing callback cancelled. + text.insert('insert', ' "./Lib/') + after.result = 'after2' + cancel = Func() + acp.text.after_cancel = cancel + trycompletions() + Equal(acp._delayed_completion_index, text.index('insert')) + Equal(cancel.args, (cb1,)) + Equal(after.args, + (acp.popupwait, acp._delayed_open_completions, ac.TRY_F)) + Equal(acp._delayed_completion_id, 'after2') def test_delayed_open_completions(self): - # Test that autocomplete._delayed_completion_id set to None - # and that open_completions is not called if the index is not - # equal to _delayed_completion_index. + Equal = self.assertEqual acp = self.autocomplete - acp.open_completions = Func() + open_c = Func() + acp.open_completions = open_c + self.text.insert('1.0', '"dict.') + + # Set autocomplete._delayed_completion_id to None. + # Text index changed, don't call open_completions. acp._delayed_completion_id = 'after' acp._delayed_completion_index = self.text.index('insert+1c') - acp._delayed_open_completions(1, 2, 3) + acp._delayed_open_completions('dummy') self.assertIsNone(acp._delayed_completion_id) - self.assertEqual(acp.open_completions.called, 0) + Equal(open_c.called, 0) - # Test that open_completions is called if indexes match. + # Text index unchanged, call open_completions. acp._delayed_completion_index = self.text.index('insert') - acp._delayed_open_completions(1, 2, 3, ac.COMPLETE_FILES) - self.assertEqual(acp.open_completions.args, (1, 2, 3, 2)) + acp._delayed_open_completions((1, 2, 3, ac.FILES)) + self.assertEqual(open_c.args[0], (1, 2, 3, ac.FILES)) + + def test_oc_cancel_comment(self): + none = self.assertIsNone + acp = self.autocomplete + + # Comment is in neither code or string. + acp._delayed_completion_id = 'after' + after = Func(result='after') + acp.text.after_cancel = after + self.text.insert(1.0, '# comment') + none(acp.open_completions(ac.TAB)) # From 'else' after 'elif'. + none(acp._delayed_completion_id) + + def test_oc_no_list(self): + acp = self.autocomplete + fetch = Func(result=([],[])) + acp.fetch_completions = fetch + self.text.insert('1.0', 'object') + self.assertIsNone(acp.open_completions(ac.TAB)) + self.text.insert('insert', '.') + self.assertIsNone(acp.open_completions(ac.TAB)) + self.assertEqual(fetch.called, 2) + + + def test_open_completions_none(self): + # Test other two None returns. + none = self.assertIsNone + acp = self.autocomplete + + # No object for attributes or need call not allowed. + self.text.insert(1.0, '.') + none(acp.open_completions(ac.TAB)) + self.text.insert('insert', ' int().') + none(acp.open_completions(ac.TAB)) + + # Blank or quote trigger 'if complete ...'. + self.text.delete(1.0, 'end') + self.assertFalse(acp.open_completions(ac.TAB)) + self.text.insert('1.0', '"') + self.assertFalse(acp.open_completions(ac.TAB)) + self.text.delete('1.0', 'end') + + class dummy_acw(): + __init__ = Func() + show_window = Func(result=False) + hide_window = Func() def test_open_completions(self): - # Test completions of files and attributes as well as non-completion - # of errors. - self.text.insert('1.0', 'pr') - self.assertTrue(self.autocomplete.open_completions(False, True, True)) + # Test completions of files and attributes. + acp = self.autocomplete + fetch = Func(result=(['tem'],['tem', '_tem'])) + acp.fetch_completions = fetch + def make_acw(): return self.dummy_acw() + acp._make_autocomplete_window = make_acw + + self.text.insert('1.0', 'int.') + acp.open_completions(ac.TAB) + self.assertIsInstance(acp.autocompletewindow, self.dummy_acw) self.text.delete('1.0', 'end') # Test files. self.text.insert('1.0', '"t') - #self.assertTrue(self.autocomplete.open_completions(False, True, True)) - self.text.delete('1.0', 'end') - - # Test with blank will fail. - self.assertFalse(self.autocomplete.open_completions(False, True, True)) - - # Test with only string quote will fail. - self.text.insert('1.0', '"') - self.assertFalse(self.autocomplete.open_completions(False, True, True)) + self.assertTrue(acp.open_completions(ac.TAB)) self.text.delete('1.0', 'end') def test_fetch_completions(self): @@ -174,21 +224,21 @@ def test_fetch_completions(self): # a small list containing non-private variables. # For file completion, a large list containing all files in the path, # and a small list containing files that do not start with '.'. - autocomplete = self.autocomplete - small, large = self.autocomplete.fetch_completions( - '', ac.COMPLETE_ATTRIBUTES) + acp = self.autocomplete + small, large = acp.fetch_completions( + '', ac.ATTRS) if __main__.__file__ != ac.__file__: self.assertNotIn('AutoComplete', small) # See issue 36405. # Test attributes - s, b = autocomplete.fetch_completions('', ac.COMPLETE_ATTRIBUTES) + s, b = acp.fetch_completions('', ac.ATTRS) self.assertLess(len(small), len(large)) self.assertTrue(all(filter(lambda x: x.startswith('_'), s))) self.assertTrue(any(filter(lambda x: x.startswith('_'), b))) # Test smalll should respect to __all__. with patch.dict('__main__.__dict__', {'__all__': ['a', 'b']}): - s, b = autocomplete.fetch_completions('', ac.COMPLETE_ATTRIBUTES) + s, b = acp.fetch_completions('', ac.ATTRS) self.assertEqual(s, ['a', 'b']) self.assertIn('__name__', b) # From __main__.__dict__ self.assertIn('sum', b) # From __main__.__builtins__.__dict__ @@ -197,7 +247,7 @@ def test_fetch_completions(self): mock = Mock() mock._private = Mock() with patch.dict('__main__.__dict__', {'foo': mock}): - s, b = autocomplete.fetch_completions('foo', ac.COMPLETE_ATTRIBUTES) + s, b = acp.fetch_completions('foo', ac.ATTRS) self.assertNotIn('_private', s) self.assertIn('_private', b) self.assertEqual(s, [i for i in sorted(dir(mock)) if i[:1] != '_']) @@ -211,36 +261,36 @@ def _listdir(path): return ['monty', 'python', '.hidden'] with patch.object(os, 'listdir', _listdir): - s, b = autocomplete.fetch_completions('', ac.COMPLETE_FILES) + s, b = acp.fetch_completions('', ac.FILES) self.assertEqual(s, ['bar', 'foo']) self.assertEqual(b, ['.hidden', 'bar', 'foo']) - s, b = autocomplete.fetch_completions('~', ac.COMPLETE_FILES) + s, b = acp.fetch_completions('~', ac.FILES) self.assertEqual(s, ['monty', 'python']) self.assertEqual(b, ['.hidden', 'monty', 'python']) def test_get_entity(self): # Test that a name is in the namespace of sys.modules and # __main__.__dict__. - autocomplete = self.autocomplete + acp = self.autocomplete Equal = self.assertEqual - Equal(self.autocomplete.get_entity('int'), int) + Equal(acp.get_entity('int'), int) # Test name from sys.modules. mock = Mock() with patch.dict('sys.modules', {'tempfile': mock}): - Equal(autocomplete.get_entity('tempfile'), mock) + Equal(acp.get_entity('tempfile'), mock) # Test name from __main__.__dict__. di = {'foo': 10, 'bar': 20} with patch.dict('__main__.__dict__', {'d': di}): - Equal(autocomplete.get_entity('d'), di) + Equal(acp.get_entity('d'), di) # Test name not in namespace. with patch.dict('__main__.__dict__', {}): with self.assertRaises(NameError): - autocomplete.get_entity('not_exist') + acp.get_entity('not_exist') if __name__ == '__main__': diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst new file mode 100644 index 000000000000..a44fd3b59b4f --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst @@ -0,0 +1 @@ +IDLE - Refactor autocompete and improve testing. From webhook-mailer at python.org Sun Aug 4 20:09:40 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 05 Aug 2019 00:09:40 -0000 Subject: [Python-checkins] bpo-36419: IDLE - Refactor autocompete and improve testing. (GH-15121) Message-ID: https://github.com/python/cpython/commit/4969192f99046bc0f6453185082c00f7a6e132ec commit: 4969192f99046bc0f6453185082c00f7a6e132ec branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-04T17:09:36-07:00 summary: bpo-36419: IDLE - Refactor autocompete and improve testing. (GH-15121) (cherry picked from commit 1213123005d9f94bb5027c0a5256ea4d3e97b61d) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst M Lib/idlelib/autocomplete.py M Lib/idlelib/autocomplete_w.py M Lib/idlelib/idle_test/test_autocomplete.py diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index e20b757d8710..c623d45a1534 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -8,42 +8,45 @@ import string import sys -# These constants represent the two different types of completions. -# They must be defined here so autocomple_w can import them. -COMPLETE_ATTRIBUTES, COMPLETE_FILES = range(1, 2+1) - +# Two types of completions; defined here for autocomplete_w import below. +ATTRS, FILES = 0, 1 from idlelib import autocomplete_w from idlelib.config import idleConf from idlelib.hyperparser import HyperParser +# Tuples passed to open_completions. +# EvalFunc, Complete, WantWin, Mode +FORCE = True, False, True, None # Control-Space. +TAB = False, True, True, None # Tab. +TRY_A = False, False, False, ATTRS # '.' for attributes. +TRY_F = False, False, False, FILES # '/' in quotes for file name. + # This string includes all chars that may be in an identifier. # TODO Update this here and elsewhere. ID_CHARS = string.ascii_letters + string.digits + "_" -SEPS = os.sep -if os.altsep: # e.g. '/' on Windows... - SEPS += os.altsep - +SEPS = f"{os.sep}{os.altsep if os.altsep else ''}" +TRIGGERS = f".{SEPS}" class AutoComplete: def __init__(self, editwin=None): self.editwin = editwin - if editwin is not None: # not in subprocess or test + if editwin is not None: # not in subprocess or no-gui test self.text = editwin.text - self.autocompletewindow = None - # id of delayed call, and the index of the text insert when - # the delayed call was issued. If _delayed_completion_id is - # None, there is no delayed call. - self._delayed_completion_id = None - self._delayed_completion_index = None + self.autocompletewindow = None + # id of delayed call, and the index of the text insert when + # the delayed call was issued. If _delayed_completion_id is + # None, there is no delayed call. + self._delayed_completion_id = None + self._delayed_completion_index = None @classmethod def reload(cls): cls.popupwait = idleConf.GetOption( "extensions", "AutoComplete", "popupwait", type="int", default=0) - def _make_autocomplete_window(self): + def _make_autocomplete_window(self): # Makes mocking easier. return autocomplete_w.AutoCompleteWindow(self.text) def _remove_autocomplete_window(self, event=None): @@ -52,30 +55,12 @@ def _remove_autocomplete_window(self, event=None): self.autocompletewindow = None def force_open_completions_event(self, event): - """Happens when the user really wants to open a completion list, even - if a function call is needed. - """ - self.open_completions(True, False, True) + "(^space) Open completion list, even if a function call is needed." + self.open_completions(FORCE) return "break" - def try_open_completions_event(self, event): - """Happens when it would be nice to open a completion list, but not - really necessary, for example after a dot, so function - calls won't be made. - """ - lastchar = self.text.get("insert-1c") - if lastchar == ".": - self._open_completions_later(False, False, False, - COMPLETE_ATTRIBUTES) - elif lastchar in SEPS: - self._open_completions_later(False, False, False, - COMPLETE_FILES) - def autocomplete_event(self, event): - """Happens when the user wants to complete his word, and if necessary, - open a completion list after that (if there is more than one - completion) - """ + "(tab) Complete word or open list if multiple options." if hasattr(event, "mc_state") and event.mc_state or\ not self.text.get("insert linestart", "insert").strip(): # A modifier was pressed along with the tab or @@ -85,34 +70,34 @@ def autocomplete_event(self, event): self.autocompletewindow.complete() return "break" else: - opened = self.open_completions(False, True, True) + opened = self.open_completions(TAB) return "break" if opened else None - def _open_completions_later(self, *args): - self._delayed_completion_index = self.text.index("insert") - if self._delayed_completion_id is not None: - self.text.after_cancel(self._delayed_completion_id) - self._delayed_completion_id = \ - self.text.after(self.popupwait, self._delayed_open_completions, - *args) - - def _delayed_open_completions(self, *args): + def try_open_completions_event(self, event=None): + "(./) Open completion list after pause with no movement." + lastchar = self.text.get("insert-1c") + if lastchar in TRIGGERS: + args = TRY_A if lastchar == "." else TRY_F + self._delayed_completion_index = self.text.index("insert") + if self._delayed_completion_id is not None: + self.text.after_cancel(self._delayed_completion_id) + self._delayed_completion_id = self.text.after( + self.popupwait, self._delayed_open_completions, args) + + def _delayed_open_completions(self, args): + "Call open_completions if index unchanged." self._delayed_completion_id = None if self.text.index("insert") == self._delayed_completion_index: - self.open_completions(*args) + self.open_completions(args) - def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): + def open_completions(self, args): """Find the completions and create the AutoCompleteWindow. Return True if successful (no syntax error or so found). If complete is True, then if there's nothing to complete and no start of completion, won't open completions and return False. If mode is given, will open a completion list only in this mode. - - Action Function Eval Complete WantWin Mode - ^space force_open_completions True, False, True no - . or / try_open_completions False, False, False yes - tab autocomplete False, True, True no """ + evalfuncs, complete, wantwin, mode = args # Cancel another delayed call, if it exists. if self._delayed_completion_id is not None: self.text.after_cancel(self._delayed_completion_id) @@ -121,14 +106,14 @@ def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): hp = HyperParser(self.editwin, "insert") curline = self.text.get("insert linestart", "insert") i = j = len(curline) - if hp.is_in_string() and (not mode or mode==COMPLETE_FILES): + if hp.is_in_string() and (not mode or mode==FILES): # Find the beginning of the string. # fetch_completions will look at the file system to determine # whether the string value constitutes an actual file name # XXX could consider raw strings here and unescape the string # value if it's not raw. self._remove_autocomplete_window() - mode = COMPLETE_FILES + mode = FILES # Find last separator or string start while i and curline[i-1] not in "'\"" + SEPS: i -= 1 @@ -138,17 +123,17 @@ def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): while i and curline[i-1] not in "'\"": i -= 1 comp_what = curline[i:j] - elif hp.is_in_code() and (not mode or mode==COMPLETE_ATTRIBUTES): + elif hp.is_in_code() and (not mode or mode==ATTRS): self._remove_autocomplete_window() - mode = COMPLETE_ATTRIBUTES + mode = ATTRS while i and (curline[i-1] in ID_CHARS or ord(curline[i-1]) > 127): i -= 1 comp_start = curline[i:j] - if i and curline[i-1] == '.': + if i and curline[i-1] == '.': # Need object with attributes. hp.set_index("insert-%dc" % (len(curline)-(i-1))) comp_what = hp.get_expression() - if not comp_what or \ - (not evalfuncs and comp_what.find('(') != -1): + if (not comp_what or + (not evalfuncs and comp_what.find('(') != -1)): return None else: comp_what = "" @@ -163,7 +148,7 @@ def open_completions(self, evalfuncs, complete, userWantsWin, mode=None): self.autocompletewindow = self._make_autocomplete_window() return not self.autocompletewindow.show_window( comp_lists, "insert-%dc" % len(comp_start), - complete, mode, userWantsWin) + complete, mode, wantwin) def fetch_completions(self, what, mode): """Return a pair of lists of completions for something. The first list @@ -185,7 +170,7 @@ def fetch_completions(self, what, mode): return rpcclt.remotecall("exec", "get_the_completion_list", (what, mode), {}) else: - if mode == COMPLETE_ATTRIBUTES: + if mode == ATTRS: if what == "": namespace = {**__main__.__builtins__.__dict__, **__main__.__dict__} @@ -207,7 +192,7 @@ def fetch_completions(self, what, mode): except: return [], [] - elif mode == COMPLETE_FILES: + elif mode == FILES: if what == "": what = "." try: diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index c24962527736..c69ab4a36836 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -6,7 +6,7 @@ from tkinter import * from tkinter.ttk import Frame, Scrollbar -from idlelib.autocomplete import COMPLETE_FILES, COMPLETE_ATTRIBUTES +from idlelib.autocomplete import FILES, ATTRS from idlelib.multicall import MC_SHIFT HIDE_VIRTUAL_EVENT_NAME = "<>" @@ -39,8 +39,7 @@ def __init__(self, widget): self.completions = None # A list with more completions, or None self.morecompletions = None - # The completion mode. Either autocomplete.COMPLETE_ATTRIBUTES or - # autocomplete.COMPLETE_FILES + # The completion mode, either autocomplete.ATTRS or .FILES. self.mode = None # The current completion start, on the text box (a string) self.start = None @@ -73,8 +72,8 @@ def _change_start(self, newstart): def _binary_search(self, s): """Find the first index in self.completions where completions[i] is - greater or equal to s, or the last index if there is no such - one.""" + greater or equal to s, or the last index if there is no such. + """ i = 0; j = len(self.completions) while j > i: m = (i + j) // 2 @@ -87,7 +86,8 @@ def _binary_search(self, s): def _complete_string(self, s): """Assuming that s is the prefix of a string in self.completions, return the longest string which is a prefix of all the strings which - s is a prefix of them. If s is not a prefix of a string, return s.""" + s is a prefix of them. If s is not a prefix of a string, return s. + """ first = self._binary_search(s) if self.completions[first][:len(s)] != s: # There is not even one completion which s is a prefix of. @@ -116,8 +116,10 @@ def _complete_string(self, s): return first_comp[:i] def _selection_changed(self): - """Should be called when the selection of the Listbox has changed. - Updates the Listbox display and calls _change_start.""" + """Call when the selection of the Listbox has changed. + + Updates the Listbox display and calls _change_start. + """ cursel = int(self.listbox.curselection()[0]) self.listbox.see(cursel) @@ -153,8 +155,10 @@ def _selection_changed(self): def show_window(self, comp_lists, index, complete, mode, userWantsWin): """Show the autocomplete list, bind events. - If complete is True, complete the text, and if there is exactly one - matching completion, don't open a list.""" + + If complete is True, complete the text, and if there is exactly + one matching completion, don't open a list. + """ # Handle the start we already have self.completions, self.morecompletions = comp_lists self.mode = mode @@ -300,7 +304,7 @@ def keypress_event(self, event): if keysym != "Tab": self.lastkey_was_tab = False if (len(keysym) == 1 or keysym in ("underscore", "BackSpace") - or (self.mode == COMPLETE_FILES and keysym in + or (self.mode == FILES and keysym in ("period", "minus"))) \ and not (state & ~MC_SHIFT): # Normal editing of text @@ -329,10 +333,10 @@ def keypress_event(self, event): self.hide_window() return 'break' - elif (self.mode == COMPLETE_ATTRIBUTES and keysym in + elif (self.mode == ATTRS and keysym in ("period", "space", "parenleft", "parenright", "bracketleft", "bracketright")) or \ - (self.mode == COMPLETE_FILES and keysym in + (self.mode == FILES and keysym in ("slash", "backslash", "quotedbl", "apostrophe")) \ and not (state & ~MC_SHIFT): # If start is a prefix of the selection, but is not '' when @@ -340,7 +344,7 @@ def keypress_event(self, event): # selected completion. Anyway, close the list. cursel = int(self.listbox.curselection()[0]) if self.completions[cursel][:len(self.start)] == self.start \ - and (self.mode == COMPLETE_ATTRIBUTES or self.start): + and (self.mode == ATTRS or self.start): self._change_start(self.completions[cursel]) self.hide_window() return None diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py index 6181b29ec250..2c478cd5c2a1 100644 --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -1,4 +1,4 @@ -"Test autocomplete, coverage 87%." +"Test autocomplete, coverage 93%." import unittest from unittest.mock import Mock, patch @@ -45,127 +45,177 @@ def setUp(self): def test_init(self): self.assertEqual(self.autocomplete.editwin, self.editor) + self.assertEqual(self.autocomplete.text, self.text) def test_make_autocomplete_window(self): testwin = self.autocomplete._make_autocomplete_window() self.assertIsInstance(testwin, acw.AutoCompleteWindow) def test_remove_autocomplete_window(self): - self.autocomplete.autocompletewindow = ( - self.autocomplete._make_autocomplete_window()) - self.autocomplete._remove_autocomplete_window() - self.assertIsNone(self.autocomplete.autocompletewindow) + acp = self.autocomplete + acp.autocompletewindow = m = Mock() + acp._remove_autocomplete_window() + m.hide_window.assert_called_once() + self.assertIsNone(acp.autocompletewindow) def test_force_open_completions_event(self): - # Test that force_open_completions_event calls _open_completions. - o_cs = Func() - self.autocomplete.open_completions = o_cs - self.autocomplete.force_open_completions_event('event') - self.assertEqual(o_cs.args, (True, False, True)) - - def test_try_open_completions_event(self): - Equal = self.assertEqual - autocomplete = self.autocomplete - trycompletions = self.autocomplete.try_open_completions_event - o_c_l = Func() - autocomplete._open_completions_later = o_c_l - - # _open_completions_later should not be called with no text in editor. - trycompletions('event') - Equal(o_c_l.args, None) - - # _open_completions_later should be called with COMPLETE_ATTRIBUTES (1). - self.text.insert('1.0', 're.') - trycompletions('event') - Equal(o_c_l.args, (False, False, False, 1)) - - # _open_completions_later should be called with COMPLETE_FILES (2). - self.text.delete('1.0', 'end') - self.text.insert('1.0', '"./Lib/') - trycompletions('event') - Equal(o_c_l.args, (False, False, False, 2)) + # Call _open_completions and break. + acp = self.autocomplete + open_c = Func() + acp.open_completions = open_c + self.assertEqual(acp.force_open_completions_event('event'), 'break') + self.assertEqual(open_c.args[0], ac.FORCE) def test_autocomplete_event(self): Equal = self.assertEqual - autocomplete = self.autocomplete + acp = self.autocomplete - # Test that the autocomplete event is ignored if user is pressing a - # modifier key in addition to the tab key. + # Result of autocomplete event: If modified tab, None. ev = Event(mc_state=True) - self.assertIsNone(autocomplete.autocomplete_event(ev)) + self.assertIsNone(acp.autocomplete_event(ev)) del ev.mc_state - # Test that tab after whitespace is ignored. + # If tab after whitespace, None. self.text.insert('1.0', ' """Docstring.\n ') - self.assertIsNone(autocomplete.autocomplete_event(ev)) + self.assertIsNone(acp.autocomplete_event(ev)) self.text.delete('1.0', 'end') - # If autocomplete window is open, complete() method is called. + # If active autocomplete window, complete() and 'break'. self.text.insert('1.0', 're.') - # This must call autocomplete._make_autocomplete_window(). - Equal(self.autocomplete.autocomplete_event(ev), 'break') - - # If autocomplete window is not active or does not exist, - # open_completions is called. Return depends on its return. - autocomplete._remove_autocomplete_window() - o_cs = Func() # .result = None. - autocomplete.open_completions = o_cs - Equal(self.autocomplete.autocomplete_event(ev), None) - Equal(o_cs.args, (False, True, True)) - o_cs.result = True - Equal(self.autocomplete.autocomplete_event(ev), 'break') - Equal(o_cs.args, (False, True, True)) - - def test_open_completions_later(self): - # Test that autocomplete._delayed_completion_id is set. + acp.autocompletewindow = mock = Mock() + mock.is_active = Mock(return_value=True) + Equal(acp.autocomplete_event(ev), 'break') + mock.complete.assert_called_once() + acp.autocompletewindow = None + + # If no active autocomplete window, open_completions(), None/break. + open_c = Func(result=False) + acp.open_completions = open_c + Equal(acp.autocomplete_event(ev), None) + Equal(open_c.args[0], ac.TAB) + open_c.result = True + Equal(acp.autocomplete_event(ev), 'break') + Equal(open_c.args[0], ac.TAB) + + def test_try_open_completions_event(self): + Equal = self.assertEqual + text = self.text acp = self.autocomplete + trycompletions = acp.try_open_completions_event + after = Func(result='after1') + acp.text.after = after + + # If no text or trigger, after not called. + trycompletions() + Equal(after.called, 0) + text.insert('1.0', 're') + trycompletions() + Equal(after.called, 0) + + # Attribute needed, no existing callback. + text.insert('insert', ' re.') acp._delayed_completion_id = None - acp._open_completions_later(False, False, False, ac.COMPLETE_ATTRIBUTES) + trycompletions() + Equal(acp._delayed_completion_index, text.index('insert')) + Equal(after.args, + (acp.popupwait, acp._delayed_open_completions, ac.TRY_A)) cb1 = acp._delayed_completion_id - self.assertTrue(cb1.startswith('after')) - - # Test that cb1 is cancelled and cb2 is new. - acp._open_completions_later(False, False, False, ac.COMPLETE_FILES) - self.assertNotIn(cb1, self.root.tk.call('after', 'info')) - cb2 = acp._delayed_completion_id - self.assertTrue(cb2.startswith('after') and cb2 != cb1) - self.text.after_cancel(cb2) + Equal(cb1, 'after1') + + # File needed, existing callback cancelled. + text.insert('insert', ' "./Lib/') + after.result = 'after2' + cancel = Func() + acp.text.after_cancel = cancel + trycompletions() + Equal(acp._delayed_completion_index, text.index('insert')) + Equal(cancel.args, (cb1,)) + Equal(after.args, + (acp.popupwait, acp._delayed_open_completions, ac.TRY_F)) + Equal(acp._delayed_completion_id, 'after2') def test_delayed_open_completions(self): - # Test that autocomplete._delayed_completion_id set to None - # and that open_completions is not called if the index is not - # equal to _delayed_completion_index. + Equal = self.assertEqual acp = self.autocomplete - acp.open_completions = Func() + open_c = Func() + acp.open_completions = open_c + self.text.insert('1.0', '"dict.') + + # Set autocomplete._delayed_completion_id to None. + # Text index changed, don't call open_completions. acp._delayed_completion_id = 'after' acp._delayed_completion_index = self.text.index('insert+1c') - acp._delayed_open_completions(1, 2, 3) + acp._delayed_open_completions('dummy') self.assertIsNone(acp._delayed_completion_id) - self.assertEqual(acp.open_completions.called, 0) + Equal(open_c.called, 0) - # Test that open_completions is called if indexes match. + # Text index unchanged, call open_completions. acp._delayed_completion_index = self.text.index('insert') - acp._delayed_open_completions(1, 2, 3, ac.COMPLETE_FILES) - self.assertEqual(acp.open_completions.args, (1, 2, 3, 2)) + acp._delayed_open_completions((1, 2, 3, ac.FILES)) + self.assertEqual(open_c.args[0], (1, 2, 3, ac.FILES)) + + def test_oc_cancel_comment(self): + none = self.assertIsNone + acp = self.autocomplete + + # Comment is in neither code or string. + acp._delayed_completion_id = 'after' + after = Func(result='after') + acp.text.after_cancel = after + self.text.insert(1.0, '# comment') + none(acp.open_completions(ac.TAB)) # From 'else' after 'elif'. + none(acp._delayed_completion_id) + + def test_oc_no_list(self): + acp = self.autocomplete + fetch = Func(result=([],[])) + acp.fetch_completions = fetch + self.text.insert('1.0', 'object') + self.assertIsNone(acp.open_completions(ac.TAB)) + self.text.insert('insert', '.') + self.assertIsNone(acp.open_completions(ac.TAB)) + self.assertEqual(fetch.called, 2) + + + def test_open_completions_none(self): + # Test other two None returns. + none = self.assertIsNone + acp = self.autocomplete + + # No object for attributes or need call not allowed. + self.text.insert(1.0, '.') + none(acp.open_completions(ac.TAB)) + self.text.insert('insert', ' int().') + none(acp.open_completions(ac.TAB)) + + # Blank or quote trigger 'if complete ...'. + self.text.delete(1.0, 'end') + self.assertFalse(acp.open_completions(ac.TAB)) + self.text.insert('1.0', '"') + self.assertFalse(acp.open_completions(ac.TAB)) + self.text.delete('1.0', 'end') + + class dummy_acw(): + __init__ = Func() + show_window = Func(result=False) + hide_window = Func() def test_open_completions(self): - # Test completions of files and attributes as well as non-completion - # of errors. - self.text.insert('1.0', 'pr') - self.assertTrue(self.autocomplete.open_completions(False, True, True)) + # Test completions of files and attributes. + acp = self.autocomplete + fetch = Func(result=(['tem'],['tem', '_tem'])) + acp.fetch_completions = fetch + def make_acw(): return self.dummy_acw() + acp._make_autocomplete_window = make_acw + + self.text.insert('1.0', 'int.') + acp.open_completions(ac.TAB) + self.assertIsInstance(acp.autocompletewindow, self.dummy_acw) self.text.delete('1.0', 'end') # Test files. self.text.insert('1.0', '"t') - #self.assertTrue(self.autocomplete.open_completions(False, True, True)) - self.text.delete('1.0', 'end') - - # Test with blank will fail. - self.assertFalse(self.autocomplete.open_completions(False, True, True)) - - # Test with only string quote will fail. - self.text.insert('1.0', '"') - self.assertFalse(self.autocomplete.open_completions(False, True, True)) + self.assertTrue(acp.open_completions(ac.TAB)) self.text.delete('1.0', 'end') def test_fetch_completions(self): @@ -174,21 +224,21 @@ def test_fetch_completions(self): # a small list containing non-private variables. # For file completion, a large list containing all files in the path, # and a small list containing files that do not start with '.'. - autocomplete = self.autocomplete - small, large = self.autocomplete.fetch_completions( - '', ac.COMPLETE_ATTRIBUTES) + acp = self.autocomplete + small, large = acp.fetch_completions( + '', ac.ATTRS) if __main__.__file__ != ac.__file__: self.assertNotIn('AutoComplete', small) # See issue 36405. # Test attributes - s, b = autocomplete.fetch_completions('', ac.COMPLETE_ATTRIBUTES) + s, b = acp.fetch_completions('', ac.ATTRS) self.assertLess(len(small), len(large)) self.assertTrue(all(filter(lambda x: x.startswith('_'), s))) self.assertTrue(any(filter(lambda x: x.startswith('_'), b))) # Test smalll should respect to __all__. with patch.dict('__main__.__dict__', {'__all__': ['a', 'b']}): - s, b = autocomplete.fetch_completions('', ac.COMPLETE_ATTRIBUTES) + s, b = acp.fetch_completions('', ac.ATTRS) self.assertEqual(s, ['a', 'b']) self.assertIn('__name__', b) # From __main__.__dict__ self.assertIn('sum', b) # From __main__.__builtins__.__dict__ @@ -197,7 +247,7 @@ def test_fetch_completions(self): mock = Mock() mock._private = Mock() with patch.dict('__main__.__dict__', {'foo': mock}): - s, b = autocomplete.fetch_completions('foo', ac.COMPLETE_ATTRIBUTES) + s, b = acp.fetch_completions('foo', ac.ATTRS) self.assertNotIn('_private', s) self.assertIn('_private', b) self.assertEqual(s, [i for i in sorted(dir(mock)) if i[:1] != '_']) @@ -211,36 +261,36 @@ def _listdir(path): return ['monty', 'python', '.hidden'] with patch.object(os, 'listdir', _listdir): - s, b = autocomplete.fetch_completions('', ac.COMPLETE_FILES) + s, b = acp.fetch_completions('', ac.FILES) self.assertEqual(s, ['bar', 'foo']) self.assertEqual(b, ['.hidden', 'bar', 'foo']) - s, b = autocomplete.fetch_completions('~', ac.COMPLETE_FILES) + s, b = acp.fetch_completions('~', ac.FILES) self.assertEqual(s, ['monty', 'python']) self.assertEqual(b, ['.hidden', 'monty', 'python']) def test_get_entity(self): # Test that a name is in the namespace of sys.modules and # __main__.__dict__. - autocomplete = self.autocomplete + acp = self.autocomplete Equal = self.assertEqual - Equal(self.autocomplete.get_entity('int'), int) + Equal(acp.get_entity('int'), int) # Test name from sys.modules. mock = Mock() with patch.dict('sys.modules', {'tempfile': mock}): - Equal(autocomplete.get_entity('tempfile'), mock) + Equal(acp.get_entity('tempfile'), mock) # Test name from __main__.__dict__. di = {'foo': 10, 'bar': 20} with patch.dict('__main__.__dict__', {'d': di}): - Equal(autocomplete.get_entity('d'), di) + Equal(acp.get_entity('d'), di) # Test name not in namespace. with patch.dict('__main__.__dict__', {}): with self.assertRaises(NameError): - autocomplete.get_entity('not_exist') + acp.get_entity('not_exist') if __name__ == '__main__': diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst new file mode 100644 index 000000000000..a44fd3b59b4f --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst @@ -0,0 +1 @@ +IDLE - Refactor autocompete and improve testing. From webhook-mailer at python.org Mon Aug 5 03:20:42 2019 From: webhook-mailer at python.org (Inada Naoki) Date: Mon, 05 Aug 2019 07:20:42 -0000 Subject: [Python-checkins] bpo-37729: gc: write stats at once (GH-15050) Message-ID: https://github.com/python/cpython/commit/e8ea34855c7635f8a84b430f17dc01a666f4c0ef commit: e8ea34855c7635f8a84b430f17dc01a666f4c0ef branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Inada Naoki date: 2019-08-05T16:20:25+09:00 summary: bpo-37729: gc: write stats at once (GH-15050) gc used several PySys_WriteStderr() calls to write stats. It caused stats mixed up when stderr is shared by multiple processes like this: gc: collecting generation 2... gc: objects in each generation: 0 0gc: collecting generation 2... gc: objects in each generation: 0 0 126077 126077 gc: objects in permanent generation: 0 gc: objects in permanent generation: 0 gc: done, 112575 unreachable, 0 uncollectablegc: done, 112575 unreachable, 0 uncollectable, 0.2223s elapsed , 0.2344s elapsed (cherry picked from commit bf8162c8c45338470bbe487c8769bba20bde66c2) Co-authored-by: Inada Naoki files: M Modules/gcmodule.c diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 0cf00e839661..21839d95bd8c 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -962,6 +962,25 @@ clear_freelists(void) (void)PyContext_ClearFreeList(); } +// Show stats for objects in each gennerations. +static void +show_stats_each_generations(struct _gc_runtime_state *state) +{ + char buf[100]; + size_t pos = 0; + + for (int i = 0; i < NUM_GENERATIONS && pos < sizeof(buf); i++) { + pos += PyOS_snprintf(buf+pos, sizeof(buf)-pos, + " %"PY_FORMAT_SIZE_T"d", + gc_list_size(GEN_HEAD(state, i))); + } + + PySys_FormatStderr( + "gc: objects in each generation:%s\n" + "gc: objects in permanent generation: %zd\n", + buf, gc_list_size(&state->permanent_generation.head)); +} + /* This is the main function. Read this to understand how the * collection process works. */ static Py_ssize_t @@ -979,17 +998,9 @@ collect(struct _gc_runtime_state *state, int generation, _PyTime_t t1 = 0; /* initialize to prevent a compiler warning */ 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(state, i))); - PySys_WriteStderr("\ngc: objects in permanent generation: %zd", - gc_list_size(&state->permanent_generation.head)); + PySys_WriteStderr("gc: collecting generation %d...\n", generation); + show_stats_each_generations(state); t1 = _PyTime_GetMonotonicClock(); - - PySys_WriteStderr("\n"); } if (PyDTrace_GC_START_ENABLED()) @@ -1103,16 +1114,10 @@ collect(struct _gc_runtime_state *state, int generation, debug_cycle("uncollectable", FROM_GC(gc)); } if (state->debug & DEBUG_STATS) { - _PyTime_t t2 = _PyTime_GetMonotonicClock(); - - if (m == 0 && n == 0) - PySys_WriteStderr("gc: done"); - else - PySys_FormatStderr( - "gc: done, %zd unreachable, %zd uncollectable", - n+m, n); - PySys_WriteStderr(", %.4fs elapsed\n", - _PyTime_AsSecondsDouble(t2 - t1)); + double d = _PyTime_AsSecondsDouble(_PyTime_GetMonotonicClock() - t1); + PySys_FormatStderr( + "gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n", + n+m, n, d); } /* Append instances in the uncollectable set to a Python From webhook-mailer at python.org Mon Aug 5 05:19:32 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 05 Aug 2019 09:19:32 -0000 Subject: [Python-checkins] [2.7] bpo-37730: Fix usage of NotImplemented instead of NotImplementedError in docs. (GH-15062). (GH-15133) Message-ID: https://github.com/python/cpython/commit/35f9bccd8198330579ecb4b4c503062f8b5da130 commit: 35f9bccd8198330579ecb4b4c503062f8b5da130 branch: 2.7 author: David H committer: Serhiy Storchaka date: 2019-08-05T12:19:26+03:00 summary: [2.7] bpo-37730: Fix usage of NotImplemented instead of NotImplementedError in docs. (GH-15062). (GH-15133) (cherry picked from commit ed5e8e06cbf766e89d6c58a882ee024abb5b2ed7) Co-authored-by: David H files: M Doc/library/_winreg.rst M PC/_winreg.c diff --git a/Doc/library/_winreg.rst b/Doc/library/_winreg.rst index a87cb9c51d98..177e1994f3fa 100644 --- a/Doc/library/_winreg.rst +++ b/Doc/library/_winreg.rst @@ -427,7 +427,7 @@ This module offers the following functions: *key* is an already open key, or one of the predefined :ref:`HKEY_* constants `. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit + Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating system. If the key is not on the reflection list, the function succeeds but has no @@ -442,7 +442,7 @@ This module offers the following functions: *key* is an already open key, or one of the predefined :ref:`HKEY_* constants `. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit + Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating system. Restoring reflection for a key does not affect reflection of any subkeys. @@ -457,7 +457,7 @@ This module offers the following functions: Returns ``True`` if reflection is disabled. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit + Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating system. diff --git a/PC/_winreg.c b/PC/_winreg.c index 3b887e075334..e0fdff2250ba 100644 --- a/PC/_winreg.c +++ b/PC/_winreg.c @@ -322,19 +322,19 @@ PyDoc_STRVAR(SetValueEx_doc, PyDoc_STRVAR(DisableReflectionKey_doc, "Disables registry reflection for 32-bit processes running on a 64-bit\n" -"Operating System. Will generally raise NotImplemented if executed on\n" +"Operating System. Will generally raise NotImplementedError if executed on\n" "a 32-bit Operating System.\n" "If the key is not on the reflection list, the function succeeds but has no effect.\n" "Disabling reflection for a key does not affect reflection of any subkeys."); PyDoc_STRVAR(EnableReflectionKey_doc, "Restores registry reflection for the specified disabled key.\n" -"Will generally raise NotImplemented if executed on a 32-bit Operating System.\n" +"Will generally raise NotImplementedError if executed on a 32-bit Operating System.\n" "Restoring reflection for a key does not affect reflection of any subkeys."); PyDoc_STRVAR(QueryReflectionKey_doc, "bool = QueryReflectionKey(hkey) - Determines the reflection state for the specified key.\n" -"Will generally raise NotImplemented if executed on a 32-bit Operating System.\n"); +"Will generally raise NotImplementedError if executed on a 32-bit Operating System.\n"); /* PyHKEY docstrings */ PyDoc_STRVAR(PyHKEY_doc, From webhook-mailer at python.org Mon Aug 5 16:33:27 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Mon, 05 Aug 2019 20:33:27 -0000 Subject: [Python-checkins] bpo-37759: First round of major edits to Whatsnew 3.8 (GH-15127) Message-ID: https://github.com/python/cpython/commit/4f9ffc9d1a6a293563deaaaaf4a13331302219b4 commit: 4f9ffc9d1a6a293563deaaaaf4a13331302219b4 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-05T13:33:19-07:00 summary: bpo-37759: First round of major edits to Whatsnew 3.8 (GH-15127) files: A Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i.rst M Doc/whatsnew/3.8.rst diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 0455688841fb..d8062e772f6e 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -42,21 +42,25 @@ This saves the maintainer the effort of going through the Mercurial log when researching a change. -This article explains the new features in Python 3.8, compared to 3.7. +:Editor: Raymond Hettinger +This article explains the new features in Python 3.8, compared to 3.7. For full details, see the :ref:`changelog `. -.. note:: +Prerelease users should be aware that this document is currently in +draft form. It will be updated as Python 3.8 moves towards release, so +it's worth checking back even after reading earlier versions. Some +notable items not yet covered are: - Prerelease users should be aware that this document is currently in draft - form. It will be updated substantially as Python 3.8 moves towards release, - so it's worth checking back even after reading earlier versions. +* :pep:`578` - Runtime audit hooks for potentially sensitive operations +* ``python -m asyncio`` runs a natively async REPL - Some notable items not yet covered here: +.. testsetup:: - * :pep:`578` - Runtime audit hooks for potentially sensitive operations - * ``python -m asyncio`` runs a natively async REPL - * ... + from datetime import date + from math import cos, radians + import re + import math Summary -- Release highlights @@ -76,12 +80,43 @@ New Features Assignment expressions ---------------------- -There is new syntax (the "walrus operator", ``:=``) to assign values -to variables as part of an expression. Example:: +There is new syntax ``:=`` that assigns values to variables as part of a larger +expression. It is affectionately known as "walrus operator" due to +its resemblance to `the eyes and tusks of a walrus +`_. + +In this example, the assignment expression helps avoid calling +:func:`len` twice:: if (n := len(a)) > 10: print(f"List is too long ({n} elements, expected <= 10)") +A similar benefit arises during regular expression matching where +match objects are needed twice, once to test whether a match +occurred and another to extract a subgroup:: + + discount = 0.0 + if (mo := re.search(r'(\d+)% discount', advertisement)): + discount = float(mo.group(1)) / 100.0 + +The operator is also useful with while-loops that compute +a value to test loop termination and then need that same +value again in the body of the loop:: + + # Loop over fixed length blocks + while (block := f.read(256)) != '': + process(block) + +Another motivating use case arises in list comprehensions where +a value computed in a filtering condition is also needed in +the expression body:: + + [clean_name.title() for name in names + if (clean_name := normalize('NFC', name)) in allowed_names] + +Try to limit use of the walrus operator to clean cases that reduce +complexity and improve readability. + See :pep:`572` for a full description. (Contributed by Emily Morehouse in :issue:`35224`.) @@ -92,20 +127,69 @@ See :pep:`572` for a full description. 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:: +There is a new function parameter syntax ``/`` to indicate that some +function parameters must be specified positionally and cannot be used as +keyword arguments. This is the same notation shown by ``help()`` for C +functions annotated with Larry Hastings' `Argument Clinic +`_ tool. + +In the following example, parameters *a* and *b* are positional-only, +while *c* or *d* can be positional or keyword, and *e* or *f* are +required to be keywords:: + + def f(a, b, /, c, d, *, e, f): + print(a, b, c, d, e, f) + +The following is a valid call:: + + f(10, 20, 30, d=40, e=50, f=60) + +However, these are invalid calls:: + + f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument + f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument + +One use case for this notation is that it allows pure Python functions +to fully emulate behaviors of existing C coded functions. For example, +the built-in :func:`pow` function does not accept keyword arguments:: def pow(x, y, z=None, /): - r = x**y - if z is not None: - r %= z - return r + "Emulate the built in pow() function" + r = x ** y + return r if z is None else r%z + +Another use case is to preclude keyword arguments when the parameter +name is not helpful. For example, the builtin :func:`len` function has +the signature ``len(obj, /)``. This precludes awkward calls such as:: -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. + len(obj='hello') # The "obj" keyword argument impairs readability + +A further benefit of marking a parameter as positional-only is that it +allows the parameter name to be changed in the future without risk of +breaking client code. For example, in the :mod:`statistics` module, the +parameter name *dist* may be changed in the future. This was made +possible with the following function specification:: + + def quantiles(dist, /, *, n=4, method='exclusive') + ... + +Since the parameters to the left of ``/`` are not exposed as possible +keywords, the parameters names remain available for use in ``**kwargs``:: + + >>> def f(a, b, /, **kwargs): + ... print(a, b, kwargs) + ... + >>> f(10, 20, a=1, b=2, c=3) # a and b are used in two ways + 10 20 {'a': 1, 'b': 2, 'c': 3} + +This greatly simplifies the implementation of functions and methods +that need to accept arbitrary keyword arguments. For example, here +is an except from code in the :mod:`collections` module:: + + class Counter(dict): + + def __init__(self, iterable=None, /, **kwds): + # Note "iterable" is a possible keyword argument See :pep:`570` for a full description. @@ -174,17 +258,31 @@ Android and Cygwin, whose cases are handled by the script); this change is backward incompatible on purpose. (Contributed by Victor Stinner in :issue:`36721`.) -f-strings now support = for quick and easy debugging ------------------------------------------------------ -Add ``=`` specifier to f-strings. ``f'{expr=}'`` expands -to the text of the expression, an equal sign, then the repr of the -evaluated expression. So:: +f-strings support ``=`` for self-documenting expressions and debugging +---------------------------------------------------------------------- + +Added an ``=`` specifier to :term:`f-string`\s. An f-string such as +``f'{expr=}'`` will expand to the text of the expression, an equal sign, +then the representation of the evaluated expression. For example: - x = 3 - print(f'{x*9 + 15=}') + >>> user = 'eric_idle' + >>> member_since = date(1975, 7, 31) + >>> f'{user=} {member_since=}' + "user='eric_idle' member_since=datetime.date(1975, 7, 31)" -Would print ``x*9 + 15=42``. +The usual :ref:`f-string format specifiers ` allow more +control over how the result of the expression is displayed:: + + >>> delta = date.today() - member_since + >>> f'{user=!s} {delta.days=:,d}' + 'user=eric_idle delta.days=16,075' + +The ``=`` specifier will display the whole expression so that +calculations can be shown:: + + >>> print(f'{theta=} {cos(radians(theta))=:.3f}') + theta=30 cos(radians(theta))=0.866 (Contributed by Eric V. Smith and Larry Hastings in :issue:`36817`.) @@ -295,7 +393,13 @@ Other Language Changes or :meth:`~object.__complex__` is not available. (Contributed by Serhiy Storchaka in :issue:`20092`.) -* Added support of ``\N{name}`` escapes in :mod:`regular expressions `. +* Added support of ``\N{name}`` escapes in :mod:`regular expressions `:: + + >>> notice = 'Copyright ? 2019' + >>> copyright_year_pattern = re.compile(r'\N{copyright sign}\s*(\d{4})') + >>> int(copyright_year_pattern.search(notice).group(1)) + 2019 + (Contributed by Jonathan Eunice and Serhiy Storchaka in :issue:`30688`.) * Dict and dictviews are now iterable in reversed insertion order using @@ -343,10 +447,30 @@ Other Language Changes * Added new ``replace()`` method to the code type (:class:`types.CodeType`). (Contributed by Victor Stinner in :issue:`37032`.) -* For integers, the three-argument form of the :func:`pow` function now permits - the exponent to be negative in the case where the base is relatively prime to - the modulus. It then computes a modular inverse to the base when the exponent - is ``-1``, and a suitable power of that inverse for other negative exponents. +* For integers, the three-argument form of the :func:`pow` function now + permits the exponent to be negative in the case where the base is + relatively prime to the modulus. It then computes a modular inverse to + the base when the exponent is ``-1``, and a suitable power of that + inverse for other negative exponents. For example, to compute the + `modular multiplicative inverse + `_ of 38 + modulo 137, write:: + + >>> pow(38, -1, 137) + 119 + >>> 119 * 38 % 137 + 1 + + Modular inverses arise in the solution of `linear Diophantine + equations `_. + For example, to find integer solutions for ``4258? + 147? = 369``, + first rewrite as ``4258? ? 369 (mod 147)`` then solve: + + >>> x = 369 * pow(4258, -1, 147) % 147 + >>> y = (4258 * x - 369) // -147 + >>> 4258 * x + 147 * y + 369 + (Contributed by Mark Dickinson in :issue:`36027`.) * When dictionary comprehensions are evaluated, the key is now evaluated before @@ -576,7 +700,14 @@ Formerly, it only supported the 2-D case. Added new function, :func:`math.prod`, as analogous function to :func:`sum` that returns the product of a 'start' value (default: 1) times an iterable of -numbers. (Contributed by Pablo Galindo in :issue:`35606`) +numbers:: + + >>> prior = 0.8 + >>> likelihoods = [0.625, 0.84, 0.30] + >>> (link: http://math.prod) math.prod(likelihoods, start=prior) + 0.126 + +(Contributed by Pablo Galindo in :issue:`35606`) Added new function :func:`math.isqrt` for computing integer square roots. (Contributed by Mark Dickinson in :issue:`36887`.) @@ -1357,7 +1488,7 @@ Changes in the Python API * :func:`shutil.copyfile` default buffer size on Windows was changed from 16 KiB to 1 MiB. -* ``PyGC_Head`` struct is changed completely. All code touched the +* The ``PyGC_Head`` struct has changed completely. All code that touched the struct member should be rewritten. (See :issue:`33597`) * The ``PyInterpreterState`` struct has been moved into the "internal" diff --git a/Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i.rst b/Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i.rst new file mode 100644 index 000000000000..90fb7213ebde --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i.rst @@ -0,0 +1 @@ +Beginning edits to Whatsnew 3.8 From webhook-mailer at python.org Mon Aug 5 18:22:18 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Mon, 05 Aug 2019 22:22:18 -0000 Subject: [Python-checkins] bpo-37759: First round of major edits to Whatsnew 3.8 (GH-15127) (GH-15139) Message-ID: https://github.com/python/cpython/commit/26f91db5ba487033994b396011518cfc80bf8401 commit: 26f91db5ba487033994b396011518cfc80bf8401 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-05T15:22:13-07:00 summary: bpo-37759: First round of major edits to Whatsnew 3.8 (GH-15127) (GH-15139) (cherry picked from commit 4f9ffc9d1a6a293563deaaaaf4a13331302219b4) Co-authored-by: Raymond Hettinger files: A Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i.rst M Doc/whatsnew/3.8.rst diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 967b3f2d68b9..9f7058274514 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -42,21 +42,25 @@ This saves the maintainer the effort of going through the Mercurial log when researching a change. -This article explains the new features in Python 3.8, compared to 3.7. +:Editor: Raymond Hettinger +This article explains the new features in Python 3.8, compared to 3.7. For full details, see the :ref:`changelog `. -.. note:: +Prerelease users should be aware that this document is currently in +draft form. It will be updated as Python 3.8 moves towards release, so +it's worth checking back even after reading earlier versions. Some +notable items not yet covered are: - Prerelease users should be aware that this document is currently in draft - form. It will be updated substantially as Python 3.8 moves towards release, - so it's worth checking back even after reading earlier versions. +* :pep:`578` - Runtime audit hooks for potentially sensitive operations +* ``python -m asyncio`` runs a natively async REPL - Some notable items not yet covered here: +.. testsetup:: - * :pep:`578` - Runtime audit hooks for potentially sensitive operations - * ``python -m asyncio`` runs a natively async REPL - * ... + from datetime import date + from math import cos, radians + import re + import math Summary -- Release highlights @@ -76,12 +80,43 @@ New Features Assignment expressions ---------------------- -There is new syntax (the "walrus operator", ``:=``) to assign values -to variables as part of an expression. Example:: +There is new syntax ``:=`` that assigns values to variables as part of a larger +expression. It is affectionately known as "walrus operator" due to +its resemblance to `the eyes and tusks of a walrus +`_. + +In this example, the assignment expression helps avoid calling +:func:`len` twice:: if (n := len(a)) > 10: print(f"List is too long ({n} elements, expected <= 10)") +A similar benefit arises during regular expression matching where +match objects are needed twice, once to test whether a match +occurred and another to extract a subgroup:: + + discount = 0.0 + if (mo := re.search(r'(\d+)% discount', advertisement)): + discount = float(mo.group(1)) / 100.0 + +The operator is also useful with while-loops that compute +a value to test loop termination and then need that same +value again in the body of the loop:: + + # Loop over fixed length blocks + while (block := f.read(256)) != '': + process(block) + +Another motivating use case arises in list comprehensions where +a value computed in a filtering condition is also needed in +the expression body:: + + [clean_name.title() for name in names + if (clean_name := normalize('NFC', name)) in allowed_names] + +Try to limit use of the walrus operator to clean cases that reduce +complexity and improve readability. + See :pep:`572` for a full description. (Contributed by Emily Morehouse in :issue:`35224`.) @@ -92,20 +127,69 @@ See :pep:`572` for a full description. 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:: +There is a new function parameter syntax ``/`` to indicate that some +function parameters must be specified positionally and cannot be used as +keyword arguments. This is the same notation shown by ``help()`` for C +functions annotated with Larry Hastings' `Argument Clinic +`_ tool. + +In the following example, parameters *a* and *b* are positional-only, +while *c* or *d* can be positional or keyword, and *e* or *f* are +required to be keywords:: + + def f(a, b, /, c, d, *, e, f): + print(a, b, c, d, e, f) + +The following is a valid call:: + + f(10, 20, 30, d=40, e=50, f=60) + +However, these are invalid calls:: + + f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument + f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument + +One use case for this notation is that it allows pure Python functions +to fully emulate behaviors of existing C coded functions. For example, +the built-in :func:`pow` function does not accept keyword arguments:: def pow(x, y, z=None, /): - r = x**y - if z is not None: - r %= z - return r + "Emulate the built in pow() function" + r = x ** y + return r if z is None else r%z + +Another use case is to preclude keyword arguments when the parameter +name is not helpful. For example, the builtin :func:`len` function has +the signature ``len(obj, /)``. This precludes awkward calls such as:: -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. + len(obj='hello') # The "obj" keyword argument impairs readability + +A further benefit of marking a parameter as positional-only is that it +allows the parameter name to be changed in the future without risk of +breaking client code. For example, in the :mod:`statistics` module, the +parameter name *dist* may be changed in the future. This was made +possible with the following function specification:: + + def quantiles(dist, /, *, n=4, method='exclusive') + ... + +Since the parameters to the left of ``/`` are not exposed as possible +keywords, the parameters names remain available for use in ``**kwargs``:: + + >>> def f(a, b, /, **kwargs): + ... print(a, b, kwargs) + ... + >>> f(10, 20, a=1, b=2, c=3) # a and b are used in two ways + 10 20 {'a': 1, 'b': 2, 'c': 3} + +This greatly simplifies the implementation of functions and methods +that need to accept arbitrary keyword arguments. For example, here +is an except from code in the :mod:`collections` module:: + + class Counter(dict): + + def __init__(self, iterable=None, /, **kwds): + # Note "iterable" is a possible keyword argument See :pep:`570` for a full description. @@ -174,17 +258,31 @@ Android and Cygwin, whose cases are handled by the script); this change is backward incompatible on purpose. (Contributed by Victor Stinner in :issue:`36721`.) -f-strings now support = for quick and easy debugging ------------------------------------------------------ -Add ``=`` specifier to f-strings. ``f'{expr=}'`` expands -to the text of the expression, an equal sign, then the repr of the -evaluated expression. So:: +f-strings support ``=`` for self-documenting expressions and debugging +---------------------------------------------------------------------- + +Added an ``=`` specifier to :term:`f-string`\s. An f-string such as +``f'{expr=}'`` will expand to the text of the expression, an equal sign, +then the representation of the evaluated expression. For example: - x = 3 - print(f'{x*9 + 15=}') + >>> user = 'eric_idle' + >>> member_since = date(1975, 7, 31) + >>> f'{user=} {member_since=}' + "user='eric_idle' member_since=datetime.date(1975, 7, 31)" -Would print ``x*9 + 15=42``. +The usual :ref:`f-string format specifiers ` allow more +control over how the result of the expression is displayed:: + + >>> delta = date.today() - member_since + >>> f'{user=!s} {delta.days=:,d}' + 'user=eric_idle delta.days=16,075' + +The ``=`` specifier will display the whole expression so that +calculations can be shown:: + + >>> print(f'{theta=} {cos(radians(theta))=:.3f}') + theta=30 cos(radians(theta))=0.866 (Contributed by Eric V. Smith and Larry Hastings in :issue:`36817`.) @@ -295,7 +393,13 @@ Other Language Changes or :meth:`~object.__complex__` is not available. (Contributed by Serhiy Storchaka in :issue:`20092`.) -* Added support of ``\N{name}`` escapes in :mod:`regular expressions `. +* Added support of ``\N{name}`` escapes in :mod:`regular expressions `:: + + >>> notice = 'Copyright ? 2019' + >>> copyright_year_pattern = re.compile(r'\N{copyright sign}\s*(\d{4})') + >>> int(copyright_year_pattern.search(notice).group(1)) + 2019 + (Contributed by Jonathan Eunice and Serhiy Storchaka in :issue:`30688`.) * Dict and dictviews are now iterable in reversed insertion order using @@ -343,10 +447,30 @@ Other Language Changes * Added new ``replace()`` method to the code type (:class:`types.CodeType`). (Contributed by Victor Stinner in :issue:`37032`.) -* For integers, the three-argument form of the :func:`pow` function now permits - the exponent to be negative in the case where the base is relatively prime to - the modulus. It then computes a modular inverse to the base when the exponent - is ``-1``, and a suitable power of that inverse for other negative exponents. +* For integers, the three-argument form of the :func:`pow` function now + permits the exponent to be negative in the case where the base is + relatively prime to the modulus. It then computes a modular inverse to + the base when the exponent is ``-1``, and a suitable power of that + inverse for other negative exponents. For example, to compute the + `modular multiplicative inverse + `_ of 38 + modulo 137, write:: + + >>> pow(38, -1, 137) + 119 + >>> 119 * 38 % 137 + 1 + + Modular inverses arise in the solution of `linear Diophantine + equations `_. + For example, to find integer solutions for ``4258? + 147? = 369``, + first rewrite as ``4258? ? 369 (mod 147)`` then solve: + + >>> x = 369 * pow(4258, -1, 147) % 147 + >>> y = (4258 * x - 369) // -147 + >>> 4258 * x + 147 * y + 369 + (Contributed by Mark Dickinson in :issue:`36027`.) * When dictionary comprehensions are evaluated, the key is now evaluated before @@ -573,7 +697,14 @@ Formerly, it only supported the 2-D case. Added new function, :func:`math.prod`, as analogous function to :func:`sum` that returns the product of a 'start' value (default: 1) times an iterable of -numbers. (Contributed by Pablo Galindo in :issue:`35606`) +numbers:: + + >>> prior = 0.8 + >>> likelihoods = [0.625, 0.84, 0.30] + >>> (link: http://math.prod) math.prod(likelihoods, start=prior) + 0.126 + +(Contributed by Pablo Galindo in :issue:`35606`) Added new function :func:`math.isqrt` for computing integer square roots. (Contributed by Mark Dickinson in :issue:`36887`.) @@ -1354,7 +1485,7 @@ Changes in the Python API * :func:`shutil.copyfile` default buffer size on Windows was changed from 16 KiB to 1 MiB. -* ``PyGC_Head`` struct is changed completely. All code touched the +* The ``PyGC_Head`` struct has changed completely. All code that touched the struct member should be rewritten. (See :issue:`33597`) * The ``PyInterpreterState`` struct has been moved into the "internal" diff --git a/Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i.rst b/Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i.rst new file mode 100644 index 000000000000..90fb7213ebde --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i.rst @@ -0,0 +1 @@ +Beginning edits to Whatsnew 3.8 From webhook-mailer at python.org Tue Aug 6 17:12:33 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 06 Aug 2019 21:12:33 -0000 Subject: [Python-checkins] Improve signal documentation (GH-14274) Message-ID: https://github.com/python/cpython/commit/cfebfef2def48095aa1f4c790a35e51818d67502 commit: cfebfef2def48095aa1f4c790a35e51818d67502 branch: master author: G?ry Ogam committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-06T14:12:22-07:00 summary: Improve signal documentation (GH-14274) * add a missing ``.. availability::`` reST explicit markup; * more consistent "see man page" sentences. files: M Doc/library/signal.rst diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index 01200b4df880..8fecc2b7eed0 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -95,7 +95,7 @@ The variables defined in the :mod:`signal` module are: All the signal numbers are defined symbolically. For example, the hangup signal is defined as :const:`signal.SIGHUP`; the variable names are identical to the - names used in C programs, as found in ````. The Unix man page for + names used in C programs, as found in ````. The Unix man page for ':c:func:`signal`' lists the existing signals (on some systems this is :manpage:`signal(2)`, on others the list is in :manpage:`signal(7)`). Note that not all systems define the same set of signal names; only those names defined by @@ -193,10 +193,10 @@ The :mod:`signal` module defines the following functions: canceled (only one alarm can be scheduled at any time). The returned value is then the number of seconds before any previously set alarm was to have been delivered. If *time* is zero, no alarm is scheduled, and any scheduled alarm is - canceled. If the return value is zero, no alarm is currently scheduled. (See - the Unix man page :manpage:`alarm(2)`.) + canceled. If the return value is zero, no alarm is currently scheduled. - .. availability:: Unix. + .. availability:: Unix. See the man page :manpage:`alarm(2)` for further + information. .. function:: getsignal(signalnum) @@ -231,8 +231,10 @@ The :mod:`signal` module defines the following functions: .. function:: pause() Cause the process to sleep until a signal is received; the appropriate handler - will then be called. Returns nothing. Not on Windows. (See the Unix man page - :manpage:`signal(2)`.) + will then be called. Returns nothing. + + .. availability:: Unix. See the man page :manpage:`signal(2)` for further + information. See also :func:`sigwait`, :func:`sigwaitinfo`, :func:`sigtimedwait` and :func:`sigpending`. @@ -262,8 +264,8 @@ The :mod:`signal` module defines the following functions: If *signalnum* is 0, then no signal is sent, but error checking is still performed; this can be used to check if the target thread is still running. - .. availability:: Unix (see the man page :manpage:`pthread_kill(3)` for further - information). + .. availability:: Unix. See the man page :manpage:`pthread_kill(3)` for further + information. See also :func:`os.kill`. @@ -293,7 +295,7 @@ The :mod:`signal` module defines the following functions: For example, ``signal.pthread_sigmask(signal.SIG_BLOCK, [])`` reads the signal mask of the calling thread. - .. availability:: Unix. See the man page :manpage:`sigprocmask(3)` and + .. availability:: Unix. See the man page :manpage:`sigprocmask(3)` and :manpage:`pthread_sigmask(3)` for further information. See also :func:`pause`, :func:`sigpending` and :func:`sigwait`. @@ -380,8 +382,8 @@ The :mod:`signal` module defines the following functions: calls will be restarted when interrupted by signal *signalnum*, otherwise system calls will be interrupted. Returns nothing. - .. availability:: Unix (see the man page :manpage:`siginterrupt(3)` - for further information). + .. availability:: Unix. See the man page :manpage:`siginterrupt(3)` + for further information. Note that installing a signal handler with :func:`signal` will reset the restart behaviour to interruptible by implicitly calling @@ -394,7 +396,7 @@ The :mod:`signal` module defines the following functions: be a callable Python object taking two arguments (see below), or one of the special values :const:`signal.SIG_IGN` or :const:`signal.SIG_DFL`. The previous signal handler will be returned (see the description of :func:`getsignal` - above). (See the Unix man page :manpage:`signal(2)`.) + above). (See the Unix man page :manpage:`signal(2)` for further information.) When threads are enabled, this function can only be called from the main thread; attempting to call it from other threads will cause a :exc:`ValueError` @@ -420,8 +422,8 @@ The :mod:`signal` module defines the following functions: thread (i.e., the signals which have been raised while blocked). Return the set of the pending signals. - .. availability:: Unix (see the man page :manpage:`sigpending(2)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigpending(2)` for further + information. See also :func:`pause`, :func:`pthread_sigmask` and :func:`sigwait`. @@ -434,8 +436,8 @@ The :mod:`signal` module defines the following functions: signals specified in the signal set *sigset*. The function accepts the signal (removes it from the pending list of signals), and returns the signal number. - .. availability:: Unix (see the man page :manpage:`sigwait(3)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigwait(3)` for further + information. See also :func:`pause`, :func:`pthread_sigmask`, :func:`sigpending`, :func:`sigwaitinfo` and :func:`sigtimedwait`. @@ -459,8 +461,8 @@ The :mod:`signal` module defines the following functions: :attr:`si_errno`, :attr:`si_pid`, :attr:`si_uid`, :attr:`si_status`, :attr:`si_band`. - .. availability:: Unix (see the man page :manpage:`sigwaitinfo(2)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigwaitinfo(2)` for further + information. See also :func:`pause`, :func:`sigwait` and :func:`sigtimedwait`. @@ -478,8 +480,8 @@ The :mod:`signal` module defines the following functions: specifying a timeout. If *timeout* is specified as :const:`0`, a poll is performed. Returns :const:`None` if a timeout occurs. - .. availability:: Unix (see the man page :manpage:`sigtimedwait(2)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigtimedwait(2)` for further + information. See also :func:`pause`, :func:`sigwait` and :func:`sigwaitinfo`. From webhook-mailer at python.org Tue Aug 6 17:53:32 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 06 Aug 2019 21:53:32 -0000 Subject: [Python-checkins] Improve signal documentation (GH-14274) Message-ID: https://github.com/python/cpython/commit/ef0b81927ab3bf2b838964e78c7b8a91c9a61e12 commit: ef0b81927ab3bf2b838964e78c7b8a91c9a61e12 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-06T14:53:27-07:00 summary: Improve signal documentation (GH-14274) * add a missing ``.. availability::`` reST explicit markup; * more consistent "see man page" sentences. (cherry picked from commit cfebfef2def48095aa1f4c790a35e51818d67502) Co-authored-by: G?ry Ogam files: M Doc/library/signal.rst diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index 01200b4df880..8fecc2b7eed0 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -95,7 +95,7 @@ The variables defined in the :mod:`signal` module are: All the signal numbers are defined symbolically. For example, the hangup signal is defined as :const:`signal.SIGHUP`; the variable names are identical to the - names used in C programs, as found in ````. The Unix man page for + names used in C programs, as found in ````. The Unix man page for ':c:func:`signal`' lists the existing signals (on some systems this is :manpage:`signal(2)`, on others the list is in :manpage:`signal(7)`). Note that not all systems define the same set of signal names; only those names defined by @@ -193,10 +193,10 @@ The :mod:`signal` module defines the following functions: canceled (only one alarm can be scheduled at any time). The returned value is then the number of seconds before any previously set alarm was to have been delivered. If *time* is zero, no alarm is scheduled, and any scheduled alarm is - canceled. If the return value is zero, no alarm is currently scheduled. (See - the Unix man page :manpage:`alarm(2)`.) + canceled. If the return value is zero, no alarm is currently scheduled. - .. availability:: Unix. + .. availability:: Unix. See the man page :manpage:`alarm(2)` for further + information. .. function:: getsignal(signalnum) @@ -231,8 +231,10 @@ The :mod:`signal` module defines the following functions: .. function:: pause() Cause the process to sleep until a signal is received; the appropriate handler - will then be called. Returns nothing. Not on Windows. (See the Unix man page - :manpage:`signal(2)`.) + will then be called. Returns nothing. + + .. availability:: Unix. See the man page :manpage:`signal(2)` for further + information. See also :func:`sigwait`, :func:`sigwaitinfo`, :func:`sigtimedwait` and :func:`sigpending`. @@ -262,8 +264,8 @@ The :mod:`signal` module defines the following functions: If *signalnum* is 0, then no signal is sent, but error checking is still performed; this can be used to check if the target thread is still running. - .. availability:: Unix (see the man page :manpage:`pthread_kill(3)` for further - information). + .. availability:: Unix. See the man page :manpage:`pthread_kill(3)` for further + information. See also :func:`os.kill`. @@ -293,7 +295,7 @@ The :mod:`signal` module defines the following functions: For example, ``signal.pthread_sigmask(signal.SIG_BLOCK, [])`` reads the signal mask of the calling thread. - .. availability:: Unix. See the man page :manpage:`sigprocmask(3)` and + .. availability:: Unix. See the man page :manpage:`sigprocmask(3)` and :manpage:`pthread_sigmask(3)` for further information. See also :func:`pause`, :func:`sigpending` and :func:`sigwait`. @@ -380,8 +382,8 @@ The :mod:`signal` module defines the following functions: calls will be restarted when interrupted by signal *signalnum*, otherwise system calls will be interrupted. Returns nothing. - .. availability:: Unix (see the man page :manpage:`siginterrupt(3)` - for further information). + .. availability:: Unix. See the man page :manpage:`siginterrupt(3)` + for further information. Note that installing a signal handler with :func:`signal` will reset the restart behaviour to interruptible by implicitly calling @@ -394,7 +396,7 @@ The :mod:`signal` module defines the following functions: be a callable Python object taking two arguments (see below), or one of the special values :const:`signal.SIG_IGN` or :const:`signal.SIG_DFL`. The previous signal handler will be returned (see the description of :func:`getsignal` - above). (See the Unix man page :manpage:`signal(2)`.) + above). (See the Unix man page :manpage:`signal(2)` for further information.) When threads are enabled, this function can only be called from the main thread; attempting to call it from other threads will cause a :exc:`ValueError` @@ -420,8 +422,8 @@ The :mod:`signal` module defines the following functions: thread (i.e., the signals which have been raised while blocked). Return the set of the pending signals. - .. availability:: Unix (see the man page :manpage:`sigpending(2)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigpending(2)` for further + information. See also :func:`pause`, :func:`pthread_sigmask` and :func:`sigwait`. @@ -434,8 +436,8 @@ The :mod:`signal` module defines the following functions: signals specified in the signal set *sigset*. The function accepts the signal (removes it from the pending list of signals), and returns the signal number. - .. availability:: Unix (see the man page :manpage:`sigwait(3)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigwait(3)` for further + information. See also :func:`pause`, :func:`pthread_sigmask`, :func:`sigpending`, :func:`sigwaitinfo` and :func:`sigtimedwait`. @@ -459,8 +461,8 @@ The :mod:`signal` module defines the following functions: :attr:`si_errno`, :attr:`si_pid`, :attr:`si_uid`, :attr:`si_status`, :attr:`si_band`. - .. availability:: Unix (see the man page :manpage:`sigwaitinfo(2)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigwaitinfo(2)` for further + information. See also :func:`pause`, :func:`sigwait` and :func:`sigtimedwait`. @@ -478,8 +480,8 @@ The :mod:`signal` module defines the following functions: specifying a timeout. If *timeout* is specified as :const:`0`, a poll is performed. Returns :const:`None` if a timeout occurs. - .. availability:: Unix (see the man page :manpage:`sigtimedwait(2)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigtimedwait(2)` for further + information. See also :func:`pause`, :func:`sigwait` and :func:`sigwaitinfo`. From webhook-mailer at python.org Tue Aug 6 17:55:52 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 06 Aug 2019 21:55:52 -0000 Subject: [Python-checkins] Improve signal documentation (GH-14274) Message-ID: https://github.com/python/cpython/commit/18343aba78dea0c23abcb6e615e70f89764ae9a4 commit: 18343aba78dea0c23abcb6e615e70f89764ae9a4 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-06T14:55:48-07:00 summary: Improve signal documentation (GH-14274) * add a missing ``.. availability::`` reST explicit markup; * more consistent "see man page" sentences. (cherry picked from commit cfebfef2def48095aa1f4c790a35e51818d67502) Co-authored-by: G?ry Ogam files: M Doc/library/signal.rst diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index b6716eea95fb..75008118b7ca 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -95,7 +95,7 @@ The variables defined in the :mod:`signal` module are: All the signal numbers are defined symbolically. For example, the hangup signal is defined as :const:`signal.SIGHUP`; the variable names are identical to the - names used in C programs, as found in ````. The Unix man page for + names used in C programs, as found in ````. The Unix man page for ':c:func:`signal`' lists the existing signals (on some systems this is :manpage:`signal(2)`, on others the list is in :manpage:`signal(7)`). Note that not all systems define the same set of signal names; only those names defined by @@ -193,10 +193,10 @@ The :mod:`signal` module defines the following functions: canceled (only one alarm can be scheduled at any time). The returned value is then the number of seconds before any previously set alarm was to have been delivered. If *time* is zero, no alarm is scheduled, and any scheduled alarm is - canceled. If the return value is zero, no alarm is currently scheduled. (See - the Unix man page :manpage:`alarm(2)`.) + canceled. If the return value is zero, no alarm is currently scheduled. - .. availability:: Unix. + .. availability:: Unix. See the man page :manpage:`alarm(2)` for further + information. .. function:: getsignal(signalnum) @@ -213,8 +213,10 @@ The :mod:`signal` module defines the following functions: .. function:: pause() Cause the process to sleep until a signal is received; the appropriate handler - will then be called. Returns nothing. Not on Windows. (See the Unix man page - :manpage:`signal(2)`.) + will then be called. Returns nothing. + + .. availability:: Unix. See the man page :manpage:`signal(2)` for further + information. See also :func:`sigwait`, :func:`sigwaitinfo`, :func:`sigtimedwait` and :func:`sigpending`. @@ -237,8 +239,8 @@ The :mod:`signal` module defines the following functions: If *signalnum* is 0, then no signal is sent, but error checking is still performed; this can be used to check if the target thread is still running. - .. availability:: Unix (see the man page :manpage:`pthread_kill(3)` for further - information). + .. availability:: Unix. See the man page :manpage:`pthread_kill(3)` for further + information. See also :func:`os.kill`. @@ -268,7 +270,7 @@ The :mod:`signal` module defines the following functions: For example, ``signal.pthread_sigmask(signal.SIG_BLOCK, [])`` reads the signal mask of the calling thread. - .. availability:: Unix. See the man page :manpage:`sigprocmask(3)` and + .. availability:: Unix. See the man page :manpage:`sigprocmask(3)` and :manpage:`pthread_sigmask(3)` for further information. See also :func:`pause`, :func:`sigpending` and :func:`sigwait`. @@ -355,8 +357,8 @@ The :mod:`signal` module defines the following functions: calls will be restarted when interrupted by signal *signalnum*, otherwise system calls will be interrupted. Returns nothing. - .. availability:: Unix (see the man page :manpage:`siginterrupt(3)` - for further information). + .. availability:: Unix. See the man page :manpage:`siginterrupt(3)` + for further information. Note that installing a signal handler with :func:`signal` will reset the restart behaviour to interruptible by implicitly calling @@ -369,7 +371,7 @@ The :mod:`signal` module defines the following functions: be a callable Python object taking two arguments (see below), or one of the special values :const:`signal.SIG_IGN` or :const:`signal.SIG_DFL`. The previous signal handler will be returned (see the description of :func:`getsignal` - above). (See the Unix man page :manpage:`signal(2)`.) + above). (See the Unix man page :manpage:`signal(2)` for further information.) When threads are enabled, this function can only be called from the main thread; attempting to call it from other threads will cause a :exc:`ValueError` @@ -395,8 +397,8 @@ The :mod:`signal` module defines the following functions: thread (i.e., the signals which have been raised while blocked). Return the set of the pending signals. - .. availability:: Unix (see the man page :manpage:`sigpending(2)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigpending(2)` for further + information. See also :func:`pause`, :func:`pthread_sigmask` and :func:`sigwait`. @@ -409,8 +411,8 @@ The :mod:`signal` module defines the following functions: signals specified in the signal set *sigset*. The function accepts the signal (removes it from the pending list of signals), and returns the signal number. - .. availability:: Unix (see the man page :manpage:`sigwait(3)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigwait(3)` for further + information. See also :func:`pause`, :func:`pthread_sigmask`, :func:`sigpending`, :func:`sigwaitinfo` and :func:`sigtimedwait`. @@ -434,8 +436,8 @@ The :mod:`signal` module defines the following functions: :attr:`si_errno`, :attr:`si_pid`, :attr:`si_uid`, :attr:`si_status`, :attr:`si_band`. - .. availability:: Unix (see the man page :manpage:`sigwaitinfo(2)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigwaitinfo(2)` for further + information. See also :func:`pause`, :func:`sigwait` and :func:`sigtimedwait`. @@ -453,8 +455,8 @@ The :mod:`signal` module defines the following functions: specifying a timeout. If *timeout* is specified as :const:`0`, a poll is performed. Returns :const:`None` if a timeout occurs. - .. availability:: Unix (see the man page :manpage:`sigtimedwait(2)` for further - information). + .. availability:: Unix. See the man page :manpage:`sigtimedwait(2)` for further + information. See also :func:`pause`, :func:`sigwait` and :func:`sigwaitinfo`. From webhook-mailer at python.org Tue Aug 6 19:59:10 2019 From: webhook-mailer at python.org (Jason R. Coombs) Date: Tue, 06 Aug 2019 23:59:10 -0000 Subject: [Python-checkins] Make importlib.metadata a simple module (#15153) Message-ID: https://github.com/python/cpython/commit/3a5c433fce7312748859290b9d8db5b6507660f9 commit: 3a5c433fce7312748859290b9d8db5b6507660f9 branch: master author: Barry Warsaw committer: Jason R. Coombs date: 2019-08-06T19:59:07-04:00 summary: Make importlib.metadata a simple module (#15153) files: A Lib/importlib/metadata.py D Lib/importlib/metadata/__init__.py diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata.py similarity index 100% rename from Lib/importlib/metadata/__init__.py rename to Lib/importlib/metadata.py From webhook-mailer at python.org Tue Aug 6 20:38:35 2019 From: webhook-mailer at python.org (Inada Naoki) Date: Wed, 07 Aug 2019 00:38:35 -0000 Subject: [Python-checkins] bpo-34488: optimize BytesIO.writelines() (GH-8904) Message-ID: https://github.com/python/cpython/commit/3e41f3cabb661824a1a197116f7f5ead64eb6ced commit: 3e41f3cabb661824a1a197116f7f5ead64eb6ced branch: master author: Sergey Fedoseev committer: Inada Naoki date: 2019-08-07T09:38:31+09:00 summary: bpo-34488: optimize BytesIO.writelines() (GH-8904) Avoid the creation of unused int object for each line. files: A Misc/NEWS.d/next/Library/2019-08-06-21-30-58.bpo-34488.OqxVo8.rst M Modules/_io/bytesio.c diff --git a/Misc/NEWS.d/next/Library/2019-08-06-21-30-58.bpo-34488.OqxVo8.rst b/Misc/NEWS.d/next/Library/2019-08-06-21-30-58.bpo-34488.OqxVo8.rst new file mode 100644 index 000000000000..1e7e5a6ba0bc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-06-21-30-58.bpo-34488.OqxVo8.rst @@ -0,0 +1,2 @@ +:meth:`writelines` method of :class:`io.BytesIO` is now slightly faster +when many small lines are passed. Patch by Sergey Fedoseev. diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 19e1ed8441e3..793ce920004e 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -31,17 +31,34 @@ typedef struct { * exports > 0. Py_REFCNT(buf) == 1, any modifications are forbidden. */ +static int +check_closed(bytesio *self) +{ + if (self->buf == NULL) { + PyErr_SetString(PyExc_ValueError, "I/O operation on closed file."); + return 1; + } + return 0; +} + +static int +check_exports(bytesio *self) +{ + if (self->exports > 0) { + PyErr_SetString(PyExc_BufferError, + "Existing exports of data: object cannot be re-sized"); + return 1; + } + return 0; +} + #define CHECK_CLOSED(self) \ - if ((self)->buf == NULL) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on closed file."); \ + if (check_closed(self)) { \ return NULL; \ } #define CHECK_EXPORTS(self) \ - if ((self)->exports > 0) { \ - PyErr_SetString(PyExc_BufferError, \ - "Existing exports of data: object cannot be re-sized"); \ + if (check_exports(self)) { \ return NULL; \ } @@ -156,23 +173,41 @@ resize_buffer(bytesio *self, size_t size) } /* Internal routine for writing a string of bytes to the buffer of a BytesIO - object. Returns the number of bytes written, or -1 on error. */ -static Py_ssize_t -write_bytes(bytesio *self, const char *bytes, Py_ssize_t len) + object. Returns the number of bytes written, or -1 on error. + Inlining is disabled because it's significantly decreases performance + of writelines() in PGO build. */ +_Py_NO_INLINE static Py_ssize_t +write_bytes(bytesio *self, PyObject *b) { - size_t endpos; - assert(self->buf != NULL); - assert(self->pos >= 0); - assert(len >= 0); + if (check_closed(self)) { + return -1; + } + if (check_exports(self)) { + return -1; + } - endpos = (size_t)self->pos + len; + Py_buffer buf; + if (PyObject_GetBuffer(b, &buf, PyBUF_CONTIG_RO) < 0) { + return -1; + } + Py_ssize_t len = buf.len; + if (len == 0) { + goto done; + } + + assert(self->pos >= 0); + size_t endpos = (size_t)self->pos + len; if (endpos > (size_t)PyBytes_GET_SIZE(self->buf)) { - if (resize_buffer(self, endpos) < 0) - return -1; + if (resize_buffer(self, endpos) < 0) { + len = -1; + goto done; + } } else if (SHARED_BUF(self)) { - if (unshare_buffer(self, Py_MAX(endpos, (size_t)self->string_size)) < 0) - return -1; + if (unshare_buffer(self, Py_MAX(endpos, (size_t)self->string_size)) < 0) { + len = -1; + goto done; + } } if (self->pos > self->string_size) { @@ -190,7 +225,7 @@ write_bytes(bytesio *self, const char *bytes, Py_ssize_t len) /* Copy the data to the internal buffer, overwriting some of the existing data if self->pos < self->string_size. */ - memcpy(PyBytes_AS_STRING(self->buf) + self->pos, bytes, len); + memcpy(PyBytes_AS_STRING(self->buf) + self->pos, buf.buf, len); self->pos = endpos; /* Set the new length of the internal string if it has changed. */ @@ -198,6 +233,8 @@ write_bytes(bytesio *self, const char *bytes, Py_ssize_t len) self->string_size = endpos; } + done: + PyBuffer_Release(&buf); return len; } @@ -669,19 +706,7 @@ static PyObject * _io_BytesIO_write(bytesio *self, PyObject *b) /*[clinic end generated code: output=53316d99800a0b95 input=f5ec7c8c64ed720a]*/ { - Py_ssize_t n = 0; - Py_buffer buf; - - CHECK_CLOSED(self); - CHECK_EXPORTS(self); - - if (PyObject_GetBuffer(b, &buf, PyBUF_CONTIG_RO) < 0) - return NULL; - - if (buf.len != 0) - n = write_bytes(self, buf.buf, buf.len); - - PyBuffer_Release(&buf); + Py_ssize_t n = write_bytes(self, b); return n >= 0 ? PyLong_FromSsize_t(n) : NULL; } @@ -702,7 +727,6 @@ _io_BytesIO_writelines(bytesio *self, PyObject *lines) /*[clinic end generated code: output=7f33aa3271c91752 input=e972539176fc8fc1]*/ { PyObject *it, *item; - PyObject *ret; CHECK_CLOSED(self); @@ -711,13 +735,12 @@ _io_BytesIO_writelines(bytesio *self, PyObject *lines) return NULL; while ((item = PyIter_Next(it)) != NULL) { - ret = _io_BytesIO_write(self, item); + Py_ssize_t ret = write_bytes(self, item); Py_DECREF(item); - if (ret == NULL) { + if (ret < 0) { Py_DECREF(it); return NULL; } - Py_DECREF(ret); } Py_DECREF(it); From webhook-mailer at python.org Tue Aug 6 20:56:26 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Wed, 07 Aug 2019 00:56:26 -0000 Subject: [Python-checkins] bpo-37646: Document that eval() cannot access nested scopes (GH-15117) Message-ID: https://github.com/python/cpython/commit/610a4823cc0a3c2380ad0dfe64ae483ced4e5304 commit: 610a4823cc0a3c2380ad0dfe64ae483ced4e5304 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-06T17:56:22-07:00 summary: bpo-37646: Document that eval() cannot access nested scopes (GH-15117) files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index e146f5a95acc..c225f3dee921 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -465,12 +465,16 @@ are always available. They are listed here in alphabetical order. dictionaries as global and local namespace. If the *globals* dictionary is present and does not contain a value for the key ``__builtins__``, a reference to the dictionary of the built-in module :mod:`builtins` is - inserted under that key before *expression* is parsed. - This means that *expression* normally has full - access to the standard :mod:`builtins` module and restricted environments are - propagated. If the *locals* dictionary is omitted it defaults to the *globals* - dictionary. If both dictionaries are omitted, the expression is executed in the - environment where :func:`eval` is called. The return value is the result of + inserted under that key before *expression* is parsed. This means that + *expression* normally has full access to the standard :mod:`builtins` + module and restricted environments are propagated. If the *locals* + dictionary is omitted it defaults to the *globals* dictionary. If both + dictionaries are omitted, the expression is executed with the *globals* and + *locals* in the environment where :func:`eval` is called. Note, *eval()* + does not have access to the :term:`nested scope`\s (non-locals) in the + enclosing environment. + + The return value is the result of the evaluated expression. Syntax errors are reported as exceptions. Example: >>> x = 1 From webhook-mailer at python.org Tue Aug 6 21:08:03 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Wed, 07 Aug 2019 01:08:03 -0000 Subject: [Python-checkins] bpo-37646: Document that eval() cannot access nested scopes (GH-15117) (GH-15155) Message-ID: https://github.com/python/cpython/commit/9341dcb4b9520ab92df10d4256e93a50e1e7d19f commit: 9341dcb4b9520ab92df10d4256e93a50e1e7d19f branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-06T18:07:59-07:00 summary: bpo-37646: Document that eval() cannot access nested scopes (GH-15117) (GH-15155) (cherry picked from commit 610a4823cc0a3c2380ad0dfe64ae483ced4e5304) Co-authored-by: Raymond Hettinger files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index e146f5a95acc..c225f3dee921 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -465,12 +465,16 @@ are always available. They are listed here in alphabetical order. dictionaries as global and local namespace. If the *globals* dictionary is present and does not contain a value for the key ``__builtins__``, a reference to the dictionary of the built-in module :mod:`builtins` is - inserted under that key before *expression* is parsed. - This means that *expression* normally has full - access to the standard :mod:`builtins` module and restricted environments are - propagated. If the *locals* dictionary is omitted it defaults to the *globals* - dictionary. If both dictionaries are omitted, the expression is executed in the - environment where :func:`eval` is called. The return value is the result of + inserted under that key before *expression* is parsed. This means that + *expression* normally has full access to the standard :mod:`builtins` + module and restricted environments are propagated. If the *locals* + dictionary is omitted it defaults to the *globals* dictionary. If both + dictionaries are omitted, the expression is executed with the *globals* and + *locals* in the environment where :func:`eval` is called. Note, *eval()* + does not have access to the :term:`nested scope`\s (non-locals) in the + enclosing environment. + + The return value is the result of the evaluated expression. Syntax errors are reported as exceptions. Example: >>> x = 1 From webhook-mailer at python.org Tue Aug 6 21:38:26 2019 From: webhook-mailer at python.org (Jason R. Coombs) Date: Wed, 07 Aug 2019 01:38:26 -0000 Subject: [Python-checkins] Make importlib.metadata a simple module (GH-15153) (GH-15154) Message-ID: https://github.com/python/cpython/commit/e780d2f1f5e621adf5a2a8b39cb266946bcc0a18 commit: e780d2f1f5e621adf5a2a8b39cb266946bcc0a18 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Jason R. Coombs date: 2019-08-06T21:38:22-04:00 summary: Make importlib.metadata a simple module (GH-15153) (GH-15154) (cherry picked from commit 3a5c433fce7312748859290b9d8db5b6507660f9) Co-authored-by: Barry Warsaw files: A Lib/importlib/metadata.py D Lib/importlib/metadata/__init__.py diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata.py similarity index 100% rename from Lib/importlib/metadata/__init__.py rename to Lib/importlib/metadata.py From webhook-mailer at python.org Wed Aug 7 00:37:16 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 07 Aug 2019 04:37:16 -0000 Subject: [Python-checkins] bpo-37004: Documented asymmetry of string arguments in difflib.SequenceMatcher for ratio method (GH-13482) Message-ID: https://github.com/python/cpython/commit/e9cbcd0018abd2a5f2348c45d5c9c4265c4f42dc commit: e9cbcd0018abd2a5f2348c45d5c9c4265c4f42dc branch: master author: sweeneyde <36520290+sweeneyde at users.noreply.github.com> committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-06T21:37:08-07:00 summary: bpo-37004: Documented asymmetry of string arguments in difflib.SequenceMatcher for ratio method (GH-13482) https://bugs.python.org/issue37004 files: A Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst M Doc/library/difflib.rst diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst index f044cb2d6e0a..e245ab81cfb9 100644 --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -543,6 +543,16 @@ The :class:`SequenceMatcher` class has this constructor: to try :meth:`quick_ratio` or :meth:`real_quick_ratio` first to get an upper bound. + .. note:: + + Caution: The result of a :meth:`ratio` call may depend on the order of + the arguments. For instance:: + + >>> SequenceMatcher(None, 'tide', 'diet').ratio() + 0.25 + >>> SequenceMatcher(None, 'diet', 'tide').ratio() + 0.5 + .. method:: quick_ratio() diff --git a/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst b/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst new file mode 100644 index 000000000000..dfc8b7ed74ca --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst @@ -0,0 +1 @@ +In the documentation for difflib, a note was added explicitly warning that the results of SequenceMatcher's ratio method may depend on the order of the input strings. \ No newline at end of file From webhook-mailer at python.org Wed Aug 7 01:02:27 2019 From: webhook-mailer at python.org (Carol Willing) Date: Wed, 07 Aug 2019 05:02:27 -0000 Subject: [Python-checkins] Update pickle.rst (GH-14128) Message-ID: https://github.com/python/cpython/commit/362f5350eb5e2c7bfb0b0a8c306a2e128c3aee93 commit: 362f5350eb5e2c7bfb0b0a8c306a2e128c3aee93 branch: master author: G?ry Ogam committer: Carol Willing date: 2019-08-06T22:02:23-07:00 summary: Update pickle.rst (GH-14128) * Edits for readability and grammar files: M Doc/library/pickle.rst diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst index e6025aeaf476..09c9c86abbba 100644 --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -197,8 +197,9 @@ process more convenient: .. function:: dump(obj, file, protocol=None, \*, fix_imports=True, buffer_callback=None) - Write a pickled representation of *obj* to the open :term:`file object` *file*. - This is equivalent to ``Pickler(file, protocol).dump(obj)``. + Write the pickled representation of the object *obj* to the open + :term:`file object` *file*. This is equivalent to + ``Pickler(file, protocol).dump(obj)``. Arguments *file*, *protocol*, *fix_imports* and *buffer_callback* have the same meaning as in the :class:`Pickler` constructor. @@ -208,7 +209,7 @@ process more convenient: .. function:: dumps(obj, protocol=None, \*, fix_imports=True, buffer_callback=None) - Return the pickled representation of the object as a :class:`bytes` object, + Return the pickled representation of the object *obj* as a :class:`bytes` object, instead of writing it to a file. Arguments *protocol*, *fix_imports* and *buffer_callback* have the same @@ -219,13 +220,13 @@ process more convenient: .. function:: load(file, \*, fix_imports=True, encoding="ASCII", errors="strict", buffers=None) - Read a pickled object representation from the open :term:`file object` + Read the pickled representation of an object from the open :term:`file object` *file* and return the reconstituted object hierarchy specified therein. This is equivalent to ``Unpickler(file).load()``. The protocol version of the pickle is detected automatically, so no - protocol argument is needed. Bytes past the pickled object's - representation are ignored. + protocol argument is needed. Bytes past the pickled representation + of the object are ignored. Arguments *file*, *fix_imports*, *encoding*, *errors*, *strict* and *buffers* have the same meaning as in the :class:`Unpickler` constructor. @@ -235,12 +236,12 @@ process more convenient: .. function:: loads(bytes_object, \*, fix_imports=True, encoding="ASCII", errors="strict", buffers=None) - Read a pickled object hierarchy from a :class:`bytes` object and return the - reconstituted object hierarchy specified therein. + Return the reconstituted object hierarchy of the pickled representation + *bytes_object* of an object. The protocol version of the pickle is detected automatically, so no - protocol argument is needed. Bytes past the pickled object's - representation are ignored. + protocol argument is needed. Bytes past the pickled representation + of the object are ignored. Arguments *file*, *fix_imports*, *encoding*, *errors*, *strict* and *buffers* have the same meaning as in the :class:`Unpickler` constructor. @@ -311,7 +312,7 @@ The :mod:`pickle` module exports three classes, :class:`Pickler`, .. method:: dump(obj) - Write a pickled representation of *obj* to the open file object given in + Write the pickled representation of *obj* to the open file object given in the constructor. .. method:: persistent_id(obj) @@ -412,9 +413,10 @@ The :mod:`pickle` module exports three classes, :class:`Pickler`, .. method:: load() - Read a pickled object representation from the open file object given in - the constructor, and return the reconstituted object hierarchy specified - therein. Bytes past the pickled object's representation are ignored. + Read the pickled representation of an object from the open file object + given in the constructor, and return the reconstituted object hierarchy + specified therein. Bytes past the pickled representation of the object + are ignored. .. method:: persistent_load(pid) @@ -717,13 +719,13 @@ alphanumeric characters (for protocol 0) [#]_ or just an arbitrary object (for any newer protocol). The resolution of such persistent IDs is not defined by the :mod:`pickle` -module; it will delegate this resolution to the user defined methods on the +module; it will delegate this resolution to the user-defined methods on the pickler and unpickler, :meth:`~Pickler.persistent_id` and :meth:`~Unpickler.persistent_load` respectively. -To pickle objects that have an external persistent id, the pickler must have a +To pickle objects that have an external persistent ID, the pickler must have a custom :meth:`~Pickler.persistent_id` method that takes an object as an -argument and returns either ``None`` or the persistent id for that object. +argument and returns either ``None`` or the persistent ID for that object. When ``None`` is returned, the pickler simply pickles the object as normal. When a persistent ID string is returned, the pickler will pickle that object, along with a marker so that the unpickler will recognize it as a persistent ID. From webhook-mailer at python.org Wed Aug 7 11:39:37 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Wed, 07 Aug 2019 15:39:37 -0000 Subject: [Python-checkins] bpo-37004: Documented asymmetry of string arguments in difflib.SequenceMatcher for ratio method (GH-13482) (#15157) Message-ID: https://github.com/python/cpython/commit/1a3a40c1cb582e436d568009fae2b06c0b1978ed commit: 1a3a40c1cb582e436d568009fae2b06c0b1978ed branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2019-08-07T11:39:14-04:00 summary: bpo-37004: Documented asymmetry of string arguments in difflib.SequenceMatcher for ratio method (GH-13482) (#15157) https://bugs.python.org/issue37004 (cherry picked from commit e9cbcd0018abd2a5f2348c45d5c9c4265c4f42dc) Co-authored-by: sweeneyde <36520290+sweeneyde at users.noreply.github.com> files: A Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst M Doc/library/difflib.rst diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst index f044cb2d6e0a..e245ab81cfb9 100644 --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -543,6 +543,16 @@ The :class:`SequenceMatcher` class has this constructor: to try :meth:`quick_ratio` or :meth:`real_quick_ratio` first to get an upper bound. + .. note:: + + Caution: The result of a :meth:`ratio` call may depend on the order of + the arguments. For instance:: + + >>> SequenceMatcher(None, 'tide', 'diet').ratio() + 0.25 + >>> SequenceMatcher(None, 'diet', 'tide').ratio() + 0.5 + .. method:: quick_ratio() diff --git a/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst b/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst new file mode 100644 index 000000000000..dfc8b7ed74ca --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst @@ -0,0 +1 @@ +In the documentation for difflib, a note was added explicitly warning that the results of SequenceMatcher's ratio method may depend on the order of the input strings. \ No newline at end of file From webhook-mailer at python.org Wed Aug 7 11:39:53 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Wed, 07 Aug 2019 15:39:53 -0000 Subject: [Python-checkins] bpo-37004: Documented asymmetry of string arguments in difflib.SequenceMatcher for ratio method (GH-13482) (#15158) Message-ID: https://github.com/python/cpython/commit/7dafbe81bd0afb8bd67bc3a4c851a6c728fd87fe commit: 7dafbe81bd0afb8bd67bc3a4c851a6c728fd87fe branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2019-08-07T11:39:47-04:00 summary: bpo-37004: Documented asymmetry of string arguments in difflib.SequenceMatcher for ratio method (GH-13482) (#15158) https://bugs.python.org/issue37004 (cherry picked from commit e9cbcd0018abd2a5f2348c45d5c9c4265c4f42dc) Co-authored-by: sweeneyde <36520290+sweeneyde at users.noreply.github.com> files: A Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst M Doc/library/difflib.rst diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst index f044cb2d6e0a..e245ab81cfb9 100644 --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -543,6 +543,16 @@ The :class:`SequenceMatcher` class has this constructor: to try :meth:`quick_ratio` or :meth:`real_quick_ratio` first to get an upper bound. + .. note:: + + Caution: The result of a :meth:`ratio` call may depend on the order of + the arguments. For instance:: + + >>> SequenceMatcher(None, 'tide', 'diet').ratio() + 0.25 + >>> SequenceMatcher(None, 'diet', 'tide').ratio() + 0.5 + .. method:: quick_ratio() diff --git a/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst b/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst new file mode 100644 index 000000000000..dfc8b7ed74ca --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst @@ -0,0 +1 @@ +In the documentation for difflib, a note was added explicitly warning that the results of SequenceMatcher's ratio method may depend on the order of the input strings. \ No newline at end of file From webhook-mailer at python.org Wed Aug 7 13:49:47 2019 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 07 Aug 2019 17:49:47 -0000 Subject: [Python-checkins] bpo-37734: Fix use of registry values to launch Python from Microsoft Store app (GH-15146) Message-ID: https://github.com/python/cpython/commit/1fab9cbfbaf19a7bc79cef382136fcf9491e3183 commit: 1fab9cbfbaf19a7bc79cef382136fcf9491e3183 branch: master author: Steve Dower committer: GitHub date: 2019-08-07T10:49:40-07:00 summary: bpo-37734: Fix use of registry values to launch Python from Microsoft Store app (GH-15146) files: A Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst M PC/layout/main.py M PC/layout/support/appxmanifest.py diff --git a/Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst b/Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst new file mode 100644 index 000000000000..51feecb076ba --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst @@ -0,0 +1 @@ +Fix use of registry values to launch Python from Microsoft Store app. diff --git a/PC/layout/main.py b/PC/layout/main.py index fe934bfb1ab3..07b7e6d57429 100644 --- a/PC/layout/main.py +++ b/PC/layout/main.py @@ -153,9 +153,15 @@ def in_build(f, dest="", new_name=None): yield "libs/" + n + ".lib", lib if ns.include_appxmanifest: + yield from in_build("python_uwp.exe", new_name="python{}".format(VER_DOT)) + yield from in_build("pythonw_uwp.exe", new_name="pythonw{}".format(VER_DOT)) + # For backwards compatibility, but we don't reference these ourselves. yield from in_build("python_uwp.exe", new_name="python") yield from in_build("pythonw_uwp.exe", new_name="pythonw") else: + yield from in_build("python.exe", new_name="python{}".format(VER_DOT)) + yield from in_build("pythonw.exe", new_name="pythonw{}".format(VER_DOT)) + # For backwards compatibility, but we don't reference these ourselves. yield from in_build("python.exe", new_name="python") yield from in_build("pythonw.exe", new_name="pythonw") @@ -163,9 +169,9 @@ def in_build(f, dest="", new_name=None): if ns.include_launchers and ns.include_appxmanifest: if ns.include_pip: - yield from in_build("python_uwp.exe", new_name="pip") + yield from in_build("python_uwp.exe", new_name="pip{}".format(VER_DOT)) if ns.include_idle: - yield from in_build("pythonw_uwp.exe", new_name="idle") + yield from in_build("pythonw_uwp.exe", new_name="idle{}".format(VER_DOT)) if ns.include_stable: yield from in_build(PYTHON_STABLE_DLL_NAME) diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index 58fba8443f17..0a0f1fc8181c 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -154,9 +154,9 @@ "SysVersion": VER_DOT, "Version": "{}.{}.{}".format(VER_MAJOR, VER_MINOR, VER_MICRO), "InstallPath": { - "": "[{AppVPackageRoot}]", - "ExecutablePath": "[{AppVPackageRoot}]\\python.exe", - "WindowedExecutablePath": "[{AppVPackageRoot}]\\pythonw.exe", + "": "[{{AppVPackageRoot}}]", + "ExecutablePath": "[{{AppVPackageRoot}}]\\python{}.exe".format(VER_DOT), + "WindowedExecutablePath": "[{{AppVPackageRoot}}]\\pythonw{}.exe".format(VER_DOT), }, "Help": { "Main Python Documentation": { @@ -395,7 +395,7 @@ def get_appxmanifest(ns): ns, xml, "Python", - "python", + "python{}".format(VER_DOT), ["python", "python{}".format(VER_MAJOR), "python{}".format(VER_DOT)], PYTHON_VE_DATA, "console", @@ -406,7 +406,7 @@ def get_appxmanifest(ns): ns, xml, "PythonW", - "pythonw", + "pythonw{}".format(VER_DOT), ["pythonw", "pythonw{}".format(VER_MAJOR), "pythonw{}".format(VER_DOT)], PYTHONW_VE_DATA, "windows", @@ -418,7 +418,7 @@ def get_appxmanifest(ns): ns, xml, "Pip", - "pip", + "pip{}".format(VER_DOT), ["pip", "pip{}".format(VER_MAJOR), "pip{}".format(VER_DOT)], PIP_VE_DATA, "console", @@ -430,7 +430,7 @@ def get_appxmanifest(ns): ns, xml, "Idle", - "idle", + "idle{}".format(VER_DOT), ["idle", "idle{}".format(VER_MAJOR), "idle{}".format(VER_DOT)], IDLE_VE_DATA, "windows", From webhook-mailer at python.org Wed Aug 7 13:50:21 2019 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 07 Aug 2019 17:50:21 -0000 Subject: [Python-checkins] bpo-37778: Fixes the icons used for file associations to the Microsoft Store package (GH-15150) Message-ID: https://github.com/python/cpython/commit/87ce9588ceb4b4dd625913344844390f0b991b0c commit: 87ce9588ceb4b4dd625913344844390f0b991b0c branch: master author: Steve Dower committer: GitHub date: 2019-08-07T10:50:17-07:00 summary: bpo-37778: Fixes the icons used for file associations to the Microsoft Store package (GH-15150) files: A Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst A PC/icons/py.png M PC/layout/support/appxmanifest.py diff --git a/Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst b/Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst new file mode 100644 index 000000000000..14d81c05ee84 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst @@ -0,0 +1 @@ +Fixes the icons used for file associations to the Microsoft Store package. diff --git a/PC/icons/py.png b/PC/icons/py.png new file mode 100644 index 000000000000..5c184e6a745f Binary files /dev/null and b/PC/icons/py.png differ diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index 0a0f1fc8181c..4273b427e903 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -65,6 +65,8 @@ BackgroundColor="transparent", ) +PY_PNG = '_resources/py.png' + APPXMANIFEST_NS = { "": "http://schemas.microsoft.com/appx/manifest/foundation/windows10", "m": "http://schemas.microsoft.com/appx/manifest/foundation/windows10", @@ -278,12 +280,16 @@ def add_alias(xml, appid, alias, subsystem="windows"): e = find_or_add(e, "uap5:ExecutionAlias", ("Alias", alias)) -def add_file_type(xml, appid, name, suffix, parameters='"%1"'): +def add_file_type(xml, appid, name, suffix, parameters='"%1"', info=None, logo=None): app = _get_app(xml, appid) e = find_or_add(app, "m:Extensions") e = find_or_add(e, "uap3:Extension", ("Category", "windows.fileTypeAssociation")) e = find_or_add(e, "uap3:FileTypeAssociation", ("Name", name)) e.set("Parameters", parameters) + if info: + find_or_add(e, "uap:DisplayName").text = info + if logo: + find_or_add(e, "uap:Logo").text = logo e = find_or_add(e, "uap:SupportedFileTypes") if isinstance(suffix, str): suffix = [suffix] @@ -399,7 +405,7 @@ def get_appxmanifest(ns): ["python", "python{}".format(VER_MAJOR), "python{}".format(VER_DOT)], PYTHON_VE_DATA, "console", - ("python.file", [".py"]), + ("python.file", [".py"], '"%1"', 'Python File', PY_PNG), ) add_application( @@ -410,7 +416,7 @@ def get_appxmanifest(ns): ["pythonw", "pythonw{}".format(VER_MAJOR), "pythonw{}".format(VER_DOT)], PYTHONW_VE_DATA, "windows", - ("python.windowedfile", [".pyw"]), + ("python.windowedfile", [".pyw"], '"%1"', 'Python File (no console)', PY_PNG), ) if ns.include_pip and ns.include_launchers: @@ -422,7 +428,7 @@ def get_appxmanifest(ns): ["pip", "pip{}".format(VER_MAJOR), "pip{}".format(VER_DOT)], PIP_VE_DATA, "console", - ("python.wheel", [".whl"], 'install "%1"'), + ("python.wheel", [".whl"], 'install "%1"', 'Python Wheel'), ) if ns.include_idle and ns.include_launchers: @@ -459,16 +465,15 @@ def get_appx_layout(ns): yield "AppxManifest.xml", ("AppxManifest.xml", get_appxmanifest(ns)) yield "_resources.xml", ("_resources.xml", get_resources_xml(ns)) icons = ns.source / "PC" / "icons" - yield "_resources/pythonx44.png", icons / "pythonx44.png" - yield "_resources/pythonx44$targetsize-44_altform-unplated.png", icons / "pythonx44.png" - yield "_resources/pythonx50.png", icons / "pythonx50.png" - yield "_resources/pythonx50$targetsize-50_altform-unplated.png", icons / "pythonx50.png" - yield "_resources/pythonx150.png", icons / "pythonx150.png" - yield "_resources/pythonx150$targetsize-150_altform-unplated.png", icons / "pythonx150.png" - yield "_resources/pythonwx44.png", icons / "pythonwx44.png" - yield "_resources/pythonwx44$targetsize-44_altform-unplated.png", icons / "pythonwx44.png" - yield "_resources/pythonwx150.png", icons / "pythonwx150.png" - yield "_resources/pythonwx150$targetsize-150_altform-unplated.png", icons / "pythonwx150.png" + for px in [44, 50, 150]: + src = icons / "pythonx{}.png".format(px) + yield f"_resources/pythonx{px}.png", src + yield f"_resources/pythonx{px}$targetsize-{px}_altform-unplated.png", src + for px in [44, 150]: + src = icons / "pythonwx{}.png".format(px) + yield f"_resources/pythonwx{px}.png", src + yield f"_resources/pythonwx{px}$targetsize-{px}_altform-unplated.png", src + yield f"_resources/py.png", icons / "py.png" sccd = ns.source / SCCD_FILENAME if sccd.is_file(): # This should only be set for side-loading purposes. From webhook-mailer at python.org Wed Aug 7 14:07:48 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 07 Aug 2019 18:07:48 -0000 Subject: [Python-checkins] bpo-37734: Fix use of registry values to launch Python from Microsoft Store app (GH-15146) Message-ID: https://github.com/python/cpython/commit/eab76c3c75a572566862200728cc8d05b3298f12 commit: eab76c3c75a572566862200728cc8d05b3298f12 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-07T11:07:43-07:00 summary: bpo-37734: Fix use of registry values to launch Python from Microsoft Store app (GH-15146) (cherry picked from commit 1fab9cbfbaf19a7bc79cef382136fcf9491e3183) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst M PC/layout/main.py M PC/layout/support/appxmanifest.py diff --git a/Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst b/Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst new file mode 100644 index 000000000000..51feecb076ba --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst @@ -0,0 +1 @@ +Fix use of registry values to launch Python from Microsoft Store app. diff --git a/PC/layout/main.py b/PC/layout/main.py index fe934bfb1ab3..07b7e6d57429 100644 --- a/PC/layout/main.py +++ b/PC/layout/main.py @@ -153,9 +153,15 @@ def in_build(f, dest="", new_name=None): yield "libs/" + n + ".lib", lib if ns.include_appxmanifest: + yield from in_build("python_uwp.exe", new_name="python{}".format(VER_DOT)) + yield from in_build("pythonw_uwp.exe", new_name="pythonw{}".format(VER_DOT)) + # For backwards compatibility, but we don't reference these ourselves. yield from in_build("python_uwp.exe", new_name="python") yield from in_build("pythonw_uwp.exe", new_name="pythonw") else: + yield from in_build("python.exe", new_name="python{}".format(VER_DOT)) + yield from in_build("pythonw.exe", new_name="pythonw{}".format(VER_DOT)) + # For backwards compatibility, but we don't reference these ourselves. yield from in_build("python.exe", new_name="python") yield from in_build("pythonw.exe", new_name="pythonw") @@ -163,9 +169,9 @@ def in_build(f, dest="", new_name=None): if ns.include_launchers and ns.include_appxmanifest: if ns.include_pip: - yield from in_build("python_uwp.exe", new_name="pip") + yield from in_build("python_uwp.exe", new_name="pip{}".format(VER_DOT)) if ns.include_idle: - yield from in_build("pythonw_uwp.exe", new_name="idle") + yield from in_build("pythonw_uwp.exe", new_name="idle{}".format(VER_DOT)) if ns.include_stable: yield from in_build(PYTHON_STABLE_DLL_NAME) diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index 58fba8443f17..0a0f1fc8181c 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -154,9 +154,9 @@ "SysVersion": VER_DOT, "Version": "{}.{}.{}".format(VER_MAJOR, VER_MINOR, VER_MICRO), "InstallPath": { - "": "[{AppVPackageRoot}]", - "ExecutablePath": "[{AppVPackageRoot}]\\python.exe", - "WindowedExecutablePath": "[{AppVPackageRoot}]\\pythonw.exe", + "": "[{{AppVPackageRoot}}]", + "ExecutablePath": "[{{AppVPackageRoot}}]\\python{}.exe".format(VER_DOT), + "WindowedExecutablePath": "[{{AppVPackageRoot}}]\\pythonw{}.exe".format(VER_DOT), }, "Help": { "Main Python Documentation": { @@ -395,7 +395,7 @@ def get_appxmanifest(ns): ns, xml, "Python", - "python", + "python{}".format(VER_DOT), ["python", "python{}".format(VER_MAJOR), "python{}".format(VER_DOT)], PYTHON_VE_DATA, "console", @@ -406,7 +406,7 @@ def get_appxmanifest(ns): ns, xml, "PythonW", - "pythonw", + "pythonw{}".format(VER_DOT), ["pythonw", "pythonw{}".format(VER_MAJOR), "pythonw{}".format(VER_DOT)], PYTHONW_VE_DATA, "windows", @@ -418,7 +418,7 @@ def get_appxmanifest(ns): ns, xml, "Pip", - "pip", + "pip{}".format(VER_DOT), ["pip", "pip{}".format(VER_MAJOR), "pip{}".format(VER_DOT)], PIP_VE_DATA, "console", @@ -430,7 +430,7 @@ def get_appxmanifest(ns): ns, xml, "Idle", - "idle", + "idle{}".format(VER_DOT), ["idle", "idle{}".format(VER_MAJOR), "idle{}".format(VER_DOT)], IDLE_VE_DATA, "windows", From webhook-mailer at python.org Wed Aug 7 14:15:20 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 07 Aug 2019 18:15:20 -0000 Subject: [Python-checkins] bpo-37778: Fixes the icons used for file associations to the Microsoft Store package (GH-15150) Message-ID: https://github.com/python/cpython/commit/dc6653fd06598f42b107dcffcd089d7ee2b1cd44 commit: dc6653fd06598f42b107dcffcd089d7ee2b1cd44 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-07T11:15:15-07:00 summary: bpo-37778: Fixes the icons used for file associations to the Microsoft Store package (GH-15150) (cherry picked from commit 87ce9588ceb4b4dd625913344844390f0b991b0c) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst A PC/icons/py.png M PC/layout/support/appxmanifest.py diff --git a/Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst b/Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst new file mode 100644 index 000000000000..14d81c05ee84 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst @@ -0,0 +1 @@ +Fixes the icons used for file associations to the Microsoft Store package. diff --git a/PC/icons/py.png b/PC/icons/py.png new file mode 100644 index 000000000000..5c184e6a745f Binary files /dev/null and b/PC/icons/py.png differ diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index 0a0f1fc8181c..4273b427e903 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -65,6 +65,8 @@ BackgroundColor="transparent", ) +PY_PNG = '_resources/py.png' + APPXMANIFEST_NS = { "": "http://schemas.microsoft.com/appx/manifest/foundation/windows10", "m": "http://schemas.microsoft.com/appx/manifest/foundation/windows10", @@ -278,12 +280,16 @@ def add_alias(xml, appid, alias, subsystem="windows"): e = find_or_add(e, "uap5:ExecutionAlias", ("Alias", alias)) -def add_file_type(xml, appid, name, suffix, parameters='"%1"'): +def add_file_type(xml, appid, name, suffix, parameters='"%1"', info=None, logo=None): app = _get_app(xml, appid) e = find_or_add(app, "m:Extensions") e = find_or_add(e, "uap3:Extension", ("Category", "windows.fileTypeAssociation")) e = find_or_add(e, "uap3:FileTypeAssociation", ("Name", name)) e.set("Parameters", parameters) + if info: + find_or_add(e, "uap:DisplayName").text = info + if logo: + find_or_add(e, "uap:Logo").text = logo e = find_or_add(e, "uap:SupportedFileTypes") if isinstance(suffix, str): suffix = [suffix] @@ -399,7 +405,7 @@ def get_appxmanifest(ns): ["python", "python{}".format(VER_MAJOR), "python{}".format(VER_DOT)], PYTHON_VE_DATA, "console", - ("python.file", [".py"]), + ("python.file", [".py"], '"%1"', 'Python File', PY_PNG), ) add_application( @@ -410,7 +416,7 @@ def get_appxmanifest(ns): ["pythonw", "pythonw{}".format(VER_MAJOR), "pythonw{}".format(VER_DOT)], PYTHONW_VE_DATA, "windows", - ("python.windowedfile", [".pyw"]), + ("python.windowedfile", [".pyw"], '"%1"', 'Python File (no console)', PY_PNG), ) if ns.include_pip and ns.include_launchers: @@ -422,7 +428,7 @@ def get_appxmanifest(ns): ["pip", "pip{}".format(VER_MAJOR), "pip{}".format(VER_DOT)], PIP_VE_DATA, "console", - ("python.wheel", [".whl"], 'install "%1"'), + ("python.wheel", [".whl"], 'install "%1"', 'Python Wheel'), ) if ns.include_idle and ns.include_launchers: @@ -459,16 +465,15 @@ def get_appx_layout(ns): yield "AppxManifest.xml", ("AppxManifest.xml", get_appxmanifest(ns)) yield "_resources.xml", ("_resources.xml", get_resources_xml(ns)) icons = ns.source / "PC" / "icons" - yield "_resources/pythonx44.png", icons / "pythonx44.png" - yield "_resources/pythonx44$targetsize-44_altform-unplated.png", icons / "pythonx44.png" - yield "_resources/pythonx50.png", icons / "pythonx50.png" - yield "_resources/pythonx50$targetsize-50_altform-unplated.png", icons / "pythonx50.png" - yield "_resources/pythonx150.png", icons / "pythonx150.png" - yield "_resources/pythonx150$targetsize-150_altform-unplated.png", icons / "pythonx150.png" - yield "_resources/pythonwx44.png", icons / "pythonwx44.png" - yield "_resources/pythonwx44$targetsize-44_altform-unplated.png", icons / "pythonwx44.png" - yield "_resources/pythonwx150.png", icons / "pythonwx150.png" - yield "_resources/pythonwx150$targetsize-150_altform-unplated.png", icons / "pythonwx150.png" + for px in [44, 50, 150]: + src = icons / "pythonx{}.png".format(px) + yield f"_resources/pythonx{px}.png", src + yield f"_resources/pythonx{px}$targetsize-{px}_altform-unplated.png", src + for px in [44, 150]: + src = icons / "pythonwx{}.png".format(px) + yield f"_resources/pythonwx{px}.png", src + yield f"_resources/pythonwx{px}$targetsize-{px}_altform-unplated.png", src + yield f"_resources/py.png", icons / "py.png" sccd = ns.source / SCCD_FILENAME if sccd.is_file(): # This should only be set for side-loading purposes. From webhook-mailer at python.org Wed Aug 7 14:39:19 2019 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 07 Aug 2019 18:39:19 -0000 Subject: [Python-checkins] bpo-37734: Remove unnecessary brace escapes in PC/layout script (GH-15165) Message-ID: https://github.com/python/cpython/commit/0378d98678f3617fd44d9a6266e7c17ebce62755 commit: 0378d98678f3617fd44d9a6266e7c17ebce62755 branch: master author: Steve Dower committer: GitHub date: 2019-08-07T11:39:09-07:00 summary: bpo-37734: Remove unnecessary brace escapes in PC/layout script (GH-15165) files: M PC/layout/support/appxmanifest.py diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index 4273b427e903..de5813a2536a 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -156,7 +156,7 @@ "SysVersion": VER_DOT, "Version": "{}.{}.{}".format(VER_MAJOR, VER_MINOR, VER_MICRO), "InstallPath": { - "": "[{{AppVPackageRoot}}]", + "": "[{AppVPackageRoot}]", "ExecutablePath": "[{{AppVPackageRoot}}]\\python{}.exe".format(VER_DOT), "WindowedExecutablePath": "[{{AppVPackageRoot}}]\\pythonw{}.exe".format(VER_DOT), }, From webhook-mailer at python.org Wed Aug 7 14:59:13 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 07 Aug 2019 18:59:13 -0000 Subject: [Python-checkins] bpo-37734: Remove unnecessary brace escapes in PC/layout script (GH-15165) Message-ID: https://github.com/python/cpython/commit/84d31bbf1f7e10bde1ceadcfa0d83d30a04313d5 commit: 84d31bbf1f7e10bde1ceadcfa0d83d30a04313d5 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-07T11:59:09-07:00 summary: bpo-37734: Remove unnecessary brace escapes in PC/layout script (GH-15165) (cherry picked from commit 0378d98678f3617fd44d9a6266e7c17ebce62755) Co-authored-by: Steve Dower files: M PC/layout/support/appxmanifest.py diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index 4273b427e903..de5813a2536a 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -156,7 +156,7 @@ "SysVersion": VER_DOT, "Version": "{}.{}.{}".format(VER_MAJOR, VER_MINOR, VER_MICRO), "InstallPath": { - "": "[{{AppVPackageRoot}}]", + "": "[{AppVPackageRoot}]", "ExecutablePath": "[{{AppVPackageRoot}}]\\python{}.exe".format(VER_DOT), "WindowedExecutablePath": "[{{AppVPackageRoot}}]\\pythonw{}.exe".format(VER_DOT), }, From webhook-mailer at python.org Thu Aug 8 01:41:19 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 08 Aug 2019 05:41:19 -0000 Subject: [Python-checkins] bpo-34775: Return NotImplemented in PurePath division. (GH-9509) Message-ID: https://github.com/python/cpython/commit/4c69be22df3852f17873a74d015528d9a8ae92d6 commit: 4c69be22df3852f17873a74d015528d9a8ae92d6 branch: master author: aiudirog committer: Serhiy Storchaka date: 2019-08-08T08:41:10+03:00 summary: bpo-34775: Return NotImplemented in PurePath division. (GH-9509) files: A Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst M Lib/pathlib.py M Lib/test/test_pathlib.py diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 6369c4b2218d..6355ae864108 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -907,10 +907,16 @@ def joinpath(self, *args): return self._make_child(args) def __truediv__(self, key): - return self._make_child((key,)) + try: + return self._make_child((key,)) + except TypeError: + return NotImplemented def __rtruediv__(self, key): - return self._from_parts([key] + self._parts) + try: + return self._from_parts([key] + self._parts) + except TypeError: + return NotImplemented @property def parent(self): diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 069467a8459f..f74524d992a1 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2329,5 +2329,46 @@ def check(): check() +class CompatiblePathTest(unittest.TestCase): + """ + Test that a type can be made compatible with PurePath + derivatives by implementing division operator overloads. + """ + + class CompatPath: + """ + Minimum viable class to test PurePath compatibility. + Simply uses the division operator to join a given + string and the string value of another object with + a forward slash. + """ + def __init__(self, string): + self.string = string + + def __truediv__(self, other): + return type(self)(f"{self.string}/{other}") + + def __rtruediv__(self, other): + return type(self)(f"{other}/{self.string}") + + def test_truediv(self): + result = pathlib.PurePath("test") / self.CompatPath("right") + self.assertIsInstance(result, self.CompatPath) + self.assertEqual(result.string, "test/right") + + with self.assertRaises(TypeError): + # Verify improper operations still raise a TypeError + pathlib.PurePath("test") / 10 + + def test_rtruediv(self): + result = self.CompatPath("left") / pathlib.PurePath("test") + self.assertIsInstance(result, self.CompatPath) + self.assertEqual(result.string, "left/test") + + with self.assertRaises(TypeError): + # Verify improper operations still raise a TypeError + 10 / pathlib.PurePath("test") + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst b/Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst new file mode 100644 index 000000000000..f99bf5b39f95 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst @@ -0,0 +1,3 @@ +Division handling of PurePath now returns NotImplemented instead of raising +a TypeError when passed something other than an instance of str or PurePath. +Patch by Roger Aiudi. From webhook-mailer at python.org Thu Aug 8 01:42:58 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 08 Aug 2019 05:42:58 -0000 Subject: [Python-checkins] bpo-37685: Fixed __eq__, __lt__ etc implementations in some classes. (GH-14952) Message-ID: https://github.com/python/cpython/commit/662db125cddbca1db68116c547c290eb3943d98e commit: 662db125cddbca1db68116c547c290eb3943d98e branch: master author: Serhiy Storchaka committer: GitHub date: 2019-08-08T08:42:54+03:00 summary: bpo-37685: Fixed __eq__, __lt__ etc implementations in some classes. (GH-14952) They now return NotImplemented for unsupported type of the other operand. files: A Misc/NEWS.d/next/Library/2019-07-26-00-12-29.bpo-37685.TqckMZ.rst M Lib/asyncio/events.py M Lib/distutils/tests/test_version.py M Lib/distutils/version.py M Lib/email/headerregistry.py M Lib/importlib/_bootstrap.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_email/test_headerregistry.py M Lib/test/test_traceback.py M Lib/test/test_weakref.py M Lib/test/test_xmlrpc.py M Lib/tkinter/__init__.py M Lib/tkinter/font.py M Lib/tkinter/test/test_tkinter/test_font.py M Lib/tkinter/test/test_tkinter/test_variables.py M Lib/traceback.py M Lib/tracemalloc.py M Lib/unittest/mock.py M Lib/unittest/test/testmock/testmock.py M Lib/weakref.py M Lib/xmlrpc/client.py M Python/importlib.h M Tools/pynche/PyncheWidget.py diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index d381b1c59623..5fb546429cbe 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -119,20 +119,24 @@ def __hash__(self): return hash(self._when) def __lt__(self, other): - return self._when < other._when + if isinstance(other, TimerHandle): + return self._when < other._when + return NotImplemented def __le__(self, other): - if self._when < other._when: - return True - return self.__eq__(other) + if isinstance(other, TimerHandle): + return self._when < other._when or self.__eq__(other) + return NotImplemented def __gt__(self, other): - return self._when > other._when + if isinstance(other, TimerHandle): + return self._when > other._when + return NotImplemented def __ge__(self, other): - if self._when > other._when: - return True - return self.__eq__(other) + if isinstance(other, TimerHandle): + return self._when > other._when or self.__eq__(other) + return NotImplemented def __eq__(self, other): if isinstance(other, TimerHandle): @@ -142,10 +146,6 @@ def __eq__(self, other): self._cancelled == other._cancelled) return NotImplemented - def __ne__(self, other): - equal = self.__eq__(other) - return NotImplemented if equal is NotImplemented else not equal - def cancel(self): if not self._cancelled: self._loop._timer_handle_cancelled(self) diff --git a/Lib/distutils/tests/test_version.py b/Lib/distutils/tests/test_version.py index 15f14c7de3f1..8671cd2fc5c1 100644 --- a/Lib/distutils/tests/test_version.py +++ b/Lib/distutils/tests/test_version.py @@ -45,6 +45,14 @@ def test_cmp_strict(self): self.assertEqual(res, wanted, 'cmp(%s, %s) should be %s, got %s' % (v1, v2, wanted, res)) + res = StrictVersion(v1)._cmp(v2) + self.assertEqual(res, wanted, + 'cmp(%s, %s) should be %s, got %s' % + (v1, v2, wanted, res)) + res = StrictVersion(v1)._cmp(object()) + self.assertIs(res, NotImplemented, + 'cmp(%s, %s) should be NotImplemented, got %s' % + (v1, v2, res)) def test_cmp(self): @@ -63,6 +71,14 @@ def test_cmp(self): self.assertEqual(res, wanted, 'cmp(%s, %s) should be %s, got %s' % (v1, v2, wanted, res)) + res = LooseVersion(v1)._cmp(v2) + self.assertEqual(res, wanted, + 'cmp(%s, %s) should be %s, got %s' % + (v1, v2, wanted, res)) + res = LooseVersion(v1)._cmp(object()) + self.assertIs(res, NotImplemented, + 'cmp(%s, %s) should be NotImplemented, got %s' % + (v1, v2, res)) def test_suite(): return unittest.makeSuite(VersionTestCase) diff --git a/Lib/distutils/version.py b/Lib/distutils/version.py index af14cc134814..c33bebaed26a 100644 --- a/Lib/distutils/version.py +++ b/Lib/distutils/version.py @@ -166,6 +166,8 @@ def __str__ (self): def _cmp (self, other): if isinstance(other, str): other = StrictVersion(other) + elif not isinstance(other, StrictVersion): + return NotImplemented if self.version != other.version: # numeric versions don't match @@ -331,6 +333,8 @@ def __repr__ (self): def _cmp (self, other): if isinstance(other, str): other = LooseVersion(other) + elif not isinstance(other, LooseVersion): + return NotImplemented if self.version == other.version: return 0 diff --git a/Lib/email/headerregistry.py b/Lib/email/headerregistry.py index 8d1a2025271f..dcc960b2cdc1 100644 --- a/Lib/email/headerregistry.py +++ b/Lib/email/headerregistry.py @@ -97,8 +97,8 @@ def __str__(self): return self.addr_spec def __eq__(self, other): - if type(other) != type(self): - return False + if not isinstance(other, Address): + return NotImplemented return (self.display_name == other.display_name and self.username == other.username and self.domain == other.domain) @@ -150,8 +150,8 @@ def __str__(self): return "{}:{};".format(disp, adrstr) def __eq__(self, other): - if type(other) != type(self): - return False + if not isinstance(other, Group): + return NotImplemented return (self.display_name == other.display_name and self.addresses == other.addresses) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 5e2f520c0ef8..e17eeb658538 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -371,7 +371,7 @@ def __eq__(self, other): self.cached == other.cached and self.has_location == other.has_location) except AttributeError: - return False + return NotImplemented @property def cached(self): diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index e5ad72fe5ba8..5bc1bc2a621b 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -32,6 +32,7 @@ from asyncio import selector_events from test.test_asyncio import utils as test_utils from test import support +from test.support import ALWAYS_EQ, LARGEST, SMALLEST def tearDownModule(): @@ -2364,6 +2365,28 @@ def callback(*args): self.assertIs(NotImplemented, h1.__eq__(h3)) self.assertIs(NotImplemented, h1.__ne__(h3)) + with self.assertRaises(TypeError): + h1 < () + with self.assertRaises(TypeError): + h1 > () + with self.assertRaises(TypeError): + h1 <= () + with self.assertRaises(TypeError): + h1 >= () + self.assertFalse(h1 == ()) + self.assertTrue(h1 != ()) + + self.assertTrue(h1 == ALWAYS_EQ) + self.assertFalse(h1 != ALWAYS_EQ) + self.assertTrue(h1 < LARGEST) + self.assertFalse(h1 > LARGEST) + self.assertTrue(h1 <= LARGEST) + self.assertFalse(h1 >= LARGEST) + self.assertFalse(h1 < SMALLEST) + self.assertTrue(h1 > SMALLEST) + self.assertFalse(h1 <= SMALLEST) + self.assertTrue(h1 >= SMALLEST) + class AbstractEventLoopTests(unittest.TestCase): diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index 5d9b3576d306..4758f4b1c52e 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -7,6 +7,7 @@ from test.test_email import TestEmailBase, parameterize from email import headerregistry from email.headerregistry import Address, Group +from test.support import ALWAYS_EQ DITTO = object() @@ -1525,6 +1526,24 @@ def test_set_message_header_from_group(self): self.assertEqual(m['to'], 'foo bar:;') self.assertEqual(m['to'].addresses, g.addresses) + def test_address_comparison(self): + a = Address('foo', 'bar', 'example.com') + self.assertEqual(Address('foo', 'bar', 'example.com'), a) + self.assertNotEqual(Address('baz', 'bar', 'example.com'), a) + self.assertNotEqual(Address('foo', 'baz', 'example.com'), a) + self.assertNotEqual(Address('foo', 'bar', 'baz'), a) + self.assertFalse(a == object()) + self.assertTrue(a == ALWAYS_EQ) + + def test_group_comparison(self): + a = Address('foo', 'bar', 'example.com') + g = Group('foo bar', [a]) + self.assertEqual(Group('foo bar', (a,)), g) + self.assertNotEqual(Group('baz', [a]), g) + self.assertNotEqual(Group('foo bar', []), g) + self.assertFalse(g == object()) + self.assertTrue(g == ALWAYS_EQ) + class TestFolding(TestHeaderBase): diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 96d85e2cb8a1..72dc7afb8c5c 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -7,7 +7,7 @@ import unittest import re from test import support -from test.support import TESTFN, Error, captured_output, unlink, cpython_only +from test.support import TESTFN, Error, captured_output, unlink, cpython_only, ALWAYS_EQ from test.support.script_helper import assert_python_ok import textwrap @@ -887,6 +887,8 @@ def test_basics(self): # operator fallbacks to FrameSummary.__eq__. self.assertEqual(tuple(f), f) self.assertIsNone(f.locals) + self.assertNotEqual(f, object()) + self.assertEqual(f, ALWAYS_EQ) def test_lazy_lines(self): linecache.clearcache() @@ -1083,6 +1085,18 @@ def test_context(self): self.assertEqual(exc_info[0], exc.exc_type) self.assertEqual(str(exc_info[1]), str(exc)) + def test_comparison(self): + try: + 1/0 + except Exception: + exc_info = sys.exc_info() + exc = traceback.TracebackException(*exc_info) + exc2 = traceback.TracebackException(*exc_info) + self.assertIsNot(exc, exc2) + self.assertEqual(exc, exc2) + self.assertNotEqual(exc, object()) + self.assertEqual(exc, ALWAYS_EQ) + def test_unhashable(self): class UnhashableException(Exception): def __eq__(self, other): diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index ce5bbfccd787..41f78e7e8383 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -11,7 +11,7 @@ import random from test import support -from test.support import script_helper +from test.support import script_helper, ALWAYS_EQ # Used in ReferencesTestCase.test_ref_created_during_del() . ref_from_del = None @@ -794,6 +794,10 @@ def test_equality(self): self.assertTrue(a != c) self.assertTrue(a == d) self.assertFalse(a != d) + self.assertFalse(a == x) + self.assertTrue(a != x) + self.assertTrue(a == ALWAYS_EQ) + self.assertFalse(a != ALWAYS_EQ) del x, y, z gc.collect() for r in a, b, c: @@ -1102,6 +1106,9 @@ def _ne(a, b): _ne(a, f) _ne(b, e) _ne(b, f) + # Compare with different types + _ne(a, x.some_method) + _eq(a, ALWAYS_EQ) del x, y, z gc.collect() # Dead WeakMethods compare by identity diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index 52bacc1eafa7..e5c3496ec548 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -15,6 +15,7 @@ import io import contextlib from test import support +from test.support import ALWAYS_EQ, LARGEST, SMALLEST try: import gzip @@ -530,14 +531,10 @@ def test_comparison(self): # some other types dbytes = dstr.encode('ascii') dtuple = now.timetuple() - with self.assertRaises(TypeError): - dtime == 1970 - with self.assertRaises(TypeError): - dtime != dbytes - with self.assertRaises(TypeError): - dtime == bytearray(dbytes) - with self.assertRaises(TypeError): - dtime != dtuple + self.assertFalse(dtime == 1970) + self.assertTrue(dtime != dbytes) + self.assertFalse(dtime == bytearray(dbytes)) + self.assertTrue(dtime != dtuple) with self.assertRaises(TypeError): dtime < float(1970) with self.assertRaises(TypeError): @@ -547,6 +544,18 @@ def test_comparison(self): with self.assertRaises(TypeError): dtime >= dtuple + self.assertTrue(dtime == ALWAYS_EQ) + self.assertFalse(dtime != ALWAYS_EQ) + self.assertTrue(dtime < LARGEST) + self.assertFalse(dtime > LARGEST) + self.assertTrue(dtime <= LARGEST) + self.assertFalse(dtime >= LARGEST) + self.assertFalse(dtime < SMALLEST) + self.assertTrue(dtime > SMALLEST) + self.assertFalse(dtime <= SMALLEST) + self.assertTrue(dtime >= SMALLEST) + + class BinaryTestCase(unittest.TestCase): # XXX What should str(Binary(b"\xff")) return? I'm chosing "\xff" diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index 9626a2780db6..9258484af5fd 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -484,6 +484,8 @@ def __eq__(self, other): Note: if the Variable's master matters to behavior also compare self._master == other._master """ + if not isinstance(other, Variable): + return NotImplemented return self.__class__.__name__ == other.__class__.__name__ \ and self._name == other._name diff --git a/Lib/tkinter/font.py b/Lib/tkinter/font.py index eeff454b5306..15ad7ab4b63a 100644 --- a/Lib/tkinter/font.py +++ b/Lib/tkinter/font.py @@ -101,7 +101,9 @@ def __str__(self): return self.name def __eq__(self, other): - return isinstance(other, Font) and self.name == other.name + if not isinstance(other, Font): + return NotImplemented + return self.name == other.name def __getitem__(self, key): return self.cget(key) diff --git a/Lib/tkinter/test/test_tkinter/test_font.py b/Lib/tkinter/test/test_tkinter/test_font.py index 97cd87ccdc81..a021ea336807 100644 --- a/Lib/tkinter/test/test_tkinter/test_font.py +++ b/Lib/tkinter/test/test_tkinter/test_font.py @@ -1,7 +1,7 @@ import unittest import tkinter from tkinter import font -from test.support import requires, run_unittest, gc_collect +from test.support import requires, run_unittest, gc_collect, ALWAYS_EQ from tkinter.test.support import AbstractTkTest requires('gui') @@ -70,6 +70,7 @@ def test_eq(self): self.assertEqual(font1, font2) self.assertNotEqual(font1, font1.copy()) self.assertNotEqual(font1, 0) + self.assertEqual(font1, ALWAYS_EQ) def test_measure(self): self.assertIsInstance(self.font.measure('abc'), int) diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py index 2eb1e12671d2..08b7dedcaf93 100644 --- a/Lib/tkinter/test/test_tkinter/test_variables.py +++ b/Lib/tkinter/test/test_tkinter/test_variables.py @@ -2,6 +2,7 @@ import gc from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl, TclError) +from test.support import ALWAYS_EQ class Var(Variable): @@ -59,11 +60,17 @@ def test___eq__(self): # values doesn't matter, only class and name are checked v1 = Variable(self.root, name="abc") v2 = Variable(self.root, name="abc") + self.assertIsNot(v1, v2) self.assertEqual(v1, v2) - v3 = Variable(self.root, name="abc") - v4 = StringVar(self.root, name="abc") - self.assertNotEqual(v3, v4) + v3 = StringVar(self.root, name="abc") + self.assertNotEqual(v1, v3) + + V = type('Variable', (), {}) + self.assertNotEqual(v1, V()) + + self.assertNotEqual(v1, object()) + self.assertEqual(v1, ALWAYS_EQ) def test_invalid_name(self): with self.assertRaises(TypeError): diff --git a/Lib/traceback.py b/Lib/traceback.py index ab35da94b51e..7a4c8e19f989 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -538,7 +538,9 @@ def _load_lines(self): self.__cause__._load_lines() def __eq__(self, other): - return self.__dict__ == other.__dict__ + if isinstance(other, TracebackException): + return self.__dict__ == other.__dict__ + return NotImplemented def __str__(self): return self._str diff --git a/Lib/tracemalloc.py b/Lib/tracemalloc.py index 2c1ac3b39b07..80b521c2e1af 100644 --- a/Lib/tracemalloc.py +++ b/Lib/tracemalloc.py @@ -43,6 +43,8 @@ def __hash__(self): return hash((self.traceback, self.size, self.count)) def __eq__(self, other): + if not isinstance(other, Statistic): + return NotImplemented return (self.traceback == other.traceback and self.size == other.size and self.count == other.count) @@ -84,6 +86,8 @@ def __hash__(self): self.count, self.count_diff)) def __eq__(self, other): + if not isinstance(other, StatisticDiff): + return NotImplemented return (self.traceback == other.traceback and self.size == other.size and self.size_diff == other.size_diff @@ -153,9 +157,13 @@ def lineno(self): return self._frame[1] def __eq__(self, other): + if not isinstance(other, Frame): + return NotImplemented return (self._frame == other._frame) def __lt__(self, other): + if not isinstance(other, Frame): + return NotImplemented return (self._frame < other._frame) def __hash__(self): @@ -200,9 +208,13 @@ def __hash__(self): return hash(self._frames) def __eq__(self, other): + if not isinstance(other, Traceback): + return NotImplemented return (self._frames == other._frames) def __lt__(self, other): + if not isinstance(other, Traceback): + return NotImplemented return (self._frames < other._frames) def __str__(self): @@ -271,6 +283,8 @@ def traceback(self): return Traceback(self._trace[2]) def __eq__(self, other): + if not isinstance(other, Trace): + return NotImplemented return (self._trace == other._trace) def __hash__(self): @@ -303,6 +317,8 @@ def __contains__(self, trace): return trace._trace in self._traces def __eq__(self, other): + if not isinstance(other, _Traces): + return NotImplemented return (self._traces == other._traces) def __repr__(self): diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index b3dc640f8fe5..298b41e0d7e4 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2358,12 +2358,10 @@ def __init__(self, value=(), name=None, parent=None, two=False, def __eq__(self, other): - if other is ANY: - return True try: len_other = len(other) except TypeError: - return False + return NotImplemented self_name = '' if len(self) == 2: diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index 18efd311f9e6..69b34e9c4fb7 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -3,6 +3,7 @@ import sys import tempfile +from test.support import ALWAYS_EQ import unittest from unittest.test.testmock.support import is_instance from unittest import mock @@ -322,6 +323,8 @@ def test_calls_equal_with_any(self): self.assertFalse(mm != mock.ANY) self.assertTrue(mock.ANY == mm) self.assertFalse(mock.ANY != mm) + self.assertTrue(mm == ALWAYS_EQ) + self.assertFalse(mm != ALWAYS_EQ) call1 = mock.call(mock.MagicMock()) call2 = mock.call(mock.ANY) @@ -330,6 +333,11 @@ def test_calls_equal_with_any(self): self.assertTrue(call2 == call1) self.assertFalse(call2 != call1) + self.assertTrue(call1 == ALWAYS_EQ) + self.assertFalse(call1 != ALWAYS_EQ) + self.assertFalse(call1 == 1) + self.assertTrue(call1 != 1) + def test_assert_called_with(self): mock = Mock() diff --git a/Lib/weakref.py b/Lib/weakref.py index fa7559bb3dbf..560deee96c92 100644 --- a/Lib/weakref.py +++ b/Lib/weakref.py @@ -75,14 +75,14 @@ def __eq__(self, other): if not self._alive or not other._alive: return self is other return ref.__eq__(self, other) and self._func_ref == other._func_ref - return False + return NotImplemented def __ne__(self, other): if isinstance(other, WeakMethod): if not self._alive or not other._alive: return self is not other return ref.__ne__(self, other) or self._func_ref != other._func_ref - return True + return NotImplemented __hash__ = ref.__hash__ diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index b9875745000f..246ef27ffc24 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -313,31 +313,38 @@ def make_comparable(self, other): s = self.timetuple() o = other.timetuple() else: - otype = (hasattr(other, "__class__") - and other.__class__.__name__ - or type(other)) - raise TypeError("Can't compare %s and %s" % - (self.__class__.__name__, otype)) + s = self + o = NotImplemented return s, o def __lt__(self, other): s, o = self.make_comparable(other) + if o is NotImplemented: + return NotImplemented return s < o def __le__(self, other): s, o = self.make_comparable(other) + if o is NotImplemented: + return NotImplemented return s <= o def __gt__(self, other): s, o = self.make_comparable(other) + if o is NotImplemented: + return NotImplemented return s > o def __ge__(self, other): s, o = self.make_comparable(other) + if o is NotImplemented: + return NotImplemented return s >= o def __eq__(self, other): s, o = self.make_comparable(other) + if o is NotImplemented: + return NotImplemented return s == o def timetuple(self): diff --git a/Misc/NEWS.d/next/Library/2019-07-26-00-12-29.bpo-37685.TqckMZ.rst b/Misc/NEWS.d/next/Library/2019-07-26-00-12-29.bpo-37685.TqckMZ.rst new file mode 100644 index 000000000000..d1179a620c17 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-26-00-12-29.bpo-37685.TqckMZ.rst @@ -0,0 +1,4 @@ +Fixed ``__eq__``, ``__lt__`` etc implementations in some classes. They now +return :data:`NotImplemented` for unsupported type of the other operand. +This allows the other operand to play role (for example the equality +comparison with :data:`~unittest.mock.ANY` will return ``True``). diff --git a/Python/importlib.h b/Python/importlib.h index a6952af22b4f..5738af03b054 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -636,7 +636,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, 100,1,124,0,95,5,100,0,124,0,95,6,100,0,83,0, - 169,2,78,70,41,7,114,17,0,0,0,114,109,0,0,0, + 41,2,78,70,41,7,114,17,0,0,0,114,109,0,0,0, 114,113,0,0,0,114,114,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,218,13,95,115,101,116,95,102,105,108, @@ -662,7 +662,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 101,110,100,114,116,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, @@ -670,1120 +670,1122 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,106,0,0,0,124,0, + 0,8,0,0,0,67,0,0,0,115,108,0,0,0,124,0, 106,0,125,2,122,72,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,4,0, - 116,6,107,10,114,100,1,0,1,0,1,0,89,0,100,1, - 83,0,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,4,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,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, + 116,6,107,10,114,102,1,0,1,0,1,0,116,7,6,0, + 89,0,83,0,88,0,100,0,83,0,114,13,0,0,0,41, + 8,114,116,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, + 218,14,78,111,116,73,109,112,108,101,109,101,110,116,101,100, + 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,4,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,118,0,0,0,114,113,0,0,0,114,117, + 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,122, + 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,118,0,0,0,41, + 2,114,30,0,0,0,114,122,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,122,0,0,0,129, + 1,0,0,115,2,0,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,116,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,117,0,0,0,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,0,114,123,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,117,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,123,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,122,0,0,0,218,6,115,101,116, + 116,101,114,114,130,0,0,0,114,123,0,0,0,114,10,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,124,3,100,2,107,8,114,48, - 124,4,124,0,124,1,100,3,141,2,83,0,124,3,114,56, - 103,0,110,2,100,2,125,5,124,4,124,0,124,1,124,5, - 100,4,141,3,83,0,124,3,100,2,107,8,114,138,116,0, - 124,1,100,5,131,2,114,134,122,14,124,1,160,4,124,0, - 161,1,125,3,87,0,113,138,4,0,116,5,107,10,114,130, - 1,0,1,0,1,0,100,2,125,3,89,0,113,138,88,0, - 110,4,100,6,125,3,116,6,124,0,124,1,124,2,124,3, - 100,7,141,4,83,0,41,8,122,53,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,118,97,114,105,111,117,115,32, - 108,111,97,100,101,114,32,109,101,116,104,111,100,115,46,90, - 12,103,101,116,95,102,105,108,101,110,97,109,101,78,41,1, - 114,109,0,0,0,41,2,114,109,0,0,0,114,117,0,0, - 0,114,115,0,0,0,70,114,135,0,0,0,41,7,114,4, - 0,0,0,114,126,0,0,0,114,127,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,114,115,0,0,0,114,79,0,0,0, - 114,112,0,0,0,41,6,114,17,0,0,0,114,109,0,0, - 0,114,113,0,0,0,114,115,0,0,0,114,136,0,0,0, - 90,6,115,101,97,114,99,104,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,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,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,66,124,0,106,2,100,1,107, - 8,114,50,100,3,160,3,124,1,161,1,83,0,100,4,160, - 3,124,1,124,0,106,2,161,2,83,0,110,36,124,0,106, - 4,114,86,100,5,160,3,124,1,124,0,106,1,161,2,83, - 0,100,6,160,3,124,0,106,0,124,0,106,1,161,2,83, - 0,100,1,83,0,41,7,122,38,82,101,116,117,114,110,32, - 116,104,101,32,114,101,112,114,32,116,111,32,117,115,101,32, - 102,111,114,32,116,104,101,32,109,111,100,117,108,101,46,78, - 114,100,0,0,0,114,101,0,0,0,114,102,0,0,0,114, - 103,0,0,0,250,18,60,109,111,100,117,108,101,32,123,33, - 114,125,32,40,123,125,41,62,41,5,114,17,0,0,0,114, - 113,0,0,0,114,109,0,0,0,114,45,0,0,0,114,124, - 0,0,0,41,2,114,95,0,0,0,114,17,0,0,0,114, - 10,0,0,0,114,10,0,0,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,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, + 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,124,3,100,2,107,8, + 114,48,124,4,124,0,124,1,100,3,141,2,83,0,124,3, + 114,56,103,0,110,2,100,2,125,5,124,4,124,0,124,1, + 124,5,100,4,141,3,83,0,124,3,100,2,107,8,114,138, + 116,0,124,1,100,5,131,2,114,134,122,14,124,1,160,4, + 124,0,161,1,125,3,87,0,113,138,4,0,116,5,107,10, + 114,130,1,0,1,0,1,0,100,2,125,3,89,0,113,138, + 88,0,110,4,100,6,125,3,116,6,124,0,124,1,124,2, + 124,3,100,7,141,4,83,0,41,8,122,53,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,118,97,114,105,111,117, + 115,32,108,111,97,100,101,114,32,109,101,116,104,111,100,115, + 46,90,12,103,101,116,95,102,105,108,101,110,97,109,101,78, + 41,1,114,109,0,0,0,41,2,114,109,0,0,0,114,116, + 0,0,0,114,115,0,0,0,70,114,135,0,0,0,41,7, + 114,4,0,0,0,114,126,0,0,0,114,127,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,114,115,0,0,0,114,79,0, + 0,0,114,112,0,0,0,41,6,114,17,0,0,0,114,109, + 0,0,0,114,113,0,0,0,114,115,0,0,0,114,136,0, + 0,0,90,6,115,101,97,114,99,104,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,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,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,117,0,0,0,114,122,0,0, + 0,114,116,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,122,0,0,0, + 114,116,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,116, + 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,123,0, + 0,0,114,113,0,0,0,114,122,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,66,124,0,106,2,100, + 1,107,8,114,50,100,3,160,3,124,1,161,1,83,0,100, + 4,160,3,124,1,124,0,106,2,161,2,83,0,110,36,124, + 0,106,4,114,86,100,5,160,3,124,1,124,0,106,1,161, + 2,83,0,100,6,160,3,124,0,106,0,124,0,106,1,161, + 2,83,0,100,1,83,0,41,7,122,38,82,101,116,117,114, + 110,32,116,104,101,32,114,101,112,114,32,116,111,32,117,115, + 101,32,102,111,114,32,116,104,101,32,109,111,100,117,108,101, + 46,78,114,100,0,0,0,114,101,0,0,0,114,102,0,0, + 0,114,103,0,0,0,250,18,60,109,111,100,117,108,101,32, + 123,33,114,125,32,40,123,125,41,62,41,5,114,17,0,0, + 0,114,113,0,0,0,114,109,0,0,0,114,45,0,0,0, + 114,123,0,0,0,41,2,114,95,0,0,0,114,17,0,0, + 0,114,10,0,0,0,114,10,0,0,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,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,116,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, - 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,82,0,88,0,100,1,83,0, - 41,2,122,191,82,101,116,117,114,110,32,97,32,110,101,119, - 32,109,111,100,117,108,101,32,111,98,106,101,99,116,44,32, - 108,111,97,100,101,100,32,98,121,32,116,104,101,32,115,112, - 101,99,39,115,32,108,111,97,100,101,114,46,10,10,32,32, - 32,32,84,104,101,32,109,111,100,117,108,101,32,105,115,32, - 110,111,116,32,97,100,100,101,100,32,116,111,32,105,116,115, - 32,112,97,114,101,110,116,46,10,10,32,32,32,32,73,102, - 32,97,32,109,111,100,117,108,101,32,105,115,32,97,108,114, - 101,97,100,121,32,105,110,32,115,121,115,46,109,111,100,117, - 108,101,115,44,32,116,104,97,116,32,101,120,105,115,116,105, - 110,103,32,109,111,100,117,108,101,32,103,101,116,115,10,32, - 32,32,32,99,108,111,98,98,101,114,101,100,46,10,10,32, - 32,32,32,78,41,3,114,50,0,0,0,114,17,0,0,0, - 114,159,0,0,0,41,1,114,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,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,83,0,41,2,122,175,70,105, - 110,100,32,116,104,101,32,98,117,105,108,116,45,105,110,32, - 109,111,100,117,108,101,46,10,10,32,32,32,32,32,32,32, - 32,73,102,32,39,112,97,116,104,39,32,105,115,32,101,118, - 101,114,32,115,112,101,99,105,102,105,101,100,32,116,104,101, - 110,32,116,104,101,32,115,101,97,114,99,104,32,105,115,32, - 99,111,110,115,105,100,101,114,101,100,32,97,32,102,97,105, - 108,117,114,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,166,0,0,0,114,109,0,0,0,41,4,114,163,0,0, - 0,114,81,0,0,0,114,164,0,0,0,114,95,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218, - 11,102,105,110,100,95,109,111,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,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,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, + 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,116,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,82,0,88,0,100,1, + 83,0,41,2,122,191,82,101,116,117,114,110,32,97,32,110, + 101,119,32,109,111,100,117,108,101,32,111,98,106,101,99,116, + 44,32,108,111,97,100,101,100,32,98,121,32,116,104,101,32, + 115,112,101,99,39,115,32,108,111,97,100,101,114,46,10,10, + 32,32,32,32,84,104,101,32,109,111,100,117,108,101,32,105, + 115,32,110,111,116,32,97,100,100,101,100,32,116,111,32,105, + 116,115,32,112,97,114,101,110,116,46,10,10,32,32,32,32, + 73,102,32,97,32,109,111,100,117,108,101,32,105,115,32,97, + 108,114,101,97,100,121,32,105,110,32,115,121,115,46,109,111, + 100,117,108,101,115,44,32,116,104,97,116,32,101,120,105,115, + 116,105,110,103,32,109,111,100,117,108,101,32,103,101,116,115, + 10,32,32,32,32,99,108,111,98,98,101,114,101,100,46,10, + 10,32,32,32,32,78,41,3,114,50,0,0,0,114,17,0, + 0,0,114,159,0,0,0,41,1,114,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,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,83,0,41,2,122,175, + 70,105,110,100,32,116,104,101,32,98,117,105,108,116,45,105, + 110,32,109,111,100,117,108,101,46,10,10,32,32,32,32,32, + 32,32,32,73,102,32,39,112,97,116,104,39,32,105,115,32, + 101,118,101,114,32,115,112,101,99,105,102,105,101,100,32,116, + 104,101,110,32,116,104,101,32,115,101,97,114,99,104,32,105, + 115,32,99,111,110,115,105,100,101,114,101,100,32,97,32,102, + 97,105,108,117,114,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,166,0,0,0,114,109,0,0,0,41,4,114,163, + 0,0,0,114,81,0,0,0,114,164,0,0,0,114,95,0, 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,218,10,103,101,116,95,115,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,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,0,100,0,83,0,41,2,78, - 114,137,0,0,0,41,4,114,57,0,0,0,114,88,0,0, - 0,114,91,0,0,0,114,138,0,0,0,114,162,0,0,0, + 0,218,11,102,105,110,100,95,109,111,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,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, - 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,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,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, + 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,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,218,10,103,101,116,95,115,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,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,0,100,0,83,0,41, + 2,78,114,137,0,0,0,41,4,114,57,0,0,0,114,88, + 0,0,0,114,91,0,0,0,114,138,0,0,0,114,162,0, + 0,0,114,10,0,0,0,114,10,0,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,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, - 41,1,114,97,0,0,0,114,168,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,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, - 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, + 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,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, + 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, - 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, + 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,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,41,1,114,97,0,0,0,114,168,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,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,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,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, + 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,90,5,100,6,83,0, + 41,7,218,18,95,73,109,112,111,114,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,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,218, + 8,101,120,99,95,116,121,112,101,218,9,101,120,99,95,118, + 97,108,117,101,218,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,114,79,0,0,0,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,187,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,116,1,124,1,124,3,131,2,83,0,114,13,0, + 0,0,41,2,114,167,0,0,0,114,91,0,0,0,41,4, + 218,6,102,105,110,100,101,114,114,17,0,0,0,114,164,0, + 0,0,114,109,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,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,189,0,0,0,99, + 3,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,189,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,190,0,0,0,90,9,105, + 115,95,114,101,108,111,97,100,114,188,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,194,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,218,10,86,97,108,117,101, + 69,114,114,111,114,114,79,0,0,0,169,3,114,17,0,0, + 0,114,185,0,0,0,114,186,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,200,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,194,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,205,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,124,0,124,1,131,2, + 87,0,2,0,53,0,81,0,82,0,163,0,83,0,87,0, + 53,0,81,0,82,0,88,0,124,2,100,1,107,8,114,94, + 100,2,160,6,124,0,161,1,125,3,116,7,124,3,124,0, + 100,3,141,2,130,1,116,8,124,0,131,1,1,0,124,2, + 83,0,41,4,122,25,70,105,110,100,32,97,110,100,32,108, + 111,97,100,32,116,104,101,32,109,111,100,117,108,101,46,78, + 122,40,105,109,112,111,114,116,32,111,102,32,123,125,32,104, + 97,108,116,101,100,59,32,78,111,110,101,32,105,110,32,115, + 121,115,46,109,111,100,117,108,101,115,114,16,0,0,0,41, + 9,114,50,0,0,0,114,15,0,0,0,114,92,0,0,0, + 114,34,0,0,0,218,14,95,78,69,69,68,83,95,76,79, + 65,68,73,78,71,114,205,0,0,0,114,45,0,0,0,114, + 203,0,0,0,114,65,0,0,0,41,4,114,17,0,0,0, + 114,204,0,0,0,114,96,0,0,0,114,75,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,14, + 95,102,105,110,100,95,97,110,100,95,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,207,0, + 0,0,114,22,0,0,0,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,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, + 200,0,0,0,114,187,0,0,0,114,207,0,0,0,218,11, + 95,103,99,100,95,105,109,112,111,114,116,114,199,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,90,5,100,6,83,0,41,7, - 218,18,95,73,109,112,111,114,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,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, + 208,0,0,0,234,3,0,0,115,8,0,0,0,0,9,12, + 1,8,1,12,1,114,208,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,113,4,124,4,100,5,107,2,114,108,124, + 3,115,220,116,5,124,0,100,6,131,2,114,220,116,6,124, + 0,124,0,106,7,124,2,100,7,100,8,141,4,1,0,113, + 4,116,5,124,0,124,4,131,2,115,4,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,113,4,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,113,4,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,209,0, + 0,0,114,182,0,0,0,78,41,16,114,195,0,0,0,114, + 196,0,0,0,114,1,0,0,0,114,197,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,212,0,0,0,114, + 45,0,0,0,114,67,0,0,0,114,203,0,0,0,114,17, + 0,0,0,114,15,0,0,0,114,92,0,0,0,114,34,0, + 0,0,114,206,0,0,0,41,8,114,96,0,0,0,218,8, + 102,114,111,109,108,105,115,116,114,204,0,0,0,114,210,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,213,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,213,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,191,0,0,0,114,192, + 0,0,0,114,193,0,0,0,114,129,0,0,0,41,3,218, + 7,103,108,111,98,97,108,115,114,185,0,0,0,114,95,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,218,8,101, - 120,99,95,116,121,112,101,218,9,101,120,99,95,118,97,108, - 117,101,218,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,114,79,0,0,0,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,187,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,116,1,124,1,124,3,131,2,83,0,114,13,0,0,0, - 41,2,114,167,0,0,0,114,91,0,0,0,41,4,218,6, - 102,105,110,100,101,114,114,17,0,0,0,114,164,0,0,0, - 114,109,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,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,189,0,0,0,99,3,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,189,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,190,0,0,0,90,9,105,115,95, - 114,101,108,111,97,100,114,188,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,194,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,218,10,86,97,108,117,101,69,114, - 114,111,114,114,79,0,0,0,169,3,114,17,0,0,0,114, - 185,0,0,0,114,186,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,200,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,194,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,205,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,124,0,124,1,131,2,87,0, - 2,0,53,0,81,0,82,0,163,0,83,0,87,0,53,0, - 81,0,82,0,88,0,124,2,100,1,107,8,114,94,100,2, - 160,6,124,0,161,1,125,3,116,7,124,3,124,0,100,3, - 141,2,130,1,116,8,124,0,131,1,1,0,124,2,83,0, - 41,4,122,25,70,105,110,100,32,97,110,100,32,108,111,97, - 100,32,116,104,101,32,109,111,100,117,108,101,46,78,122,40, - 105,109,112,111,114,116,32,111,102,32,123,125,32,104,97,108, - 116,101,100,59,32,78,111,110,101,32,105,110,32,115,121,115, - 46,109,111,100,117,108,101,115,114,16,0,0,0,41,9,114, - 50,0,0,0,114,15,0,0,0,114,92,0,0,0,114,34, - 0,0,0,218,14,95,78,69,69,68,83,95,76,79,65,68, - 73,78,71,114,205,0,0,0,114,45,0,0,0,114,203,0, - 0,0,114,65,0,0,0,41,4,114,17,0,0,0,114,204, - 0,0,0,114,96,0,0,0,114,75,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,218,14,95,102, - 105,110,100,95,97,110,100,95,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,207,0,0,0, - 114,22,0,0,0,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,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,200,0, - 0,0,114,187,0,0,0,114,207,0,0,0,218,11,95,103, - 99,100,95,105,109,112,111,114,116,114,199,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,208,0, - 0,0,234,3,0,0,115,8,0,0,0,0,9,12,1,8, - 1,12,1,114,208,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,113,4,124,4,100,5,107,2,114,108,124,3,115, - 220,116,5,124,0,100,6,131,2,114,220,116,6,124,0,124, - 0,106,7,124,2,100,7,100,8,141,4,1,0,113,4,116, - 5,124,0,124,4,131,2,115,4,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,113,4,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,113,4,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,209,0,0,0, - 114,182,0,0,0,78,41,16,114,195,0,0,0,114,196,0, - 0,0,114,1,0,0,0,114,197,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,212,0,0,0,114,45,0, - 0,0,114,67,0,0,0,114,203,0,0,0,114,17,0,0, - 0,114,15,0,0,0,114,92,0,0,0,114,34,0,0,0, - 114,206,0,0,0,41,8,114,96,0,0,0,218,8,102,114, - 111,109,108,105,115,116,114,204,0,0,0,114,210,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,213,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,213,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,191,0,0,0,114,192,0,0, - 0,114,193,0,0,0,114,129,0,0,0,41,3,218,7,103, - 108,111,98,97,108,115,114,185,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,219,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,0,125,6,116,1,124,6,131, - 1,125,7,116,0,124,0,124,7,124,4,131,3,125,5,124, - 3,115,150,124,4,100,1,107,2,114,84,116,0,124,0,160, - 2,100,3,161,1,100,1,25,0,131,1,83,0,124,0,115, - 92,124,5,83,0,116,3,124,0,131,1,116,3,124,0,160, - 2,100,3,161,1,100,1,25,0,131,1,24,0,125,8,116, - 4,106,5,124,5,106,6,100,2,116,3,124,5,106,6,131, - 1,124,8,24,0,133,2,25,0,25,0,83,0,110,26,116, - 7,124,5,100,4,131,2,114,172,116,8,124,5,124,3,116, - 0,131,3,83,0,124,5,83,0,100,2,83,0,41,5,97, - 215,1,0,0,73,109,112,111,114,116,32,97,32,109,111,100, - 117,108,101,46,10,10,32,32,32,32,84,104,101,32,39,103, - 108,111,98,97,108,115,39,32,97,114,103,117,109,101,110,116, - 32,105,115,32,117,115,101,100,32,116,111,32,105,110,102,101, - 114,32,119,104,101,114,101,32,116,104,101,32,105,109,112,111, - 114,116,32,105,115,32,111,99,99,117,114,114,105,110,103,32, - 102,114,111,109,10,32,32,32,32,116,111,32,104,97,110,100, - 108,101,32,114,101,108,97,116,105,118,101,32,105,109,112,111, - 114,116,115,46,32,84,104,101,32,39,108,111,99,97,108,115, - 39,32,97,114,103,117,109,101,110,116,32,105,115,32,105,103, - 110,111,114,101,100,46,32,84,104,101,10,32,32,32,32,39, - 102,114,111,109,108,105,115,116,39,32,97,114,103,117,109,101, - 110,116,32,115,112,101,99,105,102,105,101,115,32,119,104,97, - 116,32,115,104,111,117,108,100,32,101,120,105,115,116,32,97, - 115,32,97,116,116,114,105,98,117,116,101,115,32,111,110,32, - 116,104,101,32,109,111,100,117,108,101,10,32,32,32,32,98, - 101,105,110,103,32,105,109,112,111,114,116,101,100,32,40,101, - 46,103,46,32,96,96,102,114,111,109,32,109,111,100,117,108, - 101,32,105,109,112,111,114,116,32,60,102,114,111,109,108,105, - 115,116,62,96,96,41,46,32,32,84,104,101,32,39,108,101, - 118,101,108,39,10,32,32,32,32,97,114,103,117,109,101,110, - 116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101, - 32,112,97,99,107,97,103,101,32,108,111,99,97,116,105,111, - 110,32,116,111,32,105,109,112,111,114,116,32,102,114,111,109, - 32,105,110,32,97,32,114,101,108,97,116,105,118,101,10,32, - 32,32,32,105,109,112,111,114,116,32,40,101,46,103,46,32, - 96,96,102,114,111,109,32,46,46,112,107,103,32,105,109,112, - 111,114,116,32,109,111,100,96,96,32,119,111,117,108,100,32, - 104,97,118,101,32,97,32,39,108,101,118,101,108,39,32,111, - 102,32,50,41,46,10,10,32,32,32,32,114,22,0,0,0, - 78,114,128,0,0,0,114,141,0,0,0,41,9,114,208,0, - 0,0,114,219,0,0,0,218,9,112,97,114,116,105,116,105, - 111,110,114,184,0,0,0,114,15,0,0,0,114,92,0,0, - 0,114,1,0,0,0,114,4,0,0,0,114,213,0,0,0, - 41,9,114,17,0,0,0,114,218,0,0,0,218,6,108,111, - 99,97,108,115,114,214,0,0,0,114,186,0,0,0,114,96, - 0,0,0,90,8,103,108,111,98,97,108,115,95,114,185,0, - 0,0,90,7,99,117,116,95,111,102,102,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,218,10,95,95,105,109, - 112,111,114,116,95,95,57,4,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,222,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,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,223,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,191,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,195,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,223,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,227,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,227,0, - 0,0,114,15,0,0,0,114,190,0,0,0,114,120,0,0, - 0,114,160,0,0,0,114,173,0,0,0,41,2,114,225,0, - 0,0,114,226,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, - 228,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,115,116,97,108,108,32,105,109, - 112,111,114,116,101,114,115,32,116,104,97,116,32,114,101,113, - 117,105,114,101,32,101,120,116,101,114,110,97,108,32,102,105, - 108,101,115,121,115,116,101,109,32,97,99,99,101,115,115,114, - 22,0,0,0,78,41,6,218,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,126,0,0,0,114,228,0,0,0,114,15,0, - 0,0,114,92,0,0,0,114,1,0,0,0,41,1,114,229, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,27,95,105,110,115,116,97,108,108,95,101,120,116, - 101,114,110,97,108,95,105,109,112,111,114,116,101,114,115,144, - 4,0,0,115,6,0,0,0,0,3,8,1,4,1,114,230, - 0,0,0,41,2,78,78,41,1,78,41,2,78,114,22,0, - 0,0,41,4,78,78,114,10,0,0,0,114,22,0,0,0, - 41,50,114,3,0,0,0,114,126,0,0,0,114,12,0,0, - 0,114,18,0,0,0,114,59,0,0,0,114,33,0,0,0, - 114,42,0,0,0,114,19,0,0,0,114,20,0,0,0,114, - 49,0,0,0,114,50,0,0,0,114,53,0,0,0,114,65, - 0,0,0,114,67,0,0,0,114,76,0,0,0,114,86,0, - 0,0,114,90,0,0,0,114,97,0,0,0,114,111,0,0, - 0,114,112,0,0,0,114,91,0,0,0,114,142,0,0,0, - 114,148,0,0,0,114,152,0,0,0,114,107,0,0,0,114, - 93,0,0,0,114,158,0,0,0,114,159,0,0,0,114,94, - 0,0,0,114,160,0,0,0,114,173,0,0,0,114,178,0, - 0,0,114,187,0,0,0,114,189,0,0,0,114,194,0,0, - 0,114,200,0,0,0,90,15,95,69,82,82,95,77,83,71, - 95,80,82,69,70,73,88,114,202,0,0,0,114,205,0,0, - 0,218,6,111,98,106,101,99,116,114,206,0,0,0,114,207, - 0,0,0,114,208,0,0,0,114,213,0,0,0,114,219,0, - 0,0,114,222,0,0,0,114,223,0,0,0,114,227,0,0, - 0,114,228,0,0,0,114,230,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218, - 8,60,109,111,100,117,108,101,62,1,0,0,0,115,94,0, - 0,0,4,24,4,2,8,8,8,8,4,2,4,3,16,4, - 14,68,14,21,14,16,8,37,8,17,8,11,14,8,8,11, - 8,12,8,16,8,36,14,101,16,26,10,45,14,72,8,17, - 8,17,8,30,8,37,8,42,8,15,14,73,14,79,14,13, - 8,9,8,9,10,47,8,16,4,1,8,2,8,27,6,3, - 8,16,10,15,14,37,8,27,10,37,8,7,8,35,8,8, + 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,219,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,0,125,6,116,1,124, + 6,131,1,125,7,116,0,124,0,124,7,124,4,131,3,125, + 5,124,3,115,150,124,4,100,1,107,2,114,84,116,0,124, + 0,160,2,100,3,161,1,100,1,25,0,131,1,83,0,124, + 0,115,92,124,5,83,0,116,3,124,0,131,1,116,3,124, + 0,160,2,100,3,161,1,100,1,25,0,131,1,24,0,125, + 8,116,4,106,5,124,5,106,6,100,2,116,3,124,5,106, + 6,131,1,124,8,24,0,133,2,25,0,25,0,83,0,110, + 26,116,7,124,5,100,4,131,2,114,172,116,8,124,5,124, + 3,116,0,131,3,83,0,124,5,83,0,100,2,83,0,41, + 5,97,215,1,0,0,73,109,112,111,114,116,32,97,32,109, + 111,100,117,108,101,46,10,10,32,32,32,32,84,104,101,32, + 39,103,108,111,98,97,108,115,39,32,97,114,103,117,109,101, + 110,116,32,105,115,32,117,115,101,100,32,116,111,32,105,110, + 102,101,114,32,119,104,101,114,101,32,116,104,101,32,105,109, + 112,111,114,116,32,105,115,32,111,99,99,117,114,114,105,110, + 103,32,102,114,111,109,10,32,32,32,32,116,111,32,104,97, + 110,100,108,101,32,114,101,108,97,116,105,118,101,32,105,109, + 112,111,114,116,115,46,32,84,104,101,32,39,108,111,99,97, + 108,115,39,32,97,114,103,117,109,101,110,116,32,105,115,32, + 105,103,110,111,114,101,100,46,32,84,104,101,10,32,32,32, + 32,39,102,114,111,109,108,105,115,116,39,32,97,114,103,117, + 109,101,110,116,32,115,112,101,99,105,102,105,101,115,32,119, + 104,97,116,32,115,104,111,117,108,100,32,101,120,105,115,116, + 32,97,115,32,97,116,116,114,105,98,117,116,101,115,32,111, + 110,32,116,104,101,32,109,111,100,117,108,101,10,32,32,32, + 32,98,101,105,110,103,32,105,109,112,111,114,116,101,100,32, + 40,101,46,103,46,32,96,96,102,114,111,109,32,109,111,100, + 117,108,101,32,105,109,112,111,114,116,32,60,102,114,111,109, + 108,105,115,116,62,96,96,41,46,32,32,84,104,101,32,39, + 108,101,118,101,108,39,10,32,32,32,32,97,114,103,117,109, + 101,110,116,32,114,101,112,114,101,115,101,110,116,115,32,116, + 104,101,32,112,97,99,107,97,103,101,32,108,111,99,97,116, + 105,111,110,32,116,111,32,105,109,112,111,114,116,32,102,114, + 111,109,32,105,110,32,97,32,114,101,108,97,116,105,118,101, + 10,32,32,32,32,105,109,112,111,114,116,32,40,101,46,103, + 46,32,96,96,102,114,111,109,32,46,46,112,107,103,32,105, + 109,112,111,114,116,32,109,111,100,96,96,32,119,111,117,108, + 100,32,104,97,118,101,32,97,32,39,108,101,118,101,108,39, + 32,111,102,32,50,41,46,10,10,32,32,32,32,114,22,0, + 0,0,78,114,128,0,0,0,114,141,0,0,0,41,9,114, + 208,0,0,0,114,219,0,0,0,218,9,112,97,114,116,105, + 116,105,111,110,114,184,0,0,0,114,15,0,0,0,114,92, + 0,0,0,114,1,0,0,0,114,4,0,0,0,114,213,0, + 0,0,41,9,114,17,0,0,0,114,218,0,0,0,218,6, + 108,111,99,97,108,115,114,214,0,0,0,114,186,0,0,0, + 114,96,0,0,0,90,8,103,108,111,98,97,108,115,95,114, + 185,0,0,0,90,7,99,117,116,95,111,102,102,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,10,95,95, + 105,109,112,111,114,116,95,95,57,4,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, + 222,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,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,223,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,191,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,195,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,223,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, + 227,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, + 227,0,0,0,114,15,0,0,0,114,190,0,0,0,114,119, + 0,0,0,114,160,0,0,0,114,173,0,0,0,41,2,114, + 225,0,0,0,114,226,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,228,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,115,116,97,108,108,32, + 105,109,112,111,114,116,101,114,115,32,116,104,97,116,32,114, + 101,113,117,105,114,101,32,101,120,116,101,114,110,97,108,32, + 102,105,108,101,115,121,115,116,101,109,32,97,99,99,101,115, + 115,114,22,0,0,0,78,41,6,218,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,126,0,0,0,114,228,0,0,0,114, + 15,0,0,0,114,92,0,0,0,114,1,0,0,0,41,1, + 114,229,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,27,95,105,110,115,116,97,108,108,95,101, + 120,116,101,114,110,97,108,95,105,109,112,111,114,116,101,114, + 115,144,4,0,0,115,6,0,0,0,0,3,8,1,4,1, + 114,230,0,0,0,41,2,78,78,41,1,78,41,2,78,114, + 22,0,0,0,41,4,78,78,114,10,0,0,0,114,22,0, + 0,0,41,50,114,3,0,0,0,114,126,0,0,0,114,12, + 0,0,0,114,18,0,0,0,114,59,0,0,0,114,33,0, + 0,0,114,42,0,0,0,114,19,0,0,0,114,20,0,0, + 0,114,49,0,0,0,114,50,0,0,0,114,53,0,0,0, + 114,65,0,0,0,114,67,0,0,0,114,76,0,0,0,114, + 86,0,0,0,114,90,0,0,0,114,97,0,0,0,114,111, + 0,0,0,114,112,0,0,0,114,91,0,0,0,114,142,0, + 0,0,114,148,0,0,0,114,152,0,0,0,114,107,0,0, + 0,114,93,0,0,0,114,158,0,0,0,114,159,0,0,0, + 114,94,0,0,0,114,160,0,0,0,114,173,0,0,0,114, + 178,0,0,0,114,187,0,0,0,114,189,0,0,0,114,194, + 0,0,0,114,200,0,0,0,90,15,95,69,82,82,95,77, + 83,71,95,80,82,69,70,73,88,114,202,0,0,0,114,205, + 0,0,0,218,6,111,98,106,101,99,116,114,206,0,0,0, + 114,207,0,0,0,114,208,0,0,0,114,213,0,0,0,114, + 219,0,0,0,114,222,0,0,0,114,223,0,0,0,114,227, + 0,0,0,114,228,0,0,0,114,230,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,218,8,60,109,111,100,117,108,101,62,1,0,0,0,115, + 94,0,0,0,4,24,4,2,8,8,8,8,4,2,4,3, + 16,4,14,68,14,21,14,16,8,37,8,17,8,11,14,8, + 8,11,8,12,8,16,8,36,14,101,16,26,10,45,14,72, + 8,17,8,17,8,30,8,37,8,42,8,15,14,73,14,79, + 14,13,8,9,8,9,10,47,8,16,4,1,8,2,8,27, + 6,3,8,16,10,15,14,37,8,27,10,37,8,7,8,35, + 8,8, }; diff --git a/Tools/pynche/PyncheWidget.py b/Tools/pynche/PyncheWidget.py index 364f22b0b209..ef12198a2183 100644 --- a/Tools/pynche/PyncheWidget.py +++ b/Tools/pynche/PyncheWidget.py @@ -281,10 +281,14 @@ def popup(self, event=None): self.__window.deiconify() def __eq__(self, other): - return self.__menutext == other.__menutext + if isinstance(self, PopupViewer): + return self.__menutext == other.__menutext + return NotImplemented def __lt__(self, other): - return self.__menutext < other.__menutext + if isinstance(self, PopupViewer): + return self.__menutext < other.__menutext + return NotImplemented def make_view_popups(switchboard, root, extrapath): From webhook-mailer at python.org Thu Aug 8 01:43:22 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 08 Aug 2019 05:43:22 -0000 Subject: [Python-checkins] bpo-37685: Use singletons ALWAYS_EQ and NEVER_EQ in more tests. (GH-15167) Message-ID: https://github.com/python/cpython/commit/7d44e7a4563072d0fad00427b76b94cad61c38ae commit: 7d44e7a4563072d0fad00427b76b94cad61c38ae branch: master author: Serhiy Storchaka committer: GitHub date: 2019-08-08T08:43:18+03:00 summary: bpo-37685: Use singletons ALWAYS_EQ and NEVER_EQ in more tests. (GH-15167) files: M Lib/test/support/__init__.py M Lib/test/test_collections.py M Lib/test/test_compare.py M Lib/test/test_contains.py M Lib/test/test_dict_version.py M Lib/test/test_enum.py M Lib/test/test_inspect.py M Lib/test/test_range.py M Lib/test/test_urllib2.py diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index d34f2efaed53..00e734e7059f 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -3123,6 +3123,8 @@ def __eq__(self, other): return False def __ne__(self, other): return True + def __hash__(self): + return 1 NEVER_EQ = _NEVER_EQ() diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 0119c77ac02a..7f01de6f433d 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1472,9 +1472,6 @@ def __lt__(self, x): def test_issue26915(self): # Container membership test should check identity first - class CustomEqualObject: - def __eq__(self, other): - return False class CustomSequence(Sequence): def __init__(self, seq): self._seq = seq @@ -1484,7 +1481,7 @@ def __len__(self): return len(self._seq) nan = float('nan') - obj = CustomEqualObject() + obj = support.NEVER_EQ seq = CustomSequence([nan, obj, nan]) containers = [ seq, diff --git a/Lib/test/test_compare.py b/Lib/test/test_compare.py index 471c8dae767a..2b3faed7965b 100644 --- a/Lib/test/test_compare.py +++ b/Lib/test/test_compare.py @@ -1,4 +1,5 @@ import unittest +from test.support import ALWAYS_EQ class Empty: def __repr__(self): @@ -14,13 +15,6 @@ def __repr__(self): def __eq__(self, other): return self.arg == other -class Anything: - def __eq__(self, other): - return True - - def __ne__(self, other): - return False - class ComparisonTest(unittest.TestCase): set1 = [2, 2.0, 2, 2+0j, Cmp(2.0)] set2 = [[1], (3,), None, Empty()] @@ -113,11 +107,11 @@ class C: def test_issue_1393(self): x = lambda: None - self.assertEqual(x, Anything()) - self.assertEqual(Anything(), x) + self.assertEqual(x, ALWAYS_EQ) + self.assertEqual(ALWAYS_EQ, x) y = object() - self.assertEqual(y, Anything()) - self.assertEqual(Anything(), y) + self.assertEqual(y, ALWAYS_EQ) + self.assertEqual(ALWAYS_EQ, y) if __name__ == '__main__': diff --git a/Lib/test/test_contains.py b/Lib/test/test_contains.py index 036a1d012dbd..471d04a76ca4 100644 --- a/Lib/test/test_contains.py +++ b/Lib/test/test_contains.py @@ -1,5 +1,6 @@ from collections import deque import unittest +from test.support import NEVER_EQ class base_set: @@ -69,13 +70,7 @@ def test_nonreflexive(self): # containment and equality tests involving elements that are # not necessarily equal to themselves - class MyNonReflexive(object): - def __eq__(self, other): - return False - def __hash__(self): - return 28 - - values = float('nan'), 1, None, 'abc', MyNonReflexive() + values = float('nan'), 1, None, 'abc', NEVER_EQ constructors = list, tuple, dict.fromkeys, set, frozenset, deque for constructor in constructors: container = constructor(values) diff --git a/Lib/test/test_dict_version.py b/Lib/test/test_dict_version.py index cb79e7434c29..b23786514f82 100644 --- a/Lib/test/test_dict_version.py +++ b/Lib/test/test_dict_version.py @@ -98,20 +98,25 @@ def __eq__(self, other): value2 = AlwaysEqual() self.assertTrue(value1 == value2) self.assertFalse(value1 != value2) + self.assertIsNot(value1, value2) d = self.new_dict() self.check_version_changed(d, d.__setitem__, 'key', value1) + self.assertIs(d['key'], value1) # setting a key to a value equal to the current value # with dict.__setitem__() must change the version self.check_version_changed(d, d.__setitem__, 'key', value2) + self.assertIs(d['key'], value2) # setting a key to a value equal to the current value # with dict.update() must change the version self.check_version_changed(d, d.update, key=value1) + self.assertIs(d['key'], value1) d2 = self.new_dict(key=value2) self.check_version_changed(d, d.update, d2) + self.assertIs(d['key'], value2) def test_setdefault(self): d = self.new_dict() diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index 7bccd6660b52..ec1cfeab12d7 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -9,6 +9,7 @@ from io import StringIO from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL from test import support +from test.support import ALWAYS_EQ from datetime import timedelta @@ -1509,13 +1510,10 @@ class Color(AutoNumber): self.assertEqual(list(map(int, Color)), [1, 2, 3]) def test_equality(self): - class AlwaysEqual: - def __eq__(self, other): - return True class OrdinaryEnum(Enum): a = 1 - self.assertEqual(AlwaysEqual(), OrdinaryEnum.a) - self.assertEqual(OrdinaryEnum.a, AlwaysEqual()) + self.assertEqual(ALWAYS_EQ, OrdinaryEnum.a) + self.assertEqual(OrdinaryEnum.a, ALWAYS_EQ) def test_ordered_mixin(self): class OrderedEnum(Enum): diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 1cd4ea28939d..6c9f52977807 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -25,7 +25,7 @@ ThreadPoolExecutor = None from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only -from test.support import MISSING_C_DOCSTRINGS, cpython_only +from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ from test.support.script_helper import assert_python_ok, assert_python_failure from test import inspect_fodder as mod from test import inspect_fodder2 as mod2 @@ -118,10 +118,6 @@ def gen_coroutine_function_example(self): yield return 'spam' -class EqualsToAll: - def __eq__(self, other): - return True - class TestPredicates(IsTestBase): def test_excluding_predicates(self): @@ -2978,8 +2974,8 @@ def test_signature_equality(self): def foo(a, *, b:int) -> float: pass self.assertFalse(inspect.signature(foo) == 42) self.assertTrue(inspect.signature(foo) != 42) - self.assertTrue(inspect.signature(foo) == EqualsToAll()) - self.assertFalse(inspect.signature(foo) != EqualsToAll()) + self.assertTrue(inspect.signature(foo) == ALWAYS_EQ) + self.assertFalse(inspect.signature(foo) != ALWAYS_EQ) def bar(a, *, b:int) -> float: pass self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) @@ -3246,8 +3242,8 @@ def test_signature_parameter_equality(self): self.assertFalse(p != p) self.assertFalse(p == 42) self.assertTrue(p != 42) - self.assertTrue(p == EqualsToAll()) - self.assertFalse(p != EqualsToAll()) + self.assertTrue(p == ALWAYS_EQ) + self.assertFalse(p != ALWAYS_EQ) self.assertTrue(p == P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)) @@ -3584,8 +3580,8 @@ def foo(a): pass ba = inspect.signature(foo).bind(1) self.assertTrue(ba == ba) self.assertFalse(ba != ba) - self.assertTrue(ba == EqualsToAll()) - self.assertFalse(ba != EqualsToAll()) + self.assertTrue(ba == ALWAYS_EQ) + self.assertFalse(ba != ALWAYS_EQ) ba2 = inspect.signature(foo).bind(1) self.assertTrue(ba == ba2) diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py index 94c96a941b12..73cbcc4717d7 100644 --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -4,6 +4,7 @@ import sys import pickle import itertools +from test.support import ALWAYS_EQ # pure Python implementations (3 args only), for comparison def pyrange(start, stop, step): @@ -289,11 +290,7 @@ def __eq__(self, other): self.assertRaises(ValueError, range(1, 2**100, 2).index, 2**87) self.assertEqual(range(1, 2**100, 2).index(2**87+1), 2**86) - class AlwaysEqual(object): - def __eq__(self, other): - return True - always_equal = AlwaysEqual() - self.assertEqual(range(10).index(always_equal), 0) + self.assertEqual(range(10).index(ALWAYS_EQ), 0) def test_user_index_method(self): bignum = 2*sys.maxsize @@ -344,11 +341,7 @@ def test_count(self): self.assertEqual(range(1, 2**100, 2).count(2**87), 0) self.assertEqual(range(1, 2**100, 2).count(2**87+1), 1) - class AlwaysEqual(object): - def __eq__(self, other): - return True - always_equal = AlwaysEqual() - self.assertEqual(range(10).count(always_equal), 10) + self.assertEqual(range(10).count(ALWAYS_EQ), 10) self.assertEqual(len(range(sys.maxsize, sys.maxsize+10)), 10) @@ -429,9 +422,7 @@ def test_types(self): self.assertIn(True, range(3)) self.assertIn(1+0j, range(3)) - class C1: - def __eq__(self, other): return True - self.assertIn(C1(), range(3)) + self.assertIn(ALWAYS_EQ, range(3)) # Objects are never coerced into other types for comparison. class C2: diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py index debb3c2400a8..7b576db4e3aa 100644 --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -634,17 +634,12 @@ def test_http_error(self): [("http_error_302")], ] handlers = add_ordered_mock_handlers(o, meth_spec) - - class Unknown: - def __eq__(self, other): - return True - req = Request("http://example.com/") o.open(req) assert len(o.calls) == 2 calls = [(handlers[0], "http_open", (req,)), (handlers[2], "http_error_302", - (req, Unknown(), 302, "", {}))] + (req, support.ALWAYS_EQ, 302, "", {}))] for expected, got in zip(calls, o.calls): handler, method_name, args = expected self.assertEqual((handler, method_name), got[:2]) From webhook-mailer at python.org Thu Aug 8 04:23:12 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 08 Aug 2019 08:23:12 -0000 Subject: [Python-checkins] bpo-35892: Add usage note to mode() (GH-15122) Message-ID: https://github.com/python/cpython/commit/e43e7ed36480190083740fd75e2b9cdca72f1a68 commit: e43e7ed36480190083740fd75e2b9cdca72f1a68 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-08T01:23:05-07:00 summary: bpo-35892: Add usage note to mode() (GH-15122) files: M Doc/library/statistics.rst diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 3a2a1f94db47..bb77228ceac1 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -313,7 +313,9 @@ However, for reading convenience, most of the examples show sorted sequences. measure of central location. If there are multiple modes, returns the first one encountered in the *data*. - If *data* is empty, :exc:`StatisticsError` is raised. + If the smallest or largest of multiple modes is desired instead, use + ``min(multimode(data))`` or ``max(multimode(data))``. If the input *data* is + empty, :exc:`StatisticsError` is raised. ``mode`` assumes discrete data, and returns a single value. This is the standard treatment of the mode as commonly taught in schools: From webhook-mailer at python.org Thu Aug 8 04:37:01 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 08 Aug 2019 08:37:01 -0000 Subject: [Python-checkins] bpo-35892: Add usage note to mode() (GH-15122) (GH-15176) Message-ID: https://github.com/python/cpython/commit/5925b7d555bc36bd43ee8704ae75cc51900cf2d4 commit: 5925b7d555bc36bd43ee8704ae75cc51900cf2d4 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-08T01:36:55-07:00 summary: bpo-35892: Add usage note to mode() (GH-15122) (GH-15176) (cherry picked from commit e43e7ed36480190083740fd75e2b9cdca72f1a68) Co-authored-by: Raymond Hettinger files: M Doc/library/statistics.rst diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index a906a591e62c..1a19e3741921 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -313,7 +313,9 @@ However, for reading convenience, most of the examples show sorted sequences. measure of central location. If there are multiple modes, returns the first one encountered in the *data*. - If *data* is empty, :exc:`StatisticsError` is raised. + If the smallest or largest of multiple modes is desired instead, use + ``min(multimode(data))`` or ``max(multimode(data))``. If the input *data* is + empty, :exc:`StatisticsError` is raised. ``mode`` assumes discrete data, and returns a single value. This is the standard treatment of the mode as commonly taught in schools: From webhook-mailer at python.org Thu Aug 8 04:57:14 2019 From: webhook-mailer at python.org (Inada Naoki) Date: Thu, 08 Aug 2019 08:57:14 -0000 Subject: [Python-checkins] bpo-37587: optimize json.loads (GH-15134) Message-ID: https://github.com/python/cpython/commit/2a570af12ac5e4ac5575a68f8739b31c24d01367 commit: 2a570af12ac5e4ac5575a68f8739b31c24d01367 branch: master author: Inada Naoki committer: GitHub date: 2019-08-08T17:57:10+09:00 summary: bpo-37587: optimize json.loads (GH-15134) Use a tighter scope temporary variable to help register allocation. 1% speedup for large string. Use PyDict_SetItemDefault() for memoizing keys. At most 4% speedup when the cache hit ratio is low. files: M Modules/_json.c diff --git a/Modules/_json.c b/Modules/_json.c index 76da1d345e9d..112903ea577a 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -433,16 +433,21 @@ scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next } while (1) { /* Find the end of the string or the next escape */ - Py_UCS4 c = 0; - for (next = end; next < len; next++) { - c = PyUnicode_READ(kind, buf, next); - if (c == '"' || c == '\\') { - break; - } - else if (c <= 0x1f && strict) { - raise_errmsg("Invalid control character at", pystr, next); - goto bail; + Py_UCS4 c; + { + // Use tight scope variable to help register allocation. + Py_UCS4 d = 0; + for (next = end; next < len; next++) { + d = PyUnicode_READ(kind, buf, next); + if (d == '"' || d == '\\') { + break; + } + if (d <= 0x1f && strict) { + raise_errmsg("Invalid control character at", pystr, next); + goto bail; + } } + c = d; } if (!(c == '"' || c == '\\')) { raise_errmsg("Unterminated string starting at", pystr, begin); @@ -749,19 +754,13 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx); if (key == NULL) goto bail; - memokey = PyDict_GetItemWithError(s->memo, key); - if (memokey != NULL) { - Py_INCREF(memokey); - Py_DECREF(key); - key = memokey; - } - else if (PyErr_Occurred()) { + memokey = PyDict_SetDefault(s->memo, key, key); + if (memokey == NULL) { goto bail; } - else { - if (PyDict_SetItem(s->memo, key, key) < 0) - goto bail; - } + Py_INCREF(memokey); + Py_DECREF(key); + key = memokey; idx = next_idx; /* skip whitespace between key and : delimiter, read :, skip whitespace */ From webhook-mailer at python.org Thu Aug 8 16:02:58 2019 From: webhook-mailer at python.org (Paul Moore) Date: Thu, 08 Aug 2019 20:02:58 -0000 Subject: [Python-checkins] bpo-25172: Raise appropriate ImportError msg when crypt module used on Windows (GH-15149) Message-ID: https://github.com/python/cpython/commit/f4e725f224b864bf9bf405ff7f863cda46fca1cd commit: f4e725f224b864bf9bf405ff7f863cda46fca1cd branch: master author: shireenrao committer: Paul Moore date: 2019-08-08T21:02:49+01:00 summary: bpo-25172: Raise appropriate ImportError msg when crypt module used on Windows (GH-15149) files: A Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst M Lib/crypt.py diff --git a/Lib/crypt.py b/Lib/crypt.py index b0e47f430c3c..8846602d7613 100644 --- a/Lib/crypt.py +++ b/Lib/crypt.py @@ -1,6 +1,15 @@ """Wrapper to the POSIX crypt library call and associated functionality.""" -import _crypt +import sys as _sys + +try: + import _crypt +except ModuleNotFoundError: + if _sys.platform == 'win32': + raise ImportError("The crypt module is not supported on Windows") + else: + raise ImportError("The required _crypt module was not built as part of CPython") + import string as _string from random import SystemRandom as _SystemRandom from collections import namedtuple as _namedtuple diff --git a/Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst b/Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst new file mode 100644 index 000000000000..47106d887921 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst @@ -0,0 +1 @@ +Trying to import the :mod:`crypt` module on Windows will result in an :exc:`ImportError` with a message explaining that the module isn't supported on Windows. On other platforms, if the underlying ``_crypt`` module is not available, the ImportError will include a message explaining the problem. From webhook-mailer at python.org Thu Aug 8 17:48:05 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 08 Aug 2019 21:48:05 -0000 Subject: [Python-checkins] bpo-37268: test_parser fails when run with -Werror (GH-15183) Message-ID: https://github.com/python/cpython/commit/10a0a093231ea82a3bfd33fd63322aebd8406866 commit: 10a0a093231ea82a3bfd33fd63322aebd8406866 branch: master author: Zackery Spytz committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-08T14:48:00-07:00 summary: bpo-37268: test_parser fails when run with -Werror (GH-15183) Use warnings.filterwarnings() when importing the deprecated parser module. @pablogsal https://bugs.python.org/issue37268 Automerge-Triggered-By: @pablogsal files: M Lib/test/test_parser.py diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index ec1845d7fe9a..7295f66d393a 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -1,5 +1,9 @@ import copy -import parser +import warnings +with warnings.catch_warnings(): + warnings.filterwarnings('ignore', 'The parser module is deprecated', + DeprecationWarning) + import parser import pickle import unittest import operator From webhook-mailer at python.org Thu Aug 8 18:25:49 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Thu, 08 Aug 2019 22:25:49 -0000 Subject: [Python-checkins] bpo-37795: Capture DeprecationWarnings in the test suite (GH-15184) Message-ID: https://github.com/python/cpython/commit/aa542c2cf26c5af9298dda6064576b18906cdfbf commit: aa542c2cf26c5af9298dda6064576b18906cdfbf branch: master author: Pablo Galindo committer: GitHub date: 2019-08-08T23:25:46+01:00 summary: bpo-37795: Capture DeprecationWarnings in the test suite (GH-15184) files: M Lib/distutils/tests/test_bdist.py M Lib/test/test_httplib.py diff --git a/Lib/distutils/tests/test_bdist.py b/Lib/distutils/tests/test_bdist.py index c80b3edc0220..130d8bf155a4 100644 --- a/Lib/distutils/tests/test_bdist.py +++ b/Lib/distutils/tests/test_bdist.py @@ -2,6 +2,7 @@ import os import unittest from test.support import run_unittest +import warnings from distutils.command.bdist import bdist from distutils.tests import support @@ -38,7 +39,10 @@ def test_skip_build(self): names.append('bdist_msi') for name in names: - subcmd = cmd.get_finalized_command(name) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', 'bdist_wininst command is deprecated', + DeprecationWarning) + subcmd = cmd.get_finalized_command(name) if getattr(subcmd, '_unsupported', False): # command is not supported on this build continue diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 9148169cc7c2..656932fbaab7 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -7,6 +7,7 @@ import re import socket import threading +import warnings import unittest TestCase = unittest.TestCase @@ -1759,8 +1760,11 @@ def test_tls13_pha(self): self.assertIs(h._context, context) self.assertFalse(h._context.post_handshake_auth) - h = client.HTTPSConnection('localhost', 443, context=context, - cert_file=CERT_localhost) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', 'key_file, cert_file and check_hostname are deprecated', + DeprecationWarning) + h = client.HTTPSConnection('localhost', 443, context=context, + cert_file=CERT_localhost) self.assertTrue(h._context.post_handshake_auth) From webhook-mailer at python.org Thu Aug 8 19:12:37 2019 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 08 Aug 2019 23:12:37 -0000 Subject: [Python-checkins] bpo-36511: Fix failures in Windows ARM32 buildbot (GH-15181) Message-ID: https://github.com/python/cpython/commit/ed70a344b5fbddea85726ebc1964ee0cfdef9c40 commit: ed70a344b5fbddea85726ebc1964ee0cfdef9c40 branch: master author: Paul Monson committer: Steve Dower date: 2019-08-08T16:12:33-07:00 summary: bpo-36511: Fix failures in Windows ARM32 buildbot (GH-15181) files: M Lib/test/libregrtest/win_utils.py M Tools/buildbot/remoteDeploy.bat diff --git a/Lib/test/libregrtest/win_utils.py b/Lib/test/libregrtest/win_utils.py index 0e6bfa8e10f7..ec2d6c663e83 100644 --- a/Lib/test/libregrtest/win_utils.py +++ b/Lib/test/libregrtest/win_utils.py @@ -25,6 +25,7 @@ class WindowsLoadTracker(): def __init__(self): self.load = 0.0 + self.p = None self.start() def start(self): diff --git a/Tools/buildbot/remoteDeploy.bat b/Tools/buildbot/remoteDeploy.bat index 8b0ce239e1a4..6b86e1e59b07 100644 --- a/Tools/buildbot/remoteDeploy.bat +++ b/Tools/buildbot/remoteDeploy.bat @@ -36,6 +36,7 @@ for /f "USEBACKQ" %%i in (`dir PCbuild\arm32\*.pyd /b`) do @scp PCBuild\arm32\%% for /f "USEBACKQ" %%i in (`dir PCbuild\arm32\*.dll /b`) do @scp PCBuild\arm32\%%i "%SSH_SERVER%:%REMOTE_PYTHON_DIR%PCBuild\arm32" scp -r "%PYTHON_SOURCE%Include" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%Include" scp -r "%PYTHON_SOURCE%Lib" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%Lib" +scp -r "%PYTHON_SOURCE%Parser" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%Parser" scp -r "%PYTHON_SOURCE%Tools" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%Tools" scp "%PYTHON_SOURCE%Modules\Setup" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%Modules" scp "%PYTHON_SOURCE%PC\pyconfig.h" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%PC" From webhook-mailer at python.org Thu Aug 8 20:23:02 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Fri, 09 Aug 2019 00:23:02 -0000 Subject: [Python-checkins] [3.8] bpo-37795: Capture DeprecationWarnings in the test suite (GH-15184) (GH-15188) Message-ID: https://github.com/python/cpython/commit/162d45c531552d0699f945d2c22a763941dca3c1 commit: 162d45c531552d0699f945d2c22a763941dca3c1 branch: 3.8 author: Pablo Galindo committer: GitHub date: 2019-08-09T01:22:59+01:00 summary: [3.8] bpo-37795: Capture DeprecationWarnings in the test suite (GH-15184) (GH-15188) (cherry picked from commit aa542c2) Co-authored-by: Pablo Galindo files: M Lib/distutils/tests/test_bdist.py M Lib/test/test_httplib.py diff --git a/Lib/distutils/tests/test_bdist.py b/Lib/distutils/tests/test_bdist.py index c80b3edc0220..130d8bf155a4 100644 --- a/Lib/distutils/tests/test_bdist.py +++ b/Lib/distutils/tests/test_bdist.py @@ -2,6 +2,7 @@ import os import unittest from test.support import run_unittest +import warnings from distutils.command.bdist import bdist from distutils.tests import support @@ -38,7 +39,10 @@ def test_skip_build(self): names.append('bdist_msi') for name in names: - subcmd = cmd.get_finalized_command(name) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', 'bdist_wininst command is deprecated', + DeprecationWarning) + subcmd = cmd.get_finalized_command(name) if getattr(subcmd, '_unsupported', False): # command is not supported on this build continue diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 9148169cc7c2..656932fbaab7 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -7,6 +7,7 @@ import re import socket import threading +import warnings import unittest TestCase = unittest.TestCase @@ -1759,8 +1760,11 @@ def test_tls13_pha(self): self.assertIs(h._context, context) self.assertFalse(h._context.post_handshake_auth) - h = client.HTTPSConnection('localhost', 443, context=context, - cert_file=CERT_localhost) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', 'key_file, cert_file and check_hostname are deprecated', + DeprecationWarning) + h = client.HTTPSConnection('localhost', 443, context=context, + cert_file=CERT_localhost) self.assertTrue(h._context.post_handshake_auth) From webhook-mailer at python.org Fri Aug 9 04:30:51 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 09 Aug 2019 08:30:51 -0000 Subject: [Python-checkins] bpo-34155: Dont parse domains containing @ (GH-13079) Message-ID: https://github.com/python/cpython/commit/c48d606adcef395e59fd555496c42203b01dd3e8 commit: c48d606adcef395e59fd555496c42203b01dd3e8 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-09T01:30:33-07:00 summary: bpo-34155: Dont parse domains containing @ (GH-13079) Before: >>> email.message_from_string('From: a at malicious.org@important.com', policy=email.policy.default)['from'].addresses (Address(display_name='', username='a', domain='malicious.org'),) >>> parseaddr('a at malicious.org@important.com') ('', 'a at malicious.org') After: >>> email.message_from_string('From: a at malicious.org@important.com', policy=email.policy.default)['from'].addresses (Address(display_name='', username='', domain=''),) >>> parseaddr('a at malicious.org@important.com') ('', 'a@') https://bugs.python.org/issue34155 (cherry picked from commit 8cb65d1381b027f0b09ee36bfed7f35bb4dec9a9) Co-authored-by: jpic files: A Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst M Lib/email/_header_value_parser.py M Lib/email/_parseaddr.py M Lib/test/test_email/test__header_value_parser.py M Lib/test/test_email/test_email.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 801ae728dd13..c09f4f121ffb 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1585,6 +1585,8 @@ def get_domain(value): token, value = get_dot_atom(value) except errors.HeaderParseError: token, value = get_atom(value) + if value and value[0] == '@': + raise errors.HeaderParseError('Invalid Domain') if leader is not None: token[:0] = [leader] domain.append(token) diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py index cdfa3729adc7..41ff6f8c000d 100644 --- a/Lib/email/_parseaddr.py +++ b/Lib/email/_parseaddr.py @@ -379,7 +379,12 @@ def getaddrspec(self): aslist.append('@') self.pos += 1 self.gotonext() - return EMPTYSTRING.join(aslist) + self.getdomain() + domain = self.getdomain() + if not domain: + # Invalid domain, return an empty address instead of returning a + # local part to denote failed parsing. + return EMPTYSTRING + return EMPTYSTRING.join(aslist) + domain def getdomain(self): """Get the complete domain name from an address.""" @@ -394,6 +399,10 @@ def getdomain(self): elif self.field[self.pos] == '.': self.pos += 1 sdlist.append('.') + elif self.field[self.pos] == '@': + # bpo-34155: Don't parse domains with two `@` like + # `a at malicious.org@important.com`. + return EMPTYSTRING elif self.field[self.pos] in self.atomends: break else: diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index 9e862feab10c..0f19f8bcc2e0 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -1448,6 +1448,16 @@ def test_get_addr_spec_dot_atom(self): self.assertEqual(addr_spec.domain, 'example.com') self.assertEqual(addr_spec.addr_spec, 'star.a.star at example.com') + def test_get_addr_spec_multiple_domains(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star at a.star@example.com') + + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star at a@example.com') + + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star at 172.17.0.1@example.com') + # get_obs_route def test_get_obs_route_simple(self): diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index c29cc56203b1..aa775881c552 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3041,6 +3041,20 @@ def test_parseaddr_empty(self): self.assertEqual(utils.parseaddr('<>'), ('', '')) self.assertEqual(utils.formataddr(utils.parseaddr('<>')), '') + def test_parseaddr_multiple_domains(self): + self.assertEqual( + utils.parseaddr('a at b@c'), + ('', '') + ) + self.assertEqual( + utils.parseaddr('a at b.c@c'), + ('', '') + ) + self.assertEqual( + utils.parseaddr('a at 172.17.0.1@c'), + ('', '') + ) + def test_noquote_dump(self): self.assertEqual( utils.formataddr(('A Silly Person', 'person at dom.ain')), diff --git a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst new file mode 100644 index 000000000000..50292e29ed1d --- /dev/null +++ b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst @@ -0,0 +1 @@ +Fix parsing of invalid email addresses with more than one ``@`` (e.g. a at b@c.com.) to not return the part before 2nd ``@`` as valid email address. Patch by maxking & jpic. From webhook-mailer at python.org Fri Aug 9 04:31:33 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 09 Aug 2019 08:31:33 -0000 Subject: [Python-checkins] bpo-34155: Dont parse domains containing @ (GH-13079) Message-ID: https://github.com/python/cpython/commit/217077440a6938a0b428f67cfef6e053c4f8673c commit: 217077440a6938a0b428f67cfef6e053c4f8673c branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-09T01:31:27-07:00 summary: bpo-34155: Dont parse domains containing @ (GH-13079) Before: >>> email.message_from_string('From: a at malicious.org@important.com', policy=email.policy.default)['from'].addresses (Address(display_name='', username='a', domain='malicious.org'),) >>> parseaddr('a at malicious.org@important.com') ('', 'a at malicious.org') After: >>> email.message_from_string('From: a at malicious.org@important.com', policy=email.policy.default)['from'].addresses (Address(display_name='', username='', domain=''),) >>> parseaddr('a at malicious.org@important.com') ('', 'a@') https://bugs.python.org/issue34155 (cherry picked from commit 8cb65d1381b027f0b09ee36bfed7f35bb4dec9a9) Co-authored-by: jpic files: A Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst M Lib/email/_header_value_parser.py M Lib/email/_parseaddr.py M Lib/test/test_email/test__header_value_parser.py M Lib/test/test_email/test_email.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 7dfd9780a6e9..a93079278893 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1566,6 +1566,8 @@ def get_domain(value): token, value = get_dot_atom(value) except errors.HeaderParseError: token, value = get_atom(value) + if value and value[0] == '@': + raise errors.HeaderParseError('Invalid Domain') if leader is not None: token[:0] = [leader] domain.append(token) diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py index cdfa3729adc7..41ff6f8c000d 100644 --- a/Lib/email/_parseaddr.py +++ b/Lib/email/_parseaddr.py @@ -379,7 +379,12 @@ def getaddrspec(self): aslist.append('@') self.pos += 1 self.gotonext() - return EMPTYSTRING.join(aslist) + self.getdomain() + domain = self.getdomain() + if not domain: + # Invalid domain, return an empty address instead of returning a + # local part to denote failed parsing. + return EMPTYSTRING + return EMPTYSTRING.join(aslist) + domain def getdomain(self): """Get the complete domain name from an address.""" @@ -394,6 +399,10 @@ def getdomain(self): elif self.field[self.pos] == '.': self.pos += 1 sdlist.append('.') + elif self.field[self.pos] == '@': + # bpo-34155: Don't parse domains with two `@` like + # `a at malicious.org@important.com`. + return EMPTYSTRING elif self.field[self.pos] in self.atomends: break else: diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index f4aad851c677..010be9fa4ae6 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -1428,6 +1428,16 @@ def test_get_addr_spec_dot_atom(self): self.assertEqual(addr_spec.domain, 'example.com') self.assertEqual(addr_spec.addr_spec, 'star.a.star at example.com') + def test_get_addr_spec_multiple_domains(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star at a.star@example.com') + + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star at a@example.com') + + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star at 172.17.0.1@example.com') + # get_obs_route def test_get_obs_route_simple(self): diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index c29cc56203b1..aa775881c552 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3041,6 +3041,20 @@ def test_parseaddr_empty(self): self.assertEqual(utils.parseaddr('<>'), ('', '')) self.assertEqual(utils.formataddr(utils.parseaddr('<>')), '') + def test_parseaddr_multiple_domains(self): + self.assertEqual( + utils.parseaddr('a at b@c'), + ('', '') + ) + self.assertEqual( + utils.parseaddr('a at b.c@c'), + ('', '') + ) + self.assertEqual( + utils.parseaddr('a at 172.17.0.1@c'), + ('', '') + ) + def test_noquote_dump(self): self.assertEqual( utils.formataddr(('A Silly Person', 'person at dom.ain')), diff --git a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst new file mode 100644 index 000000000000..50292e29ed1d --- /dev/null +++ b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst @@ -0,0 +1 @@ +Fix parsing of invalid email addresses with more than one ``@`` (e.g. a at b@c.com.) to not return the part before 2nd ``@`` as valid email address. Patch by maxking & jpic. From webhook-mailer at python.org Fri Aug 9 10:22:22 2019 From: webhook-mailer at python.org (Paul Ganssle) Date: Fri, 09 Aug 2019 14:22:22 -0000 Subject: [Python-checkins] bpo-37642: Update acceptable offsets in timezone (GH-14878) Message-ID: https://github.com/python/cpython/commit/92c7e30adf5c81a54d6e5e555a6bdfaa60157a0d commit: 92c7e30adf5c81a54d6e5e555a6bdfaa60157a0d branch: master author: Ngalim Siregar committer: Paul Ganssle date: 2019-08-09T10:22:16-04:00 summary: bpo-37642: Update acceptable offsets in timezone (GH-14878) This fixes an inconsistency between the Python and C implementations of the datetime module. The pure python version of the code was not accepting offsets greater than 23:59 but less than 24:00. This is an accidental legacy of the original implementation, which was put in place before tzinfo allowed sub-minute time zone offsets. GH-14878 files: A Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst M Lib/datetime.py M Lib/test/datetimetester.py M Misc/ACKS M Modules/_datetimemodule.c diff --git a/Lib/datetime.py b/Lib/datetime.py index d4c7a1ff9004..0adf1dd67dfb 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -2269,7 +2269,7 @@ def fromutc(self, dt): raise TypeError("fromutc() argument must be a datetime instance" " or None") - _maxoffset = timedelta(hours=23, minutes=59) + _maxoffset = timedelta(hours=24, microseconds=-1) _minoffset = -_maxoffset @staticmethod @@ -2293,8 +2293,11 @@ def _name_from_offset(delta): return f'UTC{sign}{hours:02d}:{minutes:02d}' timezone.utc = timezone._create(timedelta(0)) -timezone.min = timezone._create(timezone._minoffset) -timezone.max = timezone._create(timezone._maxoffset) +# bpo-37642: These attributes are rounded to the nearest minute for backwards +# compatibility, even though the constructor will accept a wider range of +# values. This may change in the future. +timezone.min = timezone._create(-timedelta(hours=23, minutes=59)) +timezone.max = timezone._create(timedelta(hours=23, minutes=59)) _EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc) # Some time zone algebra. For a datetime x, let diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 99b620ce2f41..d0101c98bc76 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -388,6 +388,31 @@ def test_deepcopy(self): tz_copy = copy.deepcopy(tz) self.assertIs(tz_copy, tz) + def test_offset_boundaries(self): + # Test timedeltas close to the boundaries + time_deltas = [ + timedelta(hours=23, minutes=59), + timedelta(hours=23, minutes=59, seconds=59), + timedelta(hours=23, minutes=59, seconds=59, microseconds=999999), + ] + time_deltas.extend([-delta for delta in time_deltas]) + + for delta in time_deltas: + with self.subTest(test_type='good', delta=delta): + timezone(delta) + + # Test timedeltas on and outside the boundaries + bad_time_deltas = [ + timedelta(hours=24), + timedelta(hours=24, microseconds=1), + ] + bad_time_deltas.extend([-delta for delta in bad_time_deltas]) + + for delta in bad_time_deltas: + with self.subTest(test_type='bad', delta=delta): + with self.assertRaises(ValueError): + timezone(delta) + ############################################################################# # Base class for testing a particular aspect of timedelta, time, date and diff --git a/Misc/ACKS b/Misc/ACKS index 8c834b43120b..3b4cf85c75fe 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1881,3 +1881,4 @@ Aleksandr Balezin Robert Leenders Tim Hopper Dan Lidral-Porter +Ngalim Siregar diff --git a/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst b/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst new file mode 100644 index 000000000000..09ff257597e8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst @@ -0,0 +1,3 @@ +Allowed the pure Python implementation of :class:`datetime.timezone` to represent +sub-minute offsets close to minimum and maximum boundaries, specifically in the +ranges (23:59, 24:00) and (-23:59, 24:00). Patch by Ngalim Siregar diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index b55922cd961a..6d28b3e511c2 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1099,7 +1099,9 @@ new_timezone(PyObject *offset, PyObject *name) Py_INCREF(PyDateTime_TimeZone_UTC); return PyDateTime_TimeZone_UTC; } - if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) || + if ((GET_TD_DAYS(offset) == -1 && + GET_TD_SECONDS(offset) == 0 && + GET_TD_MICROSECONDS(offset) < 1) || GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { PyErr_Format(PyExc_ValueError, "offset must be a timedelta" " strictly between -timedelta(hours=24) and" @@ -1169,7 +1171,9 @@ call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg) if (offset == Py_None || offset == NULL) return offset; if (PyDelta_Check(offset)) { - if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) || + if ((GET_TD_DAYS(offset) == -1 && + GET_TD_SECONDS(offset) == 0 && + GET_TD_MICROSECONDS(offset) < 1) || GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { Py_DECREF(offset); PyErr_Format(PyExc_ValueError, "offset must be a timedelta" @@ -6481,6 +6485,9 @@ PyInit__datetime(void) PyDateTime_TimeZone_UTC = x; CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC; + /* bpo-37642: These attributes are rounded to the nearest minute for backwards + * compatibility, even though the constructor will accept a wider range of + * values. This may change in the future.*/ delta = new_delta(-1, 60, 0, 1); /* -23:59 */ if (delta == NULL) return NULL; From webhook-mailer at python.org Fri Aug 9 11:22:26 2019 From: webhook-mailer at python.org (Ned Deily) Date: Fri, 09 Aug 2019 15:22:26 -0000 Subject: [Python-checkins] bpo-34155: Dont parse domains containing @ (GH-13079) (GH-14826) Message-ID: https://github.com/python/cpython/commit/13a19139b5e76175bc95294d54afc9425e4f36c9 commit: 13a19139b5e76175bc95294d54afc9425e4f36c9 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2019-08-09T11:22:19-04:00 summary: bpo-34155: Dont parse domains containing @ (GH-13079) (GH-14826) Before: >>> email.message_from_string('From: a at malicious.org@important.com', policy=email.policy.default)['from'].addresses (Address(display_name='', username='a', domain='malicious.org'),) >>> parseaddr('a at malicious.org@important.com') ('', 'a at malicious.org') After: >>> email.message_from_string('From: a at malicious.org@important.com', policy=email.policy.default)['from'].addresses (Address(display_name='', username='', domain=''),) >>> parseaddr('a at malicious.org@important.com') ('', 'a@') https://bugs.python.org/issue34155 (cherry picked from commit 8cb65d1381b027f0b09ee36bfed7f35bb4dec9a9) Co-authored-by: jpic files: A Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst M Lib/email/_header_value_parser.py M Lib/email/_parseaddr.py M Lib/test/test_email/test__header_value_parser.py M Lib/test/test_email/test_email.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 737951e4b1b1..bc9c9b6241d4 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1561,6 +1561,8 @@ def get_domain(value): token, value = get_dot_atom(value) except errors.HeaderParseError: token, value = get_atom(value) + if value and value[0] == '@': + raise errors.HeaderParseError('Invalid Domain') if leader is not None: token[:0] = [leader] domain.append(token) diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py index cdfa3729adc7..41ff6f8c000d 100644 --- a/Lib/email/_parseaddr.py +++ b/Lib/email/_parseaddr.py @@ -379,7 +379,12 @@ def getaddrspec(self): aslist.append('@') self.pos += 1 self.gotonext() - return EMPTYSTRING.join(aslist) + self.getdomain() + domain = self.getdomain() + if not domain: + # Invalid domain, return an empty address instead of returning a + # local part to denote failed parsing. + return EMPTYSTRING + return EMPTYSTRING.join(aslist) + domain def getdomain(self): """Get the complete domain name from an address.""" @@ -394,6 +399,10 @@ def getdomain(self): elif self.field[self.pos] == '.': self.pos += 1 sdlist.append('.') + elif self.field[self.pos] == '@': + # bpo-34155: Don't parse domains with two `@` like + # `a at malicious.org@important.com`. + return EMPTYSTRING elif self.field[self.pos] in self.atomends: break else: diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index a2c900fa7fd2..02ef3e1006c6 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -1418,6 +1418,16 @@ def test_get_addr_spec_dot_atom(self): self.assertEqual(addr_spec.domain, 'example.com') self.assertEqual(addr_spec.addr_spec, 'star.a.star at example.com') + def test_get_addr_spec_multiple_domains(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star at a.star@example.com') + + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star at a@example.com') + + with self.assertRaises(errors.HeaderParseError): + parser.get_addr_spec('star at 172.17.0.1@example.com') + # get_obs_route def test_get_obs_route_simple(self): diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index f97ccc6711cc..68d052279987 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3035,6 +3035,20 @@ def test_parseaddr_empty(self): self.assertEqual(utils.parseaddr('<>'), ('', '')) self.assertEqual(utils.formataddr(utils.parseaddr('<>')), '') + def test_parseaddr_multiple_domains(self): + self.assertEqual( + utils.parseaddr('a at b@c'), + ('', '') + ) + self.assertEqual( + utils.parseaddr('a at b.c@c'), + ('', '') + ) + self.assertEqual( + utils.parseaddr('a at 172.17.0.1@c'), + ('', '') + ) + def test_noquote_dump(self): self.assertEqual( utils.formataddr(('A Silly Person', 'person at dom.ain')), diff --git a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst new file mode 100644 index 000000000000..50292e29ed1d --- /dev/null +++ b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst @@ -0,0 +1 @@ +Fix parsing of invalid email addresses with more than one ``@`` (e.g. a at b@c.com.) to not return the part before 2nd ``@`` as valid email address. Patch by maxking & jpic. From webhook-mailer at python.org Fri Aug 9 18:34:28 2019 From: webhook-mailer at python.org (Gregory P. Smith) Date: Fri, 09 Aug 2019 22:34:28 -0000 Subject: [Python-checkins] [3.8] bpo-32912: Revert SyntaxWarning on invalid escape sequences (GH-15142) Message-ID: https://github.com/python/cpython/commit/4c5b6bac2408f879231c7cd38d67657dd4804e7c commit: 4c5b6bac2408f879231c7cd38d67657dd4804e7c branch: 3.8 author: Serhiy Storchaka committer: Gregory P. Smith date: 2019-08-09T15:34:22-07:00 summary: [3.8] bpo-32912: Revert SyntaxWarning on invalid escape sequences (GH-15142) * bpo-32912: Revert warnings for invalid escape sequences. DeprecationWarning will continue to be emitted for invalid escape sequences in string and bytes literals in 3.8 just as it did in 3.7. SyntaxWarning may be emitted in the future. But per mailing list discussion, we don't yet know when because we haven't settled on how to do so in a non-disruptive manner. files: A Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912.UDwSMJ.rst M Doc/reference/lexical_analysis.rst M Doc/whatsnew/3.8.rst M Lib/test/test_fstring.py M Lib/test/test_string_literals.py M Python/ast.c diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index cc1b2f57a70e..7e1e17edb2d8 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -594,11 +594,9 @@ escape sequences only recognized in string literals fall into the category of unrecognized escapes for bytes literals. .. versionchanged:: 3.6 - Unrecognized escape sequences produce a :exc:`DeprecationWarning`. - - .. versionchanged:: 3.8 - Unrecognized escape sequences produce a :exc:`SyntaxWarning`. In - some future version of Python they will be a :exc:`SyntaxError`. + Unrecognized escape sequences produce a :exc:`DeprecationWarning`. In + a future Python version they will be a :exc:`SyntaxWarning` and + eventually a :exc:`SyntaxError`. Even in a raw literal, quotes can be escaped with a backslash, but the backslash remains in the result; for example, ``r"\""`` is a valid string diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 9f7058274514..83caa2cc5abc 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -414,11 +414,6 @@ Other Language Changes and :keyword:`return` statements. (Contributed by David Cuthbert and Jordan Chapman in :issue:`32117`.) -* A backslash-character pair that is not a valid escape sequence generates - a :exc:`DeprecationWarning` since Python 3.6. In Python 3.8 it generates - a :exc:`SyntaxWarning` instead. - (Contributed by Serhiy Storchaka in :issue:`32912`.) - * The compiler now produces a :exc:`SyntaxWarning` in some cases when a comma is missed before tuple or list. For example:: diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index fb761441fcee..49663923e7f5 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -649,7 +649,7 @@ def test_backslashes_in_string_part(self): self.assertEqual(f'2\x203', '2 3') self.assertEqual(f'\x203', ' 3') - with self.assertWarns(SyntaxWarning): # invalid escape sequence + with self.assertWarns(DeprecationWarning): # invalid escape sequence value = eval(r"f'\{6*7}'") self.assertEqual(value, '\\42') self.assertEqual(f'\\{6*7}', '\\42') diff --git a/Lib/test/test_string_literals.py b/Lib/test/test_string_literals.py index 5961d591c448..0cea2edc32af 100644 --- a/Lib/test/test_string_literals.py +++ b/Lib/test/test_string_literals.py @@ -32,6 +32,7 @@ import shutil import tempfile import unittest +import warnings TEMPLATE = r"""# coding: %s @@ -110,10 +111,24 @@ def test_eval_str_invalid_escape(self): for b in range(1, 128): if b in b"""\n\r"'01234567NU\\abfnrtuvx""": continue - with self.assertWarns(SyntaxWarning): + with self.assertWarns(DeprecationWarning): self.assertEqual(eval(r"'\%c'" % b), '\\' + chr(b)) - self.check_syntax_warning("'''\n\\z'''") + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', category=DeprecationWarning) + eval("'''\n\\z'''") + self.assertEqual(len(w), 1) + self.assertEqual(w[0].filename, '') + self.assertEqual(w[0].lineno, 1) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('error', category=DeprecationWarning) + with self.assertRaises(SyntaxError) as cm: + eval("'''\n\\z'''") + exc = cm.exception + self.assertEqual(w, []) + self.assertEqual(exc.filename, '') + self.assertEqual(exc.lineno, 1) def test_eval_str_raw(self): self.assertEqual(eval(""" r'x' """), 'x') @@ -145,10 +160,24 @@ def test_eval_bytes_invalid_escape(self): for b in range(1, 128): if b in b"""\n\r"'01234567\\abfnrtvx""": continue - with self.assertWarns(SyntaxWarning): + with self.assertWarns(DeprecationWarning): self.assertEqual(eval(r"b'\%c'" % b), b'\\' + bytes([b])) - self.check_syntax_warning("b'''\n\\z'''") + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', category=DeprecationWarning) + eval("b'''\n\\z'''") + self.assertEqual(len(w), 1) + self.assertEqual(w[0].filename, '') + self.assertEqual(w[0].lineno, 1) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('error', category=DeprecationWarning) + with self.assertRaises(SyntaxError) as cm: + eval("b'''\n\\z'''") + exc = cm.exception + self.assertEqual(w, []) + self.assertEqual(exc.filename, '') + self.assertEqual(exc.lineno, 1) def test_eval_bytes_raw(self): self.assertEqual(eval(""" br'x' """), b'x') diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912.UDwSMJ.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912.UDwSMJ.rst new file mode 100644 index 000000000000..e18d8adfbee9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912.UDwSMJ.rst @@ -0,0 +1,3 @@ +Reverted :issue:`32912`: emitting :exc:`SyntaxWarning` instead of +:exc:`DeprecationWarning` for invalid escape sequences in string and bytes +literals. diff --git a/Python/ast.c b/Python/ast.c index f6c2049ae2cf..9947824de744 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -4674,12 +4674,12 @@ warn_invalid_escape_sequence(struct compiling *c, const node *n, if (msg == NULL) { return -1; } - if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, + if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, msg, c->c_filename, LINENO(n), NULL, NULL) < 0) { - if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { - /* Replace the SyntaxWarning exception with a SyntaxError + if (PyErr_ExceptionMatches(PyExc_DeprecationWarning)) { + /* Replace the DeprecationWarning exception with a SyntaxError to get a more accurate error report */ PyErr_Clear(); ast_error(c, n, "%U", msg); From webhook-mailer at python.org Sat Aug 10 03:19:16 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 10 Aug 2019 07:19:16 -0000 Subject: [Python-checkins] bpo-32912: Revert SyntaxWarning on invalid escape sequences. (GH-15195) Message-ID: https://github.com/python/cpython/commit/b4be87a04a2a8ccfd2480e19dc527589fce53555 commit: b4be87a04a2a8ccfd2480e19dc527589fce53555 branch: master author: Gregory P. Smith committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-10T00:19:07-07:00 summary: bpo-32912: Revert SyntaxWarning on invalid escape sequences. (GH-15195) DeprecationWarning will continue to be emitted for invalid escape sequences in string and bytes literals just as it did in 3.7. SyntaxWarning may be emitted in the future. But per mailing list discussion, we don't yet know when because we haven't settled on how to do so in a non-disruptive manner. (Applies 4c5b6bac2408f879231c7cd38d67657dd4804e7c to the master branch). (This is https://github.com/python/cpython/pull/15142 for master/3.9) https://bugs.python.org/issue32912 Automerge-Triggered-By: @gpshead files: A Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912.UDwSMJ.rst M Doc/reference/lexical_analysis.rst M Doc/whatsnew/3.8.rst M Lib/test/test_fstring.py M Lib/test/test_string_literals.py M Python/ast.c diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index cc1b2f57a70e..7e1e17edb2d8 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -594,11 +594,9 @@ escape sequences only recognized in string literals fall into the category of unrecognized escapes for bytes literals. .. versionchanged:: 3.6 - Unrecognized escape sequences produce a :exc:`DeprecationWarning`. - - .. versionchanged:: 3.8 - Unrecognized escape sequences produce a :exc:`SyntaxWarning`. In - some future version of Python they will be a :exc:`SyntaxError`. + Unrecognized escape sequences produce a :exc:`DeprecationWarning`. In + a future Python version they will be a :exc:`SyntaxWarning` and + eventually a :exc:`SyntaxError`. Even in a raw literal, quotes can be escaped with a backslash, but the backslash remains in the result; for example, ``r"\""`` is a valid string diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index d8062e772f6e..82da10cc3be8 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -414,11 +414,6 @@ Other Language Changes and :keyword:`return` statements. (Contributed by David Cuthbert and Jordan Chapman in :issue:`32117`.) -* A backslash-character pair that is not a valid escape sequence generates - a :exc:`DeprecationWarning` since Python 3.6. In Python 3.8 it generates - a :exc:`SyntaxWarning` instead. - (Contributed by Serhiy Storchaka in :issue:`32912`.) - * The compiler now produces a :exc:`SyntaxWarning` in some cases when a comma is missed before tuple or list. For example:: diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index fb761441fcee..49663923e7f5 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -649,7 +649,7 @@ def test_backslashes_in_string_part(self): self.assertEqual(f'2\x203', '2 3') self.assertEqual(f'\x203', ' 3') - with self.assertWarns(SyntaxWarning): # invalid escape sequence + with self.assertWarns(DeprecationWarning): # invalid escape sequence value = eval(r"f'\{6*7}'") self.assertEqual(value, '\\42') self.assertEqual(f'\\{6*7}', '\\42') diff --git a/Lib/test/test_string_literals.py b/Lib/test/test_string_literals.py index 5961d591c448..0cea2edc32af 100644 --- a/Lib/test/test_string_literals.py +++ b/Lib/test/test_string_literals.py @@ -32,6 +32,7 @@ import shutil import tempfile import unittest +import warnings TEMPLATE = r"""# coding: %s @@ -110,10 +111,24 @@ def test_eval_str_invalid_escape(self): for b in range(1, 128): if b in b"""\n\r"'01234567NU\\abfnrtuvx""": continue - with self.assertWarns(SyntaxWarning): + with self.assertWarns(DeprecationWarning): self.assertEqual(eval(r"'\%c'" % b), '\\' + chr(b)) - self.check_syntax_warning("'''\n\\z'''") + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', category=DeprecationWarning) + eval("'''\n\\z'''") + self.assertEqual(len(w), 1) + self.assertEqual(w[0].filename, '') + self.assertEqual(w[0].lineno, 1) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('error', category=DeprecationWarning) + with self.assertRaises(SyntaxError) as cm: + eval("'''\n\\z'''") + exc = cm.exception + self.assertEqual(w, []) + self.assertEqual(exc.filename, '') + self.assertEqual(exc.lineno, 1) def test_eval_str_raw(self): self.assertEqual(eval(""" r'x' """), 'x') @@ -145,10 +160,24 @@ def test_eval_bytes_invalid_escape(self): for b in range(1, 128): if b in b"""\n\r"'01234567\\abfnrtvx""": continue - with self.assertWarns(SyntaxWarning): + with self.assertWarns(DeprecationWarning): self.assertEqual(eval(r"b'\%c'" % b), b'\\' + bytes([b])) - self.check_syntax_warning("b'''\n\\z'''") + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', category=DeprecationWarning) + eval("b'''\n\\z'''") + self.assertEqual(len(w), 1) + self.assertEqual(w[0].filename, '') + self.assertEqual(w[0].lineno, 1) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('error', category=DeprecationWarning) + with self.assertRaises(SyntaxError) as cm: + eval("b'''\n\\z'''") + exc = cm.exception + self.assertEqual(w, []) + self.assertEqual(exc.filename, '') + self.assertEqual(exc.lineno, 1) def test_eval_bytes_raw(self): self.assertEqual(eval(""" br'x' """), b'x') diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912.UDwSMJ.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912.UDwSMJ.rst new file mode 100644 index 000000000000..e18d8adfbee9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912.UDwSMJ.rst @@ -0,0 +1,3 @@ +Reverted :issue:`32912`: emitting :exc:`SyntaxWarning` instead of +:exc:`DeprecationWarning` for invalid escape sequences in string and bytes +literals. diff --git a/Python/ast.c b/Python/ast.c index 976be70d4d70..8b3dbead2fdc 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -4671,12 +4671,12 @@ warn_invalid_escape_sequence(struct compiling *c, const node *n, if (msg == NULL) { return -1; } - if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, + if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, msg, c->c_filename, LINENO(n), NULL, NULL) < 0) { - if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { - /* Replace the SyntaxWarning exception with a SyntaxError + if (PyErr_ExceptionMatches(PyExc_DeprecationWarning)) { + /* Replace the DeprecationWarning exception with a SyntaxError to get a more accurate error report */ PyErr_Clear(); ast_error(c, n, "%U", msg); From webhook-mailer at python.org Sat Aug 10 03:20:31 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 10 Aug 2019 07:20:31 -0000 Subject: [Python-checkins] Delete leftover clinic-generated file for C zipimport. (GH-15174) Message-ID: https://github.com/python/cpython/commit/51aac15f6d525595e200e3580409c4b8656e8a96 commit: 51aac15f6d525595e200e3580409c4b8656e8a96 branch: master author: Greg Price committer: Serhiy Storchaka date: 2019-08-10T10:20:27+03:00 summary: Delete leftover clinic-generated file for C zipimport. (GH-15174) files: D Modules/clinic/zipimport.c.h diff --git a/Modules/clinic/zipimport.c.h b/Modules/clinic/zipimport.c.h deleted file mode 100644 index aabe7a05ae9d..000000000000 --- a/Modules/clinic/zipimport.c.h +++ /dev/null @@ -1,325 +0,0 @@ -/*[clinic input] -preserve -[clinic start generated code]*/ - -PyDoc_STRVAR(zipimport_zipimporter___init____doc__, -"zipimporter(archivepath, /)\n" -"--\n" -"\n" -"Create a new zipimporter instance.\n" -"\n" -" archivepath\n" -" A path-like object to a zipfile, or to a specific path inside\n" -" a zipfile.\n" -"\n" -"\'archivepath\' must be a path-like object to a zipfile, or to a specific path\n" -"inside a zipfile. For example, it can be \'/tmp/myimport.zip\', or\n" -"\'/tmp/myimport.zip/mydirectory\', if mydirectory is a valid directory inside\n" -"the archive.\n" -"\n" -"\'ZipImportError\' is raised if \'archivepath\' doesn\'t point to a valid Zip\n" -"archive.\n" -"\n" -"The \'archive\' attribute of the zipimporter object contains the name of the\n" -"zipfile targeted."); - -static int -zipimport_zipimporter___init___impl(ZipImporter *self, PyObject *path); - -static int -zipimport_zipimporter___init__(PyObject *self, PyObject *args, PyObject *kwargs) -{ - int return_value = -1; - PyObject *path; - - if ((Py_TYPE(self) == &ZipImporter_Type) && - !_PyArg_NoKeywords("zipimporter", kwargs)) { - goto exit; - } - if (!PyArg_ParseTuple(args, "O&:zipimporter", - PyUnicode_FSDecoder, &path)) { - goto exit; - } - return_value = zipimport_zipimporter___init___impl((ZipImporter *)self, path); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_find_module__doc__, -"find_module($self, fullname, path=None, /)\n" -"--\n" -"\n" -"Search for a module specified by \'fullname\'.\n" -"\n" -"\'fullname\' must be the fully qualified (dotted) module name. It returns the\n" -"zipimporter instance itself if the module was found, or None if it wasn\'t.\n" -"The optional \'path\' argument is ignored -- it\'s there for compatibility\n" -"with the importer protocol."); - -#define ZIPIMPORT_ZIPIMPORTER_FIND_MODULE_METHODDEF \ - {"find_module", (PyCFunction)(void *)zipimport_zipimporter_find_module, METH_FASTCALL, zipimport_zipimporter_find_module__doc__}, - -static PyObject * -zipimport_zipimporter_find_module_impl(ZipImporter *self, PyObject *fullname, - PyObject *path); - -static PyObject * -zipimport_zipimporter_find_module(ZipImporter *self, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *fullname; - PyObject *path = Py_None; - - if (!_PyArg_ParseStack(args, nargs, "U|O:find_module", - &fullname, &path)) { - goto exit; - } - return_value = zipimport_zipimporter_find_module_impl(self, fullname, path); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_find_loader__doc__, -"find_loader($self, fullname, path=None, /)\n" -"--\n" -"\n" -"Search for a module specified by \'fullname\'.\n" -"\n" -"\'fullname\' must be the fully qualified (dotted) module name. It returns the\n" -"zipimporter instance itself if the module was found, a string containing the\n" -"full path name if it\'s possibly a portion of a namespace package,\n" -"or None otherwise. The optional \'path\' argument is ignored -- it\'s\n" -"there for compatibility with the importer protocol."); - -#define ZIPIMPORT_ZIPIMPORTER_FIND_LOADER_METHODDEF \ - {"find_loader", (PyCFunction)(void *)zipimport_zipimporter_find_loader, METH_FASTCALL, zipimport_zipimporter_find_loader__doc__}, - -static PyObject * -zipimport_zipimporter_find_loader_impl(ZipImporter *self, PyObject *fullname, - PyObject *path); - -static PyObject * -zipimport_zipimporter_find_loader(ZipImporter *self, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *fullname; - PyObject *path = Py_None; - - if (!_PyArg_ParseStack(args, nargs, "U|O:find_loader", - &fullname, &path)) { - goto exit; - } - return_value = zipimport_zipimporter_find_loader_impl(self, fullname, path); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_load_module__doc__, -"load_module($self, fullname, /)\n" -"--\n" -"\n" -"Load the module specified by \'fullname\'.\n" -"\n" -"\'fullname\' must be the fully qualified (dotted) module name. It returns the\n" -"imported module, or raises ZipImportError if it wasn\'t found."); - -#define ZIPIMPORT_ZIPIMPORTER_LOAD_MODULE_METHODDEF \ - {"load_module", (PyCFunction)zipimport_zipimporter_load_module, METH_O, zipimport_zipimporter_load_module__doc__}, - -static PyObject * -zipimport_zipimporter_load_module_impl(ZipImporter *self, PyObject *fullname); - -static PyObject * -zipimport_zipimporter_load_module(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:load_module", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_load_module_impl(self, fullname); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_get_filename__doc__, -"get_filename($self, fullname, /)\n" -"--\n" -"\n" -"Return the filename for the specified module."); - -#define ZIPIMPORT_ZIPIMPORTER_GET_FILENAME_METHODDEF \ - {"get_filename", (PyCFunction)zipimport_zipimporter_get_filename, METH_O, zipimport_zipimporter_get_filename__doc__}, - -static PyObject * -zipimport_zipimporter_get_filename_impl(ZipImporter *self, - PyObject *fullname); - -static PyObject * -zipimport_zipimporter_get_filename(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:get_filename", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_get_filename_impl(self, fullname); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_is_package__doc__, -"is_package($self, fullname, /)\n" -"--\n" -"\n" -"Return True if the module specified by fullname is a package.\n" -"\n" -"Raise ZipImportError if the module couldn\'t be found."); - -#define ZIPIMPORT_ZIPIMPORTER_IS_PACKAGE_METHODDEF \ - {"is_package", (PyCFunction)zipimport_zipimporter_is_package, METH_O, zipimport_zipimporter_is_package__doc__}, - -static PyObject * -zipimport_zipimporter_is_package_impl(ZipImporter *self, PyObject *fullname); - -static PyObject * -zipimport_zipimporter_is_package(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:is_package", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_is_package_impl(self, fullname); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_get_data__doc__, -"get_data($self, pathname, /)\n" -"--\n" -"\n" -"Return the data associated with \'pathname\'.\n" -"\n" -"Raise OSError if the file was not found."); - -#define ZIPIMPORT_ZIPIMPORTER_GET_DATA_METHODDEF \ - {"get_data", (PyCFunction)zipimport_zipimporter_get_data, METH_O, zipimport_zipimporter_get_data__doc__}, - -static PyObject * -zipimport_zipimporter_get_data_impl(ZipImporter *self, PyObject *path); - -static PyObject * -zipimport_zipimporter_get_data(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *path; - - if (!PyArg_Parse(arg, "U:get_data", &path)) { - goto exit; - } - return_value = zipimport_zipimporter_get_data_impl(self, path); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_get_code__doc__, -"get_code($self, fullname, /)\n" -"--\n" -"\n" -"Return the code object for the specified module.\n" -"\n" -"Raise ZipImportError if the module couldn\'t be found."); - -#define ZIPIMPORT_ZIPIMPORTER_GET_CODE_METHODDEF \ - {"get_code", (PyCFunction)zipimport_zipimporter_get_code, METH_O, zipimport_zipimporter_get_code__doc__}, - -static PyObject * -zipimport_zipimporter_get_code_impl(ZipImporter *self, PyObject *fullname); - -static PyObject * -zipimport_zipimporter_get_code(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:get_code", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_get_code_impl(self, fullname); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_get_source__doc__, -"get_source($self, fullname, /)\n" -"--\n" -"\n" -"Return the source code for the specified module.\n" -"\n" -"Raise ZipImportError if the module couldn\'t be found, return None if the\n" -"archive does contain the module, but has no source for it."); - -#define ZIPIMPORT_ZIPIMPORTER_GET_SOURCE_METHODDEF \ - {"get_source", (PyCFunction)zipimport_zipimporter_get_source, METH_O, zipimport_zipimporter_get_source__doc__}, - -static PyObject * -zipimport_zipimporter_get_source_impl(ZipImporter *self, PyObject *fullname); - -static PyObject * -zipimport_zipimporter_get_source(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:get_source", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_get_source_impl(self, fullname); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_get_resource_reader__doc__, -"get_resource_reader($self, fullname, /)\n" -"--\n" -"\n" -"Return the ResourceReader for a package in a zip file.\n" -"\n" -"If \'fullname\' is a package within the zip file, return the \'ResourceReader\'\n" -"object for the package. Otherwise return None."); - -#define ZIPIMPORT_ZIPIMPORTER_GET_RESOURCE_READER_METHODDEF \ - {"get_resource_reader", (PyCFunction)zipimport_zipimporter_get_resource_reader, METH_O, zipimport_zipimporter_get_resource_reader__doc__}, - -static PyObject * -zipimport_zipimporter_get_resource_reader_impl(ZipImporter *self, - PyObject *fullname); - -static PyObject * -zipimport_zipimporter_get_resource_reader(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:get_resource_reader", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_get_resource_reader_impl(self, fullname); - -exit: - return return_value; -} -/*[clinic end generated code: output=854ce3502180dc1f input=a9049054013a1b77]*/ From webhook-mailer at python.org Sat Aug 10 03:37:39 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 10 Aug 2019 07:37:39 -0000 Subject: [Python-checkins] Delete leftover clinic-generated file for C zipimport. (GH-15174) Message-ID: https://github.com/python/cpython/commit/c61f9b57cfce9e96bdea5674634e3a9c185b675f commit: c61f9b57cfce9e96bdea5674634e3a9c185b675f branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-10T00:37:35-07:00 summary: Delete leftover clinic-generated file for C zipimport. (GH-15174) (cherry picked from commit 51aac15f6d525595e200e3580409c4b8656e8a96) Co-authored-by: Greg Price files: D Modules/clinic/zipimport.c.h diff --git a/Modules/clinic/zipimport.c.h b/Modules/clinic/zipimport.c.h deleted file mode 100644 index aabe7a05ae9d..000000000000 --- a/Modules/clinic/zipimport.c.h +++ /dev/null @@ -1,325 +0,0 @@ -/*[clinic input] -preserve -[clinic start generated code]*/ - -PyDoc_STRVAR(zipimport_zipimporter___init____doc__, -"zipimporter(archivepath, /)\n" -"--\n" -"\n" -"Create a new zipimporter instance.\n" -"\n" -" archivepath\n" -" A path-like object to a zipfile, or to a specific path inside\n" -" a zipfile.\n" -"\n" -"\'archivepath\' must be a path-like object to a zipfile, or to a specific path\n" -"inside a zipfile. For example, it can be \'/tmp/myimport.zip\', or\n" -"\'/tmp/myimport.zip/mydirectory\', if mydirectory is a valid directory inside\n" -"the archive.\n" -"\n" -"\'ZipImportError\' is raised if \'archivepath\' doesn\'t point to a valid Zip\n" -"archive.\n" -"\n" -"The \'archive\' attribute of the zipimporter object contains the name of the\n" -"zipfile targeted."); - -static int -zipimport_zipimporter___init___impl(ZipImporter *self, PyObject *path); - -static int -zipimport_zipimporter___init__(PyObject *self, PyObject *args, PyObject *kwargs) -{ - int return_value = -1; - PyObject *path; - - if ((Py_TYPE(self) == &ZipImporter_Type) && - !_PyArg_NoKeywords("zipimporter", kwargs)) { - goto exit; - } - if (!PyArg_ParseTuple(args, "O&:zipimporter", - PyUnicode_FSDecoder, &path)) { - goto exit; - } - return_value = zipimport_zipimporter___init___impl((ZipImporter *)self, path); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_find_module__doc__, -"find_module($self, fullname, path=None, /)\n" -"--\n" -"\n" -"Search for a module specified by \'fullname\'.\n" -"\n" -"\'fullname\' must be the fully qualified (dotted) module name. It returns the\n" -"zipimporter instance itself if the module was found, or None if it wasn\'t.\n" -"The optional \'path\' argument is ignored -- it\'s there for compatibility\n" -"with the importer protocol."); - -#define ZIPIMPORT_ZIPIMPORTER_FIND_MODULE_METHODDEF \ - {"find_module", (PyCFunction)(void *)zipimport_zipimporter_find_module, METH_FASTCALL, zipimport_zipimporter_find_module__doc__}, - -static PyObject * -zipimport_zipimporter_find_module_impl(ZipImporter *self, PyObject *fullname, - PyObject *path); - -static PyObject * -zipimport_zipimporter_find_module(ZipImporter *self, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *fullname; - PyObject *path = Py_None; - - if (!_PyArg_ParseStack(args, nargs, "U|O:find_module", - &fullname, &path)) { - goto exit; - } - return_value = zipimport_zipimporter_find_module_impl(self, fullname, path); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_find_loader__doc__, -"find_loader($self, fullname, path=None, /)\n" -"--\n" -"\n" -"Search for a module specified by \'fullname\'.\n" -"\n" -"\'fullname\' must be the fully qualified (dotted) module name. It returns the\n" -"zipimporter instance itself if the module was found, a string containing the\n" -"full path name if it\'s possibly a portion of a namespace package,\n" -"or None otherwise. The optional \'path\' argument is ignored -- it\'s\n" -"there for compatibility with the importer protocol."); - -#define ZIPIMPORT_ZIPIMPORTER_FIND_LOADER_METHODDEF \ - {"find_loader", (PyCFunction)(void *)zipimport_zipimporter_find_loader, METH_FASTCALL, zipimport_zipimporter_find_loader__doc__}, - -static PyObject * -zipimport_zipimporter_find_loader_impl(ZipImporter *self, PyObject *fullname, - PyObject *path); - -static PyObject * -zipimport_zipimporter_find_loader(ZipImporter *self, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *fullname; - PyObject *path = Py_None; - - if (!_PyArg_ParseStack(args, nargs, "U|O:find_loader", - &fullname, &path)) { - goto exit; - } - return_value = zipimport_zipimporter_find_loader_impl(self, fullname, path); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_load_module__doc__, -"load_module($self, fullname, /)\n" -"--\n" -"\n" -"Load the module specified by \'fullname\'.\n" -"\n" -"\'fullname\' must be the fully qualified (dotted) module name. It returns the\n" -"imported module, or raises ZipImportError if it wasn\'t found."); - -#define ZIPIMPORT_ZIPIMPORTER_LOAD_MODULE_METHODDEF \ - {"load_module", (PyCFunction)zipimport_zipimporter_load_module, METH_O, zipimport_zipimporter_load_module__doc__}, - -static PyObject * -zipimport_zipimporter_load_module_impl(ZipImporter *self, PyObject *fullname); - -static PyObject * -zipimport_zipimporter_load_module(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:load_module", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_load_module_impl(self, fullname); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_get_filename__doc__, -"get_filename($self, fullname, /)\n" -"--\n" -"\n" -"Return the filename for the specified module."); - -#define ZIPIMPORT_ZIPIMPORTER_GET_FILENAME_METHODDEF \ - {"get_filename", (PyCFunction)zipimport_zipimporter_get_filename, METH_O, zipimport_zipimporter_get_filename__doc__}, - -static PyObject * -zipimport_zipimporter_get_filename_impl(ZipImporter *self, - PyObject *fullname); - -static PyObject * -zipimport_zipimporter_get_filename(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:get_filename", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_get_filename_impl(self, fullname); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_is_package__doc__, -"is_package($self, fullname, /)\n" -"--\n" -"\n" -"Return True if the module specified by fullname is a package.\n" -"\n" -"Raise ZipImportError if the module couldn\'t be found."); - -#define ZIPIMPORT_ZIPIMPORTER_IS_PACKAGE_METHODDEF \ - {"is_package", (PyCFunction)zipimport_zipimporter_is_package, METH_O, zipimport_zipimporter_is_package__doc__}, - -static PyObject * -zipimport_zipimporter_is_package_impl(ZipImporter *self, PyObject *fullname); - -static PyObject * -zipimport_zipimporter_is_package(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:is_package", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_is_package_impl(self, fullname); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_get_data__doc__, -"get_data($self, pathname, /)\n" -"--\n" -"\n" -"Return the data associated with \'pathname\'.\n" -"\n" -"Raise OSError if the file was not found."); - -#define ZIPIMPORT_ZIPIMPORTER_GET_DATA_METHODDEF \ - {"get_data", (PyCFunction)zipimport_zipimporter_get_data, METH_O, zipimport_zipimporter_get_data__doc__}, - -static PyObject * -zipimport_zipimporter_get_data_impl(ZipImporter *self, PyObject *path); - -static PyObject * -zipimport_zipimporter_get_data(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *path; - - if (!PyArg_Parse(arg, "U:get_data", &path)) { - goto exit; - } - return_value = zipimport_zipimporter_get_data_impl(self, path); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_get_code__doc__, -"get_code($self, fullname, /)\n" -"--\n" -"\n" -"Return the code object for the specified module.\n" -"\n" -"Raise ZipImportError if the module couldn\'t be found."); - -#define ZIPIMPORT_ZIPIMPORTER_GET_CODE_METHODDEF \ - {"get_code", (PyCFunction)zipimport_zipimporter_get_code, METH_O, zipimport_zipimporter_get_code__doc__}, - -static PyObject * -zipimport_zipimporter_get_code_impl(ZipImporter *self, PyObject *fullname); - -static PyObject * -zipimport_zipimporter_get_code(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:get_code", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_get_code_impl(self, fullname); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_get_source__doc__, -"get_source($self, fullname, /)\n" -"--\n" -"\n" -"Return the source code for the specified module.\n" -"\n" -"Raise ZipImportError if the module couldn\'t be found, return None if the\n" -"archive does contain the module, but has no source for it."); - -#define ZIPIMPORT_ZIPIMPORTER_GET_SOURCE_METHODDEF \ - {"get_source", (PyCFunction)zipimport_zipimporter_get_source, METH_O, zipimport_zipimporter_get_source__doc__}, - -static PyObject * -zipimport_zipimporter_get_source_impl(ZipImporter *self, PyObject *fullname); - -static PyObject * -zipimport_zipimporter_get_source(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:get_source", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_get_source_impl(self, fullname); - -exit: - return return_value; -} - -PyDoc_STRVAR(zipimport_zipimporter_get_resource_reader__doc__, -"get_resource_reader($self, fullname, /)\n" -"--\n" -"\n" -"Return the ResourceReader for a package in a zip file.\n" -"\n" -"If \'fullname\' is a package within the zip file, return the \'ResourceReader\'\n" -"object for the package. Otherwise return None."); - -#define ZIPIMPORT_ZIPIMPORTER_GET_RESOURCE_READER_METHODDEF \ - {"get_resource_reader", (PyCFunction)zipimport_zipimporter_get_resource_reader, METH_O, zipimport_zipimporter_get_resource_reader__doc__}, - -static PyObject * -zipimport_zipimporter_get_resource_reader_impl(ZipImporter *self, - PyObject *fullname); - -static PyObject * -zipimport_zipimporter_get_resource_reader(ZipImporter *self, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *fullname; - - if (!PyArg_Parse(arg, "U:get_resource_reader", &fullname)) { - goto exit; - } - return_value = zipimport_zipimporter_get_resource_reader_impl(self, fullname); - -exit: - return return_value; -} -/*[clinic end generated code: output=854ce3502180dc1f input=a9049054013a1b77]*/ From webhook-mailer at python.org Sun Aug 11 16:45:16 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 11 Aug 2019 20:45:16 -0000 Subject: [Python-checkins] bpo-32178: Fix IndexError trying to parse 'To' header starting with ':'. (GH-15044) Message-ID: https://github.com/python/cpython/commit/09a1872a8007048dcdf825a476816c5e3498b8f8 commit: 09a1872a8007048dcdf825a476816c5e3498b8f8 branch: master author: Abhilash Raj committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-11T13:45:09-07:00 summary: bpo-32178: Fix IndexError trying to parse 'To' header starting with ':'. (GH-15044) This should fix the IndexError trying to retrieve `DisplayName.display_name` and `DisplayName.value` when the `value` is basically an empty string. https://bugs.python.org/issue32178 files: A Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst M Lib/email/_header_value_parser.py M Lib/test/test_email/test__header_value_parser.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 641e0979f3d7..ea33bd8eda7d 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -561,6 +561,8 @@ class DisplayName(Phrase): @property def display_name(self): res = TokenList(self) + if len(res) == 0: + return res.value if res[0].token_type == 'cfws': res.pop(0) else: @@ -582,7 +584,7 @@ def value(self): for x in self: if x.token_type == 'quoted-string': quote = True - if quote: + if len(self) != 0 and quote: pre = post = '' if self[0].token_type=='cfws' or self[0][0].token_type=='cfws': pre = ' ' diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index f6e5886f7571..b3e6b2661524 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -1700,6 +1700,14 @@ def test_get_display_name_ending_with_obsolete(self): self.assertEqual(display_name[3].comments, ['with trailing comment']) self.assertEqual(display_name.display_name, 'simple phrase.') + def test_get_display_name_for_invalid_address_field(self): + # bpo-32178: Test that address fields starting with `:` don't cause + # IndexError when parsing the display name. + display_name = self._test_get_x( + parser.get_display_name, + ':Foo ', '', '', [errors.InvalidHeaderDefect], ':Foo ') + self.assertEqual(display_name.value, '') + # get_name_addr def test_get_name_addr_angle_addr_only(self): diff --git a/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst b/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst new file mode 100644 index 000000000000..5e7a2e964d93 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst @@ -0,0 +1 @@ +Fix IndexError in :mod:`email` package when trying to parse invalid address fields starting with ``:``. From webhook-mailer at python.org Sun Aug 11 17:04:35 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 11 Aug 2019 21:04:35 -0000 Subject: [Python-checkins] bpo-32178: Fix IndexError trying to parse 'To' header starting with ':'. (GH-15044) Message-ID: https://github.com/python/cpython/commit/9500bbe9372f6080decc49d2fd9365f0b927a0e2 commit: 9500bbe9372f6080decc49d2fd9365f0b927a0e2 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-11T14:04:31-07:00 summary: bpo-32178: Fix IndexError trying to parse 'To' header starting with ':'. (GH-15044) This should fix the IndexError trying to retrieve `DisplayName.display_name` and `DisplayName.value` when the `value` is basically an empty string. https://bugs.python.org/issue32178 (cherry picked from commit 09a1872a8007048dcdf825a476816c5e3498b8f8) Co-authored-by: Abhilash Raj files: A Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst M Lib/email/_header_value_parser.py M Lib/test/test_email/test__header_value_parser.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index a93079278893..3d369e4822cd 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -549,6 +549,8 @@ class DisplayName(Phrase): @property def display_name(self): res = TokenList(self) + if len(res) == 0: + return res.value if res[0].token_type == 'cfws': res.pop(0) else: @@ -570,7 +572,7 @@ def value(self): for x in self: if x.token_type == 'quoted-string': quote = True - if quote: + if len(self) != 0 and quote: pre = post = '' if self[0].token_type=='cfws' or self[0][0].token_type=='cfws': pre = ' ' diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index 010be9fa4ae6..198cf17bbf3e 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -1680,6 +1680,14 @@ def test_get_display_name_ending_with_obsolete(self): self.assertEqual(display_name[3].comments, ['with trailing comment']) self.assertEqual(display_name.display_name, 'simple phrase.') + def test_get_display_name_for_invalid_address_field(self): + # bpo-32178: Test that address fields starting with `:` don't cause + # IndexError when parsing the display name. + display_name = self._test_get_x( + parser.get_display_name, + ':Foo ', '', '', [errors.InvalidHeaderDefect], ':Foo ') + self.assertEqual(display_name.value, '') + # get_name_addr def test_get_name_addr_angle_addr_only(self): diff --git a/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst b/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst new file mode 100644 index 000000000000..5e7a2e964d93 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst @@ -0,0 +1 @@ +Fix IndexError in :mod:`email` package when trying to parse invalid address fields starting with ``:``. From webhook-mailer at python.org Sun Aug 11 17:05:41 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 11 Aug 2019 21:05:41 -0000 Subject: [Python-checkins] bpo-32178: Fix IndexError trying to parse 'To' header starting with ':'. (GH-15044) Message-ID: https://github.com/python/cpython/commit/dec231a73c2a463b29f19c4e8357602c10a68856 commit: dec231a73c2a463b29f19c4e8357602c10a68856 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-11T14:05:37-07:00 summary: bpo-32178: Fix IndexError trying to parse 'To' header starting with ':'. (GH-15044) This should fix the IndexError trying to retrieve `DisplayName.display_name` and `DisplayName.value` when the `value` is basically an empty string. https://bugs.python.org/issue32178 (cherry picked from commit 09a1872a8007048dcdf825a476816c5e3498b8f8) Co-authored-by: Abhilash Raj files: A Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst M Lib/email/_header_value_parser.py M Lib/test/test_email/test__header_value_parser.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index c09f4f121ffb..666be034420e 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -566,6 +566,8 @@ class DisplayName(Phrase): @property def display_name(self): res = TokenList(self) + if len(res) == 0: + return res.value if res[0].token_type == 'cfws': res.pop(0) else: @@ -587,7 +589,7 @@ def value(self): for x in self: if x.token_type == 'quoted-string': quote = True - if quote: + if len(self) != 0 and quote: pre = post = '' if self[0].token_type=='cfws' or self[0][0].token_type=='cfws': pre = ' ' diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index 0f19f8bcc2e0..dd6975784568 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -1700,6 +1700,14 @@ def test_get_display_name_ending_with_obsolete(self): self.assertEqual(display_name[3].comments, ['with trailing comment']) self.assertEqual(display_name.display_name, 'simple phrase.') + def test_get_display_name_for_invalid_address_field(self): + # bpo-32178: Test that address fields starting with `:` don't cause + # IndexError when parsing the display name. + display_name = self._test_get_x( + parser.get_display_name, + ':Foo ', '', '', [errors.InvalidHeaderDefect], ':Foo ') + self.assertEqual(display_name.value, '') + # get_name_addr def test_get_name_addr_angle_addr_only(self): diff --git a/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst b/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst new file mode 100644 index 000000000000..5e7a2e964d93 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst @@ -0,0 +1 @@ +Fix IndexError in :mod:`email` package when trying to parse invalid address fields starting with ``:``. From webhook-mailer at python.org Sun Aug 11 17:41:03 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 11 Aug 2019 21:41:03 -0000 Subject: [Python-checkins] bpo-37819: Add Fraction.as_integer_ratio() (GH-15212) Message-ID: https://github.com/python/cpython/commit/f03b4c8a48f62134799d368b78da35301af466a3 commit: f03b4c8a48f62134799d368b78da35301af466a3 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-11T14:40:59-07:00 summary: bpo-37819: Add Fraction.as_integer_ratio() (GH-15212) files: A Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst M Doc/library/fractions.rst M Lib/fractions.py M Lib/test/test_fractions.py diff --git a/Doc/library/fractions.rst b/Doc/library/fractions.rst index b5a818e1cafa..58e7126b0bf2 100644 --- a/Doc/library/fractions.rst +++ b/Doc/library/fractions.rst @@ -94,6 +94,13 @@ another rational number, or from a string. Denominator of the Fraction in lowest term. + .. method:: as_integer_ratio() + + Return a tuple of two integers, whose ratio is equal + to the Fraction and with a positive denominator. + + .. versionadded:: 3.8 + .. method:: from_float(flt) This class method constructs a :class:`Fraction` representing the exact diff --git a/Lib/fractions.py b/Lib/fractions.py index 7443bd3e0c6a..e774d58e4035 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -216,6 +216,14 @@ def from_decimal(cls, dec): (cls.__name__, dec, type(dec).__name__)) return cls(*dec.as_integer_ratio()) + def as_integer_ratio(self): + """Return the integer ratio as a tuple. + + Return a tuple of two integers, whose ratio is equal to the + Fraction and with a positive denominator. + """ + return (self._numerator, self._denominator) + def limit_denominator(self, max_denominator=1000000): """Closest Fraction to self with denominator at most max_denominator. diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py index 277916220051..18ab28cfebe0 100644 --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -302,6 +302,12 @@ def testFromDecimal(self): ValueError, "cannot convert NaN to integer ratio", F.from_decimal, Decimal("snan")) + def test_as_integer_ratio(self): + self.assertEqual(F(4, 6).as_integer_ratio(), (2, 3)) + self.assertEqual(F(-4, 6).as_integer_ratio(), (-2, 3)) + self.assertEqual(F(4, -6).as_integer_ratio(), (-2, 3)) + self.assertEqual(F(0, 6).as_integer_ratio(), (0, 1)) + def testLimitDenominator(self): rpi = F('3.1415926535897932') self.assertEqual(rpi.limit_denominator(10000), F(355, 113)) diff --git a/Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst b/Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst new file mode 100644 index 000000000000..cfc1f1afb4f7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst @@ -0,0 +1,2 @@ +Add Fraction.as_integer_ratio() to match the corresponding methods in bool, +int, float, and decimal. From webhook-mailer at python.org Sun Aug 11 18:02:28 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 11 Aug 2019 22:02:28 -0000 Subject: [Python-checkins] bpo-37819: Add Fraction.as_integer_ratio() (GH-15212) (GH-15215) Message-ID: https://github.com/python/cpython/commit/5ba1cb03939bd86d026db667580f590966b573ea commit: 5ba1cb03939bd86d026db667580f590966b573ea branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-11T15:02:23-07:00 summary: bpo-37819: Add Fraction.as_integer_ratio() (GH-15212) (GH-15215) (cherry picked from commit f03b4c8a48f62134799d368b78da35301af466a3) Co-authored-by: Raymond Hettinger files: A Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst M Doc/library/fractions.rst M Lib/fractions.py M Lib/test/test_fractions.py diff --git a/Doc/library/fractions.rst b/Doc/library/fractions.rst index b5a818e1cafa..58e7126b0bf2 100644 --- a/Doc/library/fractions.rst +++ b/Doc/library/fractions.rst @@ -94,6 +94,13 @@ another rational number, or from a string. Denominator of the Fraction in lowest term. + .. method:: as_integer_ratio() + + Return a tuple of two integers, whose ratio is equal + to the Fraction and with a positive denominator. + + .. versionadded:: 3.8 + .. method:: from_float(flt) This class method constructs a :class:`Fraction` representing the exact diff --git a/Lib/fractions.py b/Lib/fractions.py index 7443bd3e0c6a..e774d58e4035 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -216,6 +216,14 @@ def from_decimal(cls, dec): (cls.__name__, dec, type(dec).__name__)) return cls(*dec.as_integer_ratio()) + def as_integer_ratio(self): + """Return the integer ratio as a tuple. + + Return a tuple of two integers, whose ratio is equal to the + Fraction and with a positive denominator. + """ + return (self._numerator, self._denominator) + def limit_denominator(self, max_denominator=1000000): """Closest Fraction to self with denominator at most max_denominator. diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py index 277916220051..18ab28cfebe0 100644 --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -302,6 +302,12 @@ def testFromDecimal(self): ValueError, "cannot convert NaN to integer ratio", F.from_decimal, Decimal("snan")) + def test_as_integer_ratio(self): + self.assertEqual(F(4, 6).as_integer_ratio(), (2, 3)) + self.assertEqual(F(-4, 6).as_integer_ratio(), (-2, 3)) + self.assertEqual(F(4, -6).as_integer_ratio(), (-2, 3)) + self.assertEqual(F(0, 6).as_integer_ratio(), (0, 1)) + def testLimitDenominator(self): rpi = F('3.1415926535897932') self.assertEqual(rpi.limit_denominator(10000), F(355, 113)) diff --git a/Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst b/Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst new file mode 100644 index 000000000000..cfc1f1afb4f7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst @@ -0,0 +1,2 @@ +Add Fraction.as_integer_ratio() to match the corresponding methods in bool, +int, float, and decimal. From webhook-mailer at python.org Mon Aug 12 02:57:10 2019 From: webhook-mailer at python.org (Chris Withers) Date: Mon, 12 Aug 2019 06:57:10 -0000 Subject: [Python-checkins] Fix docs for assert_called and assert_called_once (#15197) Message-ID: https://github.com/python/cpython/commit/f9590edfeae192ba95aadaee9460dc03a366c51a commit: f9590edfeae192ba95aadaee9460dc03a366c51a branch: master author: Ismail S committer: Chris Withers date: 2019-08-12T01:57:03-05:00 summary: Fix docs for assert_called and assert_called_once (#15197) files: M Doc/library/unittest.mock.rst diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index 46e8ef38ab11..19e9715102bf 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -286,7 +286,7 @@ the *new_callable* argument to :func:`patch`. used to set attributes on the mock after it is created. See the :meth:`configure_mock` method for details. - .. method:: assert_called(*args, **kwargs) + .. method:: assert_called() Assert that the mock was called at least once. @@ -297,7 +297,7 @@ the *new_callable* argument to :func:`patch`. .. versionadded:: 3.6 - .. method:: assert_called_once(*args, **kwargs) + .. method:: assert_called_once() Assert that the mock was called exactly once. From webhook-mailer at python.org Mon Aug 12 04:19:01 2019 From: webhook-mailer at python.org (Chris Withers) Date: Mon, 12 Aug 2019 08:19:01 -0000 Subject: [Python-checkins] Fix docs for assert_called and assert_called_once (GH-15218) Message-ID: https://github.com/python/cpython/commit/9286677538f3cd15aaad7628f4a95ab6aa97536b commit: 9286677538f3cd15aaad7628f4a95ab6aa97536b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Chris Withers date: 2019-08-12T09:18:55+01:00 summary: Fix docs for assert_called and assert_called_once (GH-15218) (cherry picked from commit f9590edfeae192ba95aadaee9460dc03a366c51a) Co-authored-by: Ismail S files: M Doc/library/unittest.mock.rst diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index b76ae712a971..36cc0c2fc4bd 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -262,7 +262,7 @@ the *new_callable* argument to :func:`patch`. used to set attributes on the mock after it is created. See the :meth:`configure_mock` method for details. - .. method:: assert_called(*args, **kwargs) + .. method:: assert_called() Assert that the mock was called at least once. @@ -273,7 +273,7 @@ the *new_callable* argument to :func:`patch`. .. versionadded:: 3.6 - .. method:: assert_called_once(*args, **kwargs) + .. method:: assert_called_once() Assert that the mock was called exactly once. From webhook-mailer at python.org Mon Aug 12 04:19:51 2019 From: webhook-mailer at python.org (Chris Withers) Date: Mon, 12 Aug 2019 08:19:51 -0000 Subject: [Python-checkins] Fix docs for assert_called and assert_called_once (GH-15219) Message-ID: https://github.com/python/cpython/commit/2f087e279b94609073f630a86508b3a169c5e045 commit: 2f087e279b94609073f630a86508b3a169c5e045 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Chris Withers date: 2019-08-12T09:19:47+01:00 summary: Fix docs for assert_called and assert_called_once (GH-15219) (cherry picked from commit f9590edfeae192ba95aadaee9460dc03a366c51a) Co-authored-by: Ismail S files: M Doc/library/unittest.mock.rst diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index 46e8ef38ab11..19e9715102bf 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -286,7 +286,7 @@ the *new_callable* argument to :func:`patch`. used to set attributes on the mock after it is created. See the :meth:`configure_mock` method for details. - .. method:: assert_called(*args, **kwargs) + .. method:: assert_called() Assert that the mock was called at least once. @@ -297,7 +297,7 @@ the *new_callable* argument to :func:`patch`. .. versionadded:: 3.6 - .. method:: assert_called_once(*args, **kwargs) + .. method:: assert_called_once() Assert that the mock was called exactly once. From webhook-mailer at python.org Mon Aug 12 13:41:32 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 12 Aug 2019 17:41:32 -0000 Subject: [Python-checkins] bpo-37804: Remove the deprecated method threading.Thread.isAlive() (GH-15225) Message-ID: https://github.com/python/cpython/commit/44046fe4fc7f00a6eb855b33e6a3f953cf5233a5 commit: 44046fe4fc7f00a6eb855b33e6a3f953cf5233a5 branch: master author: Dong-hee Na committer: Victor Stinner date: 2019-08-12T19:41:08+02:00 summary: bpo-37804: Remove the deprecated method threading.Thread.isAlive() (GH-15225) files: A Misc/NEWS.d/next/Library/2019-08-12-23-07-47.bpo-37804.Ene6L-.rst M Doc/whatsnew/3.9.rst M Lib/test/test_threading.py M Lib/threading.py diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 61d9e745e87c..f09e09c2b905 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -186,6 +186,10 @@ Removed removed. They were deprecated since Python 3.7. (Contributed by Victor Stinner in :issue:`37320`.) +* The :meth:`~threading.Thread.isAlive()` method of :class:`threading.Thread` + has been removed. It was deprecated since Python 3.8. + Use :meth:`~threading.Thread.is_alive()` instead. + (Contributed by Dong-hee Na in :issue:`37804`.) Porting to Python 3.9 ===================== diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 1466d25e9482..7c16974c1630 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -422,8 +422,6 @@ def test_old_threading_api(self): t.setDaemon(True) t.getName() t.setName("name") - with self.assertWarnsRegex(DeprecationWarning, 'use is_alive()'): - t.isAlive() e = threading.Event() e.isSet() threading.activeCount() diff --git a/Lib/threading.py b/Lib/threading.py index cec9cdb8e698..32a3d7c30336 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -1088,16 +1088,6 @@ def is_alive(self): self._wait_for_tstate_lock(False) return not self._is_stopped - def isAlive(self): - """Return whether the thread is alive. - - This method is deprecated, use is_alive() instead. - """ - import warnings - warnings.warn('isAlive() is deprecated, use is_alive() instead', - DeprecationWarning, stacklevel=2) - return self.is_alive() - @property def daemon(self): """A boolean value indicating whether this thread is a daemon thread. diff --git a/Misc/NEWS.d/next/Library/2019-08-12-23-07-47.bpo-37804.Ene6L-.rst b/Misc/NEWS.d/next/Library/2019-08-12-23-07-47.bpo-37804.Ene6L-.rst new file mode 100644 index 000000000000..ebbcb5aa7788 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-12-23-07-47.bpo-37804.Ene6L-.rst @@ -0,0 +1,2 @@ +Remove the deprecated method `threading.Thread.isAlive()`. Patch by Dong-hee +Na. From webhook-mailer at python.org Mon Aug 12 16:06:07 2019 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 12 Aug 2019 20:06:07 -0000 Subject: [Python-checkins] bpo-37354: Make Powershell Activate.ps1 script static to allow for signing (GH-14967) Message-ID: https://github.com/python/cpython/commit/732775d6be8062e72cf4995d5a9db0170e22c233 commit: 732775d6be8062e72cf4995d5a9db0170e22c233 branch: master author: Derek Keeler committer: Steve Dower date: 2019-08-12T13:06:02-07:00 summary: bpo-37354: Make Powershell Activate.ps1 script static to allow for signing (GH-14967) - Remove use of replacement text in the script - Make use of the pyvenv.cfg file for prompt value. - Add parameters to allow more flexibility - Make use of the current path, and assumptions about where env puts things, to compensate - Make the script a bit more 'idiomatic' Powershell - Add script documentation (Get-Help .\.venv\Scripts\Activate.ps1 shows PS help page now files: A Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst M Lib/venv/scripts/common/Activate.ps1 diff --git a/Lib/venv/scripts/common/Activate.ps1 b/Lib/venv/scripts/common/Activate.ps1 index de22962630aa..699c84097f1a 100644 --- a/Lib/venv/scripts/common/Activate.ps1 +++ b/Lib/venv/scripts/common/Activate.ps1 @@ -1,56 +1,231 @@ -function Script:add-bin([string]$envPath) { - $binPath = Join-Path -Path $env:VIRTUAL_ENV -ChildPath '__VENV_BIN_NAME__' - return ($binPath, $envPath) -join [IO.Path]::PathSeparator -} +<# +.Synopsis +Activate a Python virtual environment for the current Powershell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> function global:deactivate ([switch]$NonDestructive) { # Revert to original values - if (Test-Path function:_OLD_VIRTUAL_PROMPT) { - copy-item function:_OLD_VIRTUAL_PROMPT function:prompt - remove-item function:_OLD_VIRTUAL_PROMPT + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT } - if (Test-Path env:_OLD_VIRTUAL_PYTHONHOME) { - copy-item env:_OLD_VIRTUAL_PYTHONHOME env:PYTHONHOME - remove-item env:_OLD_VIRTUAL_PYTHONHOME + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME } - if (Test-Path env:_OLD_VIRTUAL_PATH) { - copy-item env:_OLD_VIRTUAL_PATH env:PATH - remove-item env:_OLD_VIRTUAL_PATH + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH } - if (Test-Path env:VIRTUAL_ENV) { - remove-item env:VIRTUAL_ENV + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0,1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } } + return $pyvenvConfig +} + - if (!$NonDestructive) { - # Self destruct! - remove-item function:deactivate +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + $VenvDir = $VenvDir.Insert($VenvDir.Length, "/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf } } +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. deactivate -nondestructive -$env:VIRTUAL_ENV="__VENV_DIR__" +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" -if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) { # Set the prompt to include the env name # Make sure _OLD_VIRTUAL_PROMPT is global - function global:_OLD_VIRTUAL_PROMPT {""} - copy-item function:prompt function:_OLD_VIRTUAL_PROMPT + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + function global:prompt { - Write-Host -NoNewline -ForegroundColor Green '__VENV_PROMPT__' + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " _OLD_VIRTUAL_PROMPT } } # Clear PYTHONHOME -if (Test-Path env:PYTHONHOME) { - copy-item env:PYTHONHOME env:_OLD_VIRTUAL_PYTHONHOME - remove-item env:PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME } # Add the venv to the PATH -copy-item env:PATH env:_OLD_VIRTUAL_PATH -$env:PATH = add-bin $env:PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst b/Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst new file mode 100644 index 000000000000..a314bcc9bf90 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst @@ -0,0 +1 @@ +Make Activate.ps1 Powershell script static to allow for signing it. From webhook-mailer at python.org Mon Aug 12 17:09:32 2019 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 12 Aug 2019 21:09:32 -0000 Subject: [Python-checkins] [3.8] bpo-37354: Make Powershell Activate.ps1 script static to allow for signing (GH-14967) Message-ID: https://github.com/python/cpython/commit/0c64b57e0155c333b7c96ec2af009c1388cd5d31 commit: 0c64b57e0155c333b7c96ec2af009c1388cd5d31 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Steve Dower date: 2019-08-12T14:09:26-07:00 summary: [3.8] bpo-37354: Make Powershell Activate.ps1 script static to allow for signing (GH-14967) - Remove use of replacement text in the script - Make use of the pyvenv.cfg file for prompt value. - Add parameters to allow more flexibility - Make use of the current path, and assumptions about where env puts things, to compensate - Make the script a bit more 'idiomatic' Powershell - Add script documentation (Get-Help .\.venv\Scripts\Activate.ps1 shows PS help page now (cherry picked from commit 732775d6be8062e72cf4995d5a9db0170e22c233) Co-authored-by: Derek Keeler files: A Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst M Lib/venv/scripts/common/Activate.ps1 diff --git a/Lib/venv/scripts/common/Activate.ps1 b/Lib/venv/scripts/common/Activate.ps1 index de22962630aa..699c84097f1a 100644 --- a/Lib/venv/scripts/common/Activate.ps1 +++ b/Lib/venv/scripts/common/Activate.ps1 @@ -1,56 +1,231 @@ -function Script:add-bin([string]$envPath) { - $binPath = Join-Path -Path $env:VIRTUAL_ENV -ChildPath '__VENV_BIN_NAME__' - return ($binPath, $envPath) -join [IO.Path]::PathSeparator -} +<# +.Synopsis +Activate a Python virtual environment for the current Powershell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> function global:deactivate ([switch]$NonDestructive) { # Revert to original values - if (Test-Path function:_OLD_VIRTUAL_PROMPT) { - copy-item function:_OLD_VIRTUAL_PROMPT function:prompt - remove-item function:_OLD_VIRTUAL_PROMPT + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT } - if (Test-Path env:_OLD_VIRTUAL_PYTHONHOME) { - copy-item env:_OLD_VIRTUAL_PYTHONHOME env:PYTHONHOME - remove-item env:_OLD_VIRTUAL_PYTHONHOME + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME } - if (Test-Path env:_OLD_VIRTUAL_PATH) { - copy-item env:_OLD_VIRTUAL_PATH env:PATH - remove-item env:_OLD_VIRTUAL_PATH + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH } - if (Test-Path env:VIRTUAL_ENV) { - remove-item env:VIRTUAL_ENV + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0,1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } } + return $pyvenvConfig +} + - if (!$NonDestructive) { - # Self destruct! - remove-item function:deactivate +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + $VenvDir = $VenvDir.Insert($VenvDir.Length, "/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf } } +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. deactivate -nondestructive -$env:VIRTUAL_ENV="__VENV_DIR__" +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" -if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) { # Set the prompt to include the env name # Make sure _OLD_VIRTUAL_PROMPT is global - function global:_OLD_VIRTUAL_PROMPT {""} - copy-item function:prompt function:_OLD_VIRTUAL_PROMPT + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + function global:prompt { - Write-Host -NoNewline -ForegroundColor Green '__VENV_PROMPT__' + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " _OLD_VIRTUAL_PROMPT } } # Clear PYTHONHOME -if (Test-Path env:PYTHONHOME) { - copy-item env:PYTHONHOME env:_OLD_VIRTUAL_PYTHONHOME - remove-item env:PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME } # Add the venv to the PATH -copy-item env:PATH env:_OLD_VIRTUAL_PATH -$env:PATH = add-bin $env:PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst b/Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst new file mode 100644 index 000000000000..a314bcc9bf90 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst @@ -0,0 +1 @@ +Make Activate.ps1 Powershell script static to allow for signing it. From webhook-mailer at python.org Mon Aug 12 17:09:40 2019 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 12 Aug 2019 21:09:40 -0000 Subject: [Python-checkins] bpo-37354: Sign Activate.ps1 for release (GH-15235) Message-ID: https://github.com/python/cpython/commit/3e34a25a7a5c9ea2c46f2daeeb60f072faa5aaa1 commit: 3e34a25a7a5c9ea2c46f2daeeb60f072faa5aaa1 branch: master author: Steve Dower committer: GitHub date: 2019-08-12T14:09:36-07:00 summary: bpo-37354: Sign Activate.ps1 for release (GH-15235) files: M .azure-pipelines/windows-release/msi-steps.yml M .azure-pipelines/windows-release/stage-build.yml M .azure-pipelines/windows-release/stage-layout-full.yml M .azure-pipelines/windows-release/stage-layout-msix.yml M .azure-pipelines/windows-release/stage-layout-nuget.yml M .azure-pipelines/windows-release/stage-sign.yml diff --git a/.azure-pipelines/windows-release/msi-steps.yml b/.azure-pipelines/windows-release/msi-steps.yml index c55fa534eaec..f7bff162f8e0 100644 --- a/.azure-pipelines/windows-release/msi-steps.yml +++ b/.azure-pipelines/windows-release/msi-steps.yml @@ -51,6 +51,10 @@ steps: artifactName: tcltk_lib_amd64 targetPath: $(Build.BinariesDirectory)\tcltk_lib_amd64 + - powershell: | + copy $(Build.BinariesDirectory)\amd64\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force + displayName: 'Copy signed files into sources' + - script: | call Tools\msi\get_externals.bat call PCbuild\find_python.bat diff --git a/.azure-pipelines/windows-release/stage-build.yml b/.azure-pipelines/windows-release/stage-build.yml index ce7b38176935..c98576ef9705 100644 --- a/.azure-pipelines/windows-release/stage-build.yml +++ b/.azure-pipelines/windows-release/stage-build.yml @@ -122,7 +122,7 @@ jobs: displayName: Publish Tcl/Tk Library pool: - vmName: win2016-vs2017 + vmName: windows-latest workspace: clean: all diff --git a/.azure-pipelines/windows-release/stage-layout-full.yml b/.azure-pipelines/windows-release/stage-layout-full.yml index 8b412dffcc82..12c347239013 100644 --- a/.azure-pipelines/windows-release/stage-layout-full.yml +++ b/.azure-pipelines/windows-release/stage-layout-full.yml @@ -47,6 +47,10 @@ jobs: artifactName: tcltk_lib_$(Name) targetPath: $(Build.BinariesDirectory)\tcltk_lib + - powershell: | + copy $(Build.BinariesDirectory)\bin\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force + displayName: 'Copy signed files into sources' + - template: ./layout-command.yml - powershell: | diff --git a/.azure-pipelines/windows-release/stage-layout-msix.yml b/.azure-pipelines/windows-release/stage-layout-msix.yml index 7d66e8f9821c..ba86392f3ec6 100644 --- a/.azure-pipelines/windows-release/stage-layout-msix.yml +++ b/.azure-pipelines/windows-release/stage-layout-msix.yml @@ -40,6 +40,10 @@ jobs: artifactName: tcltk_lib_$(Name) targetPath: $(Build.BinariesDirectory)\tcltk_lib + - powershell: | + copy $(Build.BinariesDirectory)\bin\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force + displayName: 'Copy signed files into sources' + - template: ./layout-command.yml - powershell: | diff --git a/.azure-pipelines/windows-release/stage-layout-nuget.yml b/.azure-pipelines/windows-release/stage-layout-nuget.yml index 01512975e9db..7954c4547f50 100644 --- a/.azure-pipelines/windows-release/stage-layout-nuget.yml +++ b/.azure-pipelines/windows-release/stage-layout-nuget.yml @@ -29,6 +29,10 @@ jobs: artifactName: bin_$(Name) targetPath: $(Build.BinariesDirectory)\bin + - powershell: | + copy $(Build.BinariesDirectory)\bin\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force + displayName: 'Copy signed files into sources' + - template: ./layout-command.yml - powershell: | diff --git a/.azure-pipelines/windows-release/stage-sign.yml b/.azure-pipelines/windows-release/stage-sign.yml index d6984a0a137c..2307c6c9c8f9 100644 --- a/.azure-pipelines/windows-release/stage-sign.yml +++ b/.azure-pipelines/windows-release/stage-sign.yml @@ -1,3 +1,7 @@ +parameters: + Include: '*.exe, *.dll, *.pyd, *.cat, *.ps1' + Exclude: 'vcruntime*, libffi*, libcrypto*, libssl*' + jobs: - job: Sign_Python displayName: Sign Python binaries @@ -17,7 +21,7 @@ jobs: Name: amd64 steps: - - checkout: none + - template: ./checkout.yml - template: ./find-sdk.yml - powershell: | @@ -31,13 +35,18 @@ jobs: targetPath: $(Build.BinariesDirectory)\bin - powershell: | - $files = (gi *.exe, *.dll, *.pyd, *.cat -Exclude vcruntime*, libffi*, libcrypto*, libssl*) + copy "$(Build.SourcesDirectory)\Lib\venv\scripts\common\Activate.ps1" . + displayName: 'Copy files from source' + workingDirectory: $(Build.BinariesDirectory)\bin + + - powershell: | + $files = (gi ${{ parameters.Include }} -Exclude ${{ parameters.Exclude }}) signtool sign /a /n "$(SigningCertificate)" /fd sha256 /d "$(SigningDescription)" $files displayName: 'Sign binaries' workingDirectory: $(Build.BinariesDirectory)\bin - powershell: | - $files = (gi *.exe, *.dll, *.pyd, *.cat -Exclude vcruntime*, libffi*, libcrypto*, libssl*) + $files = (gi ${{ parameters.Include }} -Exclude ${{ parameters.Exclude }}) $failed = $true foreach ($retry in 1..10) { signtool timestamp /t http://timestamp.verisign.com/scripts/timestamp.dll $files From webhook-mailer at python.org Mon Aug 12 17:35:22 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 12 Aug 2019 21:35:22 -0000 Subject: [Python-checkins] bpo-37354: Sign Activate.ps1 for release (GH-15235) Message-ID: https://github.com/python/cpython/commit/2b98d8ec7ec3d41c6403ff9f6677a00ea0cb8b92 commit: 2b98d8ec7ec3d41c6403ff9f6677a00ea0cb8b92 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-12T14:35:16-07:00 summary: bpo-37354: Sign Activate.ps1 for release (GH-15235) (cherry picked from commit 3e34a25a7a5c9ea2c46f2daeeb60f072faa5aaa1) Co-authored-by: Steve Dower files: M .azure-pipelines/windows-release/msi-steps.yml M .azure-pipelines/windows-release/stage-build.yml M .azure-pipelines/windows-release/stage-layout-full.yml M .azure-pipelines/windows-release/stage-layout-msix.yml M .azure-pipelines/windows-release/stage-layout-nuget.yml M .azure-pipelines/windows-release/stage-sign.yml diff --git a/.azure-pipelines/windows-release/msi-steps.yml b/.azure-pipelines/windows-release/msi-steps.yml index c55fa534eaec..f7bff162f8e0 100644 --- a/.azure-pipelines/windows-release/msi-steps.yml +++ b/.azure-pipelines/windows-release/msi-steps.yml @@ -51,6 +51,10 @@ steps: artifactName: tcltk_lib_amd64 targetPath: $(Build.BinariesDirectory)\tcltk_lib_amd64 + - powershell: | + copy $(Build.BinariesDirectory)\amd64\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force + displayName: 'Copy signed files into sources' + - script: | call Tools\msi\get_externals.bat call PCbuild\find_python.bat diff --git a/.azure-pipelines/windows-release/stage-build.yml b/.azure-pipelines/windows-release/stage-build.yml index ce7b38176935..c98576ef9705 100644 --- a/.azure-pipelines/windows-release/stage-build.yml +++ b/.azure-pipelines/windows-release/stage-build.yml @@ -122,7 +122,7 @@ jobs: displayName: Publish Tcl/Tk Library pool: - vmName: win2016-vs2017 + vmName: windows-latest workspace: clean: all diff --git a/.azure-pipelines/windows-release/stage-layout-full.yml b/.azure-pipelines/windows-release/stage-layout-full.yml index 8b412dffcc82..12c347239013 100644 --- a/.azure-pipelines/windows-release/stage-layout-full.yml +++ b/.azure-pipelines/windows-release/stage-layout-full.yml @@ -47,6 +47,10 @@ jobs: artifactName: tcltk_lib_$(Name) targetPath: $(Build.BinariesDirectory)\tcltk_lib + - powershell: | + copy $(Build.BinariesDirectory)\bin\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force + displayName: 'Copy signed files into sources' + - template: ./layout-command.yml - powershell: | diff --git a/.azure-pipelines/windows-release/stage-layout-msix.yml b/.azure-pipelines/windows-release/stage-layout-msix.yml index 7d66e8f9821c..ba86392f3ec6 100644 --- a/.azure-pipelines/windows-release/stage-layout-msix.yml +++ b/.azure-pipelines/windows-release/stage-layout-msix.yml @@ -40,6 +40,10 @@ jobs: artifactName: tcltk_lib_$(Name) targetPath: $(Build.BinariesDirectory)\tcltk_lib + - powershell: | + copy $(Build.BinariesDirectory)\bin\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force + displayName: 'Copy signed files into sources' + - template: ./layout-command.yml - powershell: | diff --git a/.azure-pipelines/windows-release/stage-layout-nuget.yml b/.azure-pipelines/windows-release/stage-layout-nuget.yml index 01512975e9db..7954c4547f50 100644 --- a/.azure-pipelines/windows-release/stage-layout-nuget.yml +++ b/.azure-pipelines/windows-release/stage-layout-nuget.yml @@ -29,6 +29,10 @@ jobs: artifactName: bin_$(Name) targetPath: $(Build.BinariesDirectory)\bin + - powershell: | + copy $(Build.BinariesDirectory)\bin\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force + displayName: 'Copy signed files into sources' + - template: ./layout-command.yml - powershell: | diff --git a/.azure-pipelines/windows-release/stage-sign.yml b/.azure-pipelines/windows-release/stage-sign.yml index d6984a0a137c..2307c6c9c8f9 100644 --- a/.azure-pipelines/windows-release/stage-sign.yml +++ b/.azure-pipelines/windows-release/stage-sign.yml @@ -1,3 +1,7 @@ +parameters: + Include: '*.exe, *.dll, *.pyd, *.cat, *.ps1' + Exclude: 'vcruntime*, libffi*, libcrypto*, libssl*' + jobs: - job: Sign_Python displayName: Sign Python binaries @@ -17,7 +21,7 @@ jobs: Name: amd64 steps: - - checkout: none + - template: ./checkout.yml - template: ./find-sdk.yml - powershell: | @@ -31,13 +35,18 @@ jobs: targetPath: $(Build.BinariesDirectory)\bin - powershell: | - $files = (gi *.exe, *.dll, *.pyd, *.cat -Exclude vcruntime*, libffi*, libcrypto*, libssl*) + copy "$(Build.SourcesDirectory)\Lib\venv\scripts\common\Activate.ps1" . + displayName: 'Copy files from source' + workingDirectory: $(Build.BinariesDirectory)\bin + + - powershell: | + $files = (gi ${{ parameters.Include }} -Exclude ${{ parameters.Exclude }}) signtool sign /a /n "$(SigningCertificate)" /fd sha256 /d "$(SigningDescription)" $files displayName: 'Sign binaries' workingDirectory: $(Build.BinariesDirectory)\bin - powershell: | - $files = (gi *.exe, *.dll, *.pyd, *.cat -Exclude vcruntime*, libffi*, libcrypto*, libssl*) + $files = (gi ${{ parameters.Include }} -Exclude ${{ parameters.Exclude }}) $failed = $true foreach ($retry in 1..10) { signtool timestamp /t http://timestamp.verisign.com/scripts/timestamp.dll $files From webhook-mailer at python.org Mon Aug 12 17:56:44 2019 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 12 Aug 2019 21:56:44 -0000 Subject: [Python-checkins] Remove versioned executables from non-APPX packages (GH-15237) Message-ID: https://github.com/python/cpython/commit/c1aeb292d206e12b900dc4f7f816246c3a57c2ac commit: c1aeb292d206e12b900dc4f7f816246c3a57c2ac branch: master author: Steve Dower committer: GitHub date: 2019-08-12T14:56:39-07:00 summary: Remove versioned executables from non-APPX packages (GH-15237) files: M PC/layout/main.py diff --git a/PC/layout/main.py b/PC/layout/main.py index 07b7e6d57429..e59858196249 100644 --- a/PC/layout/main.py +++ b/PC/layout/main.py @@ -159,9 +159,6 @@ def in_build(f, dest="", new_name=None): yield from in_build("python_uwp.exe", new_name="python") yield from in_build("pythonw_uwp.exe", new_name="pythonw") else: - yield from in_build("python.exe", new_name="python{}".format(VER_DOT)) - yield from in_build("pythonw.exe", new_name="pythonw{}".format(VER_DOT)) - # For backwards compatibility, but we don't reference these ourselves. yield from in_build("python.exe", new_name="python") yield from in_build("pythonw.exe", new_name="pythonw") From webhook-mailer at python.org Mon Aug 12 18:16:46 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 12 Aug 2019 22:16:46 -0000 Subject: [Python-checkins] Remove versioned executables from non-APPX packages (GH-15237) Message-ID: https://github.com/python/cpython/commit/a150feeeb8efe99218e315c93f9ff1f158e18f10 commit: a150feeeb8efe99218e315c93f9ff1f158e18f10 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-12T15:16:36-07:00 summary: Remove versioned executables from non-APPX packages (GH-15237) (cherry picked from commit c1aeb292d206e12b900dc4f7f816246c3a57c2ac) Co-authored-by: Steve Dower files: M PC/layout/main.py diff --git a/PC/layout/main.py b/PC/layout/main.py index 07b7e6d57429..e59858196249 100644 --- a/PC/layout/main.py +++ b/PC/layout/main.py @@ -159,9 +159,6 @@ def in_build(f, dest="", new_name=None): yield from in_build("python_uwp.exe", new_name="python") yield from in_build("pythonw_uwp.exe", new_name="pythonw") else: - yield from in_build("python.exe", new_name="python{}".format(VER_DOT)) - yield from in_build("pythonw.exe", new_name="pythonw{}".format(VER_DOT)) - # For backwards compatibility, but we don't reference these ourselves. yield from in_build("python.exe", new_name="python") yield from in_build("pythonw.exe", new_name="pythonw") From webhook-mailer at python.org Mon Aug 12 18:55:24 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Mon, 12 Aug 2019 22:55:24 -0000 Subject: [Python-checkins] bpo-37759: Second round of edits to Whatsnew 3.8 (GH-15204) Message-ID: https://github.com/python/cpython/commit/66a34d35e4c97da9840a29ba9fba76721021c463 commit: 66a34d35e4c97da9840a29ba9fba76721021c463 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-12T15:55:18-07:00 summary: bpo-37759: Second round of edits to Whatsnew 3.8 (GH-15204) files: M Doc/whatsnew/3.8.rst diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 82da10cc3be8..e8238251d6ea 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -39,7 +39,7 @@ module. (Contributed by P.Y. Developer in :issue:`12345`.) - This saves the maintainer the effort of going through the Mercurial log + This saves the maintainer the effort of going through the Git log when researching a change. :Editor: Raymond Hettinger @@ -59,6 +59,7 @@ notable items not yet covered are: from datetime import date from math import cos, radians + from unicodedata import normalize import re import math @@ -383,9 +384,13 @@ Other Language Changes was lifted. (Contributed by Serhiy Storchaka in :issue:`32489`.) -* The :class:`int` type now has a new :meth:`~int.as_integer_ratio` method - compatible with the existing :meth:`float.as_integer_ratio` method. - (Contributed by Lisa Roach in :issue:`33073`.) +* The :class:`bool`, :class:`int`, and :class:`fractions.Fraction` types + now have an :meth:`~int.as_integer_ratio` method like that found in + :class:`float` and :class:`decimal.Decimal`. This minor API extension + makes it possible to write ``numerator, denominator = + x.as_integer_ratio()`` and have it work across multiple numeric types. + (Contributed by Lisa Roach in :issue:`33073` and Raymond Hettinger in + :issue:`37819`.) * Constructors of :class:`int`, :class:`float` and :class:`complex` will now use the :meth:`~object.__index__` special method, if available and the @@ -410,19 +415,26 @@ Other Language Changes never intended to permit more than a bare name on the left-hand side of a keyword argument assignment term. See :issue:`34641`. -* Iterable unpacking is now allowed without parentheses in :keyword:`yield` - and :keyword:`return` statements. - (Contributed by David Cuthbert and Jordan Chapman in :issue:`32117`.) +* Generalized iterable unpacking in :keyword:`yield` and + :keyword:`return` statements no longer requires enclosing parentheses. + This brings the *yield* and *return* syntax into better agreement with + normal assignment syntax:: + + >>> def parse(family): + lastname, *members = family.split() + return lastname.upper(), *members -* The compiler now produces a :exc:`SyntaxWarning` in some cases when a comma - is missed before tuple or list. For example:: + >>> parse('simpsons homer marge bart lisa sally') + ('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'sally') - data = [ - (1, 2, 3) # oops, missing comma! - (4, 5, 6) - ] - (Contributed by Serhiy Storchaka in :issue:`15248`.) + (Contributed by David Cuthbert and Jordan Chapman in :issue:`32117`.) + +* When a comma is missed in code such as ``[(10, 20) (30, 40)]``, the + compiler displays a :exc:`SyntaxWarning` with a helpful suggestion. + This improves on just having a :exc:`TypeError` indicating that the + first tuple was not callable. (Contributed by Serhiy Storchaka in + :issue:`15248`.) * Arithmetic operations between subclasses of :class:`datetime.date` or :class:`datetime.datetime` and :class:`datetime.timedelta` objects now return @@ -439,7 +451,25 @@ Other Language Changes and Windows use this to properly terminate scripts in interactive sessions. (Contributed by Google via Gregory P. Smith in :issue:`1054041`.) -* Added new ``replace()`` method to the code type (:class:`types.CodeType`). +* Some advanced styles of programming require updating the + :class:`types.CodeType` object for an existing function. Since code + objects are immutable, a new code object needs to be created, one + that is modeled on the existing code object. With 19 parameters, + this was somewhat tedious. Now, the new ``replace()`` method makes + it possible to create a clone with a few altered parameters. + + Here's an example that alters the :func:`statistics.mean` function to + prevent the *data* parameter from being used as a keyword argument:: + + >>> from statistics import mean + >>> mean(data=[10, 20, 90]) + 40 + >>> mean.__code__ = mean.__code__.replace(co_posonlyargcount=1) + >>> mean(data=[10, 20, 90]) + Traceback (most recent call last): + ... + TypeError: mean() got some positional-only arguments passed as keyword arguments: 'data' + (Contributed by Victor Stinner in :issue:`37032`.) * For integers, the three-argument form of the :func:`pow` function now @@ -468,17 +498,55 @@ Other Language Changes (Contributed by Mark Dickinson in :issue:`36027`.) -* When dictionary comprehensions are evaluated, the key is now evaluated before - the value, as proposed by :pep:`572`. +* Dict comprehensions have been synced-up with dict literals so that the + key is computed first and the value second:: + + >>> # Dict comprehension + >>> cast = {input('role? '): input('actor? ') for i in range(2)} + role? King Arthur + actor? Chapman + role? Black Knight + actor? Cleese + + >>> # Dict literal + >>> cast = {input('role? '): input('actor? ')} + role? Sir Robin + actor? Eric Idle + + The guaranteed execution order is helpful with assignment expressions + because variables assigned in the key expression will be available in + the value expression:: + + >>> names = ['Martin von L?wis', '?ukasz Langa', 'Walter D?rwald'] + >>> {(n := normalize('NFC', name)).casefold() : n for name in names} + {'martin von l?wis': 'Martin von L?wis', + '?ukasz langa': '?ukasz Langa', + 'walter d?rwald': 'Walter D?rwald'} New Modules =========== * The new :mod:`importlib.metadata` module provides (provisional) support for - reading metadata from third-party packages. For example, you can extract an - installed package's version number, list of entry points, and more. See - :issue:`34632` for additional details. + reading metadata from third-party packages. For example, it can extract an + installed package's version number, list of entry points, and more:: + + >>> # Note following example requires that the popular "requests" + >>> # package has been installed. + >>> + >>> from importlib.metadata import version, requires, files + >>> version('requests') + '2.22.0' + >>> list(requires('requests')) + ['chardet (<3.1.0,>=3.0.2)'] + >>> list(files('requests'))[:5] + [PackagePath('requests-2.22.0.dist-info/INSTALLER'), + PackagePath('requests-2.22.0.dist-info/LICENSE'), + PackagePath('requests-2.22.0.dist-info/METADATA'), + PackagePath('requests-2.22.0.dist-info/RECORD'), + PackagePath('requests-2.22.0.dist-info/WHEEL')] + + (Contributed in :issue:`34632` by Barry Warsaw and Jason R. Coombs.) Improved Modules From webhook-mailer at python.org Mon Aug 12 21:03:02 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Tue, 13 Aug 2019 01:03:02 -0000 Subject: [Python-checkins] bpo-37759: Second round of edits to Whatsnew 3.8 (GH-15204) (GH-15240) Message-ID: https://github.com/python/cpython/commit/9bedb8c9e60fab4f49ee12b95f8073ee9f577f81 commit: 9bedb8c9e60fab4f49ee12b95f8073ee9f577f81 branch: 3.8 author: Raymond Hettinger committer: GitHub date: 2019-08-12T18:02:58-07:00 summary: bpo-37759: Second round of edits to Whatsnew 3.8 (GH-15204) (GH-15240) (cherry picked from commit 66a34d35e4c97da9840a29ba9fba76721021c463) files: M Doc/whatsnew/3.8.rst diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 83caa2cc5abc..e8238251d6ea 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -39,7 +39,7 @@ module. (Contributed by P.Y. Developer in :issue:`12345`.) - This saves the maintainer the effort of going through the Mercurial log + This saves the maintainer the effort of going through the Git log when researching a change. :Editor: Raymond Hettinger @@ -59,6 +59,7 @@ notable items not yet covered are: from datetime import date from math import cos, radians + from unicodedata import normalize import re import math @@ -383,9 +384,13 @@ Other Language Changes was lifted. (Contributed by Serhiy Storchaka in :issue:`32489`.) -* The :class:`int` type now has a new :meth:`~int.as_integer_ratio` method - compatible with the existing :meth:`float.as_integer_ratio` method. - (Contributed by Lisa Roach in :issue:`33073`.) +* The :class:`bool`, :class:`int`, and :class:`fractions.Fraction` types + now have an :meth:`~int.as_integer_ratio` method like that found in + :class:`float` and :class:`decimal.Decimal`. This minor API extension + makes it possible to write ``numerator, denominator = + x.as_integer_ratio()`` and have it work across multiple numeric types. + (Contributed by Lisa Roach in :issue:`33073` and Raymond Hettinger in + :issue:`37819`.) * Constructors of :class:`int`, :class:`float` and :class:`complex` will now use the :meth:`~object.__index__` special method, if available and the @@ -410,19 +415,26 @@ Other Language Changes never intended to permit more than a bare name on the left-hand side of a keyword argument assignment term. See :issue:`34641`. -* Iterable unpacking is now allowed without parentheses in :keyword:`yield` - and :keyword:`return` statements. - (Contributed by David Cuthbert and Jordan Chapman in :issue:`32117`.) +* Generalized iterable unpacking in :keyword:`yield` and + :keyword:`return` statements no longer requires enclosing parentheses. + This brings the *yield* and *return* syntax into better agreement with + normal assignment syntax:: + + >>> def parse(family): + lastname, *members = family.split() + return lastname.upper(), *members -* The compiler now produces a :exc:`SyntaxWarning` in some cases when a comma - is missed before tuple or list. For example:: + >>> parse('simpsons homer marge bart lisa sally') + ('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'sally') - data = [ - (1, 2, 3) # oops, missing comma! - (4, 5, 6) - ] - (Contributed by Serhiy Storchaka in :issue:`15248`.) + (Contributed by David Cuthbert and Jordan Chapman in :issue:`32117`.) + +* When a comma is missed in code such as ``[(10, 20) (30, 40)]``, the + compiler displays a :exc:`SyntaxWarning` with a helpful suggestion. + This improves on just having a :exc:`TypeError` indicating that the + first tuple was not callable. (Contributed by Serhiy Storchaka in + :issue:`15248`.) * Arithmetic operations between subclasses of :class:`datetime.date` or :class:`datetime.datetime` and :class:`datetime.timedelta` objects now return @@ -439,7 +451,25 @@ Other Language Changes and Windows use this to properly terminate scripts in interactive sessions. (Contributed by Google via Gregory P. Smith in :issue:`1054041`.) -* Added new ``replace()`` method to the code type (:class:`types.CodeType`). +* Some advanced styles of programming require updating the + :class:`types.CodeType` object for an existing function. Since code + objects are immutable, a new code object needs to be created, one + that is modeled on the existing code object. With 19 parameters, + this was somewhat tedious. Now, the new ``replace()`` method makes + it possible to create a clone with a few altered parameters. + + Here's an example that alters the :func:`statistics.mean` function to + prevent the *data* parameter from being used as a keyword argument:: + + >>> from statistics import mean + >>> mean(data=[10, 20, 90]) + 40 + >>> mean.__code__ = mean.__code__.replace(co_posonlyargcount=1) + >>> mean(data=[10, 20, 90]) + Traceback (most recent call last): + ... + TypeError: mean() got some positional-only arguments passed as keyword arguments: 'data' + (Contributed by Victor Stinner in :issue:`37032`.) * For integers, the three-argument form of the :func:`pow` function now @@ -468,14 +498,55 @@ Other Language Changes (Contributed by Mark Dickinson in :issue:`36027`.) -* When dictionary comprehensions are evaluated, the key is now evaluated before - the value, as proposed by :pep:`572`. +* Dict comprehensions have been synced-up with dict literals so that the + key is computed first and the value second:: + + >>> # Dict comprehension + >>> cast = {input('role? '): input('actor? ') for i in range(2)} + role? King Arthur + actor? Chapman + role? Black Knight + actor? Cleese + + >>> # Dict literal + >>> cast = {input('role? '): input('actor? ')} + role? Sir Robin + actor? Eric Idle + + The guaranteed execution order is helpful with assignment expressions + because variables assigned in the key expression will be available in + the value expression:: + + >>> names = ['Martin von L?wis', '?ukasz Langa', 'Walter D?rwald'] + >>> {(n := normalize('NFC', name)).casefold() : n for name in names} + {'martin von l?wis': 'Martin von L?wis', + '?ukasz langa': '?ukasz Langa', + 'walter d?rwald': 'Walter D?rwald'} New Modules =========== -* None yet. +* The new :mod:`importlib.metadata` module provides (provisional) support for + reading metadata from third-party packages. For example, it can extract an + installed package's version number, list of entry points, and more:: + + >>> # Note following example requires that the popular "requests" + >>> # package has been installed. + >>> + >>> from importlib.metadata import version, requires, files + >>> version('requests') + '2.22.0' + >>> list(requires('requests')) + ['chardet (<3.1.0,>=3.0.2)'] + >>> list(files('requests'))[:5] + [PackagePath('requests-2.22.0.dist-info/INSTALLER'), + PackagePath('requests-2.22.0.dist-info/LICENSE'), + PackagePath('requests-2.22.0.dist-info/METADATA'), + PackagePath('requests-2.22.0.dist-info/RECORD'), + PackagePath('requests-2.22.0.dist-info/WHEEL')] + + (Contributed in :issue:`34632` by Barry Warsaw and Jason R. Coombs.) Improved Modules From webhook-mailer at python.org Tue Aug 13 01:21:07 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Tue, 13 Aug 2019 05:21:07 -0000 Subject: [Python-checkins] bpo-37760: Factor out the basic UCD parsing logic of makeunicodedata. (GH-15130) Message-ID: https://github.com/python/cpython/commit/ef2af1ad44be0542a47270d5173a0b920c3a450d commit: ef2af1ad44be0542a47270d5173a0b920c3a450d branch: master author: Greg Price committer: Benjamin Peterson date: 2019-08-12T22:20:56-07:00 summary: bpo-37760: Factor out the basic UCD parsing logic of makeunicodedata. (GH-15130) There were 10 copies of this, and almost as many distinct versions of exactly how it was written. They're all implementing the same standard. Pull them out to the top, so the more interesting logic that remains becomes easier to read. files: M Tools/unicode/makeunicodedata.py diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py index 5b9427acd390..1be93ec479c8 100644 --- a/Tools/unicode/makeunicodedata.py +++ b/Tools/unicode/makeunicodedata.py @@ -30,8 +30,9 @@ import sys import zipfile -from textwrap import dedent from functools import partial +from textwrap import dedent +from typing import * SCRIPT = sys.argv[0] VERSION = "3.3" @@ -903,6 +904,32 @@ def open_data(template, version): return open(local, 'rb') +class UcdFile: + ''' + A file in the standard format of the UCD. + + See: https://www.unicode.org/reports/tr44/#Format_Conventions + + Note that, as described there, the Unihan data files have their + own separate format. + ''' + + def __init__(self, template: str, version: str) -> None: + self.template = template + self.version = version + + def records(self) -> Iterator[List[str]]: + with open_data(self.template, self.version) as file: + for line in file: + line = line.split('#', 1)[0].strip() + if not line: + continue + yield [field.strip() for field in line.split(';')] + + def __iter__(self) -> Iterator[List[str]]: + return self.records() + + # -------------------------------------------------------------------- # the following support code is taken from the unidb utilities # Copyright (c) 1999-2000 by Secret Labs AB @@ -922,14 +949,9 @@ def __init__(self, version, cjk_check=True): self.changed = [] table = [None] * 0x110000 - with open_data(UNICODE_DATA, version) as file: - while 1: - s = file.readline() - if not s: - break - s = s.strip().split(";") - char = int(s[0], 16) - table[char] = s + for s in UcdFile(UNICODE_DATA, version): + char = int(s[0], 16) + table[char] = s cjk_ranges_found = [] @@ -968,17 +990,12 @@ def __init__(self, version, # in order to take advantage of the compression and lookup # algorithms used for the other characters pua_index = NAME_ALIASES_START - with open_data(NAME_ALIASES, version) as file: - for s in file: - s = s.strip() - if not s or s.startswith('#'): - continue - char, name, abbrev = s.split(';') - char = int(char, 16) - self.aliases.append((name, char)) - # also store the name in the PUA 1 - self.table[pua_index][1] = name - pua_index += 1 + for char, name, abbrev in UcdFile(NAME_ALIASES, version): + char = int(char, 16) + self.aliases.append((name, char)) + # also store the name in the PUA 1 + self.table[pua_index][1] = name + pua_index += 1 assert pua_index - NAME_ALIASES_START == len(self.aliases) self.named_sequences = [] @@ -988,50 +1005,32 @@ def __init__(self, version, assert pua_index < NAMED_SEQUENCES_START pua_index = NAMED_SEQUENCES_START - with open_data(NAMED_SEQUENCES, version) as file: - for s in file: - s = s.strip() - if not s or s.startswith('#'): - continue - name, chars = s.split(';') - chars = tuple(int(char, 16) for char in chars.split()) - # check that the structure defined in makeunicodename is OK - assert 2 <= len(chars) <= 4, "change the Py_UCS2 array size" - assert all(c <= 0xFFFF for c in chars), ("use Py_UCS4 in " - "the NamedSequence struct and in unicodedata_lookup") - self.named_sequences.append((name, chars)) - # also store these in the PUA 1 - self.table[pua_index][1] = name - pua_index += 1 + for name, chars in UcdFile(NAMED_SEQUENCES, version): + chars = tuple(int(char, 16) for char in chars.split()) + # check that the structure defined in makeunicodename is OK + assert 2 <= len(chars) <= 4, "change the Py_UCS2 array size" + assert all(c <= 0xFFFF for c in chars), ("use Py_UCS4 in " + "the NamedSequence struct and in unicodedata_lookup") + self.named_sequences.append((name, chars)) + # also store these in the PUA 1 + self.table[pua_index][1] = name + pua_index += 1 assert pua_index - NAMED_SEQUENCES_START == len(self.named_sequences) self.exclusions = {} - with open_data(COMPOSITION_EXCLUSIONS, version) as file: - for s in file: - s = s.strip() - if not s: - continue - if s[0] == '#': - continue - char = int(s.split()[0],16) - self.exclusions[char] = 1 + for char, in UcdFile(COMPOSITION_EXCLUSIONS, version): + char = int(char, 16) + self.exclusions[char] = 1 widths = [None] * 0x110000 - with open_data(EASTASIAN_WIDTH, version) as file: - for s in file: - s = s.strip() - if not s: - continue - if s[0] == '#': - continue - s = s.split()[0].split(';') - if '..' in s[0]: - first, last = [int(c, 16) for c in s[0].split('..')] - chars = list(range(first, last+1)) - else: - chars = [int(s[0], 16)] - for char in chars: - widths[char] = s[1] + for s in UcdFile(EASTASIAN_WIDTH, version): + if '..' in s[0]: + first, last = [int(c, 16) for c in s[0].split('..')] + chars = list(range(first, last+1)) + else: + chars = [int(s[0], 16)] + for char in chars: + widths[char] = s[1] for i in range(0, 0x110000): if table[i] is not None: @@ -1041,38 +1040,27 @@ def __init__(self, version, if table[i] is not None: table[i].append(set()) - with open_data(DERIVED_CORE_PROPERTIES, version) as file: - for s in file: - s = s.split('#', 1)[0].strip() - if not s: - continue - - r, p = s.split(";") - r = r.strip() - p = p.strip() - if ".." in r: - first, last = [int(c, 16) for c in r.split('..')] - chars = list(range(first, last+1)) - else: - chars = [int(r, 16)] - for char in chars: - if table[char]: - # Some properties (e.g. Default_Ignorable_Code_Point) - # apply to unassigned code points; ignore them - table[char][-1].add(p) - - with open_data(LINE_BREAK, version) as file: - for s in file: - s = s.partition('#')[0] - s = [i.strip() for i in s.split(';')] - if len(s) < 2 or s[1] not in MANDATORY_LINE_BREAKS: - continue - if '..' not in s[0]: - first = last = int(s[0], 16) - else: - first, last = [int(c, 16) for c in s[0].split('..')] - for char in range(first, last+1): - table[char][-1].add('Line_Break') + for r, p in UcdFile(DERIVED_CORE_PROPERTIES, version): + if ".." in r: + first, last = [int(c, 16) for c in r.split('..')] + chars = list(range(first, last+1)) + else: + chars = [int(r, 16)] + for char in chars: + if table[char]: + # Some properties (e.g. Default_Ignorable_Code_Point) + # apply to unassigned code points; ignore them + table[char][-1].add(p) + + for s in UcdFile(LINE_BREAK, version): + if len(s) < 2 or s[1] not in MANDATORY_LINE_BREAKS: + continue + if '..' not in s[0]: + first = last = int(s[0], 16) + else: + first, last = [int(c, 16) for c in s[0].split('..')] + for char in range(first, last+1): + table[char][-1].add('Line_Break') # We only want the quickcheck properties # Format: NF?_QC; Y(es)/N(o)/M(aybe) @@ -1083,23 +1071,19 @@ def __init__(self, version, # for older versions, and no delta records will be created. quickchecks = [0] * 0x110000 qc_order = 'NFD_QC NFKD_QC NFC_QC NFKC_QC'.split() - with open_data(DERIVEDNORMALIZATION_PROPS, version) as file: - for s in file: - if '#' in s: - s = s[:s.index('#')] - s = [i.strip() for i in s.split(';')] - if len(s) < 2 or s[1] not in qc_order: - continue - quickcheck = 'MN'.index(s[2]) + 1 # Maybe or No - quickcheck_shift = qc_order.index(s[1])*2 - quickcheck <<= quickcheck_shift - if '..' not in s[0]: - first = last = int(s[0], 16) - else: - first, last = [int(c, 16) for c in s[0].split('..')] - for char in range(first, last+1): - assert not (quickchecks[char]>>quickcheck_shift)&3 - quickchecks[char] |= quickcheck + for s in UcdFile(DERIVEDNORMALIZATION_PROPS, version): + if len(s) < 2 or s[1] not in qc_order: + continue + quickcheck = 'MN'.index(s[2]) + 1 # Maybe or No + quickcheck_shift = qc_order.index(s[1])*2 + quickcheck <<= quickcheck_shift + if '..' not in s[0]: + first = last = int(s[0], 16) + else: + first, last = [int(c, 16) for c in s[0].split('..')] + for char in range(first, last+1): + assert not (quickchecks[char]>>quickcheck_shift)&3 + quickchecks[char] |= quickcheck for i in range(0, 0x110000): if table[i] is not None: table[i].append(quickchecks[i]) @@ -1122,34 +1106,26 @@ def __init__(self, version, # Patch the numeric field if table[i] is not None: table[i][8] = value + sc = self.special_casing = {} - with open_data(SPECIAL_CASING, version) as file: - for s in file: - s = s[:-1].split('#', 1)[0] - if not s: - continue - data = s.split("; ") - if data[4]: - # We ignore all conditionals (since they depend on - # languages) except for one, which is hardcoded. See - # handle_capital_sigma in unicodeobject.c. - continue - c = int(data[0], 16) - lower = [int(char, 16) for char in data[1].split()] - title = [int(char, 16) for char in data[2].split()] - upper = [int(char, 16) for char in data[3].split()] - sc[c] = (lower, title, upper) + for data in UcdFile(SPECIAL_CASING, version): + if data[4]: + # We ignore all conditionals (since they depend on + # languages) except for one, which is hardcoded. See + # handle_capital_sigma in unicodeobject.c. + continue + c = int(data[0], 16) + lower = [int(char, 16) for char in data[1].split()] + title = [int(char, 16) for char in data[2].split()] + upper = [int(char, 16) for char in data[3].split()] + sc[c] = (lower, title, upper) + cf = self.case_folding = {} if version != '3.2.0': - with open_data(CASE_FOLDING, version) as file: - for s in file: - s = s[:-1].split('#', 1)[0] - if not s: - continue - data = s.split("; ") - if data[1] in "CF": - c = int(data[0], 16) - cf[c] = [int(char, 16) for char in data[2].split()] + for data in UcdFile(CASE_FOLDING, version): + if data[1] in "CF": + c = int(data[0], 16) + cf[c] = [int(char, 16) for char in data[2].split()] def uselatin1(self): # restrict character range to ISO Latin 1 From webhook-mailer at python.org Tue Aug 13 01:23:46 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Aug 2019 05:23:46 -0000 Subject: [Python-checkins] bpo-37760: Mark all generated Unicode data headers as generated. (GH-15171) Message-ID: https://github.com/python/cpython/commit/4e3dfcc4b987e683476a1b16456e57d3c9f581cb commit: 4e3dfcc4b987e683476a1b16456e57d3c9f581cb branch: master author: Greg Price committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-12T22:23:41-07:00 summary: bpo-37760: Mark all generated Unicode data headers as generated. (GH-15171) This causes them to be collapsed by default in diffs shown on GitHub. https://bugs.python.org/issue37760 Automerge-Triggered-By: @benjaminp files: M .gitattributes diff --git a/.gitattributes b/.gitattributes index c9a54fbd472e..bec16a08152e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -54,7 +54,7 @@ Python/Python-ast.c linguist-generated=true Include/opcode.h linguist-generated=true Python/opcode_targets.h linguist-generated=true Objects/typeslots.inc linguist-generated=true -Modules/unicodedata_db.h linguist-generated=true +*_db.h linguist-generated=true Doc/library/token-list.inc linguist-generated=true Include/token.h linguist-generated=true Lib/token.py linguist-generated=true From webhook-mailer at python.org Tue Aug 13 01:58:05 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Tue, 13 Aug 2019 05:58:05 -0000 Subject: [Python-checkins] bpo-37758: Clean out vestigial script-bits from test_unicodedata. (GH-15126) Message-ID: https://github.com/python/cpython/commit/def97c988be8340f33869b57942a30d10fc3a1f9 commit: def97c988be8340f33869b57942a30d10fc3a1f9 branch: master author: Greg Price committer: Benjamin Peterson date: 2019-08-12T22:58:01-07:00 summary: bpo-37758: Clean out vestigial script-bits from test_unicodedata. (GH-15126) This file started life as a script, before conversion to a `unittest` test file. Clear out some legacies of that conversion that are a bit confusing about how it works. Most notably, it's unlikely there's still a good reason to try to recover from `unicodedata` failing to import -- as there was when that logic was first added, when the module was very new. So take that out entirely. Keep `self.db` working, though, to avoid a noisy diff. files: M Lib/test/test_unicodedata.py diff --git a/Lib/test/test_unicodedata.py b/Lib/test/test_unicodedata.py index a52b6de547fb..7bc196be362b 100644 --- a/Lib/test/test_unicodedata.py +++ b/Lib/test/test_unicodedata.py @@ -1,4 +1,4 @@ -""" Test script for the unicodedata module. +""" Tests for the unicodedata module. Written by Marc-Andre Lemburg (mal at lemburg.com). @@ -6,16 +6,12 @@ """ +import hashlib import sys +import unicodedata import unittest -import hashlib from test.support import script_helper -encoding = 'utf-8' -errors = 'surrogatepass' - - -### Run tests class UnicodeMethodsTest(unittest.TestCase): @@ -61,20 +57,12 @@ def test_method_checksum(self): (char + 'ABC').title(), ] - h.update(''.join(data).encode(encoding, errors)) + h.update(''.join(data).encode('utf-8', 'surrogatepass')) result = h.hexdigest() self.assertEqual(result, self.expectedchecksum) class UnicodeDatabaseTest(unittest.TestCase): - - def setUp(self): - # In case unicodedata is not available, this will raise an ImportError, - # but the other test cases will still be run - import unicodedata - self.db = unicodedata - - def tearDown(self): - del self.db + db = unicodedata class UnicodeFunctionsTest(UnicodeDatabaseTest): From webhook-mailer at python.org Tue Aug 13 01:59:34 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Tue, 13 Aug 2019 05:59:34 -0000 Subject: [Python-checkins] bpo-37760: Constant-fold some old options in makeunicodedata. (GH-15129) Message-ID: https://github.com/python/cpython/commit/99d208efed97e02d813e8166925b998bbd0d3993 commit: 99d208efed97e02d813e8166925b998bbd0d3993 branch: master author: Greg Price committer: Benjamin Peterson date: 2019-08-12T22:59:30-07:00 summary: bpo-37760: Constant-fold some old options in makeunicodedata. (GH-15129) The `expand` option was introduced in 2000 in commit fad27aee1. It appears to have been always set since it was committed, and what it does is tell the code to do something essential. So, just always do that, and cut the option. Also cut the `linebreakprops` option, which isn't consulted anymore. files: M Tools/unicode/makeunicodedata.py diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py index 1be93ec479c8..38c1f19a6567 100644 --- a/Tools/unicode/makeunicodedata.py +++ b/Tools/unicode/makeunicodedata.py @@ -943,10 +943,7 @@ class UnicodeData: # ISO-comment, uppercase, lowercase, titlecase, ea-width, (16) # derived-props] (17) - def __init__(self, version, - linebreakprops=False, - expand=1, - cjk_check=True): + def __init__(self, version, cjk_check=True): self.changed = [] table = [None] * 0x110000 for s in UcdFile(UNICODE_DATA, version): @@ -956,26 +953,25 @@ def __init__(self, version, cjk_ranges_found = [] # expand first-last ranges - if expand: - field = None - for i in range(0, 0x110000): - s = table[i] - if s: - if s[1][-6:] == "First>": - s[1] = "" - field = s - elif s[1][-5:] == "Last>": - if s[1].startswith("": + s[1] = "" + field = s + elif s[1][-5:] == "Last>": + if s[1].startswith(" https://github.com/python/cpython/commit/c2b9d9f202e4a99fc0800b7a0f0944ac4c2382e3 commit: c2b9d9f202e4a99fc0800b7a0f0944ac4c2382e3 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-12T23:04:21-07:00 summary: bpo-37760: Mark all generated Unicode data headers as generated. (GH-15171) This causes them to be collapsed by default in diffs shown on GitHub. https://bugs.python.org/issue37760 Automerge-Triggered-By: @benjaminp (cherry picked from commit 4e3dfcc4b987e683476a1b16456e57d3c9f581cb) Co-authored-by: Greg Price files: M .gitattributes diff --git a/.gitattributes b/.gitattributes index c9a54fbd472e..bec16a08152e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -54,7 +54,7 @@ Python/Python-ast.c linguist-generated=true Include/opcode.h linguist-generated=true Python/opcode_targets.h linguist-generated=true Objects/typeslots.inc linguist-generated=true -Modules/unicodedata_db.h linguist-generated=true +*_db.h linguist-generated=true Doc/library/token-list.inc linguist-generated=true Include/token.h linguist-generated=true Lib/token.py linguist-generated=true From webhook-mailer at python.org Tue Aug 13 02:06:20 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Aug 2019 06:06:20 -0000 Subject: [Python-checkins] bpo-37760: Mark all generated Unicode data headers as generated. (GH-15171) Message-ID: https://github.com/python/cpython/commit/b02e148a0d6e7a11df93a09ea5f4e1b0ad9b77b8 commit: b02e148a0d6e7a11df93a09ea5f4e1b0ad9b77b8 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-12T23:06:16-07:00 summary: bpo-37760: Mark all generated Unicode data headers as generated. (GH-15171) This causes them to be collapsed by default in diffs shown on GitHub. https://bugs.python.org/issue37760 Automerge-Triggered-By: @benjaminp (cherry picked from commit 4e3dfcc4b987e683476a1b16456e57d3c9f581cb) Co-authored-by: Greg Price files: From webhook-mailer at python.org Tue Aug 13 13:34:12 2019 From: webhook-mailer at python.org (Steve Dower) Date: Tue, 13 Aug 2019 17:34:12 -0000 Subject: [Python-checkins] bpo-37841: Remove python_uwp dependency on msvcp140.dll (GH-15253) Message-ID: https://github.com/python/cpython/commit/b0dace3e979381426385c551b116d0f1434096ee commit: b0dace3e979381426385c551b116d0f1434096ee branch: master author: Steve Dower committer: GitHub date: 2019-08-13T10:34:07-07:00 summary: bpo-37841: Remove python_uwp dependency on msvcp140.dll (GH-15253) files: M PCbuild/python_uwp.vcxproj diff --git a/PCbuild/python_uwp.vcxproj b/PCbuild/python_uwp.vcxproj index af187dd4df30..14e138cbed3e 100644 --- a/PCbuild/python_uwp.vcxproj +++ b/PCbuild/python_uwp.vcxproj @@ -65,6 +65,15 @@ Console + + + Multithreaded + + + ucrt.lib;%(AdditionalDependencies) + libucrt;%(IgnoreSpecificDefaultLibraries) + + From webhook-mailer at python.org Tue Aug 13 13:38:08 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 13 Aug 2019 17:38:08 -0000 Subject: [Python-checkins] bpo-37583: Add err 113 to support.get_socket_conn_refused_errs() (GH-14729) Message-ID: https://github.com/python/cpython/commit/1ac2a83f30312976502fda042db5ce18d10ceec2 commit: 1ac2a83f30312976502fda042db5ce18d10ceec2 branch: master author: Hai Shi committer: Victor Stinner date: 2019-08-13T19:37:59+02:00 summary: bpo-37583: Add err 113 to support.get_socket_conn_refused_errs() (GH-14729) Add error number 113 EHOSTUNREACH to get_socket_conn_refused_errs() of test.support. files: M Lib/test/support/__init__.py diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 00e734e7059f..46d646fe5b76 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1497,6 +1497,9 @@ def get_socket_conn_refused_errs(): # bpo-31910: socket.create_connection() fails randomly # with EADDRNOTAVAIL on Travis CI errors.append(errno.EADDRNOTAVAIL) + if hasattr(errno, 'EHOSTUNREACH'): + # bpo-37583: The destination host cannot be reached + errors.append(errno.EHOSTUNREACH) if not IPV6_ENABLED: errors.append(errno.EAFNOSUPPORT) return errors From webhook-mailer at python.org Tue Aug 13 13:54:32 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Aug 2019 17:54:32 -0000 Subject: [Python-checkins] bpo-37841: Remove python_uwp dependency on msvcp140.dll (GH-15253) Message-ID: https://github.com/python/cpython/commit/853eecc7692503fec8240fd9a74d9f88e0392630 commit: 853eecc7692503fec8240fd9a74d9f88e0392630 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-13T10:54:28-07:00 summary: bpo-37841: Remove python_uwp dependency on msvcp140.dll (GH-15253) (cherry picked from commit b0dace3e979381426385c551b116d0f1434096ee) Co-authored-by: Steve Dower files: M PCbuild/python_uwp.vcxproj diff --git a/PCbuild/python_uwp.vcxproj b/PCbuild/python_uwp.vcxproj index af187dd4df30..14e138cbed3e 100644 --- a/PCbuild/python_uwp.vcxproj +++ b/PCbuild/python_uwp.vcxproj @@ -65,6 +65,15 @@ Console + + + Multithreaded + + + ucrt.lib;%(AdditionalDependencies) + libucrt;%(IgnoreSpecificDefaultLibraries) + + From webhook-mailer at python.org Tue Aug 13 14:11:54 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Aug 2019 18:11:54 -0000 Subject: [Python-checkins] bpo-37583: Add err 113 to support.get_socket_conn_refused_errs() (GH-14729) Message-ID: https://github.com/python/cpython/commit/ee989512528d178d6f088916aba3e67ea9487ceb commit: ee989512528d178d6f088916aba3e67ea9487ceb branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-13T11:11:49-07:00 summary: bpo-37583: Add err 113 to support.get_socket_conn_refused_errs() (GH-14729) Add error number 113 EHOSTUNREACH to get_socket_conn_refused_errs() of test.support. (cherry picked from commit 1ac2a83f30312976502fda042db5ce18d10ceec2) Co-authored-by: Hai Shi files: M Lib/test/support/__init__.py diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index e73c65bb9f34..e4e0481d336f 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1495,6 +1495,9 @@ def get_socket_conn_refused_errs(): # bpo-31910: socket.create_connection() fails randomly # with EADDRNOTAVAIL on Travis CI errors.append(errno.EADDRNOTAVAIL) + if hasattr(errno, 'EHOSTUNREACH'): + # bpo-37583: The destination host cannot be reached + errors.append(errno.EHOSTUNREACH) if not IPV6_ENABLED: errors.append(errno.EAFNOSUPPORT) return errors From webhook-mailer at python.org Tue Aug 13 15:05:18 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Aug 2019 19:05:18 -0000 Subject: [Python-checkins] bpo-37814: Document the empty tuple type annotation syntax (GH-15208) Message-ID: https://github.com/python/cpython/commit/8a784af750fa82c8355903309e5089eb2b60c16b commit: 8a784af750fa82c8355903309e5089eb2b60c16b branch: master author: Josh Holland committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-13T12:05:09-07:00 summary: bpo-37814: Document the empty tuple type annotation syntax (GH-15208) https://bugs.python.org/issue37814: > The empty tuple syntax in type annotations, `Tuple[()]`, is not obvious from the examples given in the documentation (I naively expected `Tuple[]` to work); it has been documented in PEP 484 and in mypy, but not in the documentation for the typing module. https://bugs.python.org/issue37814 files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index d2dd03d50fc6..12efde131657 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1245,7 +1245,8 @@ The module defines the following classes, functions and decorators: .. data:: Tuple Tuple type; ``Tuple[X, Y]`` is the type of a tuple of two items - with the first item of type X and the second of type Y. + with the first item of type X and the second of type Y. The type of + the empty tuple can be written as ``Tuple[()]``. Example: ``Tuple[T1, T2]`` is a tuple of two elements corresponding to type variables T1 and T2. ``Tuple[int, float, str]`` is a tuple From webhook-mailer at python.org Tue Aug 13 15:12:59 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Aug 2019 19:12:59 -0000 Subject: [Python-checkins] bpo-37814: Document the empty tuple type annotation syntax (GH-15208) Message-ID: https://github.com/python/cpython/commit/6ad902a08814909b4d52c4000d5a10ce58516dac commit: 6ad902a08814909b4d52c4000d5a10ce58516dac branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-13T12:12:55-07:00 summary: bpo-37814: Document the empty tuple type annotation syntax (GH-15208) https://bugs.python.org/issue37814: > The empty tuple syntax in type annotations, `Tuple[()]`, is not obvious from the examples given in the documentation (I naively expected `Tuple[]` to work); it has been documented in PEP 484 and in mypy, but not in the documentation for the typing module. https://bugs.python.org/issue37814 (cherry picked from commit 8a784af750fa82c8355903309e5089eb2b60c16b) Co-authored-by: Josh Holland files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index d2dd03d50fc6..12efde131657 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1245,7 +1245,8 @@ The module defines the following classes, functions and decorators: .. data:: Tuple Tuple type; ``Tuple[X, Y]`` is the type of a tuple of two items - with the first item of type X and the second of type Y. + with the first item of type X and the second of type Y. The type of + the empty tuple can be written as ``Tuple[()]``. Example: ``Tuple[T1, T2]`` is a tuple of two elements corresponding to type variables T1 and T2. ``Tuple[int, float, str]`` is a tuple From webhook-mailer at python.org Tue Aug 13 15:26:20 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Aug 2019 19:26:20 -0000 Subject: [Python-checkins] [3.7] bpo-37814: Document the empty tuple type annotation syntax (GH-15208) (GH-15262) Message-ID: https://github.com/python/cpython/commit/37fd9f73e2fa439554977cfba427bf94c1fedb6b commit: 37fd9f73e2fa439554977cfba427bf94c1fedb6b branch: 3.7 author: Josh Holland committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-13T12:26:12-07:00 summary: [3.7] bpo-37814: Document the empty tuple type annotation syntax (GH-15208) (GH-15262) https://bugs.python.org/issue37814: > The empty tuple syntax in type annotations, `Tuple[()]`, is not obvious from the examples given in the documentation (I naively expected `Tuple[]` to work); it has been documented in PEP 484 and in mypy, but not in the documentation for the typing module. https://bugs.python.org/issue37814 (cherry picked from commit 8a784af750fa82c8355903309e5089eb2b60c16b) Co-authored-by: Josh Holland https://bugs.python.org/issue37814 Automerge-Triggered-By: @gvanrossum files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 5adc81c1e3c8..c0b048cb2bd3 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1056,7 +1056,8 @@ The module defines the following classes, functions and decorators: .. data:: Tuple Tuple type; ``Tuple[X, Y]`` is the type of a tuple of two items - with the first item of type X and the second of type Y. + with the first item of type X and the second of type Y. The type of + the empty tuple can be written as ``Tuple[()]``. Example: ``Tuple[T1, T2]`` is a tuple of two elements corresponding to type variables T1 and T2. ``Tuple[int, float, str]`` is a tuple From webhook-mailer at python.org Tue Aug 13 15:54:07 2019 From: webhook-mailer at python.org (Antoine Pitrou) Date: Tue, 13 Aug 2019 19:54:07 -0000 Subject: [Python-checkins] bpo-37689: add Path.is_relative_to() method (GH-14982) Message-ID: https://github.com/python/cpython/commit/82642a052dc46b2180679518bc8d87e1a28a88b5 commit: 82642a052dc46b2180679518bc8d87e1a28a88b5 branch: master author: Hai Shi committer: Antoine Pitrou date: 2019-08-13T21:54:02+02:00 summary: bpo-37689: add Path.is_relative_to() method (GH-14982) files: A Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst M Doc/library/pathlib.rst M Lib/pathlib.py M Lib/test/test_pathlib.py diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 166de8de1f06..33fac5f69725 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -273,7 +273,7 @@ Methods and properties .. testsetup:: - from pathlib import PurePosixPath, PureWindowsPath + from pathlib import PurePath, PurePosixPath, PureWindowsPath Pure paths provide the following methods and properties: @@ -462,6 +462,19 @@ Pure paths provide the following methods and properties: True +.. method:: PurePath.is_relative_to(*other) + + Return whether or not this path is relative to the *other* path. + + >>> p = PurePath('/etc/passwd') + >>> p.is_relative_to('/etc') + True + >>> p.is_relative_to('/usr') + False + + .. versionadded:: 3.9 + + .. method:: PurePath.is_reserved() With :class:`PureWindowsPath`, return ``True`` if the path is considered diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 6355ae864108..80923c768268 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -886,6 +886,15 @@ def relative_to(self, *other): return self._from_parsed_parts('', root if n == 1 else '', abs_parts[n:]) + def is_relative_to(self, *other): + """Return True if the path is relative to another path or False. + """ + try: + self.relative_to(*other) + return True + except ValueError: + return False + @property def parts(self): """An object providing sequence-like access to the diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index f74524d992a1..cfda0a218826 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -619,6 +619,40 @@ def test_relative_to_common(self): self.assertRaises(ValueError, p.relative_to, '') self.assertRaises(ValueError, p.relative_to, P('a')) + def test_is_relative_to_common(self): + P = self.cls + p = P('a/b') + self.assertRaises(TypeError, p.is_relative_to) + self.assertRaises(TypeError, p.is_relative_to, b'a') + self.assertTrue(p.is_relative_to(P())) + self.assertTrue(p.is_relative_to('')) + self.assertTrue(p.is_relative_to(P('a'))) + self.assertTrue(p.is_relative_to('a/')) + self.assertTrue(p.is_relative_to(P('a/b'))) + self.assertTrue(p.is_relative_to('a/b')) + # With several args. + self.assertTrue(p.is_relative_to('a', 'b')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P('c'))) + self.assertFalse(p.is_relative_to(P('a/b/c'))) + self.assertFalse(p.is_relative_to(P('a/c'))) + self.assertFalse(p.is_relative_to(P('/a'))) + p = P('/a/b') + self.assertTrue(p.is_relative_to(P('/'))) + self.assertTrue(p.is_relative_to('/')) + self.assertTrue(p.is_relative_to(P('/a'))) + self.assertTrue(p.is_relative_to('/a')) + self.assertTrue(p.is_relative_to('/a/')) + self.assertTrue(p.is_relative_to(P('/a/b'))) + self.assertTrue(p.is_relative_to('/a/b')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P('/c'))) + self.assertFalse(p.is_relative_to(P('/a/b/c'))) + self.assertFalse(p.is_relative_to(P('/a/c'))) + self.assertFalse(p.is_relative_to(P())) + self.assertFalse(p.is_relative_to('')) + self.assertFalse(p.is_relative_to(P('a'))) + def test_pickling_common(self): P = self.cls p = P('/a/b') @@ -1062,6 +1096,59 @@ def test_relative_to(self): self.assertRaises(ValueError, p.relative_to, P('//z/Share/Foo')) self.assertRaises(ValueError, p.relative_to, P('//Server/z/Foo')) + def test_is_relative_to(self): + P = self.cls + p = P('C:Foo/Bar') + self.assertTrue(p.is_relative_to(P('c:'))) + self.assertTrue(p.is_relative_to('c:')) + self.assertTrue(p.is_relative_to(P('c:foO'))) + self.assertTrue(p.is_relative_to('c:foO')) + self.assertTrue(p.is_relative_to('c:foO/')) + self.assertTrue(p.is_relative_to(P('c:foO/baR'))) + self.assertTrue(p.is_relative_to('c:foO/baR')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P())) + self.assertFalse(p.is_relative_to('')) + self.assertFalse(p.is_relative_to(P('d:'))) + self.assertFalse(p.is_relative_to(P('/'))) + self.assertFalse(p.is_relative_to(P('Foo'))) + self.assertFalse(p.is_relative_to(P('/Foo'))) + self.assertFalse(p.is_relative_to(P('C:/Foo'))) + self.assertFalse(p.is_relative_to(P('C:Foo/Bar/Baz'))) + self.assertFalse(p.is_relative_to(P('C:Foo/Baz'))) + p = P('C:/Foo/Bar') + self.assertTrue(p.is_relative_to('c:')) + self.assertTrue(p.is_relative_to(P('c:/'))) + self.assertTrue(p.is_relative_to(P('c:/foO'))) + self.assertTrue(p.is_relative_to('c:/foO/')) + self.assertTrue(p.is_relative_to(P('c:/foO/baR'))) + self.assertTrue(p.is_relative_to('c:/foO/baR')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P('C:/Baz'))) + self.assertFalse(p.is_relative_to(P('C:/Foo/Bar/Baz'))) + self.assertFalse(p.is_relative_to(P('C:/Foo/Baz'))) + self.assertFalse(p.is_relative_to(P('C:Foo'))) + self.assertFalse(p.is_relative_to(P('d:'))) + self.assertFalse(p.is_relative_to(P('d:/'))) + self.assertFalse(p.is_relative_to(P('/'))) + self.assertFalse(p.is_relative_to(P('/Foo'))) + self.assertFalse(p.is_relative_to(P('//C/Foo'))) + # UNC paths. + p = P('//Server/Share/Foo/Bar') + self.assertTrue(p.is_relative_to(P('//sErver/sHare'))) + self.assertTrue(p.is_relative_to('//sErver/sHare')) + self.assertTrue(p.is_relative_to('//sErver/sHare/')) + self.assertTrue(p.is_relative_to(P('//sErver/sHare/Foo'))) + self.assertTrue(p.is_relative_to('//sErver/sHare/Foo')) + self.assertTrue(p.is_relative_to('//sErver/sHare/Foo/')) + self.assertTrue(p.is_relative_to(P('//sErver/sHare/Foo/Bar'))) + self.assertTrue(p.is_relative_to('//sErver/sHare/Foo/Bar')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P('/Server/Share/Foo'))) + self.assertFalse(p.is_relative_to(P('c:/Server/Share/Foo'))) + self.assertFalse(p.is_relative_to(P('//z/Share/Foo'))) + self.assertFalse(p.is_relative_to(P('//Server/z/Foo'))) + def test_is_absolute(self): P = self.cls # Under NT, only paths with both a drive and a root are absolute. diff --git a/Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst b/Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst new file mode 100644 index 000000000000..2787f9e849c2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst @@ -0,0 +1 @@ +Add :meth:`is_relative_to` in :class:`PurePath` to determine whether or not one path is relative to another. From webhook-mailer at python.org Tue Aug 13 17:27:19 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Aug 2019 21:27:19 -0000 Subject: [Python-checkins] bpo-25172: Raise appropriate ImportError msg when crypt module used on Windows (GH-15149) Message-ID: https://github.com/python/cpython/commit/7f7f74734acd729d1f82b7cf672e064c9525fced commit: 7f7f74734acd729d1f82b7cf672e064c9525fced branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-13T14:27:14-07:00 summary: bpo-25172: Raise appropriate ImportError msg when crypt module used on Windows (GH-15149) (cherry picked from commit f4e725f224b864bf9bf405ff7f863cda46fca1cd) Co-authored-by: shireenrao files: A Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst M Lib/crypt.py diff --git a/Lib/crypt.py b/Lib/crypt.py index b0e47f430c3c..8846602d7613 100644 --- a/Lib/crypt.py +++ b/Lib/crypt.py @@ -1,6 +1,15 @@ """Wrapper to the POSIX crypt library call and associated functionality.""" -import _crypt +import sys as _sys + +try: + import _crypt +except ModuleNotFoundError: + if _sys.platform == 'win32': + raise ImportError("The crypt module is not supported on Windows") + else: + raise ImportError("The required _crypt module was not built as part of CPython") + import string as _string from random import SystemRandom as _SystemRandom from collections import namedtuple as _namedtuple diff --git a/Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst b/Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst new file mode 100644 index 000000000000..47106d887921 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst @@ -0,0 +1 @@ +Trying to import the :mod:`crypt` module on Windows will result in an :exc:`ImportError` with a message explaining that the module isn't supported on Windows. On other platforms, if the underlying ``_crypt`` module is not available, the ImportError will include a message explaining the problem. From webhook-mailer at python.org Tue Aug 13 17:27:37 2019 From: webhook-mailer at python.org (Steve Dower) Date: Tue, 13 Aug 2019 21:27:37 -0000 Subject: [Python-checkins] bpo-25172: Add test for crypt ImportError on Windows (GH-15252) Message-ID: https://github.com/python/cpython/commit/243a73deee4ac61fe06602b7ed56b6df01e19f27 commit: 243a73deee4ac61fe06602b7ed56b6df01e19f27 branch: master author: shireenrao committer: Steve Dower date: 2019-08-13T14:27:34-07:00 summary: bpo-25172: Add test for crypt ImportError on Windows (GH-15252) files: M Lib/test/test_crypt.py diff --git a/Lib/test/test_crypt.py b/Lib/test/test_crypt.py index d9189fc6f28b..d29e005fdad5 100644 --- a/Lib/test/test_crypt.py +++ b/Lib/test/test_crypt.py @@ -1,9 +1,25 @@ import sys -from test import support import unittest -crypt = support.import_module('crypt') +try: + import crypt + IMPORT_ERROR = None +except ImportError as ex: + crypt = None + IMPORT_ERROR = str(ex) + + + at unittest.skipIf(crypt, 'This should only run on windows') +class TestWhyCryptDidNotImport(unittest.TestCase): + def test_failure_only_for_windows(self): + self.assertEqual(sys.platform, 'win32') + + def test_import_failure_message(self): + self.assertIn('not supported', IMPORT_ERROR) + + + at unittest.skipUnless(crypt, 'Not supported on Windows') class CryptTestCase(unittest.TestCase): def test_crypt(self): @@ -39,9 +55,13 @@ def test_methods(self): else: self.assertEqual(crypt.methods[-1], crypt.METHOD_CRYPT) - @unittest.skipUnless(crypt.METHOD_SHA256 in crypt.methods or - crypt.METHOD_SHA512 in crypt.methods, - 'requires support of SHA-2') + @unittest.skipUnless( + crypt + and ( + crypt.METHOD_SHA256 in crypt.methods or crypt.METHOD_SHA512 in crypt.methods + ), + 'requires support of SHA-2', + ) def test_sha2_rounds(self): for method in (crypt.METHOD_SHA256, crypt.METHOD_SHA512): for rounds in 1000, 10_000, 100_000: @@ -54,8 +74,9 @@ def test_sha2_rounds(self): cr2 = crypt.crypt('mypassword', cr) self.assertEqual(cr2, cr) - @unittest.skipUnless(crypt.METHOD_BLOWFISH in crypt.methods, - 'requires support of Blowfish') + @unittest.skipUnless( + crypt and crypt.METHOD_BLOWFISH in crypt.methods, 'requires support of Blowfish' + ) def test_blowfish_rounds(self): for log_rounds in range(4, 11): salt = crypt.mksalt(crypt.METHOD_BLOWFISH, rounds=1 << log_rounds) From webhook-mailer at python.org Tue Aug 13 17:52:24 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Aug 2019 21:52:24 -0000 Subject: [Python-checkins] bpo-25172: Add test for crypt ImportError on Windows (GH-15252) Message-ID: https://github.com/python/cpython/commit/e7ec9e04c82be72aef621fdfba03f41cbd8599aa commit: e7ec9e04c82be72aef621fdfba03f41cbd8599aa branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-13T14:52:20-07:00 summary: bpo-25172: Add test for crypt ImportError on Windows (GH-15252) (cherry picked from commit 243a73deee4ac61fe06602b7ed56b6df01e19f27) Co-authored-by: shireenrao files: M Lib/test/test_crypt.py diff --git a/Lib/test/test_crypt.py b/Lib/test/test_crypt.py index d9189fc6f28b..d29e005fdad5 100644 --- a/Lib/test/test_crypt.py +++ b/Lib/test/test_crypt.py @@ -1,9 +1,25 @@ import sys -from test import support import unittest -crypt = support.import_module('crypt') +try: + import crypt + IMPORT_ERROR = None +except ImportError as ex: + crypt = None + IMPORT_ERROR = str(ex) + + + at unittest.skipIf(crypt, 'This should only run on windows') +class TestWhyCryptDidNotImport(unittest.TestCase): + def test_failure_only_for_windows(self): + self.assertEqual(sys.platform, 'win32') + + def test_import_failure_message(self): + self.assertIn('not supported', IMPORT_ERROR) + + + at unittest.skipUnless(crypt, 'Not supported on Windows') class CryptTestCase(unittest.TestCase): def test_crypt(self): @@ -39,9 +55,13 @@ def test_methods(self): else: self.assertEqual(crypt.methods[-1], crypt.METHOD_CRYPT) - @unittest.skipUnless(crypt.METHOD_SHA256 in crypt.methods or - crypt.METHOD_SHA512 in crypt.methods, - 'requires support of SHA-2') + @unittest.skipUnless( + crypt + and ( + crypt.METHOD_SHA256 in crypt.methods or crypt.METHOD_SHA512 in crypt.methods + ), + 'requires support of SHA-2', + ) def test_sha2_rounds(self): for method in (crypt.METHOD_SHA256, crypt.METHOD_SHA512): for rounds in 1000, 10_000, 100_000: @@ -54,8 +74,9 @@ def test_sha2_rounds(self): cr2 = crypt.crypt('mypassword', cr) self.assertEqual(cr2, cr) - @unittest.skipUnless(crypt.METHOD_BLOWFISH in crypt.methods, - 'requires support of Blowfish') + @unittest.skipUnless( + crypt and crypt.METHOD_BLOWFISH in crypt.methods, 'requires support of Blowfish' + ) def test_blowfish_rounds(self): for log_rounds in range(4, 11): salt = crypt.mksalt(crypt.METHOD_BLOWFISH, rounds=1 << log_rounds) From webhook-mailer at python.org Tue Aug 13 21:11:05 2019 From: webhook-mailer at python.org (Senthil Kumaran) Date: Wed, 14 Aug 2019 01:11:05 -0000 Subject: [Python-checkins] bpo-37256: Wording in Request class docs (#14792) Message-ID: https://github.com/python/cpython/commit/38c7199beb30ae9a5005c0f0d9df9fae0da3680a commit: 38c7199beb30ae9a5005c0f0d9df9fae0da3680a branch: master author: Ngalim Siregar committer: Senthil Kumaran date: 2019-08-13T18:10:58-07:00 summary: bpo-37256: Wording in Request class docs (#14792) * bpo-37256: Wording in Request class docs * ?? Added by blurb_it. * Update Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst Co-Authored-By: Kyle Stanley files: A Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst M Doc/library/urllib.request.rst diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index 3b7508966691..448bc6785470 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -227,7 +227,7 @@ The following classes are provided: is not None, ``Content-Type: application/x-www-form-urlencoded`` will be added as a default. - The final two arguments are only of interest for correct handling + The next two arguments are only of interest for correct handling of third-party HTTP cookies: *origin_req_host* should be the request-host of the origin diff --git a/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst b/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst new file mode 100644 index 000000000000..480d7c87ebc4 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst @@ -0,0 +1 @@ +Fix wording of arguments for :class:`Request` in :mod:`urllib.request` From webhook-mailer at python.org Tue Aug 13 22:28:46 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 14 Aug 2019 02:28:46 -0000 Subject: [Python-checkins] bpo-37760: Factor out standard range-expanding logic in makeunicodedata. (GH-15248) Message-ID: https://github.com/python/cpython/commit/c03e698c344dfc557555b6b07a3ee2702e45f6ee commit: c03e698c344dfc557555b6b07a3ee2702e45f6ee branch: master author: Greg Price committer: Benjamin Peterson date: 2019-08-13T19:28:38-07:00 summary: bpo-37760: Factor out standard range-expanding logic in makeunicodedata. (GH-15248) Much like the lower-level logic in commit ef2af1ad4, we had 4 copies of this logic, written in a couple of different ways. They're all implementing the same standard, so write it just once. files: M Tools/unicode/makeunicodedata.py diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py index 38c1f19a6567..cc2b2981ef5b 100644 --- a/Tools/unicode/makeunicodedata.py +++ b/Tools/unicode/makeunicodedata.py @@ -32,7 +32,7 @@ from functools import partial from textwrap import dedent -from typing import * +from typing import Iterator, List, Tuple SCRIPT = sys.argv[0] VERSION = "3.3" @@ -904,6 +904,19 @@ def open_data(template, version): return open(local, 'rb') +def expand_range(char_range: str) -> Iterator[int]: + ''' + Parses ranges of code points, as described in UAX #44: + https://www.unicode.org/reports/tr44/#Code_Point_Ranges + ''' + if '..' in char_range: + first, last = [int(c, 16) for c in char_range.split('..')] + else: + first = last = int(char_range, 16) + for char in range(first, last+1): + yield char + + class UcdFile: ''' A file in the standard format of the UCD. @@ -929,6 +942,12 @@ def records(self) -> Iterator[List[str]]: def __iter__(self) -> Iterator[List[str]]: return self.records() + def expanded(self) -> Iterator[Tuple[int, List[str]]]: + for record in self.records(): + char_range, rest = record[0], record[1:] + for char in expand_range(char_range): + yield char, rest + # -------------------------------------------------------------------- # the following support code is taken from the unidb utilities @@ -955,6 +974,9 @@ def __init__(self, version, cjk_check=True): # expand first-last ranges field = None for i in range(0, 0x110000): + # The file UnicodeData.txt has its own distinct way of + # expressing ranges. See: + # https://www.unicode.org/reports/tr44/#Code_Point_Ranges s = table[i] if s: if s[1][-6:] == "First>": @@ -1019,14 +1041,8 @@ def __init__(self, version, cjk_check=True): self.exclusions[char] = 1 widths = [None] * 0x110000 - for s in UcdFile(EASTASIAN_WIDTH, version): - if '..' in s[0]: - first, last = [int(c, 16) for c in s[0].split('..')] - chars = list(range(first, last+1)) - else: - chars = [int(s[0], 16)] - for char in chars: - widths[char] = s[1] + for char, (width,) in UcdFile(EASTASIAN_WIDTH, version).expanded(): + widths[char] = width for i in range(0, 0x110000): if table[i] is not None: @@ -1036,26 +1052,16 @@ def __init__(self, version, cjk_check=True): if table[i] is not None: table[i].append(set()) - for r, p in UcdFile(DERIVED_CORE_PROPERTIES, version): - if ".." in r: - first, last = [int(c, 16) for c in r.split('..')] - chars = list(range(first, last+1)) - else: - chars = [int(r, 16)] - for char in chars: - if table[char]: - # Some properties (e.g. Default_Ignorable_Code_Point) - # apply to unassigned code points; ignore them - table[char][-1].add(p) - - for s in UcdFile(LINE_BREAK, version): - if len(s) < 2 or s[1] not in MANDATORY_LINE_BREAKS: + for char, (p,) in UcdFile(DERIVED_CORE_PROPERTIES, version).expanded(): + if table[char]: + # Some properties (e.g. Default_Ignorable_Code_Point) + # apply to unassigned code points; ignore them + table[char][-1].add(p) + + for char_range, value in UcdFile(LINE_BREAK, version): + if value not in MANDATORY_LINE_BREAKS: continue - if '..' not in s[0]: - first = last = int(s[0], 16) - else: - first, last = [int(c, 16) for c in s[0].split('..')] - for char in range(first, last+1): + for char in expand_range(char_range): table[char][-1].add('Line_Break') # We only want the quickcheck properties @@ -1073,11 +1079,7 @@ def __init__(self, version, cjk_check=True): quickcheck = 'MN'.index(s[2]) + 1 # Maybe or No quickcheck_shift = qc_order.index(s[1])*2 quickcheck <<= quickcheck_shift - if '..' not in s[0]: - first = last = int(s[0], 16) - else: - first, last = [int(c, 16) for c in s[0].split('..')] - for char in range(first, last+1): + for char in expand_range(s[0]): assert not (quickchecks[char]>>quickcheck_shift)&3 quickchecks[char] |= quickcheck for i in range(0, 0x110000): From webhook-mailer at python.org Wed Aug 14 01:51:10 2019 From: webhook-mailer at python.org (Inada Naoki) Date: Wed, 14 Aug 2019 05:51:10 -0000 Subject: [Python-checkins] bpo-37337: Fix a GCC 9 warning in Objects/descrobject.c (GH-14814) Message-ID: https://github.com/python/cpython/commit/43d564c18c97421f73025ac3132a194975c76bd6 commit: 43d564c18c97421f73025ac3132a194975c76bd6 branch: master author: Zackery Spytz committer: Inada Naoki date: 2019-08-14T14:51:06+09:00 summary: bpo-37337: Fix a GCC 9 warning in Objects/descrobject.c (GH-14814) Commit b1263d5a60d3f7ab02dd28409fff59b3815a3f67 causes GCC 9.1.0 to give a warning in Objects/descrobject.c. files: M Objects/descrobject.c diff --git a/Objects/descrobject.c b/Objects/descrobject.c index edce250c7948..9e1b281c4603 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1047,7 +1047,7 @@ mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored)) to the underlying mapping */ static PyMethodDef mappingproxy_methods[] = { - {"get", (PyCFunction)mappingproxy_get, METH_FASTCALL, + {"get", (PyCFunction)(void(*)(void))mappingproxy_get, METH_FASTCALL, PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d." " d defaults to None.")}, {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS, From webhook-mailer at python.org Wed Aug 14 05:50:37 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 09:50:37 -0000 Subject: [Python-checkins] bpo-37681: no_sanitize_thread support from GCC 5.1 (GH-15096) Message-ID: https://github.com/python/cpython/commit/7e479c82218450255572e3f5fa1549dc283901ea commit: 7e479c82218450255572e3f5fa1549dc283901ea branch: master author: Hai Shi committer: Victor Stinner date: 2019-08-14T11:50:19+02:00 summary: bpo-37681: no_sanitize_thread support from GCC 5.1 (GH-15096) Fix the following warning with GCC 4.8.5: Objects/obmalloc.c: warning: ?no_sanitize_thread? attribute directive ignored files: M Objects/obmalloc.c diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 8d5c700d5c1e..6ca7cd84eda8 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -45,9 +45,9 @@ static void _PyMem_SetupDebugHooksDomain(PyMemAllocatorDomain domain); # define _Py_NO_ADDRESS_SAFETY_ANALYSIS \ __attribute__((no_address_safety_analysis)) # endif - // TSAN is supported since GCC 4.8, but __SANITIZE_THREAD__ macro + // TSAN is supported since GCC 5.1, but __SANITIZE_THREAD__ macro // is provided only since GCC 7. -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) +# if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) # define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) # endif #endif From webhook-mailer at python.org Wed Aug 14 05:52:41 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 09:52:41 -0000 Subject: [Python-checkins] bpo-37583: Add err 113 to support.get_socket_conn_refused_errs() (GH-15259) Message-ID: https://github.com/python/cpython/commit/fbb0c032e89c42ab44f5372df40fffb34a91b575 commit: fbb0c032e89c42ab44f5372df40fffb34a91b575 branch: 3.7 author: Hai Shi committer: Victor Stinner date: 2019-08-14T11:52:36+02:00 summary: bpo-37583: Add err 113 to support.get_socket_conn_refused_errs() (GH-15259) Add error number 113 EHOSTUNREACH to get_socket_conn_refused_errs() of test.support. files: M Lib/test/support/__init__.py diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index bf1f0d2120ac..d04d19985f7a 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1423,6 +1423,9 @@ def get_socket_conn_refused_errs(): # bpo-31910: socket.create_connection() fails randomly # with EADDRNOTAVAIL on Travis CI errors.append(errno.EADDRNOTAVAIL) + if hasattr(errno, 'EHOSTUNREACH'): + # bpo-37583: The destination host cannot be reached + errors.append(errno.EHOSTUNREACH) return errors From webhook-mailer at python.org Wed Aug 14 06:08:51 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 10:08:51 -0000 Subject: [Python-checkins] bpo-37681: no_sanitize_thread support from GCC 5.1 (GH-15096) Message-ID: https://github.com/python/cpython/commit/364a1d3125af6c0ff0a4bd2c8afe70fd38f30456 commit: 364a1d3125af6c0ff0a4bd2c8afe70fd38f30456 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T03:08:46-07:00 summary: bpo-37681: no_sanitize_thread support from GCC 5.1 (GH-15096) Fix the following warning with GCC 4.8.5: Objects/obmalloc.c: warning: ?no_sanitize_thread? attribute directive ignored (cherry picked from commit 7e479c82218450255572e3f5fa1549dc283901ea) Co-authored-by: Hai Shi files: M Objects/obmalloc.c diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index fc7bef619946..0501cb992008 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -45,9 +45,9 @@ static void _PyMem_SetupDebugHooksDomain(PyMemAllocatorDomain domain); # define _Py_NO_ADDRESS_SAFETY_ANALYSIS \ __attribute__((no_address_safety_analysis)) # endif - // TSAN is supported since GCC 4.8, but __SANITIZE_THREAD__ macro + // TSAN is supported since GCC 5.1, but __SANITIZE_THREAD__ macro // is provided only since GCC 7. -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) +# if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) # define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) # endif #endif From webhook-mailer at python.org Wed Aug 14 06:16:58 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 10:16:58 -0000 Subject: [Python-checkins] bpo-37681: no_sanitize_thread support from GCC 5.1 (GH-15096) Message-ID: https://github.com/python/cpython/commit/15b6d0a712c08557a605f49034f8ad392985144c commit: 15b6d0a712c08557a605f49034f8ad392985144c branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T03:16:54-07:00 summary: bpo-37681: no_sanitize_thread support from GCC 5.1 (GH-15096) Fix the following warning with GCC 4.8.5: Objects/obmalloc.c: warning: ?no_sanitize_thread? attribute directive ignored (cherry picked from commit 7e479c82218450255572e3f5fa1549dc283901ea) Co-authored-by: Hai Shi files: M Objects/obmalloc.c diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 885ad537ad95..8446efcbd440 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -44,9 +44,9 @@ static void _PyMem_SetupDebugHooksDomain(PyMemAllocatorDomain domain); # define _Py_NO_ADDRESS_SAFETY_ANALYSIS \ __attribute__((no_address_safety_analysis)) # endif - // TSAN is supported since GCC 4.8, but __SANITIZE_THREAD__ macro + // TSAN is supported since GCC 5.1, but __SANITIZE_THREAD__ macro // is provided only since GCC 7. -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) +# if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) # define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) # endif #endif From webhook-mailer at python.org Wed Aug 14 06:31:58 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 10:31:58 -0000 Subject: [Python-checkins] bpo-37738: Fix curses addch(str, color_pair) (GH-15071) Message-ID: https://github.com/python/cpython/commit/077af8c2c93dd71086e2c5e5ff1e634b6da8f214 commit: 077af8c2c93dd71086e2c5e5ff1e634b6da8f214 branch: master author: Victor Stinner committer: GitHub date: 2019-08-14T12:31:43+02:00 summary: bpo-37738: Fix curses addch(str, color_pair) (GH-15071) Fix the implementation of curses addch(str, color_pair): pass the color pair to setcchar(), instead of always passing 0 as the color pair. files: A Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst M Modules/_cursesmodule.c diff --git a/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst b/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst new file mode 100644 index 000000000000..7e70a9c2231a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst @@ -0,0 +1,2 @@ +Fix the implementation of curses ``addch(str, color_pair)``: pass the color +pair to ``setcchar()``, instead of always passing 0 as the color pair. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index dbe3c99d7d59..c66f7943b695 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -176,6 +176,18 @@ static char *screen_encoding = NULL; /* Utility Functions */ +static inline int +color_pair_to_attr(short color_number) +{ + return ((int)color_number << 8); +} + +static inline short +attr_to_color_pair(int attr) +{ + return (short)((attr & A_COLOR) >> 8); +} + /* * Check the return code from a curses function and return None * or raise an exception as appropriate. These are exported using the @@ -606,7 +618,7 @@ _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, if (type == 2) { funcname = "add_wch"; wstr[1] = L'\0'; - setcchar(&wcval, wstr, attr, 0, NULL); + setcchar(&wcval, wstr, attr, attr_to_color_pair(attr), NULL); if (coordinates_group) rtn = mvwadd_wch(self->win,y,x, &wcval); else { @@ -2621,7 +2633,7 @@ _curses_color_pair_impl(PyObject *module, short color_number) PyCursesInitialised; PyCursesInitialisedColor; - return PyLong_FromLong((long) (color_number << 8)); + return PyLong_FromLong(color_pair_to_attr(color_number)); } /*[clinic input] @@ -3644,7 +3656,7 @@ _curses_pair_number_impl(PyObject *module, int attr) PyCursesInitialised; PyCursesInitialisedColor; - return PyLong_FromLong((long) ((attr & A_COLOR) >> 8)); + return PyLong_FromLong(attr_to_color_pair(attr)); } /*[clinic input] From webhook-mailer at python.org Wed Aug 14 06:49:17 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 10:49:17 -0000 Subject: [Python-checkins] bpo-37738: Fix curses addch(str, color_pair) (GH-15071) Message-ID: https://github.com/python/cpython/commit/984226962bc35254551d92771b5c8fb074507903 commit: 984226962bc35254551d92771b5c8fb074507903 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T03:49:13-07:00 summary: bpo-37738: Fix curses addch(str, color_pair) (GH-15071) Fix the implementation of curses addch(str, color_pair): pass the color pair to setcchar(), instead of always passing 0 as the color pair. (cherry picked from commit 077af8c2c93dd71086e2c5e5ff1e634b6da8f214) Co-authored-by: Victor Stinner files: A Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst M Modules/_cursesmodule.c diff --git a/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst b/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst new file mode 100644 index 000000000000..7e70a9c2231a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst @@ -0,0 +1,2 @@ +Fix the implementation of curses ``addch(str, color_pair)``: pass the color +pair to ``setcchar()``, instead of always passing 0 as the color pair. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 8fca7fcf1c18..819e1ee41f1c 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -176,6 +176,18 @@ static char *screen_encoding = NULL; /* Utility Functions */ +static inline int +color_pair_to_attr(short color_number) +{ + return ((int)color_number << 8); +} + +static inline short +attr_to_color_pair(int attr) +{ + return (short)((attr & A_COLOR) >> 8); +} + /* * Check the return code from a curses function and return None * or raise an exception as appropriate. These are exported using the @@ -606,7 +618,7 @@ _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, if (type == 2) { funcname = "add_wch"; wstr[1] = L'\0'; - setcchar(&wcval, wstr, attr, 0, NULL); + setcchar(&wcval, wstr, attr, attr_to_color_pair(attr), NULL); if (coordinates_group) rtn = mvwadd_wch(self->win,y,x, &wcval); else { @@ -2621,7 +2633,7 @@ _curses_color_pair_impl(PyObject *module, short color_number) PyCursesInitialised; PyCursesInitialisedColor; - return PyLong_FromLong((long) (color_number << 8)); + return PyLong_FromLong(color_pair_to_attr(color_number)); } /*[clinic input] @@ -3644,7 +3656,7 @@ _curses_pair_number_impl(PyObject *module, int attr) PyCursesInitialised; PyCursesInitialisedColor; - return PyLong_FromLong((long) ((attr & A_COLOR) >> 8)); + return PyLong_FromLong(attr_to_color_pair(attr)); } /*[clinic input] From webhook-mailer at python.org Wed Aug 14 07:00:31 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 11:00:31 -0000 Subject: [Python-checkins] bpo-37738: Fix curses addch(str, color_pair) (GH-15071) (GH-15273) Message-ID: https://github.com/python/cpython/commit/7eef81ee766c8df23e522b4e46a930cc1d360ad7 commit: 7eef81ee766c8df23e522b4e46a930cc1d360ad7 branch: 3.7 author: Victor Stinner committer: GitHub date: 2019-08-14T13:00:27+02:00 summary: bpo-37738: Fix curses addch(str, color_pair) (GH-15071) (GH-15273) Fix the implementation of curses addch(str, color_pair): pass the color pair to setcchar(), instead of always passing 0 as the color pair. (cherry picked from commit 077af8c2c93dd71086e2c5e5ff1e634b6da8f214) files: A Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst M Modules/_cursesmodule.c diff --git a/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst b/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst new file mode 100644 index 000000000000..7e70a9c2231a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst @@ -0,0 +1,2 @@ +Fix the implementation of curses ``addch(str, color_pair)``: pass the color +pair to ``setcchar()``, instead of always passing 0 as the color pair. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 45decf96a352..b0be6bb30b8f 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -178,6 +178,18 @@ static char *screen_encoding = NULL; /* Utility Functions */ +static inline int +color_pair_to_attr(short color_number) +{ + return ((int)color_number << 8); +} + +static inline short +attr_to_color_pair(int attr) +{ + return (short)((attr & A_COLOR) >> 8); +} + /* * Check the return code from a curses function and return None * or raise an exception as appropriate. These are exported using the @@ -614,7 +626,7 @@ curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, if (type == 2) { funcname = "add_wch"; wstr[1] = L'\0'; - setcchar(&wcval, wstr, attr, 0, NULL); + setcchar(&wcval, wstr, attr, attr_to_color_pair(attr), NULL); if (coordinates_group) rtn = mvwadd_wch(cwself->win,y,x, &wcval); else { @@ -2204,7 +2216,7 @@ PyCurses_color_pair(PyObject *self, PyObject *args) PyCursesInitialisedColor; if (!PyArg_ParseTuple(args, "i:color_pair", &n)) return NULL; - return PyLong_FromLong((long) (n << 8)); + return PyLong_FromLong(color_pair_to_attr(n)); } static PyObject * @@ -2802,7 +2814,7 @@ PyCurses_pair_number(PyObject *self, PyObject *args) return NULL; } - return PyLong_FromLong((long) ((n & A_COLOR) >> 8)); + return PyLong_FromLong(attr_to_color_pair(n)); } static PyObject * From webhook-mailer at python.org Wed Aug 14 07:05:24 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 11:05:24 -0000 Subject: [Python-checkins] bpo-36502: Correct documentation of str.isspace() (GH-15019) Message-ID: https://github.com/python/cpython/commit/6bccbe7dfb998af862a183f2c36f0d4603af2c29 commit: 6bccbe7dfb998af862a183f2c36f0d4603af2c29 branch: master author: Greg Price committer: Victor Stinner date: 2019-08-14T13:05:19+02:00 summary: bpo-36502: Correct documentation of str.isspace() (GH-15019) The documented definition was much broader than the real one: there are tons of characters with general category "Other", and we don't (and shouldn't) treat most of them as whitespace. Rewrite the definition to agree with the comment on _PyUnicode_IsWhitespace, and with the logic in makeunicodedata.py, which is what generates that function and so ultimately governs. Add suitable breadcrumbs so that a reader who wants to pin down exactly what this definition means (what's a "bidirectional class" of "B"?) can do so. The `unicodedata` module documentation is an appropriate central place for our references to Unicode's own copious documentation, so point there. Also add to the isspace() test a thorough check that the implementation agrees with the intended definition. files: M Doc/library/stdtypes.rst M Lib/test/test_unicode.py diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 9dd557fabaae..08c5ae876c1b 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1763,9 +1763,13 @@ expression support in the :mod:`re` module). .. method:: str.isspace() Return true if there are only whitespace characters in the string and there is - at least one character, false otherwise. Whitespace characters are those - characters defined in the Unicode character database as "Other" or "Separator" - and those with bidirectional property being one of "WS", "B", or "S". + at least one character, false otherwise. + + A character is *whitespace* if in the Unicode character database + (see :mod:`unicodedata`), either its general category is ``Zs`` + ("Separator, space"), or its bidirectional class is one of ``WS``, + ``B``, or ``S``. + .. method:: str.istitle() diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index 8be16c8da926..7bd7f51b592b 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -12,6 +12,7 @@ import struct import sys import textwrap +import unicodedata import unittest import warnings from test import support, string_tests @@ -617,11 +618,21 @@ def test_isspace(self): self.checkequalnofix(True, '\u2000', 'isspace') self.checkequalnofix(True, '\u200a', 'isspace') self.checkequalnofix(False, '\u2014', 'isspace') - # apparently there are no non-BMP spaces chars in Unicode 6 + # There are no non-BMP whitespace chars as of Unicode 12. for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E', '\U0001F40D', '\U0001F46F']: self.assertFalse(ch.isspace(), '{!a} is not space.'.format(ch)) + @support.requires_resource('cpu') + def test_isspace_invariant(self): + for codepoint in range(sys.maxunicode + 1): + char = chr(codepoint) + bidirectional = unicodedata.bidirectional(char) + category = unicodedata.category(char) + self.assertEqual(char.isspace(), + (bidirectional in ('WS', 'B', 'S') + or category == 'Zs')) + def test_isalnum(self): super().test_isalnum() for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E', From webhook-mailer at python.org Wed Aug 14 08:18:55 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 12:18:55 -0000 Subject: [Python-checkins] bpo-37531: Fix regrtest timeout for subprocesses (GH-15072) Message-ID: https://github.com/python/cpython/commit/b0c8369c603633f445ccbb5ca7a8742145ff9eec commit: b0c8369c603633f445ccbb5ca7a8742145ff9eec branch: master author: Victor Stinner committer: GitHub date: 2019-08-14T14:18:51+02:00 summary: bpo-37531: Fix regrtest timeout for subprocesses (GH-15072) Co-Authored-By: Joannah Nanjekye files: A Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst M Lib/test/libregrtest/main.py M Lib/test/libregrtest/runtest.py M Lib/test/libregrtest/runtest_mp.py M Lib/test/test_regrtest.py diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 87278d0c76a2..3cfbb4017dfb 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -14,7 +14,7 @@ from test.libregrtest.runtest import ( findtests, runtest, get_abs_module, STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED, - INTERRUPTED, CHILD_ERROR, TEST_DID_NOT_RUN, + INTERRUPTED, CHILD_ERROR, TEST_DID_NOT_RUN, TIMEOUT, PROGRESS_MIN_TIME, format_test_result, is_failed) from test.libregrtest.setup import setup_tests from test.libregrtest.pgo import setup_pgo_tests @@ -115,6 +115,8 @@ def accumulate_result(self, result, rerun=False): self.run_no_tests.append(test_name) elif ok == INTERRUPTED: self.interrupted = True + elif ok == TIMEOUT: + self.bad.append(test_name) else: raise ValueError("invalid test result: %r" % ok) diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index a43b7666cd1e..e7dce180cb37 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -13,7 +13,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 +from test.libregrtest.utils import format_duration, print_warning # Test result constants. @@ -25,6 +25,7 @@ INTERRUPTED = -4 CHILD_ERROR = -5 # error in a child process TEST_DID_NOT_RUN = -6 +TIMEOUT = -7 _FORMAT_TEST_RESULT = { PASSED: '%s passed', @@ -35,6 +36,7 @@ INTERRUPTED: '%s interrupted', CHILD_ERROR: '%s crashed', TEST_DID_NOT_RUN: '%s run no tests', + TIMEOUT: '%s timed out', } # Minimum duration of a test to display its duration or to mention that @@ -75,7 +77,10 @@ def is_failed(result, ns): def format_test_result(result): fmt = _FORMAT_TEST_RESULT.get(result.result, "%s") - return fmt % result.test_name + text = fmt % result.test_name + if result.result == TIMEOUT: + text = '%s (%s)' % (text, format_duration(result.test_time)) + return text def findtestdir(path=None): @@ -179,6 +184,7 @@ def runtest(ns, test_name): FAILED test failed PASSED test passed EMPTY_TEST_SUITE test ran no subtests. + TIMEOUT test timed out. If ns.xmlpath is not None, xml_data is a list containing each generated testsuite element. diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index aa2409b4ef79..eed643291162 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -13,7 +13,7 @@ from test.libregrtest.runtest import ( runtest, INTERRUPTED, CHILD_ERROR, PROGRESS_MIN_TIME, - format_test_result, TestResult, is_failed) + format_test_result, TestResult, is_failed, TIMEOUT) from test.libregrtest.setup import setup_tests from test.libregrtest.utils import format_duration @@ -103,11 +103,12 @@ class ExitThread(Exception): class MultiprocessThread(threading.Thread): - def __init__(self, pending, output, ns): + def __init__(self, pending, output, ns, timeout): super().__init__() self.pending = pending self.output = output self.ns = ns + self.timeout = timeout self.current_test_name = None self.start_time = None self._popen = None @@ -126,6 +127,12 @@ def __repr__(self): return '<%s>' % ' '.join(info) def kill(self): + """ + Kill the current process (if any). + + This method can be called by the thread running the process, + or by another thread. + """ self._killed = True popen = self._popen @@ -136,6 +143,13 @@ def kill(self): # does not hang popen.stdout.close() popen.stderr.close() + popen.wait() + + def mp_result_error(self, test_name, error_type, stdout='', stderr='', + err_msg=None): + test_time = time.monotonic() - self.start_time + result = TestResult(test_name, error_type, test_time, None) + return MultiprocessResult(result, stdout, stderr, err_msg) def _runtest(self, test_name): try: @@ -154,7 +168,19 @@ def _runtest(self, test_name): raise ExitThread try: + stdout, stderr = popen.communicate(timeout=self.timeout) + except subprocess.TimeoutExpired: + if self._killed: + # kill() has been called: communicate() fails + # on reading closed stdout/stderr + raise ExitThread + + popen.kill() stdout, stderr = popen.communicate() + self.kill() + + return self.mp_result_error(test_name, TIMEOUT, + stdout, stderr) except OSError: if self._killed: # kill() has been called: communicate() fails @@ -163,7 +189,6 @@ def _runtest(self, test_name): raise except: self.kill() - popen.wait() raise retcode = popen.wait() @@ -191,8 +216,7 @@ def _runtest(self, test_name): 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) + return self.mp_result_error(test_name, CHILD_ERROR, stdout, stderr, err_msg) return MultiprocessResult(result, stdout, stderr, err_msg) @@ -236,13 +260,16 @@ def __init__(self, regrtest): 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 + self.worker_timeout = self.ns.timeout * 1.5 + self.main_timeout = self.ns.timeout * 2.0 else: - self.test_timeout = None + self.worker_timeout = None + self.main_timeout = None self.workers = None def start_workers(self): - self.workers = [MultiprocessThread(self.pending, self.output, self.ns) + self.workers = [MultiprocessThread(self.pending, self.output, + self.ns, self.worker_timeout) for _ in range(self.ns.use_mp)] print("Run tests in parallel using %s child processes" % len(self.workers)) @@ -274,8 +301,8 @@ def _get_result(self): return None while True: - if self.test_timeout is not None: - faulthandler.dump_traceback_later(self.test_timeout, exit=True) + if self.main_timeout is not None: + faulthandler.dump_traceback_later(self.main_timeout, exit=True) # wait for a thread timeout = max(PROGRESS_UPDATE, PROGRESS_MIN_TIME) @@ -343,7 +370,7 @@ def run_tests(self): print() self.regrtest.interrupted = True finally: - if self.test_timeout is not None: + if self.main_timeout is not None: faulthandler.cancel_dump_traceback_later() # a test failed (and --failfast is set) or all tests completed diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index fdab8c8ef5d1..931f125eb8f9 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -1154,6 +1154,33 @@ def test_garbage(self): env_changed=[testname], fail_env_changed=True) + def test_multiprocessing_timeout(self): + code = textwrap.dedent(r""" + import time + import unittest + try: + import faulthandler + except ImportError: + faulthandler = None + + class Tests(unittest.TestCase): + # test hangs and so should be stopped by the timeout + def test_sleep(self): + # we want to test regrtest multiprocessing timeout, + # not faulthandler timeout + if faulthandler is not None: + faulthandler.cancel_dump_traceback_later() + + time.sleep(60 * 5) + """) + testname = self.create_test(code=code) + + output = self.run_tests("-j2", "--timeout=1.0", testname, exitcode=2) + self.check_executed_tests(output, [testname], + failed=testname) + self.assertRegex(output, + re.compile('%s timed out' % testname, re.MULTILINE)) + def test_unraisable_exc(self): # --fail-env-changed must catch unraisable exception code = textwrap.dedent(r""" diff --git a/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst b/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst new file mode 100644 index 000000000000..aaf1052bd3c1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst @@ -0,0 +1,2 @@ +"python3 -m test -jN --timeout=TIMEOUT" now kills a worker process if it runs +longer than *TIMEOUT* seconds. From webhook-mailer at python.org Wed Aug 14 09:55:58 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 13:55:58 -0000 Subject: [Python-checkins] bpo-37256: Wording in Request class docs (GH-14792) Message-ID: https://github.com/python/cpython/commit/3e1f135b26cf5fb3583d7e75d39b7b7a9edb472c commit: 3e1f135b26cf5fb3583d7e75d39b7b7a9edb472c branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T06:55:53-07:00 summary: bpo-37256: Wording in Request class docs (GH-14792) * bpo-37256: Wording in Request class docs * ?? Added by blurb_it. * Update Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst Co-Authored-By: Kyle Stanley (cherry picked from commit 38c7199beb30ae9a5005c0f0d9df9fae0da3680a) Co-authored-by: Ngalim Siregar files: A Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst M Doc/library/urllib.request.rst diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index 1bc81e05b38b..5d8c0ec4303c 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -220,7 +220,7 @@ The following classes are provided: is not None, ``Content-Type: application/x-www-form-urlencoded`` will be added as a default. - The final two arguments are only of interest for correct handling + The next two arguments are only of interest for correct handling of third-party HTTP cookies: *origin_req_host* should be the request-host of the origin diff --git a/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst b/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst new file mode 100644 index 000000000000..480d7c87ebc4 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst @@ -0,0 +1 @@ +Fix wording of arguments for :class:`Request` in :mod:`urllib.request` From webhook-mailer at python.org Wed Aug 14 10:10:40 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 14:10:40 -0000 Subject: [Python-checkins] bpo-36030: Improve performance of some tuple operations (GH-12052) Message-ID: https://github.com/python/cpython/commit/4fa10dde40356d7c71e5524233bafc221d9e2deb commit: 4fa10dde40356d7c71e5524233bafc221d9e2deb branch: master author: Sergey Fedoseev committer: Victor Stinner date: 2019-08-14T16:10:33+02:00 summary: bpo-36030: Improve performance of some tuple operations (GH-12052) files: M Objects/tupleobject.c diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index aeaf845d74cf..79a5d55749be 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -59,6 +59,15 @@ show_track(void) } #endif +static inline void +tuple_gc_track(PyTupleObject *op) +{ +#ifdef SHOW_TRACK_COUNT + count_tracked++; +#endif + _PyObject_GC_TRACK(op); +} + /* Print summary info about the state of the optimized allocator */ void _PyTuple_DebugMallocStats(FILE *out) @@ -76,25 +85,25 @@ _PyTuple_DebugMallocStats(FILE *out) #endif } -PyObject * -PyTuple_New(Py_ssize_t size) +/* Allocate an uninitialized tuple object. Before making it public following + steps must be done: + - initialize its items + - call tuple_gc_track() on it + Because the empty tuple is always reused and it's already tracked by GC, + this function must not be called with size == 0 (unless from PyTuple_New() + which wraps this function). +*/ +static PyTupleObject * +tuple_alloc(Py_ssize_t size) { PyTupleObject *op; - Py_ssize_t i; if (size < 0) { PyErr_BadInternalCall(); return NULL; } #if PyTuple_MAXSAVESIZE > 0 - if (size == 0 && free_list[0]) { - op = free_list[0]; - Py_INCREF(op); -#ifdef COUNT_ALLOCS - _Py_tuple_zero_allocs++; -#endif - return (PyObject *) op; - } if (size < PyTuple_MAXSAVESIZE && (op = free_list[size]) != NULL) { + assert(size != 0); free_list[size] = (PyTupleObject *) op->ob_item[0]; numfree[size]--; #ifdef COUNT_ALLOCS @@ -113,14 +122,33 @@ PyTuple_New(Py_ssize_t size) /* Check for overflow */ if ((size_t)size > ((size_t)PY_SSIZE_T_MAX - sizeof(PyTupleObject) - sizeof(PyObject *)) / sizeof(PyObject *)) { - return PyErr_NoMemory(); + return (PyTupleObject *)PyErr_NoMemory(); } op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size); if (op == NULL) return NULL; } - for (i=0; i < size; i++) + return op; +} + +PyObject * +PyTuple_New(Py_ssize_t size) +{ + PyTupleObject *op; +#if PyTuple_MAXSAVESIZE > 0 + if (size == 0 && free_list[0]) { + op = free_list[0]; + Py_INCREF(op); +#ifdef COUNT_ALLOCS + _Py_tuple_zero_allocs++; +#endif + return (PyObject *) op; + } +#endif + op = tuple_alloc(size); + for (Py_ssize_t i = 0; i < size; i++) { op->ob_item[i] = NULL; + } #if PyTuple_MAXSAVESIZE > 0 if (size == 0) { free_list[0] = op; @@ -128,10 +156,7 @@ PyTuple_New(Py_ssize_t size) Py_INCREF(op); /* extra INCREF so that this is never freed */ } #endif -#ifdef SHOW_TRACK_COUNT - count_tracked++; -#endif - _PyObject_GC_TRACK(op); + tuple_gc_track(op); return (PyObject *) op; } @@ -211,24 +236,28 @@ PyTuple_Pack(Py_ssize_t n, ...) { Py_ssize_t i; PyObject *o; - PyObject *result; PyObject **items; va_list vargs; + if (n == 0) { + return PyTuple_New(0); + } + va_start(vargs, n); - result = PyTuple_New(n); + PyTupleObject *result = tuple_alloc(n); if (result == NULL) { va_end(vargs); return NULL; } - items = ((PyTupleObject *)result)->ob_item; + items = result->ob_item; for (i = 0; i < n; i++) { o = va_arg(vargs, PyObject *); Py_INCREF(o); items[i] = o; } va_end(vargs); - return result; + tuple_gc_track(result); + return (PyObject *)result; } @@ -421,7 +450,11 @@ tupleitem(PyTupleObject *a, Py_ssize_t i) PyObject * _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n) { - PyTupleObject *tuple = (PyTupleObject *)PyTuple_New(n); + if (n == 0) { + return PyTuple_New(0); + } + + PyTupleObject *tuple = tuple_alloc(n); if (tuple == NULL) { return NULL; } @@ -431,6 +464,7 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n) Py_INCREF(item); dst[i] = item; } + tuple_gc_track(tuple); return (PyObject *)tuple; } @@ -486,7 +520,11 @@ tupleconcat(PyTupleObject *a, PyObject *bb) if (Py_SIZE(a) > PY_SSIZE_T_MAX - Py_SIZE(b)) return PyErr_NoMemory(); size = Py_SIZE(a) + Py_SIZE(b); - np = (PyTupleObject *) PyTuple_New(size); + if (size == 0) { + return PyTuple_New(0); + } + + np = tuple_alloc(size); if (np == NULL) { return NULL; } @@ -504,6 +542,7 @@ tupleconcat(PyTupleObject *a, PyObject *bb) Py_INCREF(v); dest[i] = v; } + tuple_gc_track(np); return (PyObject *)np; #undef b } @@ -515,8 +554,6 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n) Py_ssize_t size; PyTupleObject *np; PyObject **p, **items; - if (n < 0) - n = 0; if (Py_SIZE(a) == 0 || n == 1) { if (PyTuple_CheckExact(a)) { /* Since tuples are immutable, we can return a shared @@ -524,13 +561,14 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n) Py_INCREF(a); return (PyObject *)a; } - if (Py_SIZE(a) == 0) - return PyTuple_New(0); + } + if (Py_SIZE(a) == 0 || n <= 0) { + return PyTuple_New(0); } if (n > PY_SSIZE_T_MAX / Py_SIZE(a)) return PyErr_NoMemory(); size = Py_SIZE(a) * n; - np = (PyTupleObject *) PyTuple_New(size); + np = tuple_alloc(size); if (np == NULL) return NULL; p = np->ob_item; @@ -542,6 +580,7 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n) p++; } } + tuple_gc_track(np); return (PyObject *) np; } @@ -754,7 +793,6 @@ tuplesubscript(PyTupleObject* self, PyObject* item) else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength, i; size_t cur; - PyObject* result; PyObject* it; PyObject **src, **dest; @@ -774,11 +812,11 @@ tuplesubscript(PyTupleObject* self, PyObject* item) return (PyObject *)self; } else { - result = PyTuple_New(slicelength); + PyTupleObject* result = tuple_alloc(slicelength); if (!result) return NULL; src = self->ob_item; - dest = ((PyTupleObject *)result)->ob_item; + dest = result->ob_item; for (cur = start, i = 0; i < slicelength; cur += step, i++) { it = src[cur]; @@ -786,7 +824,8 @@ tuplesubscript(PyTupleObject* self, PyObject* item) dest[i] = it; } - return result; + tuple_gc_track(result); + return (PyObject *)result; } } else { From webhook-mailer at python.org Wed Aug 14 10:31:00 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 14:31:00 -0000 Subject: [Python-checkins] [3.7] bpo-37531: Fix regrtest timeout for subprocesses (GH-15072) (GH-15280) Message-ID: https://github.com/python/cpython/commit/93bee6a8d878ff952e245614c567c7c6bb7a0398 commit: 93bee6a8d878ff952e245614c567c7c6bb7a0398 branch: 3.7 author: Victor Stinner committer: GitHub date: 2019-08-14T16:30:54+02:00 summary: [3.7] bpo-37531: Fix regrtest timeout for subprocesses (GH-15072) (GH-15280) Co-Authored-By: Joannah Nanjekye (cherry picked from commit b0c8369c603633f445ccbb5ca7a8742145ff9eec) Backport also minor win_utils.py fixes from master. files: A Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst M Lib/test/libregrtest/main.py M Lib/test/libregrtest/runtest.py M Lib/test/libregrtest/runtest_mp.py M Lib/test/libregrtest/win_utils.py M Lib/test/test_regrtest.py diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 1dfbe47a2fab..ef1ecef25350 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -14,7 +14,7 @@ from test.libregrtest.runtest import ( findtests, runtest, get_abs_module, STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED, - INTERRUPTED, CHILD_ERROR, TEST_DID_NOT_RUN, + INTERRUPTED, CHILD_ERROR, TEST_DID_NOT_RUN, TIMEOUT, PROGRESS_MIN_TIME, format_test_result, is_failed) from test.libregrtest.setup import setup_tests from test.libregrtest.utils import removepy, count, format_duration, printlist @@ -114,6 +114,8 @@ def accumulate_result(self, result, rerun=False): self.run_no_tests.append(test_name) elif ok == INTERRUPTED: self.interrupted = True + elif ok == TIMEOUT: + self.bad.append(test_name) else: raise ValueError("invalid test result: %r" % ok) diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index a43b7666cd1e..e7dce180cb37 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -13,7 +13,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 +from test.libregrtest.utils import format_duration, print_warning # Test result constants. @@ -25,6 +25,7 @@ INTERRUPTED = -4 CHILD_ERROR = -5 # error in a child process TEST_DID_NOT_RUN = -6 +TIMEOUT = -7 _FORMAT_TEST_RESULT = { PASSED: '%s passed', @@ -35,6 +36,7 @@ INTERRUPTED: '%s interrupted', CHILD_ERROR: '%s crashed', TEST_DID_NOT_RUN: '%s run no tests', + TIMEOUT: '%s timed out', } # Minimum duration of a test to display its duration or to mention that @@ -75,7 +77,10 @@ def is_failed(result, ns): def format_test_result(result): fmt = _FORMAT_TEST_RESULT.get(result.result, "%s") - return fmt % result.test_name + text = fmt % result.test_name + if result.result == TIMEOUT: + text = '%s (%s)' % (text, format_duration(result.test_time)) + return text def findtestdir(path=None): @@ -179,6 +184,7 @@ def runtest(ns, test_name): FAILED test failed PASSED test passed EMPTY_TEST_SUITE test ran no subtests. + TIMEOUT test timed out. If ns.xmlpath is not None, xml_data is a list containing each generated testsuite element. diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index aa2409b4ef79..eed643291162 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -13,7 +13,7 @@ from test.libregrtest.runtest import ( runtest, INTERRUPTED, CHILD_ERROR, PROGRESS_MIN_TIME, - format_test_result, TestResult, is_failed) + format_test_result, TestResult, is_failed, TIMEOUT) from test.libregrtest.setup import setup_tests from test.libregrtest.utils import format_duration @@ -103,11 +103,12 @@ class ExitThread(Exception): class MultiprocessThread(threading.Thread): - def __init__(self, pending, output, ns): + def __init__(self, pending, output, ns, timeout): super().__init__() self.pending = pending self.output = output self.ns = ns + self.timeout = timeout self.current_test_name = None self.start_time = None self._popen = None @@ -126,6 +127,12 @@ def __repr__(self): return '<%s>' % ' '.join(info) def kill(self): + """ + Kill the current process (if any). + + This method can be called by the thread running the process, + or by another thread. + """ self._killed = True popen = self._popen @@ -136,6 +143,13 @@ def kill(self): # does not hang popen.stdout.close() popen.stderr.close() + popen.wait() + + def mp_result_error(self, test_name, error_type, stdout='', stderr='', + err_msg=None): + test_time = time.monotonic() - self.start_time + result = TestResult(test_name, error_type, test_time, None) + return MultiprocessResult(result, stdout, stderr, err_msg) def _runtest(self, test_name): try: @@ -154,7 +168,19 @@ def _runtest(self, test_name): raise ExitThread try: + stdout, stderr = popen.communicate(timeout=self.timeout) + except subprocess.TimeoutExpired: + if self._killed: + # kill() has been called: communicate() fails + # on reading closed stdout/stderr + raise ExitThread + + popen.kill() stdout, stderr = popen.communicate() + self.kill() + + return self.mp_result_error(test_name, TIMEOUT, + stdout, stderr) except OSError: if self._killed: # kill() has been called: communicate() fails @@ -163,7 +189,6 @@ def _runtest(self, test_name): raise except: self.kill() - popen.wait() raise retcode = popen.wait() @@ -191,8 +216,7 @@ def _runtest(self, test_name): 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) + return self.mp_result_error(test_name, CHILD_ERROR, stdout, stderr, err_msg) return MultiprocessResult(result, stdout, stderr, err_msg) @@ -236,13 +260,16 @@ def __init__(self, regrtest): 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 + self.worker_timeout = self.ns.timeout * 1.5 + self.main_timeout = self.ns.timeout * 2.0 else: - self.test_timeout = None + self.worker_timeout = None + self.main_timeout = None self.workers = None def start_workers(self): - self.workers = [MultiprocessThread(self.pending, self.output, self.ns) + self.workers = [MultiprocessThread(self.pending, self.output, + self.ns, self.worker_timeout) for _ in range(self.ns.use_mp)] print("Run tests in parallel using %s child processes" % len(self.workers)) @@ -274,8 +301,8 @@ def _get_result(self): return None while True: - if self.test_timeout is not None: - faulthandler.dump_traceback_later(self.test_timeout, exit=True) + if self.main_timeout is not None: + faulthandler.dump_traceback_later(self.main_timeout, exit=True) # wait for a thread timeout = max(PROGRESS_UPDATE, PROGRESS_MIN_TIME) @@ -343,7 +370,7 @@ def run_tests(self): print() self.regrtest.interrupted = True finally: - if self.test_timeout is not None: + if self.main_timeout is not None: faulthandler.cancel_dump_traceback_later() # a test failed (and --failfast is set) or all tests completed diff --git a/Lib/test/libregrtest/win_utils.py b/Lib/test/libregrtest/win_utils.py index adfe278ba39b..ec2d6c663e83 100644 --- a/Lib/test/libregrtest/win_utils.py +++ b/Lib/test/libregrtest/win_utils.py @@ -18,13 +18,14 @@ class WindowsLoadTracker(): """ This class asynchronously interacts with the `typeperf` command to read - the system load on Windows. Mulitprocessing and threads can't be used + the system load on Windows. Multiprocessing and threads can't be used here because they interfere with the test suite's cases for those modules. """ def __init__(self): self.load = 0.0 + self.p = None self.start() def start(self): diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 6b0b53142c04..7336adc4f1b8 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -1121,6 +1121,33 @@ def test_garbage(self): env_changed=[testname], fail_env_changed=True) + def test_multiprocessing_timeout(self): + code = textwrap.dedent(r""" + import time + import unittest + try: + import faulthandler + except ImportError: + faulthandler = None + + class Tests(unittest.TestCase): + # test hangs and so should be stopped by the timeout + def test_sleep(self): + # we want to test regrtest multiprocessing timeout, + # not faulthandler timeout + if faulthandler is not None: + faulthandler.cancel_dump_traceback_later() + + time.sleep(60 * 5) + """) + testname = self.create_test(code=code) + + output = self.run_tests("-j2", "--timeout=1.0", testname, exitcode=2) + self.check_executed_tests(output, [testname], + failed=testname) + self.assertRegex(output, + re.compile('%s timed out' % testname, re.MULTILINE)) + def test_cleanup(self): dirname = os.path.join(self.tmptestdir, "test_python_123") os.mkdir(dirname) diff --git a/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst b/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst new file mode 100644 index 000000000000..aaf1052bd3c1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst @@ -0,0 +1,2 @@ +"python3 -m test -jN --timeout=TIMEOUT" now kills a worker process if it runs +longer than *TIMEOUT* seconds. From webhook-mailer at python.org Wed Aug 14 10:31:36 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 14:31:36 -0000 Subject: [Python-checkins] [3.8] bpo-37531: Fix regrtest timeout for subprocesses (GH-15072) (GH-15279) Message-ID: https://github.com/python/cpython/commit/d85c5670ff1611202a25c9e0967148e72c114de9 commit: d85c5670ff1611202a25c9e0967148e72c114de9 branch: 3.8 author: Victor Stinner committer: GitHub date: 2019-08-14T16:31:32+02:00 summary: [3.8] bpo-37531: Fix regrtest timeout for subprocesses (GH-15072) (GH-15279) * bpo-37531: Fix regrtest timeout for subprocesses (GH-15072) Co-Authored-By: Joannah Nanjekye (cherry picked from commit b0c8369c603633f445ccbb5ca7a8742145ff9eec) * bpo-36511: Fix failures in Windows ARM32 buildbot (GH-15181) (cherry picked from commit ed70a344b5fbddea85726ebc1964ee0cfdef9c40) Backport also minor fixes from master (fix typo, remove importlib import). files: A Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst M Lib/test/libregrtest/__init__.py M Lib/test/libregrtest/main.py M Lib/test/libregrtest/runtest.py M Lib/test/libregrtest/runtest_mp.py M Lib/test/libregrtest/win_utils.py M Lib/test/test_regrtest.py diff --git a/Lib/test/libregrtest/__init__.py b/Lib/test/libregrtest/__init__.py index 3427b51b60af..5e8dba5dbde7 100644 --- a/Lib/test/libregrtest/__init__.py +++ b/Lib/test/libregrtest/__init__.py @@ -1,5 +1,2 @@ -# We import importlib *ASAP* in order to test #15386 -import importlib - from test.libregrtest.cmdline import _parse_args, RESOURCE_NAMES, ALL_RESOURCES from test.libregrtest.main import main diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 87278d0c76a2..3cfbb4017dfb 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -14,7 +14,7 @@ from test.libregrtest.runtest import ( findtests, runtest, get_abs_module, STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED, - INTERRUPTED, CHILD_ERROR, TEST_DID_NOT_RUN, + INTERRUPTED, CHILD_ERROR, TEST_DID_NOT_RUN, TIMEOUT, PROGRESS_MIN_TIME, format_test_result, is_failed) from test.libregrtest.setup import setup_tests from test.libregrtest.pgo import setup_pgo_tests @@ -115,6 +115,8 @@ def accumulate_result(self, result, rerun=False): self.run_no_tests.append(test_name) elif ok == INTERRUPTED: self.interrupted = True + elif ok == TIMEOUT: + self.bad.append(test_name) else: raise ValueError("invalid test result: %r" % ok) diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index a43b7666cd1e..e7dce180cb37 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -13,7 +13,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 +from test.libregrtest.utils import format_duration, print_warning # Test result constants. @@ -25,6 +25,7 @@ INTERRUPTED = -4 CHILD_ERROR = -5 # error in a child process TEST_DID_NOT_RUN = -6 +TIMEOUT = -7 _FORMAT_TEST_RESULT = { PASSED: '%s passed', @@ -35,6 +36,7 @@ INTERRUPTED: '%s interrupted', CHILD_ERROR: '%s crashed', TEST_DID_NOT_RUN: '%s run no tests', + TIMEOUT: '%s timed out', } # Minimum duration of a test to display its duration or to mention that @@ -75,7 +77,10 @@ def is_failed(result, ns): def format_test_result(result): fmt = _FORMAT_TEST_RESULT.get(result.result, "%s") - return fmt % result.test_name + text = fmt % result.test_name + if result.result == TIMEOUT: + text = '%s (%s)' % (text, format_duration(result.test_time)) + return text def findtestdir(path=None): @@ -179,6 +184,7 @@ def runtest(ns, test_name): FAILED test failed PASSED test passed EMPTY_TEST_SUITE test ran no subtests. + TIMEOUT test timed out. If ns.xmlpath is not None, xml_data is a list containing each generated testsuite element. diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index aa2409b4ef79..eed643291162 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -13,7 +13,7 @@ from test.libregrtest.runtest import ( runtest, INTERRUPTED, CHILD_ERROR, PROGRESS_MIN_TIME, - format_test_result, TestResult, is_failed) + format_test_result, TestResult, is_failed, TIMEOUT) from test.libregrtest.setup import setup_tests from test.libregrtest.utils import format_duration @@ -103,11 +103,12 @@ class ExitThread(Exception): class MultiprocessThread(threading.Thread): - def __init__(self, pending, output, ns): + def __init__(self, pending, output, ns, timeout): super().__init__() self.pending = pending self.output = output self.ns = ns + self.timeout = timeout self.current_test_name = None self.start_time = None self._popen = None @@ -126,6 +127,12 @@ def __repr__(self): return '<%s>' % ' '.join(info) def kill(self): + """ + Kill the current process (if any). + + This method can be called by the thread running the process, + or by another thread. + """ self._killed = True popen = self._popen @@ -136,6 +143,13 @@ def kill(self): # does not hang popen.stdout.close() popen.stderr.close() + popen.wait() + + def mp_result_error(self, test_name, error_type, stdout='', stderr='', + err_msg=None): + test_time = time.monotonic() - self.start_time + result = TestResult(test_name, error_type, test_time, None) + return MultiprocessResult(result, stdout, stderr, err_msg) def _runtest(self, test_name): try: @@ -154,7 +168,19 @@ def _runtest(self, test_name): raise ExitThread try: + stdout, stderr = popen.communicate(timeout=self.timeout) + except subprocess.TimeoutExpired: + if self._killed: + # kill() has been called: communicate() fails + # on reading closed stdout/stderr + raise ExitThread + + popen.kill() stdout, stderr = popen.communicate() + self.kill() + + return self.mp_result_error(test_name, TIMEOUT, + stdout, stderr) except OSError: if self._killed: # kill() has been called: communicate() fails @@ -163,7 +189,6 @@ def _runtest(self, test_name): raise except: self.kill() - popen.wait() raise retcode = popen.wait() @@ -191,8 +216,7 @@ def _runtest(self, test_name): 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) + return self.mp_result_error(test_name, CHILD_ERROR, stdout, stderr, err_msg) return MultiprocessResult(result, stdout, stderr, err_msg) @@ -236,13 +260,16 @@ def __init__(self, regrtest): 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 + self.worker_timeout = self.ns.timeout * 1.5 + self.main_timeout = self.ns.timeout * 2.0 else: - self.test_timeout = None + self.worker_timeout = None + self.main_timeout = None self.workers = None def start_workers(self): - self.workers = [MultiprocessThread(self.pending, self.output, self.ns) + self.workers = [MultiprocessThread(self.pending, self.output, + self.ns, self.worker_timeout) for _ in range(self.ns.use_mp)] print("Run tests in parallel using %s child processes" % len(self.workers)) @@ -274,8 +301,8 @@ def _get_result(self): return None while True: - if self.test_timeout is not None: - faulthandler.dump_traceback_later(self.test_timeout, exit=True) + if self.main_timeout is not None: + faulthandler.dump_traceback_later(self.main_timeout, exit=True) # wait for a thread timeout = max(PROGRESS_UPDATE, PROGRESS_MIN_TIME) @@ -343,7 +370,7 @@ def run_tests(self): print() self.regrtest.interrupted = True finally: - if self.test_timeout is not None: + if self.main_timeout is not None: faulthandler.cancel_dump_traceback_later() # a test failed (and --failfast is set) or all tests completed diff --git a/Lib/test/libregrtest/win_utils.py b/Lib/test/libregrtest/win_utils.py index adfe278ba39b..ec2d6c663e83 100644 --- a/Lib/test/libregrtest/win_utils.py +++ b/Lib/test/libregrtest/win_utils.py @@ -18,13 +18,14 @@ class WindowsLoadTracker(): """ This class asynchronously interacts with the `typeperf` command to read - the system load on Windows. Mulitprocessing and threads can't be used + the system load on Windows. Multiprocessing and threads can't be used here because they interfere with the test suite's cases for those modules. """ def __init__(self): self.load = 0.0 + self.p = None self.start() def start(self): diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index b569100c6777..0f44c7206975 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -1150,6 +1150,33 @@ def test_garbage(self): env_changed=[testname], fail_env_changed=True) + def test_multiprocessing_timeout(self): + code = textwrap.dedent(r""" + import time + import unittest + try: + import faulthandler + except ImportError: + faulthandler = None + + class Tests(unittest.TestCase): + # test hangs and so should be stopped by the timeout + def test_sleep(self): + # we want to test regrtest multiprocessing timeout, + # not faulthandler timeout + if faulthandler is not None: + faulthandler.cancel_dump_traceback_later() + + time.sleep(60 * 5) + """) + testname = self.create_test(code=code) + + output = self.run_tests("-j2", "--timeout=1.0", testname, exitcode=2) + self.check_executed_tests(output, [testname], + failed=testname) + self.assertRegex(output, + re.compile('%s timed out' % testname, re.MULTILINE)) + def test_cleanup(self): dirname = os.path.join(self.tmptestdir, "test_python_123") os.mkdir(dirname) diff --git a/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst b/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst new file mode 100644 index 000000000000..aaf1052bd3c1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst @@ -0,0 +1,2 @@ +"python3 -m test -jN --timeout=TIMEOUT" now kills a worker process if it runs +longer than *TIMEOUT* seconds. From webhook-mailer at python.org Wed Aug 14 13:06:16 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Wed, 14 Aug 2019 17:06:16 -0000 Subject: [Python-checkins] bpo-37849: IDLE: fix completion window positioning above line (GH-15267) Message-ID: https://github.com/python/cpython/commit/71662dc2f12a7e77e5e1dfe64ec87c1b459c3f59 commit: 71662dc2f12a7e77e5e1dfe64ec87c1b459c3f59 branch: master author: Tal Einat committer: Terry Jan Reedy date: 2019-08-14T13:06:06-04:00 summary: bpo-37849: IDLE: fix completion window positioning above line (GH-15267) files: A Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/autocomplete_w.py diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 0fff7003b9d6..45918cf36b41 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,11 @@ Released on 2019-10-20? ====================================== +bpo-37849: Fix completions list appearing too high or low when shown +above the current line. + +bpo-36419: Refactor autocompete and improve testing. + bpo-37748: Reorder the Run menu. Put the most common choice, Run Module, at the top. diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index c69ab4a36836..5035e067392e 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -52,10 +52,12 @@ def __init__(self, widget): # (for example, he clicked the list) self.userwantswindow = None # event ids - self.hideid = self.keypressid = self.listupdateid = self.winconfigid \ - = self.keyreleaseid = self.doubleclickid = None + self.hideid = self.keypressid = self.listupdateid = \ + self.winconfigid = self.keyreleaseid = self.doubleclickid = None # Flag set if last keypress was a tab self.lastkey_was_tab = False + # Flag set to avoid recursive callback invocations. + self.is_configuring = False def _change_start(self, newstart): min_len = min(len(self.start), len(newstart)) @@ -223,12 +225,18 @@ def show_window(self, comp_lists, index, complete, mode, userWantsWin): self.widget.event_add(KEYRELEASE_VIRTUAL_EVENT_NAME,KEYRELEASE_SEQUENCE) self.listupdateid = listbox.bind(LISTUPDATE_SEQUENCE, self.listselect_event) + self.is_configuring = False self.winconfigid = acw.bind(WINCONFIG_SEQUENCE, self.winconfig_event) self.doubleclickid = listbox.bind(DOUBLECLICK_SEQUENCE, self.doubleclick_event) return None def winconfig_event(self, event): + if self.is_configuring: + # Avoid running on recursive callback invocations. + return + + self.is_configuring = True if not self.is_active(): return # Position the completion list window @@ -236,6 +244,7 @@ def winconfig_event(self, event): text.see(self.startindex) x, y, cx, cy = text.bbox(self.startindex) acw = self.autocompletewindow + acw.update() acw_width, acw_height = acw.winfo_width(), acw.winfo_height() text_width, text_height = text.winfo_width(), text.winfo_height() new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width)) @@ -256,6 +265,8 @@ def winconfig_event(self, event): acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) self.winconfigid = None + self.is_configuring = False + def _hide_event_check(self): if not self.autocompletewindow: return diff --git a/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst b/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst new file mode 100644 index 000000000000..9f700d9031f1 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst @@ -0,0 +1,2 @@ +Fixed completions list appearing too high or low when shown above +the current line. From webhook-mailer at python.org Wed Aug 14 13:24:08 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 17:24:08 -0000 Subject: [Python-checkins] bpo-37849: IDLE: fix completion window positioning above line (GH-15267) Message-ID: https://github.com/python/cpython/commit/557802dc17498557e481f2ad3d4a83ece469e489 commit: 557802dc17498557e481f2ad3d4a83ece469e489 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T10:24:04-07:00 summary: bpo-37849: IDLE: fix completion window positioning above line (GH-15267) (cherry picked from commit 71662dc2f12a7e77e5e1dfe64ec87c1b459c3f59) Co-authored-by: Tal Einat files: A Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/autocomplete_w.py diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 0fff7003b9d6..45918cf36b41 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,11 @@ Released on 2019-10-20? ====================================== +bpo-37849: Fix completions list appearing too high or low when shown +above the current line. + +bpo-36419: Refactor autocompete and improve testing. + bpo-37748: Reorder the Run menu. Put the most common choice, Run Module, at the top. diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index c69ab4a36836..5035e067392e 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -52,10 +52,12 @@ def __init__(self, widget): # (for example, he clicked the list) self.userwantswindow = None # event ids - self.hideid = self.keypressid = self.listupdateid = self.winconfigid \ - = self.keyreleaseid = self.doubleclickid = None + self.hideid = self.keypressid = self.listupdateid = \ + self.winconfigid = self.keyreleaseid = self.doubleclickid = None # Flag set if last keypress was a tab self.lastkey_was_tab = False + # Flag set to avoid recursive callback invocations. + self.is_configuring = False def _change_start(self, newstart): min_len = min(len(self.start), len(newstart)) @@ -223,12 +225,18 @@ def show_window(self, comp_lists, index, complete, mode, userWantsWin): self.widget.event_add(KEYRELEASE_VIRTUAL_EVENT_NAME,KEYRELEASE_SEQUENCE) self.listupdateid = listbox.bind(LISTUPDATE_SEQUENCE, self.listselect_event) + self.is_configuring = False self.winconfigid = acw.bind(WINCONFIG_SEQUENCE, self.winconfig_event) self.doubleclickid = listbox.bind(DOUBLECLICK_SEQUENCE, self.doubleclick_event) return None def winconfig_event(self, event): + if self.is_configuring: + # Avoid running on recursive callback invocations. + return + + self.is_configuring = True if not self.is_active(): return # Position the completion list window @@ -236,6 +244,7 @@ def winconfig_event(self, event): text.see(self.startindex) x, y, cx, cy = text.bbox(self.startindex) acw = self.autocompletewindow + acw.update() acw_width, acw_height = acw.winfo_width(), acw.winfo_height() text_width, text_height = text.winfo_width(), text.winfo_height() new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width)) @@ -256,6 +265,8 @@ def winconfig_event(self, event): acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) self.winconfigid = None + self.is_configuring = False + def _hide_event_check(self): if not self.autocompletewindow: return diff --git a/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst b/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst new file mode 100644 index 000000000000..9f700d9031f1 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst @@ -0,0 +1,2 @@ +Fixed completions list appearing too high or low when shown above +the current line. From webhook-mailer at python.org Wed Aug 14 13:37:53 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 17:37:53 -0000 Subject: [Python-checkins] bpo-37849: IDLE: fix completion window positioning above line (GH-15267) Message-ID: https://github.com/python/cpython/commit/88cce7b59fa503616295ca1a25bce6251f9cd317 commit: 88cce7b59fa503616295ca1a25bce6251f9cd317 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T10:37:49-07:00 summary: bpo-37849: IDLE: fix completion window positioning above line (GH-15267) (cherry picked from commit 71662dc2f12a7e77e5e1dfe64ec87c1b459c3f59) Co-authored-by: Tal Einat files: A Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/autocomplete_w.py diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index d4a00027f858..b579c2c1a6dd 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,11 @@ Released on 2019-09-30? ====================================== +bpo-37849: Fix completions list appearing too high or low when shown +above the current line. + +bpo-36419: Refactor autocompete and improve testing. + bpo-37748: Reorder the Run menu. Put the most common choice, Run Module, at the top. diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index c69ab4a36836..5035e067392e 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -52,10 +52,12 @@ def __init__(self, widget): # (for example, he clicked the list) self.userwantswindow = None # event ids - self.hideid = self.keypressid = self.listupdateid = self.winconfigid \ - = self.keyreleaseid = self.doubleclickid = None + self.hideid = self.keypressid = self.listupdateid = \ + self.winconfigid = self.keyreleaseid = self.doubleclickid = None # Flag set if last keypress was a tab self.lastkey_was_tab = False + # Flag set to avoid recursive callback invocations. + self.is_configuring = False def _change_start(self, newstart): min_len = min(len(self.start), len(newstart)) @@ -223,12 +225,18 @@ def show_window(self, comp_lists, index, complete, mode, userWantsWin): self.widget.event_add(KEYRELEASE_VIRTUAL_EVENT_NAME,KEYRELEASE_SEQUENCE) self.listupdateid = listbox.bind(LISTUPDATE_SEQUENCE, self.listselect_event) + self.is_configuring = False self.winconfigid = acw.bind(WINCONFIG_SEQUENCE, self.winconfig_event) self.doubleclickid = listbox.bind(DOUBLECLICK_SEQUENCE, self.doubleclick_event) return None def winconfig_event(self, event): + if self.is_configuring: + # Avoid running on recursive callback invocations. + return + + self.is_configuring = True if not self.is_active(): return # Position the completion list window @@ -236,6 +244,7 @@ def winconfig_event(self, event): text.see(self.startindex) x, y, cx, cy = text.bbox(self.startindex) acw = self.autocompletewindow + acw.update() acw_width, acw_height = acw.winfo_width(), acw.winfo_height() text_width, text_height = text.winfo_width(), text.winfo_height() new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width)) @@ -256,6 +265,8 @@ def winconfig_event(self, event): acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) self.winconfigid = None + self.is_configuring = False + def _hide_event_check(self): if not self.autocompletewindow: return diff --git a/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst b/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst new file mode 100644 index 000000000000..9f700d9031f1 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst @@ -0,0 +1,2 @@ +Fixed completions list appearing too high or low when shown above +the current line. From webhook-mailer at python.org Wed Aug 14 17:11:37 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 21:11:37 -0000 Subject: [Python-checkins] bpo-37826: Document exception chaining in Python tutorial for errors. (GH-15243) Message-ID: https://github.com/python/cpython/commit/dcfe111eb5602333135b8776996332a8dcf59392 commit: dcfe111eb5602333135b8776996332a8dcf59392 branch: master author: Abhilash Raj committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-14T14:11:32-07:00 summary: bpo-37826: Document exception chaining in Python tutorial for errors. (GH-15243) https://bugs.python.org/issue37826 files: M Doc/tutorial/errors.rst diff --git a/Doc/tutorial/errors.rst b/Doc/tutorial/errors.rst index 4e287bbd8d29..e9a63e425279 100644 --- a/Doc/tutorial/errors.rst +++ b/Doc/tutorial/errors.rst @@ -267,6 +267,53 @@ re-raise the exception:: NameError: HiThere +.. _tut-exception-chaining: + +Exception Chaining +================== + +The :keyword:`raise` statement allows an optional :keyword:`from` which enables +chaining exceptions by setting the ``__cause__`` attribute of the raised +exception. For example:: + + raise RuntimeError from OSError + +This can be useful when you are transforming exceptions. For example:: + + >>> def func(): + ... raise IOError + ... + >>> try: + ... func() + ... except IOError as exc: + ... raise RuntimeError('Failed to open database') from exc + ... + Traceback (most recent call last): + File "", line 2, in + File "", line 2, in func + OSError + + The above exception was the direct cause of the following exception: + + Traceback (most recent call last): + File "", line 4, in + RuntimeError + +The expression following the :keyword:`from` must be either an exception or +``None``. Exception chaining happens automatically when an exception is raised +inside an exception handler or :keyword:`finally` section. Exception chaining +can be disabled by using ``from None`` idiom: + + >>> try: + ... open('database.sqlite') + ... except IOError: + ... raise RuntimeError from None + ... + Traceback (most recent call last): + File "", line 4, in + RuntimeError + + .. _tut-userexceptions: User-defined Exceptions From webhook-mailer at python.org Wed Aug 14 17:21:52 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 21:21:52 -0000 Subject: [Python-checkins] bpo-37811: FreeBSD, OSX: fix poll(2) usage in sockets module (GH-15202) Message-ID: https://github.com/python/cpython/commit/28146206578ebe1b84b48e6f255738a227058c04 commit: 28146206578ebe1b84b48e6f255738a227058c04 branch: master author: Artem Khramov committer: Victor Stinner date: 2019-08-14T23:21:48+02:00 summary: bpo-37811: FreeBSD, OSX: fix poll(2) usage in sockets module (GH-15202) FreeBSD implementation of poll(2) restricts the timeout argument to be either zero, or positive, or equal to INFTIM (-1). Unless otherwise overridden, socket timeout defaults to -1. This value is then converted to milliseconds (-1000) and used as argument to the poll syscall. poll returns EINVAL (22), and the connection fails. This bug was discovered during the EINTR handling testing, and the reproduction code can be found in https://bugs.python.org/issue23618 (see connect_eintr.py, attached). On GNU/Linux, the example runs as expected. This change is trivial: If the supplied timeout value is negative, truncate it to -1. files: A Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst M Misc/ACKS M Modules/socketmodule.c diff --git a/Misc/ACKS b/Misc/ACKS index 3b4cf85c75fe..52a5d70e5e2d 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -837,6 +837,7 @@ Lawrence Kesteloot Garvit Khatri Vivek Khera Dhiru Kholia +Artem Khramov Akshit Khurana Sanyam Khurana Mads Kiilerich diff --git a/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst b/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst new file mode 100644 index 000000000000..662e7dc41005 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst @@ -0,0 +1,4 @@ +Fix ``socket`` module's ``socket.connect(address)`` function being unable to +establish connection in case of interrupted system call. The problem was +observed on all OSes which ``poll(2)`` system call can take only +non-negative integers and -1 as a timeout value. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index f220c2636319..d4f2098e1e6f 100755 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -789,6 +789,17 @@ internal_select(PySocketSockObject *s, int writing, _PyTime_t interval, ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING); assert(ms <= INT_MAX); + /* On some OSes, typically BSD-based ones, the timeout parameter of the + poll() syscall, when negative, must be exactly INFTIM, where defined, + or -1. See issue 37811. */ + if (ms < 0) { +#ifdef INFTIM + ms = INFTIM; +#else + ms = -1; +#endif + } + Py_BEGIN_ALLOW_THREADS; n = poll(&pollfd, 1, (int)ms); Py_END_ALLOW_THREADS; From webhook-mailer at python.org Wed Aug 14 17:35:31 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 21:35:31 -0000 Subject: [Python-checkins] bpo-21131: Fix faulthandler.register(chain=True) stack (GH-15276) Message-ID: https://github.com/python/cpython/commit/ac827edc493d3ac3f5b9b0cc353df1d4b418a9aa commit: ac827edc493d3ac3f5b9b0cc353df1d4b418a9aa branch: master author: Victor Stinner committer: GitHub date: 2019-08-14T23:35:27+02:00 summary: bpo-21131: Fix faulthandler.register(chain=True) stack (GH-15276) faulthandler now allocates a dedicated stack of SIGSTKSZ*2 bytes, instead of just SIGSTKSZ bytes. Calling the previous signal handler in faulthandler signal handler uses more than SIGSTKSZ bytes of stack memory on some platforms. files: A Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst M Modules/faulthandler.c diff --git a/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst b/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst new file mode 100644 index 000000000000..d330aca1c17d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst @@ -0,0 +1,4 @@ +Fix ``faulthandler.register(chain=True)`` stack. faulthandler now allocates a +dedicated stack of ``SIGSTKSZ*2`` bytes, instead of just ``SIGSTKSZ`` bytes. +Calling the previous signal handler in faulthandler signal handler uses more +than ``SIGSTKSZ`` bytes of stack memory on some platforms. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 2331051f7907..5dbbcad057e6 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1325,7 +1325,11 @@ _PyFaulthandler_Init(int enable) * be able to allocate memory on the stack, even on a stack overflow. If it * fails, ignore the error. */ stack.ss_flags = 0; - stack.ss_size = SIGSTKSZ; + /* bpo-21131: allocate dedicated stack of SIGSTKSZ*2 bytes, instead of just + SIGSTKSZ bytes. Calling the previous signal handler in faulthandler + signal handler uses more than SIGSTKSZ bytes of stack memory on some + platforms. */ + stack.ss_size = SIGSTKSZ * 2; stack.ss_sp = PyMem_Malloc(stack.ss_size); if (stack.ss_sp != NULL) { err = sigaltstack(&stack, &old_stack); From webhook-mailer at python.org Wed Aug 14 17:47:51 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 21:47:51 -0000 Subject: [Python-checkins] bpo-37811: FreeBSD, OSX: fix poll(2) usage in sockets module (GH-15202) Message-ID: https://github.com/python/cpython/commit/123f6c4914827c4ced65d032fab74de62db31cd6 commit: 123f6c4914827c4ced65d032fab74de62db31cd6 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T14:47:43-07:00 summary: bpo-37811: FreeBSD, OSX: fix poll(2) usage in sockets module (GH-15202) FreeBSD implementation of poll(2) restricts the timeout argument to be either zero, or positive, or equal to INFTIM (-1). Unless otherwise overridden, socket timeout defaults to -1. This value is then converted to milliseconds (-1000) and used as argument to the poll syscall. poll returns EINVAL (22), and the connection fails. This bug was discovered during the EINTR handling testing, and the reproduction code can be found in https://bugs.python.org/issue23618 (see connect_eintr.py, attached). On GNU/Linux, the example runs as expected. This change is trivial: If the supplied timeout value is negative, truncate it to -1. (cherry picked from commit 28146206578ebe1b84b48e6f255738a227058c04) Co-authored-by: Artem Khramov files: A Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst M Misc/ACKS M Modules/socketmodule.c diff --git a/Misc/ACKS b/Misc/ACKS index 3e53429bf237..311259f1e5fa 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -832,6 +832,7 @@ Lawrence Kesteloot Garvit Khatri Vivek Khera Dhiru Kholia +Artem Khramov Akshit Khurana Sanyam Khurana Mads Kiilerich diff --git a/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst b/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst new file mode 100644 index 000000000000..662e7dc41005 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst @@ -0,0 +1,4 @@ +Fix ``socket`` module's ``socket.connect(address)`` function being unable to +establish connection in case of interrupted system call. The problem was +observed on all OSes which ``poll(2)`` system call can take only +non-negative integers and -1 as a timeout value. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 0470f387e3bc..910e2bdd1319 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -780,6 +780,17 @@ internal_select(PySocketSockObject *s, int writing, _PyTime_t interval, ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING); assert(ms <= INT_MAX); + /* On some OSes, typically BSD-based ones, the timeout parameter of the + poll() syscall, when negative, must be exactly INFTIM, where defined, + or -1. See issue 37811. */ + if (ms < 0) { +#ifdef INFTIM + ms = INFTIM; +#else + ms = -1; +#endif + } + Py_BEGIN_ALLOW_THREADS; n = poll(&pollfd, 1, (int)ms); Py_END_ALLOW_THREADS; From webhook-mailer at python.org Wed Aug 14 17:48:09 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 21:48:09 -0000 Subject: [Python-checkins] bpo-37811: FreeBSD, OSX: fix poll(2) usage in sockets module (GH-15202) Message-ID: https://github.com/python/cpython/commit/b0b178a2b80974da910ce6a344d66cc4d9a2fcfa commit: b0b178a2b80974da910ce6a344d66cc4d9a2fcfa branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T14:48:03-07:00 summary: bpo-37811: FreeBSD, OSX: fix poll(2) usage in sockets module (GH-15202) FreeBSD implementation of poll(2) restricts the timeout argument to be either zero, or positive, or equal to INFTIM (-1). Unless otherwise overridden, socket timeout defaults to -1. This value is then converted to milliseconds (-1000) and used as argument to the poll syscall. poll returns EINVAL (22), and the connection fails. This bug was discovered during the EINTR handling testing, and the reproduction code can be found in https://bugs.python.org/issue23618 (see connect_eintr.py, attached). On GNU/Linux, the example runs as expected. This change is trivial: If the supplied timeout value is negative, truncate it to -1. (cherry picked from commit 28146206578ebe1b84b48e6f255738a227058c04) Co-authored-by: Artem Khramov files: A Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst M Misc/ACKS M Modules/socketmodule.c diff --git a/Misc/ACKS b/Misc/ACKS index 29b6690f2174..4d8f96acfe30 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -815,6 +815,7 @@ Lawrence Kesteloot Garvit Khatri Vivek Khera Dhiru Kholia +Artem Khramov Akshit Khurana Sanyam Khurana Mads Kiilerich diff --git a/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst b/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst new file mode 100644 index 000000000000..662e7dc41005 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst @@ -0,0 +1,4 @@ +Fix ``socket`` module's ``socket.connect(address)`` function being unable to +establish connection in case of interrupted system call. The problem was +observed on all OSes which ``poll(2)`` system call can take only +non-negative integers and -1 as a timeout value. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 65385e8974cf..a9ef7e2083d5 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -741,6 +741,17 @@ internal_select(PySocketSockObject *s, int writing, _PyTime_t interval, ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING); assert(ms <= INT_MAX); + /* On some OSes, typically BSD-based ones, the timeout parameter of the + poll() syscall, when negative, must be exactly INFTIM, where defined, + or -1. See issue 37811. */ + if (ms < 0) { +#ifdef INFTIM + ms = INFTIM; +#else + ms = -1; +#endif + } + Py_BEGIN_ALLOW_THREADS; n = poll(&pollfd, 1, (int)ms); Py_END_ALLOW_THREADS; From webhook-mailer at python.org Wed Aug 14 18:02:16 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 22:02:16 -0000 Subject: [Python-checkins] bpo-21131: Fix faulthandler.register(chain=True) stack (GH-15276) Message-ID: https://github.com/python/cpython/commit/b8e682427a80798fec90dce31392beaf616c3e37 commit: b8e682427a80798fec90dce31392beaf616c3e37 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T15:02:12-07:00 summary: bpo-21131: Fix faulthandler.register(chain=True) stack (GH-15276) faulthandler now allocates a dedicated stack of SIGSTKSZ*2 bytes, instead of just SIGSTKSZ bytes. Calling the previous signal handler in faulthandler signal handler uses more than SIGSTKSZ bytes of stack memory on some platforms. (cherry picked from commit ac827edc493d3ac3f5b9b0cc353df1d4b418a9aa) Co-authored-by: Victor Stinner files: A Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst M Modules/faulthandler.c diff --git a/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst b/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst new file mode 100644 index 000000000000..d330aca1c17d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst @@ -0,0 +1,4 @@ +Fix ``faulthandler.register(chain=True)`` stack. faulthandler now allocates a +dedicated stack of ``SIGSTKSZ*2`` bytes, instead of just ``SIGSTKSZ`` bytes. +Calling the previous signal handler in faulthandler signal handler uses more +than ``SIGSTKSZ`` bytes of stack memory on some platforms. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index f2b5a503f4ee..7b325996b268 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1325,7 +1325,11 @@ _PyFaulthandler_Init(int enable) * be able to allocate memory on the stack, even on a stack overflow. If it * fails, ignore the error. */ stack.ss_flags = 0; - stack.ss_size = SIGSTKSZ; + /* bpo-21131: allocate dedicated stack of SIGSTKSZ*2 bytes, instead of just + SIGSTKSZ bytes. Calling the previous signal handler in faulthandler + signal handler uses more than SIGSTKSZ bytes of stack memory on some + platforms. */ + stack.ss_size = SIGSTKSZ * 2; stack.ss_sp = PyMem_Malloc(stack.ss_size); if (stack.ss_sp != NULL) { err = sigaltstack(&stack, &old_stack); From webhook-mailer at python.org Wed Aug 14 18:03:15 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 14 Aug 2019 22:03:15 -0000 Subject: [Python-checkins] bpo-37775: Update compileall doc for invalidation_mode parameter (GH-15148) Message-ID: https://github.com/python/cpython/commit/68e495df909a33e719e3f1ef5b4893ec785e10a4 commit: 68e495df909a33e719e3f1ef5b4893ec785e10a4 branch: master author: Hai Shi committer: Victor Stinner date: 2019-08-15T00:03:11+02:00 summary: bpo-37775: Update compileall doc for invalidation_mode parameter (GH-15148) files: M Doc/library/compileall.rst diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst index bb5000a0736c..9ce5ca819c68 100644 --- a/Doc/library/compileall.rst +++ b/Doc/library/compileall.rst @@ -120,7 +120,7 @@ runtime. Public functions ---------------- -.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1, invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP) +.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1, invalidation_mode=None) Recursively descend the directory tree named by *dir*, compiling all :file:`.py` files along the way. Return a true value if all the files compiled successfully, @@ -185,10 +185,13 @@ Public functions .. versionchanged:: 3.7 The *invalidation_mode* parameter was added. + .. versionchanged:: 3.7.2 + The *invalidation_mode* parameter's default value is updated to None. + .. versionchanged:: 3.8 Setting *workers* to 0 now chooses the optimal number of cores. -.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP) +.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=None) Compile the file with path *fullname*. Return a true value if the file compiled successfully, and a false value otherwise. @@ -232,7 +235,10 @@ Public functions .. versionchanged:: 3.7 The *invalidation_mode* parameter was added. -.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=-1, invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP) + .. versionchanged:: 3.7.2 + The *invalidation_mode* parameter's default value is updated to None. + +.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=-1, invalidation_mode=None) Byte-compile all the :file:`.py` files found along ``sys.path``. Return a true value if all the files compiled successfully, and a false value otherwise. @@ -255,6 +261,9 @@ Public functions .. versionchanged:: 3.7 The *invalidation_mode* parameter was added. + .. versionchanged:: 3.7.2 + The *invalidation_mode* parameter's default value is updated to None. + To force a recompile of all the :file:`.py` files in the :file:`Lib/` subdirectory and all its subdirectories:: From webhook-mailer at python.org Wed Aug 14 18:09:43 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 22:09:43 -0000 Subject: [Python-checkins] bpo-21131: Fix faulthandler.register(chain=True) stack (GH-15276) Message-ID: https://github.com/python/cpython/commit/1581d9c405f140491791a07dca3f6166bc499ec1 commit: 1581d9c405f140491791a07dca3f6166bc499ec1 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T15:09:39-07:00 summary: bpo-21131: Fix faulthandler.register(chain=True) stack (GH-15276) faulthandler now allocates a dedicated stack of SIGSTKSZ*2 bytes, instead of just SIGSTKSZ bytes. Calling the previous signal handler in faulthandler signal handler uses more than SIGSTKSZ bytes of stack memory on some platforms. (cherry picked from commit ac827edc493d3ac3f5b9b0cc353df1d4b418a9aa) Co-authored-by: Victor Stinner files: A Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst M Modules/faulthandler.c diff --git a/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst b/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst new file mode 100644 index 000000000000..d330aca1c17d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst @@ -0,0 +1,4 @@ +Fix ``faulthandler.register(chain=True)`` stack. faulthandler now allocates a +dedicated stack of ``SIGSTKSZ*2`` bytes, instead of just ``SIGSTKSZ`` bytes. +Calling the previous signal handler in faulthandler signal handler uses more +than ``SIGSTKSZ`` bytes of stack memory on some platforms. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 0dbd5a3342b0..97c64f633091 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -1322,7 +1322,11 @@ _PyFaulthandler_Init(int enable) * be able to allocate memory on the stack, even on a stack overflow. If it * fails, ignore the error. */ stack.ss_flags = 0; - stack.ss_size = SIGSTKSZ; + /* bpo-21131: allocate dedicated stack of SIGSTKSZ*2 bytes, instead of just + SIGSTKSZ bytes. Calling the previous signal handler in faulthandler + signal handler uses more than SIGSTKSZ bytes of stack memory on some + platforms. */ + stack.ss_size = SIGSTKSZ * 2; stack.ss_sp = PyMem_Malloc(stack.ss_size); if (stack.ss_sp != NULL) { err = sigaltstack(&stack, &old_stack); From webhook-mailer at python.org Wed Aug 14 18:22:06 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Aug 2019 22:22:06 -0000 Subject: [Python-checkins] bpo-37775: Update compileall doc for invalidation_mode parameter (GH-15148) Message-ID: https://github.com/python/cpython/commit/dbe4c286ce28402c3bce71d568ae55b91280e777 commit: dbe4c286ce28402c3bce71d568ae55b91280e777 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-14T15:22:02-07:00 summary: bpo-37775: Update compileall doc for invalidation_mode parameter (GH-15148) (cherry picked from commit 68e495df909a33e719e3f1ef5b4893ec785e10a4) Co-authored-by: Hai Shi files: M Doc/library/compileall.rst diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst index bb5000a0736c..9ce5ca819c68 100644 --- a/Doc/library/compileall.rst +++ b/Doc/library/compileall.rst @@ -120,7 +120,7 @@ runtime. Public functions ---------------- -.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1, invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP) +.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1, invalidation_mode=None) Recursively descend the directory tree named by *dir*, compiling all :file:`.py` files along the way. Return a true value if all the files compiled successfully, @@ -185,10 +185,13 @@ Public functions .. versionchanged:: 3.7 The *invalidation_mode* parameter was added. + .. versionchanged:: 3.7.2 + The *invalidation_mode* parameter's default value is updated to None. + .. versionchanged:: 3.8 Setting *workers* to 0 now chooses the optimal number of cores. -.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP) +.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=None) Compile the file with path *fullname*. Return a true value if the file compiled successfully, and a false value otherwise. @@ -232,7 +235,10 @@ Public functions .. versionchanged:: 3.7 The *invalidation_mode* parameter was added. -.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=-1, invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP) + .. versionchanged:: 3.7.2 + The *invalidation_mode* parameter's default value is updated to None. + +.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=-1, invalidation_mode=None) Byte-compile all the :file:`.py` files found along ``sys.path``. Return a true value if all the files compiled successfully, and a false value otherwise. @@ -255,6 +261,9 @@ Public functions .. versionchanged:: 3.7 The *invalidation_mode* parameter was added. + .. versionchanged:: 3.7.2 + The *invalidation_mode* parameter's default value is updated to None. + To force a recompile of all the :file:`.py` files in the :file:`Lib/` subdirectory and all its subdirectories:: From webhook-mailer at python.org Wed Aug 14 21:19:00 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Thu, 15 Aug 2019 01:19:00 -0000 Subject: [Python-checkins] bpo-37760: Avoid cluttering work tree with downloaded Unicode files. (GH-15128) Message-ID: https://github.com/python/cpython/commit/3e4498d35c34aeaf4a9c3d57509b0d3277048ac6 commit: 3e4498d35c34aeaf4a9c3d57509b0d3277048ac6 branch: master author: Greg Price committer: Benjamin Peterson date: 2019-08-14T18:18:53-07:00 summary: bpo-37760: Avoid cluttering work tree with downloaded Unicode files. (GH-15128) files: M .gitignore M Tools/unicode/makeunicodedata.py diff --git a/.gitignore b/.gitignore index 9445ef1e2c52..5f1ba0b92ceb 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,7 @@ PCbuild/arm32/ PCbuild/arm64/ PCbuild/obj/ PCbuild/win32/ +Tools/unicode/data/ .purify __pycache__ autom4te.cache diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py index cc2b2981ef5b..464a4ebf7722 100644 --- a/Tools/unicode/makeunicodedata.py +++ b/Tools/unicode/makeunicodedata.py @@ -887,15 +887,18 @@ class Difference(Exception):pass normalization_changes)) +DATA_DIR = os.path.join('Tools', 'unicode', 'data') + def open_data(template, version): - local = template % ('-'+version,) + local = os.path.join(DATA_DIR, template % ('-'+version,)) if not os.path.exists(local): import urllib.request if version == '3.2.0': # irregular url structure - url = 'http://www.unicode.org/Public/3.2-Update/' + local + url = ('http://www.unicode.org/Public/3.2-Update/'+template) % ('-'+version,) else: url = ('http://www.unicode.org/Public/%s/ucd/'+template) % (version, '') + os.makedirs(DATA_DIR, exist_ok=True) urllib.request.urlretrieve(url, filename=local) if local.endswith('.txt'): return open(local, encoding='utf-8') From webhook-mailer at python.org Thu Aug 15 08:31:38 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 15 Aug 2019 12:31:38 -0000 Subject: [Python-checkins] Replace usage of the obscure PEM_read_bio_X509_AUX with the more standard PEM_read_bio_X509 (GH-15303) Message-ID: https://github.com/python/cpython/commit/40dad9545aad4ede89abbab1c1beef5303d9573e commit: 40dad9545aad4ede89abbab1c1beef5303d9573e branch: master author: Alex Gaynor committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-15T05:31:28-07:00 summary: Replace usage of the obscure PEM_read_bio_X509_AUX with the more standard PEM_read_bio_X509 (GH-15303) X509_AUX is an odd, note widely used, OpenSSL extension to the X509 file format. This function doesn't actually use any of the extra metadata that it parses, so just use the standard API. Automerge-Triggered-By: @tiran files: M Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 3d54b844fe07..3d63612168b2 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -1822,7 +1822,7 @@ _ssl__test_decode_cert_impl(PyObject *module, PyObject *path) goto fail0; } - x = PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL); + x = PEM_read_bio_X509(cert, NULL, NULL, NULL); if (x == NULL) { PyErr_SetString(PySSLErrorObject, "Error decoding PEM-encoded file"); From webhook-mailer at python.org Thu Aug 15 08:52:57 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 15 Aug 2019 12:52:57 -0000 Subject: [Python-checkins] [3.8] Replace usage of the obscure PEM_read_bio_X509_AUX with the more standard PEM_read_bio_X509 (GH-15303) (GH-15304) Message-ID: https://github.com/python/cpython/commit/f781283ff6042fa5bc220a1572effc38b545eb20 commit: f781283ff6042fa5bc220a1572effc38b545eb20 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-15T05:52:51-07:00 summary: [3.8] Replace usage of the obscure PEM_read_bio_X509_AUX with the more standard PEM_read_bio_X509 (GH-15303) (GH-15304) X509_AUX is an odd, note widely used, OpenSSL extension to the X509 file format. This function doesn't actually use any of the extra metadata that it parses, so just use the standard API. Automerge-Triggered-By: @tiran (cherry picked from commit 40dad9545aad4ede89abbab1c1beef5303d9573e) Co-authored-by: Alex Gaynor Automerge-Triggered-By: @tiran files: M Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c index da30cbb758e2..089aa3b24a02 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -1822,7 +1822,7 @@ _ssl__test_decode_cert_impl(PyObject *module, PyObject *path) goto fail0; } - x = PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL); + x = PEM_read_bio_X509(cert, NULL, NULL, NULL); if (x == NULL) { PyErr_SetString(PySSLErrorObject, "Error decoding PEM-encoded file"); From webhook-mailer at python.org Thu Aug 15 08:56:03 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 15 Aug 2019 12:56:03 -0000 Subject: [Python-checkins] Replace usage of the obscure PEM_read_bio_X509_AUX with the more standard PEM_read_bio_X509 (GH-15303) Message-ID: https://github.com/python/cpython/commit/2b9b70765ce4d955cc2e250878694885363770b8 commit: 2b9b70765ce4d955cc2e250878694885363770b8 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-15T05:55:59-07:00 summary: Replace usage of the obscure PEM_read_bio_X509_AUX with the more standard PEM_read_bio_X509 (GH-15303) X509_AUX is an odd, note widely used, OpenSSL extension to the X509 file format. This function doesn't actually use any of the extra metadata that it parses, so just use the standard API. Automerge-Triggered-By: @tiran (cherry picked from commit 40dad9545aad4ede89abbab1c1beef5303d9573e) Co-authored-by: Alex Gaynor files: M Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c index e8955eedfa53..b079663cc223 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -1789,7 +1789,7 @@ _ssl__test_decode_cert_impl(PyObject *module, PyObject *path) goto fail0; } - x = PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL); + x = PEM_read_bio_X509(cert, NULL, NULL, NULL); if (x == NULL) { PyErr_SetString(PySSLErrorObject, "Error decoding PEM-encoded file"); From webhook-mailer at python.org Thu Aug 15 11:49:52 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 15 Aug 2019 15:49:52 -0000 Subject: [Python-checkins] bpo-37207: enable vectorcall for type.__call__ (GH-14588) Message-ID: https://github.com/python/cpython/commit/37806f404f57b234902f0c8de9a04647ad01b7f1 commit: 37806f404f57b234902f0c8de9a04647ad01b7f1 branch: master author: Jeroen Demeyer committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-15T08:49:46-07:00 summary: bpo-37207: enable vectorcall for type.__call__ (GH-14588) Base PR for other PRs that want to play with `type.__call__` such as #13930 and #14589. The author is really @markshannon I just made the PR. https://bugs.python.org/issue37207 Automerge-Triggered-By: @encukou files: A Misc/NEWS.d/next/C API/2019-07-07-10-37-07.bpo-37207.SlVNky.rst M Objects/typeobject.c diff --git a/Misc/NEWS.d/next/C API/2019-07-07-10-37-07.bpo-37207.SlVNky.rst b/Misc/NEWS.d/next/C API/2019-07-07-10-37-07.bpo-37207.SlVNky.rst new file mode 100644 index 000000000000..8df76614a0d7 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-07-07-10-37-07.bpo-37207.SlVNky.rst @@ -0,0 +1,3 @@ +The vectorcall protocol is now enabled for ``type`` objects: set +``tp_vectorcall`` to a vectorcall function to be used instead of ``tp_new`` +and ``tp_init`` when calling the class itself. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 9e5709a74f78..0ca7dcb695bb 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3614,7 +3614,7 @@ PyTypeObject PyType_Type = { sizeof(PyHeapTypeObject), /* tp_basicsize */ sizeof(PyMemberDef), /* tp_itemsize */ (destructor)type_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ + offsetof(PyTypeObject, tp_vectorcall), /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ @@ -3629,7 +3629,8 @@ PyTypeObject PyType_Type = { (setattrofunc)type_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS, /* tp_flags */ + Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS | + _Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */ type_doc, /* tp_doc */ (traverseproc)type_traverse, /* tp_traverse */ (inquiry)type_clear, /* tp_clear */ From webhook-mailer at python.org Thu Aug 15 12:19:13 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Thu, 15 Aug 2019 16:19:13 -0000 Subject: [Python-checkins] Indent code inside if block. (GH-15284) Message-ID: https://github.com/python/cpython/commit/69f37bcb28d7cd78255828029f895958b5baf6ff commit: 69f37bcb28d7cd78255828029f895958b5baf6ff branch: master author: Hansraj Das committer: Benjamin Peterson date: 2019-08-15T09:19:07-07:00 summary: Indent code inside if block. (GH-15284) Without indendation, seems like strcpy line is parallel to `if` condition. files: M Parser/tokenizer.c diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 31fe970c9003..5763e47c4b00 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1821,7 +1821,7 @@ PyTokenizer_FindEncodingFilename(int fd, PyObject *filename) if (tok->encoding) { encoding = (char *)PyMem_MALLOC(strlen(tok->encoding) + 1); if (encoding) - strcpy(encoding, tok->encoding); + strcpy(encoding, tok->encoding); } PyTokenizer_Free(tok); return encoding; From webhook-mailer at python.org Thu Aug 15 12:38:27 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 15 Aug 2019 16:38:27 -0000 Subject: [Python-checkins] Indent code inside if block. (GH-15284) Message-ID: https://github.com/python/cpython/commit/64db5aac6be73b14396bcde1648997e208b5a8da commit: 64db5aac6be73b14396bcde1648997e208b5a8da branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-15T09:38:22-07:00 summary: Indent code inside if block. (GH-15284) Without indendation, seems like strcpy line is parallel to `if` condition. (cherry picked from commit 69f37bcb28d7cd78255828029f895958b5baf6ff) Co-authored-by: Hansraj Das files: M Parser/tokenizer.c diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 31fe970c9003..5763e47c4b00 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1821,7 +1821,7 @@ PyTokenizer_FindEncodingFilename(int fd, PyObject *filename) if (tok->encoding) { encoding = (char *)PyMem_MALLOC(strlen(tok->encoding) + 1); if (encoding) - strcpy(encoding, tok->encoding); + strcpy(encoding, tok->encoding); } PyTokenizer_Free(tok); return encoding; From webhook-mailer at python.org Thu Aug 15 12:46:51 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 15 Aug 2019 16:46:51 -0000 Subject: [Python-checkins] Indent code inside if block. (GH-15284) Message-ID: https://github.com/python/cpython/commit/6ac851fadf52ccaf8a14abe1b5e6a74bd6eec69e commit: 6ac851fadf52ccaf8a14abe1b5e6a74bd6eec69e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-15T09:46:47-07:00 summary: Indent code inside if block. (GH-15284) Without indendation, seems like strcpy line is parallel to `if` condition. (cherry picked from commit 69f37bcb28d7cd78255828029f895958b5baf6ff) Co-authored-by: Hansraj Das files: M Parser/tokenizer.c diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index e374c5a4aee6..d720f19eca9d 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1890,7 +1890,7 @@ PyTokenizer_FindEncodingFilename(int fd, PyObject *filename) if (tok->encoding) { encoding = (char *)PyMem_MALLOC(strlen(tok->encoding) + 1); if (encoding) - strcpy(encoding, tok->encoding); + strcpy(encoding, tok->encoding); } PyTokenizer_Free(tok); return encoding; From webhook-mailer at python.org Thu Aug 15 15:09:11 2019 From: webhook-mailer at python.org (Paul Ganssle) Date: Thu, 15 Aug 2019 19:09:11 -0000 Subject: [Python-checkins] bpo-37642: Update acceptable offsets in timezone (GH-14878) (#15227) Message-ID: https://github.com/python/cpython/commit/27b38b99b3a154fa5c25cd67fe01fb4fc04604b0 commit: 27b38b99b3a154fa5c25cd67fe01fb4fc04604b0 branch: 3.8 author: Paul Ganssle committer: GitHub date: 2019-08-15T15:08:57-04:00 summary: bpo-37642: Update acceptable offsets in timezone (GH-14878) (#15227) This fixes an inconsistency between the Python and C implementations of the datetime module. The pure python version of the code was not accepting offsets greater than 23:59 but less than 24:00. This is an accidental legacy of the original implementation, which was put in place before tzinfo allowed sub-minute time zone offsets. GH-14878 (cherry picked from commit 92c7e30adf5c81a54d6e5e555a6bdfaa60157a0d) files: A Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst M Lib/datetime.py M Lib/test/datetimetester.py M Misc/ACKS M Modules/_datetimemodule.c diff --git a/Lib/datetime.py b/Lib/datetime.py index d4c7a1ff9004..0adf1dd67dfb 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -2269,7 +2269,7 @@ def fromutc(self, dt): raise TypeError("fromutc() argument must be a datetime instance" " or None") - _maxoffset = timedelta(hours=23, minutes=59) + _maxoffset = timedelta(hours=24, microseconds=-1) _minoffset = -_maxoffset @staticmethod @@ -2293,8 +2293,11 @@ def _name_from_offset(delta): return f'UTC{sign}{hours:02d}:{minutes:02d}' timezone.utc = timezone._create(timedelta(0)) -timezone.min = timezone._create(timezone._minoffset) -timezone.max = timezone._create(timezone._maxoffset) +# bpo-37642: These attributes are rounded to the nearest minute for backwards +# compatibility, even though the constructor will accept a wider range of +# values. This may change in the future. +timezone.min = timezone._create(-timedelta(hours=23, minutes=59)) +timezone.max = timezone._create(timedelta(hours=23, minutes=59)) _EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc) # Some time zone algebra. For a datetime x, let diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 99b620ce2f41..d0101c98bc76 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -388,6 +388,31 @@ def test_deepcopy(self): tz_copy = copy.deepcopy(tz) self.assertIs(tz_copy, tz) + def test_offset_boundaries(self): + # Test timedeltas close to the boundaries + time_deltas = [ + timedelta(hours=23, minutes=59), + timedelta(hours=23, minutes=59, seconds=59), + timedelta(hours=23, minutes=59, seconds=59, microseconds=999999), + ] + time_deltas.extend([-delta for delta in time_deltas]) + + for delta in time_deltas: + with self.subTest(test_type='good', delta=delta): + timezone(delta) + + # Test timedeltas on and outside the boundaries + bad_time_deltas = [ + timedelta(hours=24), + timedelta(hours=24, microseconds=1), + ] + bad_time_deltas.extend([-delta for delta in bad_time_deltas]) + + for delta in bad_time_deltas: + with self.subTest(test_type='bad', delta=delta): + with self.assertRaises(ValueError): + timezone(delta) + ############################################################################# # Base class for testing a particular aspect of timedelta, time, date and diff --git a/Misc/ACKS b/Misc/ACKS index 311259f1e5fa..ab874e929931 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1874,3 +1874,4 @@ Geoff Shannon Batuhan Taskaya Aleksandr Balezin Robert Leenders +Ngalim Siregar diff --git a/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst b/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst new file mode 100644 index 000000000000..09ff257597e8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst @@ -0,0 +1,3 @@ +Allowed the pure Python implementation of :class:`datetime.timezone` to represent +sub-minute offsets close to minimum and maximum boundaries, specifically in the +ranges (23:59, 24:00) and (-23:59, 24:00). Patch by Ngalim Siregar diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 80ecfc3fff0b..beb1c3cfbca9 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1099,7 +1099,9 @@ new_timezone(PyObject *offset, PyObject *name) Py_INCREF(PyDateTime_TimeZone_UTC); return PyDateTime_TimeZone_UTC; } - if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) || + if ((GET_TD_DAYS(offset) == -1 && + GET_TD_SECONDS(offset) == 0 && + GET_TD_MICROSECONDS(offset) < 1) || GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { PyErr_Format(PyExc_ValueError, "offset must be a timedelta" " strictly between -timedelta(hours=24) and" @@ -1169,7 +1171,9 @@ call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg) if (offset == Py_None || offset == NULL) return offset; if (PyDelta_Check(offset)) { - if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) || + if ((GET_TD_DAYS(offset) == -1 && + GET_TD_SECONDS(offset) == 0 && + GET_TD_MICROSECONDS(offset) < 1) || GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { Py_DECREF(offset); PyErr_Format(PyExc_ValueError, "offset must be a timedelta" @@ -6484,6 +6488,9 @@ PyInit__datetime(void) PyDateTime_TimeZone_UTC = x; CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC; + /* bpo-37642: These attributes are rounded to the nearest minute for backwards + * compatibility, even though the constructor will accept a wider range of + * values. This may change in the future.*/ delta = new_delta(-1, 60, 0, 1); /* -23:59 */ if (delta == NULL) return NULL; From webhook-mailer at python.org Thu Aug 15 15:09:41 2019 From: webhook-mailer at python.org (Paul Ganssle) Date: Thu, 15 Aug 2019 19:09:41 -0000 Subject: [Python-checkins] bpo-37642: Update acceptable offsets in timezone (GH-14878) (#15226) Message-ID: https://github.com/python/cpython/commit/ed44b84961eb0e5b97e4866c1455ac4093d27549 commit: ed44b84961eb0e5b97e4866c1455ac4093d27549 branch: 3.7 author: Paul Ganssle committer: GitHub date: 2019-08-15T15:09:37-04:00 summary: bpo-37642: Update acceptable offsets in timezone (GH-14878) (#15226) This fixes an inconsistency between the Python and C implementations of the datetime module. The pure python version of the code was not accepting offsets greater than 23:59 but less than 24:00. This is an accidental legacy of the original implementation, which was put in place before tzinfo allowed sub-minute time zone offsets. GH-14878 (cherry picked from commit 92c7e30adf5c81a54d6e5e555a6bdfaa60157a0d) files: A Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst M Lib/datetime.py M Lib/test/datetimetester.py M Misc/ACKS M Modules/_datetimemodule.c diff --git a/Lib/datetime.py b/Lib/datetime.py index 0485b0523e8d..5a2ee6a2035a 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -2226,7 +2226,7 @@ def fromutc(self, dt): raise TypeError("fromutc() argument must be a datetime instance" " or None") - _maxoffset = timedelta(hours=23, minutes=59) + _maxoffset = timedelta(hours=24, microseconds=-1) _minoffset = -_maxoffset @staticmethod @@ -2250,8 +2250,11 @@ def _name_from_offset(delta): return f'UTC{sign}{hours:02d}:{minutes:02d}' timezone.utc = timezone._create(timedelta(0)) -timezone.min = timezone._create(timezone._minoffset) -timezone.max = timezone._create(timezone._maxoffset) +# bpo-37642: These attributes are rounded to the nearest minute for backwards +# compatibility, even though the constructor will accept a wider range of +# values. This may change in the future. +timezone.min = timezone._create(-timedelta(hours=23, minutes=59)) +timezone.max = timezone._create(timedelta(hours=23, minutes=59)) _EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc) # Some time zone algebra. For a datetime x, let diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 8a5716979716..025e71de7872 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -388,6 +388,31 @@ def test_deepcopy(self): tz_copy = copy.deepcopy(tz) self.assertIs(tz_copy, tz) + def test_offset_boundaries(self): + # Test timedeltas close to the boundaries + time_deltas = [ + timedelta(hours=23, minutes=59), + timedelta(hours=23, minutes=59, seconds=59), + timedelta(hours=23, minutes=59, seconds=59, microseconds=999999), + ] + time_deltas.extend([-delta for delta in time_deltas]) + + for delta in time_deltas: + with self.subTest(test_type='good', delta=delta): + timezone(delta) + + # Test timedeltas on and outside the boundaries + bad_time_deltas = [ + timedelta(hours=24), + timedelta(hours=24, microseconds=1), + ] + bad_time_deltas.extend([-delta for delta in bad_time_deltas]) + + for delta in bad_time_deltas: + with self.subTest(test_type='bad', delta=delta): + with self.assertRaises(ValueError): + timezone(delta) + ############################################################################# # Base class for testing a particular aspect of timedelta, time, date and diff --git a/Misc/ACKS b/Misc/ACKS index 4d8f96acfe30..0283c85b174e 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1836,3 +1836,4 @@ Doug Zongker Peter ?strand Zheao Li Geoff Shannon +Ngalim Siregar diff --git a/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst b/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst new file mode 100644 index 000000000000..09ff257597e8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst @@ -0,0 +1,3 @@ +Allowed the pure Python implementation of :class:`datetime.timezone` to represent +sub-minute offsets close to minimum and maximum boundaries, specifically in the +ranges (23:59, 24:00) and (-23:59, 24:00). Patch by Ngalim Siregar diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index aa759b115f0e..655be364d9cb 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1085,7 +1085,9 @@ new_timezone(PyObject *offset, PyObject *name) Py_INCREF(PyDateTime_TimeZone_UTC); return PyDateTime_TimeZone_UTC; } - if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) || + if ((GET_TD_DAYS(offset) == -1 && + GET_TD_SECONDS(offset) == 0 && + GET_TD_MICROSECONDS(offset) < 1) || GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { PyErr_Format(PyExc_ValueError, "offset must be a timedelta" " strictly between -timedelta(hours=24) and" @@ -1155,7 +1157,9 @@ call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg) if (offset == Py_None || offset == NULL) return offset; if (PyDelta_Check(offset)) { - if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) || + if ((GET_TD_DAYS(offset) == -1 && + GET_TD_SECONDS(offset) == 0 && + GET_TD_MICROSECONDS(offset) < 1) || GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { Py_DECREF(offset); PyErr_Format(PyExc_ValueError, "offset must be a timedelta" @@ -6383,6 +6387,9 @@ PyInit__datetime(void) PyDateTime_TimeZone_UTC = x; CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC; + /* bpo-37642: These attributes are rounded to the nearest minute for backwards + * compatibility, even though the constructor will accept a wider range of + * values. This may change in the future.*/ delta = new_delta(-1, 60, 0, 1); /* -23:59 */ if (delta == NULL) return NULL; From webhook-mailer at python.org Thu Aug 15 23:58:40 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 16 Aug 2019 03:58:40 -0000 Subject: [Python-checkins] bpo-37863: Optimize Fraction.__hash__() (#15298) Message-ID: https://github.com/python/cpython/commit/f3cb68f2e4c3e0c405460f9bb881f5c1db70f535 commit: f3cb68f2e4c3e0c405460f9bb881f5c1db70f535 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-15T20:58:26-07:00 summary: bpo-37863: Optimize Fraction.__hash__() (#15298) files: A Misc/NEWS.d/next/Library/2019-08-14-20-46-39.bpo-37863.CkXqgX.rst M Lib/fractions.py diff --git a/Lib/fractions.py b/Lib/fractions.py index e774d58e4035..c922c38e2441 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -556,23 +556,19 @@ def __round__(self, ndigits=None): def __hash__(self): """hash(self)""" - # XXX since this method is expensive, consider caching the result - - # In order to make sure that the hash of a Fraction agrees - # with the hash of a numerically equal integer, float or - # Decimal instance, we follow the rules for numeric hashes - # outlined in the documentation. (See library docs, 'Built-in - # Types'). - - # dinv is the inverse of self._denominator modulo the prime - # _PyHASH_MODULUS, or 0 if self._denominator is divisible by - # _PyHASH_MODULUS. - dinv = pow(self._denominator, _PyHASH_MODULUS - 2, _PyHASH_MODULUS) - if not dinv: + # To make sure that the hash of a Fraction agrees with the hash + # of a numerically equal integer, float or Decimal instance, we + # follow the rules for numeric hashes outlined in the + # documentation. (See library docs, 'Built-in Types'). + + try: + dinv = pow(self._denominator, -1, _PyHASH_MODULUS) + except ValueError: + # ValueError means there is no modular inverse hash_ = _PyHASH_INF else: - hash_ = abs(self._numerator) * dinv % _PyHASH_MODULUS - result = hash_ if self >= 0 else -hash_ + hash_ = hash(abs(self._numerator)) * dinv % _PyHASH_MODULUS + result = hash_ if self._numerator >= 0 else -hash_ return -2 if result == -1 else result def __eq__(a, b): diff --git a/Misc/NEWS.d/next/Library/2019-08-14-20-46-39.bpo-37863.CkXqgX.rst b/Misc/NEWS.d/next/Library/2019-08-14-20-46-39.bpo-37863.CkXqgX.rst new file mode 100644 index 000000000000..90df6e9cb652 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-14-20-46-39.bpo-37863.CkXqgX.rst @@ -0,0 +1 @@ +Optimizations for Fraction.__hash__ suggested by Tim Peters. From webhook-mailer at python.org Fri Aug 16 04:27:40 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 16 Aug 2019 08:27:40 -0000 Subject: [Python-checkins] bpo-37256: Wording in Request class docs (GH-14792) Message-ID: https://github.com/python/cpython/commit/f9919121460bffc04f935dbdb85f0af3ffbd3ddf commit: f9919121460bffc04f935dbdb85f0af3ffbd3ddf branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-16T01:27:35-07:00 summary: bpo-37256: Wording in Request class docs (GH-14792) * bpo-37256: Wording in Request class docs * ?? Added by blurb_it. * Update Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst Co-Authored-By: Kyle Stanley (cherry picked from commit 38c7199beb30ae9a5005c0f0d9df9fae0da3680a) Co-authored-by: Ngalim Siregar files: A Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst M Doc/library/urllib.request.rst diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index 3b7508966691..448bc6785470 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -227,7 +227,7 @@ The following classes are provided: is not None, ``Content-Type: application/x-www-form-urlencoded`` will be added as a default. - The final two arguments are only of interest for correct handling + The next two arguments are only of interest for correct handling of third-party HTTP cookies: *origin_req_host* should be the request-host of the origin diff --git a/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst b/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst new file mode 100644 index 000000000000..480d7c87ebc4 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst @@ -0,0 +1 @@ +Fix wording of arguments for :class:`Request` in :mod:`urllib.request` From webhook-mailer at python.org Fri Aug 16 06:41:33 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 16 Aug 2019 10:41:33 -0000 Subject: [Python-checkins] bpo-37540: vectorcall: keyword names must be strings (GH-14682) Message-ID: https://github.com/python/cpython/commit/0567786d26348aa7eaf0ab1b5d038fdabe409d92 commit: 0567786d26348aa7eaf0ab1b5d038fdabe409d92 branch: master author: Jeroen Demeyer committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-16T03:41:27-07:00 summary: bpo-37540: vectorcall: keyword names must be strings (GH-14682) The fact that keyword names are strings is now part of the vectorcall and `METH_FASTCALL` protocols. The biggest concrete change is that `_PyStack_UnpackDict` now checks that and raises `TypeError` if not. CC @markshannon @vstinner https://bugs.python.org/issue37540 files: A Misc/NEWS.d/next/C API/2019-07-10-12-27-28.bpo-37540.E8Z773.rst M Doc/c-api/object.rst M Doc/c-api/structures.rst M Doc/library/dis.rst M Include/cpython/abstract.h M Lib/test/test_extcall.py M Lib/test/test_unpack_ex.py M Objects/call.c M Python/ceval.c M Python/getargs.c diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 2cf032821afb..fd1e9c65aaba 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -400,8 +400,8 @@ Object Protocol :c:func:`PyVectorcall_NARGS(nargsf) `. *kwnames* can be either NULL (no keyword arguments) or a tuple of keyword - names. In the latter case, the values of the keyword arguments are stored - in *args* after the positional arguments. + names, which must be strings. In the latter case, the values of the keyword + arguments are stored in *args* after the positional arguments. The number of keyword arguments does not influence *nargsf*. *kwnames* must contain only objects of type ``str`` (not a subclass), diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index 5184ad511cd9..d4e65afef14d 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -204,6 +204,7 @@ also keyword arguments. So there are a total of 6 calling conventions: Keyword arguments are passed the same way as in the vectorcall protocol: there is an additional fourth :c:type:`PyObject\*` parameter which is a tuple representing the names of the keyword arguments + (which are guaranteed to be strings) or possibly *NULL* if there are no keywords. The values of the keyword arguments are stored in the *args* array, after the positional arguments. diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 39a3e130afd3..4a20245e3032 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -1142,8 +1142,10 @@ All of the following opcodes use their arguments. Calls a callable object with positional (if any) and keyword arguments. *argc* indicates the total number of positional and keyword arguments. - The top element on the stack contains a tuple of keyword argument names. - Below that are keyword arguments in the order corresponding to the tuple. + The top element on the stack contains a tuple with the names of the + keyword arguments, which must be strings. + Below that are the values for the keyword arguments, + in the order corresponding to the tuple. Below that are positional arguments, with the right-most parameter on top. Below the arguments is a callable object to call. ``CALL_FUNCTION_KW`` pops all arguments and the callable object off the stack, diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h index d57aa54bc466..62a113fc00e2 100644 --- a/Include/cpython/abstract.h +++ b/Include/cpython/abstract.h @@ -88,8 +88,7 @@ _PyVectorcall_Function(PyObject *callable) of keyword arguments does not change nargsf). kwnames can also be NULL if there are no keyword arguments. - keywords must only contains str strings (no subclass), and all keys must - be unique. + keywords must only contain strings and all keys must be unique. Return the result on success. Raise an exception and return NULL on error. */ diff --git a/Lib/test/test_extcall.py b/Lib/test/test_extcall.py index 3cac3bda4253..d9dcb709f754 100644 --- a/Lib/test/test_extcall.py +++ b/Lib/test/test_extcall.py @@ -237,7 +237,7 @@ >>> f(**{1:2}) Traceback (most recent call last): ... - TypeError: f() keywords must be strings + TypeError: keywords must be strings >>> h(**{'e': 2}) Traceback (most recent call last): diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py index 45cf051f1ec1..87fea593c020 100644 --- a/Lib/test/test_unpack_ex.py +++ b/Lib/test/test_unpack_ex.py @@ -256,7 +256,7 @@ >>> f(**{1: 3}, **{1: 5}) Traceback (most recent call last): ... - TypeError: f() keywords must be strings + TypeError: f() got multiple values for keyword argument '1' Unpacking non-sequence diff --git a/Misc/NEWS.d/next/C API/2019-07-10-12-27-28.bpo-37540.E8Z773.rst b/Misc/NEWS.d/next/C API/2019-07-10-12-27-28.bpo-37540.E8Z773.rst new file mode 100644 index 000000000000..1a09c7e1330e --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-07-10-12-27-28.bpo-37540.E8Z773.rst @@ -0,0 +1,2 @@ +The vectorcall protocol now requires that the caller passes only strings as +keyword names. diff --git a/Objects/call.c b/Objects/call.c index 7d917891bc0c..8a60b3e58e30 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -322,8 +322,7 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, assert(nargs >= 0); assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); assert((nargs == 0 && nkwargs == 0) || stack != NULL); - /* kwnames must only contains str strings, no subclass, and all keys must - be unique */ + /* kwnames must only contain strings and all keys must be unique */ if (co->co_kwonlyargcount == 0 && nkwargs == 0 && (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) @@ -943,12 +942,12 @@ _PyStack_AsDict(PyObject *const *values, PyObject *kwnames) vector; return NULL with exception set on error. Return the keyword names tuple in *p_kwnames. - The newly allocated argument vector supports PY_VECTORCALL_ARGUMENTS_OFFSET. + This also checks that all keyword names are strings. If not, a TypeError is + raised. - When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames) + The newly allocated argument vector supports PY_VECTORCALL_ARGUMENTS_OFFSET. - The type of keyword keys is not checked, these checks should be done - later (ex: _PyArg_ParseStackAndKeywords). */ + When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames) */ static PyObject *const * _PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, PyObject **p_kwnames) @@ -994,7 +993,9 @@ _PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, called in the performance critical hot code. */ Py_ssize_t pos = 0, i = 0; PyObject *key, *value; + unsigned long keys_are_strings = Py_TPFLAGS_UNICODE_SUBCLASS; while (PyDict_Next(kwargs, &pos, &key, &value)) { + keys_are_strings &= Py_TYPE(key)->tp_flags; Py_INCREF(key); Py_INCREF(value); PyTuple_SET_ITEM(kwnames, i, key); @@ -1002,6 +1003,18 @@ _PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, i++; } + /* keys_are_strings has the value Py_TPFLAGS_UNICODE_SUBCLASS if that + * flag is set for all keys. Otherwise, keys_are_strings equals 0. + * We do this check once at the end instead of inside the loop above + * because it simplifies the deallocation in the failing case. + * It happens to also make the loop above slightly more efficient. */ + if (!keys_are_strings) { + PyErr_SetString(PyExc_TypeError, + "keywords must be strings"); + _PyStack_UnpackDict_Free(stack, nargs, kwnames); + return NULL; + } + *p_kwnames = kwnames; return stack; } diff --git a/Python/ceval.c b/Python/ceval.c index 7c7359166dad..ee03350031d9 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3504,7 +3504,9 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) PyObject **sp, *res, *names; names = POP(); - assert(PyTuple_CheckExact(names) && PyTuple_GET_SIZE(names) <= oparg); + assert(PyTuple_Check(names)); + assert(PyTuple_GET_SIZE(names) <= oparg); + /* We assume without checking that names contains only strings */ sp = stack_pointer; res = call_function(tstate, &sp, oparg, names); stack_pointer = sp; @@ -5372,20 +5374,12 @@ format_kwargs_error(PyThreadState *tstate, PyObject *func, PyObject *kwargs) _PyErr_Fetch(tstate, &exc, &val, &tb); if (val && PyTuple_Check(val) && PyTuple_GET_SIZE(val) == 1) { PyObject *key = PyTuple_GET_ITEM(val, 0); - if (!PyUnicode_Check(key)) { - _PyErr_Format(tstate, PyExc_TypeError, - "%.200s%.200s keywords must be strings", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func)); - } - else { - _PyErr_Format(tstate, PyExc_TypeError, - "%.200s%.200s got multiple " - "values for keyword argument '%U'", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - key); - } + _PyErr_Format(tstate, PyExc_TypeError, + "%.200s%.200s got multiple " + "values for keyword argument '%S'", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + key); Py_XDECREF(exc); Py_XDECREF(val); Py_XDECREF(tb); diff --git a/Python/getargs.c b/Python/getargs.c index 59f0fdabb74a..cdc16d4730b5 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -2043,11 +2043,7 @@ find_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key) if (kwname == key) { return kwstack[i]; } - if (!PyUnicode_Check(kwname)) { - /* ignore non-string keyword keys: - an error will be raised below */ - continue; - } + assert(PyUnicode_Check(kwname)); if (_PyUnicode_EQ(kwname, key)) { return kwstack[i]; } @@ -2275,16 +2271,11 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, j++; } - if (!PyUnicode_Check(keyword)) { - PyErr_SetString(PyExc_TypeError, - "keywords must be strings"); - return cleanreturn(0, &freelist); - } match = PySequence_Contains(kwtuple, keyword); if (match <= 0) { if (!match) { PyErr_Format(PyExc_TypeError, - "'%U' is an invalid keyword " + "'%S' is an invalid keyword " "argument for %.200s%s", keyword, (parser->fname == NULL) ? "this function" : parser->fname, @@ -2505,16 +2496,11 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, j++; } - if (!PyUnicode_Check(keyword)) { - PyErr_SetString(PyExc_TypeError, - "keywords must be strings"); - return NULL; - } match = PySequence_Contains(kwtuple, keyword); if (match <= 0) { if (!match) { PyErr_Format(PyExc_TypeError, - "'%U' is an invalid keyword " + "'%S' is an invalid keyword " "argument for %.200s%s", keyword, (parser->fname == NULL) ? "this function" : parser->fname, From webhook-mailer at python.org Fri Aug 16 22:09:32 2019 From: webhook-mailer at python.org (Tim Peters) Date: Sat, 17 Aug 2019 02:09:32 -0000 Subject: [Python-checkins] Add a minor `Fraction.__hash__()` optimization (GH-15313) Message-ID: https://github.com/python/cpython/commit/29bb227a0ce6d355a2b3e5d6a25872e3702ba9bb commit: 29bb227a0ce6d355a2b3e5d6a25872e3702ba9bb branch: master author: Tim Peters committer: GitHub date: 2019-08-16T21:09:16-05:00 summary: Add a minor `Fraction.__hash__()` optimization (GH-15313) * Add a minor `Fraction.__hash__` optimization that got lost in the shuffle. Document the optimizations. files: M Lib/fractions.py diff --git a/Lib/fractions.py b/Lib/fractions.py index c922c38e2441..2e7047a81844 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -564,10 +564,25 @@ def __hash__(self): try: dinv = pow(self._denominator, -1, _PyHASH_MODULUS) except ValueError: - # ValueError means there is no modular inverse + # ValueError means there is no modular inverse. hash_ = _PyHASH_INF else: - hash_ = hash(abs(self._numerator)) * dinv % _PyHASH_MODULUS + # The general algorithm now specifies that the absolute value of + # the hash is + # (|N| * dinv) % P + # where N is self._numerator and P is _PyHASH_MODULUS. That's + # optimized here in two ways: first, for a non-negative int i, + # hash(i) == i % P, but the int hash implementation doesn't need + # to divide, and is faster than doing % P explicitly. So we do + # hash(|N| * dinv) + # instead. Second, N is unbounded, so its product with dinv may + # be arbitrarily expensive to compute. The final answer is the + # same if we use the bounded |N| % P instead, which can again + # be done with an int hash() call. If 0 <= i < P, hash(i) == i, + # so this nested hash() call wastes a bit of time making a + # redundant copy when |N| < P, but can save an arbitrarily large + # amount of computation for large |N|. + hash_ = hash(hash(abs(self._numerator)) * dinv) result = hash_ if self._numerator >= 0 else -hash_ return -2 if result == -1 else result From webhook-mailer at python.org Sat Aug 17 16:34:15 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Aug 2019 20:34:15 -0000 Subject: [Python-checkins] fix link to time function from time_ns doc (GH-15285) Message-ID: https://github.com/python/cpython/commit/1b1d0514adbcdd859817c63d1410455c64660d78 commit: 1b1d0514adbcdd859817c63d1410455c64660d78 branch: master author: ?ric Araujo committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-17T13:34:08-07:00 summary: fix link to time function from time_ns doc (GH-15285) Because mod, func, class, etc all share one namespace, :func:time creates a link to the time module doc page rather than the time.time function. files: M Doc/library/time.rst diff --git a/Doc/library/time.rst b/Doc/library/time.rst index 6d0ceafa522a..4faa0bbebc5b 100644 --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -608,7 +608,7 @@ Functions .. function:: time_ns() -> int - Similar to :func:`time` but returns time as an integer number of nanoseconds + Similar to :func:`~time.time` but returns time as an integer number of nanoseconds since the epoch_. .. versionadded:: 3.7 From webhook-mailer at python.org Sat Aug 17 16:40:27 2019 From: webhook-mailer at python.org (Carol Willing) Date: Sat, 17 Aug 2019 20:40:27 -0000 Subject: [Python-checkins] Insert a missing close parenthesis (GH-15316) Message-ID: https://github.com/python/cpython/commit/455856391c2b4e2af79de55101421cd15901edaf commit: 455856391c2b4e2af79de55101421cd15901edaf branch: master author: cocoatomo committer: Carol Willing date: 2019-08-18T05:40:23+09:00 summary: Insert a missing close parenthesis (GH-15316) files: M Doc/c-api/veryhigh.rst diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst index 67dc11dfa9a5..cc194c200a37 100644 --- a/Doc/c-api/veryhigh.rst +++ b/Doc/c-api/veryhigh.rst @@ -117,7 +117,7 @@ the same library that the Python runtime is using. closed before PyRun_SimpleFileExFlags returns. .. note:: - On Windows, *fp* should be opened as binary mode (e.g. ``fopen(filename, "rb")``. + On Windows, *fp* should be opened as binary mode (e.g. ``fopen(filename, "rb")``). Otherwise, Python may not handle script file with LF line ending correctly. From webhook-mailer at python.org Sat Aug 17 16:50:43 2019 From: webhook-mailer at python.org (Steve Dower) Date: Sat, 17 Aug 2019 20:50:43 -0000 Subject: [Python-checkins] bpo-36266: Add module name in ImportError when DLL not found on Windows (GH-15180) Message-ID: https://github.com/python/cpython/commit/24fe46081be3d1c01b3d21cb39bc3492ab4485a3 commit: 24fe46081be3d1c01b3d21cb39bc3492ab4485a3 branch: master author: shireenrao committer: Steve Dower date: 2019-08-17T13:50:39-07:00 summary: bpo-36266: Add module name in ImportError when DLL not found on Windows (GH-15180) files: A Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst M Python/dynload_win.c diff --git a/Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst b/Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst new file mode 100644 index 000000000000..86fdd6fe17f4 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst @@ -0,0 +1 @@ +Add the module name in the formatted error message when DLL load fail happens during module import in ``_PyImport_FindSharedFuncptrWindows()``. Patch by Srinivas Nyayapati. \ No newline at end of file diff --git a/Python/dynload_win.c b/Python/dynload_win.c index 5096555e701c..6deba1134e2a 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -240,8 +240,8 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, This should not happen if called correctly. */ if (theLength == 0) { message = PyUnicode_FromFormat( - "DLL load failed with error code %u", - errorCode); + "DLL load failed with error code %u while importing %s", + errorCode, shortname); } else { /* For some reason a \r\n is appended to the text */ @@ -251,8 +251,8 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, theLength -= 2; theInfo[theLength] = '\0'; } - message = PyUnicode_FromString( - "DLL load failed: "); + message = PyUnicode_FromFormat( + "DLL load failed while importing %s: ", shortname); PyUnicode_AppendAndDel(&message, PyUnicode_FromWideChar( From webhook-mailer at python.org Sat Aug 17 16:51:15 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Aug 2019 20:51:15 -0000 Subject: [Python-checkins] fix link to time function from time_ns doc (GH-15285) Message-ID: https://github.com/python/cpython/commit/316acf27045174bf090fa5f0000eae6801e0d322 commit: 316acf27045174bf090fa5f0000eae6801e0d322 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-17T13:51:11-07:00 summary: fix link to time function from time_ns doc (GH-15285) Because mod, func, class, etc all share one namespace, :func:time creates a link to the time module doc page rather than the time.time function. (cherry picked from commit 1b1d0514adbcdd859817c63d1410455c64660d78) Co-authored-by: ?ric Araujo files: M Doc/library/time.rst diff --git a/Doc/library/time.rst b/Doc/library/time.rst index 4230c19faf10..17f8cfc54614 100644 --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -630,7 +630,7 @@ Functions .. function:: time_ns() -> int - Similar to :func:`time` but returns time as an integer number of nanoseconds + Similar to :func:`~time.time` but returns time as an integer number of nanoseconds since the epoch_. .. versionadded:: 3.7 From webhook-mailer at python.org Sat Aug 17 16:52:00 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Aug 2019 20:52:00 -0000 Subject: [Python-checkins] [3.8] fix link to time function from time_ns doc (GH-15285) (GH-15321) Message-ID: https://github.com/python/cpython/commit/7309cca1471d556c139896dd8057d1feba378113 commit: 7309cca1471d556c139896dd8057d1feba378113 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-17T13:51:57-07:00 summary: [3.8] fix link to time function from time_ns doc (GH-15285) (GH-15321) Because mod, func, class, etc all share one namespace, :func:time creates a link to the time module doc page rather than the time.time function. (cherry picked from commit 1b1d0514adbcdd859817c63d1410455c64660d78) Co-authored-by: ?ric Araujo Automerge-Triggered-By: @merwok files: M Doc/library/time.rst diff --git a/Doc/library/time.rst b/Doc/library/time.rst index 6d0ceafa522a..4faa0bbebc5b 100644 --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -608,7 +608,7 @@ Functions .. function:: time_ns() -> int - Similar to :func:`time` but returns time as an integer number of nanoseconds + Similar to :func:`~time.time` but returns time as an integer number of nanoseconds since the epoch_. .. versionadded:: 3.7 From webhook-mailer at python.org Sat Aug 17 17:11:32 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Aug 2019 21:11:32 -0000 Subject: [Python-checkins] bpo-36266: Add module name in ImportError when DLL not found on Windows (GH-15180) Message-ID: https://github.com/python/cpython/commit/786a4e1cef3eda8f434613d3801a5c7565fb5cd8 commit: 786a4e1cef3eda8f434613d3801a5c7565fb5cd8 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-17T14:11:28-07:00 summary: bpo-36266: Add module name in ImportError when DLL not found on Windows (GH-15180) (cherry picked from commit 24fe46081be3d1c01b3d21cb39bc3492ab4485a3) Co-authored-by: shireenrao files: A Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst M Python/dynload_win.c diff --git a/Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst b/Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst new file mode 100644 index 000000000000..86fdd6fe17f4 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst @@ -0,0 +1 @@ +Add the module name in the formatted error message when DLL load fail happens during module import in ``_PyImport_FindSharedFuncptrWindows()``. Patch by Srinivas Nyayapati. \ No newline at end of file diff --git a/Python/dynload_win.c b/Python/dynload_win.c index 457d47f5eed5..2f28c3cf9249 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -258,8 +258,8 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, This should not happen if called correctly. */ if (theLength == 0) { message = PyUnicode_FromFormat( - "DLL load failed with error code %u", - errorCode); + "DLL load failed with error code %u while importing %s", + errorCode, shortname); } else { /* For some reason a \r\n is appended to the text */ @@ -269,8 +269,8 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, theLength -= 2; theInfo[theLength] = '\0'; } - message = PyUnicode_FromString( - "DLL load failed: "); + message = PyUnicode_FromFormat( + "DLL load failed while importing %s: ", shortname); PyUnicode_AppendAndDel(&message, PyUnicode_FromWideChar( From webhook-mailer at python.org Mon Aug 19 05:53:41 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 19 Aug 2019 09:53:41 -0000 Subject: [Python-checkins] bpo-36502: Correct documentation of str.isspace() (GH-15019) (GH-15296) Message-ID: https://github.com/python/cpython/commit/8c1c426a631ba02357112657193f82c58d3e08b4 commit: 8c1c426a631ba02357112657193f82c58d3e08b4 branch: 3.8 author: Greg Price committer: Victor Stinner date: 2019-08-19T10:53:22+01:00 summary: bpo-36502: Correct documentation of str.isspace() (GH-15019) (GH-15296) The documented definition was much broader than the real one: there are tons of characters with general category "Other", and we don't (and shouldn't) treat most of them as whitespace. Rewrite the definition to agree with the comment on _PyUnicode_IsWhitespace, and with the logic in makeunicodedata.py, which is what generates that function and so ultimately governs. Add suitable breadcrumbs so that a reader who wants to pin down exactly what this definition means (what's a "bidirectional class" of "B"?) can do so. The `unicodedata` module documentation is an appropriate central place for our references to Unicode's own copious documentation, so point there. Also add to the isspace() test a thorough check that the implementation agrees with the intended definition. files: M Doc/library/stdtypes.rst M Lib/test/test_unicode.py diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 965167640c98..0f7c369ea51f 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1756,9 +1756,13 @@ expression support in the :mod:`re` module). .. method:: str.isspace() Return true if there are only whitespace characters in the string and there is - at least one character, false otherwise. Whitespace characters are those - characters defined in the Unicode character database as "Other" or "Separator" - and those with bidirectional property being one of "WS", "B", or "S". + at least one character, false otherwise. + + A character is *whitespace* if in the Unicode character database + (see :mod:`unicodedata`), either its general category is ``Zs`` + ("Separator, space"), or its bidirectional class is one of ``WS``, + ``B``, or ``S``. + .. method:: str.istitle() diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index 36b72e40c7e4..1d6aabdbbcc9 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -11,6 +11,7 @@ import operator import struct import sys +import unicodedata import unittest import warnings from test import support, string_tests @@ -615,11 +616,21 @@ def test_isspace(self): self.checkequalnofix(True, '\u2000', 'isspace') self.checkequalnofix(True, '\u200a', 'isspace') self.checkequalnofix(False, '\u2014', 'isspace') - # apparently there are no non-BMP spaces chars in Unicode 6 + # There are no non-BMP whitespace chars as of Unicode 12. for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E', '\U0001F40D', '\U0001F46F']: self.assertFalse(ch.isspace(), '{!a} is not space.'.format(ch)) + @support.requires_resource('cpu') + def test_isspace_invariant(self): + for codepoint in range(sys.maxunicode + 1): + char = chr(codepoint) + bidirectional = unicodedata.bidirectional(char) + category = unicodedata.category(char) + self.assertEqual(char.isspace(), + (bidirectional in ('WS', 'B', 'S') + or category == 'Zs')) + def test_isalnum(self): super().test_isalnum() for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E', From webhook-mailer at python.org Mon Aug 19 06:10:24 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 19 Aug 2019 10:10:24 -0000 Subject: [Python-checkins] bpo-36502: Correct documentation of str.isspace() (GH-15019) (GH-15296) Message-ID: https://github.com/python/cpython/commit/0fcdd8d6d67f57733203fc79e6a07a89b924a390 commit: 0fcdd8d6d67f57733203fc79e6a07a89b924a390 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-19T03:10:14-07:00 summary: bpo-36502: Correct documentation of str.isspace() (GH-15019) (GH-15296) The documented definition was much broader than the real one: there are tons of characters with general category "Other", and we don't (and shouldn't) treat most of them as whitespace. Rewrite the definition to agree with the comment on _PyUnicode_IsWhitespace, and with the logic in makeunicodedata.py, which is what generates that function and so ultimately governs. Add suitable breadcrumbs so that a reader who wants to pin down exactly what this definition means (what's a "bidirectional class" of "B"?) can do so. The `unicodedata` module documentation is an appropriate central place for our references to Unicode's own copious documentation, so point there. Also add to the isspace() test a thorough check that the implementation agrees with the intended definition. (cherry picked from commit 8c1c426a631ba02357112657193f82c58d3e08b4) Co-authored-by: Greg Price files: M Doc/library/stdtypes.rst M Lib/test/test_unicode.py diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index d35c171aba39..b9581ce1c9ae 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1731,9 +1731,13 @@ expression support in the :mod:`re` module). .. method:: str.isspace() Return true if there are only whitespace characters in the string and there is - at least one character, false otherwise. Whitespace characters are those - characters defined in the Unicode character database as "Other" or "Separator" - and those with bidirectional property being one of "WS", "B", or "S". + at least one character, false otherwise. + + A character is *whitespace* if in the Unicode character database + (see :mod:`unicodedata`), either its general category is ``Zs`` + ("Separator, space"), or its bidirectional class is one of ``WS``, + ``B``, or ``S``. + .. method:: str.istitle() diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index 1aad9334074c..4ebd82d3e0c2 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -11,6 +11,7 @@ import operator import struct import sys +import unicodedata import unittest import warnings from test import support, string_tests @@ -615,11 +616,21 @@ def test_isspace(self): self.checkequalnofix(True, '\u2000', 'isspace') self.checkequalnofix(True, '\u200a', 'isspace') self.checkequalnofix(False, '\u2014', 'isspace') - # apparently there are no non-BMP spaces chars in Unicode 6 + # There are no non-BMP whitespace chars as of Unicode 12. for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E', '\U0001F40D', '\U0001F46F']: self.assertFalse(ch.isspace(), '{!a} is not space.'.format(ch)) + @support.requires_resource('cpu') + def test_isspace_invariant(self): + for codepoint in range(sys.maxunicode + 1): + char = chr(codepoint) + bidirectional = unicodedata.bidirectional(char) + category = unicodedata.category(char) + self.assertEqual(char.isspace(), + (bidirectional in ('WS', 'B', 'S') + or category == 'Zs')) + def test_isalnum(self): super().test_isalnum() for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E', From webhook-mailer at python.org Mon Aug 19 13:07:31 2019 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 19 Aug 2019 17:07:31 -0000 Subject: [Python-checkins] Remove 'unstable' warning for Windows Store package in docs (GH-15334) Message-ID: https://github.com/python/cpython/commit/cf9360e524acafdce99a8a1e48947fd7da06f3d4 commit: cf9360e524acafdce99a8a1e48947fd7da06f3d4 branch: master author: Steve Dower committer: GitHub date: 2019-08-19T10:07:25-07:00 summary: Remove 'unstable' warning for Windows Store package in docs (GH-15334) files: M Doc/using/windows.rst diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 54f14e604b79..0b87f6e04867 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -293,12 +293,6 @@ The Microsoft Store package .. versionadded:: 3.7.2 -.. note:: - The Microsoft Store package is currently considered unstable while its - interactions with other tools and other copies of Python are evaluated. - While Python itself is stable, this installation method may change its - behavior and capabilities during Python 3.7 releases. - The Microsoft Store package is an easily installable Python interpreter that is intended mainly for interactive use, for example, by students. @@ -318,7 +312,10 @@ session by typing ``python``. Further, pip and IDLE may be used by typing All three commands are also available with version number suffixes, for example, as ``python3.exe`` and ``python3.x.exe`` as well as ``python.exe`` (where ``3.x`` is the specific version you want to launch, -such as |version|). +such as |version|). Open "Manage App Execution Aliases" through Start to +select which version of Python is associated with each command. It is +recommended to make sure that ``pip`` and ``idle`` are consistent with +whichever version of ``python`` is selected. Virtual environments can be created with ``python -m venv`` and activated and used as normal. From webhook-mailer at python.org Mon Aug 19 13:14:35 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 19 Aug 2019 17:14:35 -0000 Subject: [Python-checkins] Remove 'unstable' warning for Windows Store package in docs (GH-15334) Message-ID: https://github.com/python/cpython/commit/9aa0ab1a97a9287420bef99803872879eaa45f8f commit: 9aa0ab1a97a9287420bef99803872879eaa45f8f branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-19T10:14:31-07:00 summary: Remove 'unstable' warning for Windows Store package in docs (GH-15334) (cherry picked from commit cf9360e524acafdce99a8a1e48947fd7da06f3d4) Co-authored-by: Steve Dower files: M Doc/using/windows.rst diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 462e4c2b6c63..50eb9d3145d2 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -293,12 +293,6 @@ The Microsoft Store package .. versionadded:: 3.7.2 -.. note:: - The Microsoft Store package is currently considered unstable while its - interactions with other tools and other copies of Python are evaluated. - While Python itself is stable, this installation method may change its - behavior and capabilities during Python 3.7 releases. - The Microsoft Store package is an easily installable Python interpreter that is intended mainly for interactive use, for example, by students. @@ -318,7 +312,10 @@ session by typing ``python``. Further, pip and IDLE may be used by typing All three commands are also available with version number suffixes, for example, as ``python3.exe`` and ``python3.x.exe`` as well as ``python.exe`` (where ``3.x`` is the specific version you want to launch, -such as |version|). +such as |version|). Open "Manage App Execution Aliases" through Start to +select which version of Python is associated with each command. It is +recommended to make sure that ``pip`` and ``idle`` are consistent with +whichever version of ``python`` is selected. Virtual environments can be created with ``python -m venv`` and activated and used as normal. From webhook-mailer at python.org Mon Aug 19 18:37:21 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 19 Aug 2019 22:37:21 -0000 Subject: [Python-checkins] bpo-37788: Fix a reference leak if a thread is not joined (GH-15228) Message-ID: https://github.com/python/cpython/commit/d3dcc92778807ae8f7ebe85178f36a29711cd478 commit: d3dcc92778807ae8f7ebe85178f36a29711cd478 branch: master author: Victor Stinner committer: GitHub date: 2019-08-19T23:37:17+01:00 summary: bpo-37788: Fix a reference leak if a thread is not joined (GH-15228) Add threading.Thread.__del__() method to ensure that the thread state lock is removed from the _shutdown_locks list when a thread completes. files: A Misc/NEWS.d/next/Library/2019-08-12-17-21-10.bpo-37788.F0tR05.rst M Lib/test/test_threading.py M Lib/threading.py diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 7c16974c1630..5e90627822f9 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -761,6 +761,14 @@ def test_shutdown_locks(self): # Daemon threads must never add it to _shutdown_locks. self.assertNotIn(tstate_lock, threading._shutdown_locks) + def test_leak_without_join(self): + # bpo-37788: Test that a thread which is not joined explicitly + # does not leak. Test written for reference leak checks. + def noop(): pass + with support.wait_threads_exit(): + threading.Thread(target=noop).start() + # Thread.join() is not called + class ThreadJoinOnShutdown(BaseTestCase): diff --git a/Lib/threading.py b/Lib/threading.py index 32a3d7c30336..67e1c4facfee 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -806,6 +806,16 @@ class is implemented. # For debugging and _after_fork() _dangling.add(self) + def __del__(self): + if not self._initialized: + return + lock = self._tstate_lock + if lock is not None and not self.daemon: + # ensure that self._tstate_lock is not in _shutdown_locks + # if join() was not called explicitly + with _shutdown_locks_lock: + _shutdown_locks.discard(lock) + def _reset_internal_locks(self, is_alive): # private! Called by _after_fork() to reset our internal locks as # they may be in an invalid state leading to a deadlock or crash. diff --git a/Misc/NEWS.d/next/Library/2019-08-12-17-21-10.bpo-37788.F0tR05.rst b/Misc/NEWS.d/next/Library/2019-08-12-17-21-10.bpo-37788.F0tR05.rst new file mode 100644 index 000000000000..d9b1e82b9223 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-12-17-21-10.bpo-37788.F0tR05.rst @@ -0,0 +1 @@ +Fix a reference leak if a thread is not joined. From webhook-mailer at python.org Mon Aug 19 19:47:11 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 19 Aug 2019 23:47:11 -0000 Subject: [Python-checkins] Revert "bpo-37788: Fix a reference leak if a thread is not joined (GH-15228)" (GH-15338) Message-ID: https://github.com/python/cpython/commit/d11c2c607768fa549b1aed7899edc061b2ebf19f commit: d11c2c607768fa549b1aed7899edc061b2ebf19f branch: master author: Victor Stinner committer: GitHub date: 2019-08-20T00:47:07+01:00 summary: Revert "bpo-37788: Fix a reference leak if a thread is not joined (GH-15228)" (GH-15338) This reverts commit d3dcc92778807ae8f7ebe85178f36a29711cd478. files: D Misc/NEWS.d/next/Library/2019-08-12-17-21-10.bpo-37788.F0tR05.rst M Lib/test/test_threading.py M Lib/threading.py diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 5e90627822f9..7c16974c1630 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -761,14 +761,6 @@ def test_shutdown_locks(self): # Daemon threads must never add it to _shutdown_locks. self.assertNotIn(tstate_lock, threading._shutdown_locks) - def test_leak_without_join(self): - # bpo-37788: Test that a thread which is not joined explicitly - # does not leak. Test written for reference leak checks. - def noop(): pass - with support.wait_threads_exit(): - threading.Thread(target=noop).start() - # Thread.join() is not called - class ThreadJoinOnShutdown(BaseTestCase): diff --git a/Lib/threading.py b/Lib/threading.py index 67e1c4facfee..32a3d7c30336 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -806,16 +806,6 @@ class is implemented. # For debugging and _after_fork() _dangling.add(self) - def __del__(self): - if not self._initialized: - return - lock = self._tstate_lock - if lock is not None and not self.daemon: - # ensure that self._tstate_lock is not in _shutdown_locks - # if join() was not called explicitly - with _shutdown_locks_lock: - _shutdown_locks.discard(lock) - def _reset_internal_locks(self, is_alive): # private! Called by _after_fork() to reset our internal locks as # they may be in an invalid state leading to a deadlock or crash. diff --git a/Misc/NEWS.d/next/Library/2019-08-12-17-21-10.bpo-37788.F0tR05.rst b/Misc/NEWS.d/next/Library/2019-08-12-17-21-10.bpo-37788.F0tR05.rst deleted file mode 100644 index d9b1e82b9223..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-12-17-21-10.bpo-37788.F0tR05.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a reference leak if a thread is not joined. From webhook-mailer at python.org Mon Aug 19 21:35:18 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Tue, 20 Aug 2019 01:35:18 -0000 Subject: [Python-checkins] Delete stale comment in Python/getopt.c. (GH-14719) Message-ID: https://github.com/python/cpython/commit/d13968b1be8f4c0035b0ea891ee0f0df026cbf6c commit: d13968b1be8f4c0035b0ea891ee0f0df026cbf6c branch: master author: Hansraj Das committer: Benjamin Peterson date: 2019-08-19T18:35:13-07:00 summary: Delete stale comment in Python/getopt.c. (GH-14719) files: M Python/getopt.c diff --git a/Python/getopt.c b/Python/getopt.c index 89f773417e31..708d9ce49628 100644 --- a/Python/getopt.c +++ b/Python/getopt.c @@ -18,10 +18,6 @@ * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Nevertheless, I would like to know about bugs in this library or - * suggestions for improvement. Send bug reports and feedback to - * davegottner at delphi.com. *---------------------------------------------------------------------------*/ /* Modified to support --help and --version, as well as /? on Windows From webhook-mailer at python.org Mon Aug 19 21:41:35 2019 From: webhook-mailer at python.org (Ethan Furman) Date: Tue, 20 Aug 2019 01:41:35 -0000 Subject: [Python-checkins] Minor documentation fixes on library/enum (GH-15234) Message-ID: https://github.com/python/cpython/commit/d3c8d735147ccdde1f9bf18ba481da67564837bf commit: d3c8d735147ccdde1f9bf18ba481da67564837bf branch: master author: Antoine <43954001+awecx at users.noreply.github.com> committer: Ethan Furman date: 2019-08-19T18:41:31-07:00 summary: Minor documentation fixes on library/enum (GH-15234) * Minor documentation fixes on library/enum files: M Doc/library/enum.rst M Misc/ACKS diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index d7d319a95134..1d6912aaf19a 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -383,8 +383,8 @@ enumeration, with the exception of special methods (:meth:`__str__`, variable names listed in :attr:`_ignore_`. Note: if your enumeration defines :meth:`__new__` and/or :meth:`__init__` then -whatever value(s) were given to the enum member will be passed into those -methods. See `Planet`_ for an example. +any value(s) given to the enum member will be passed into those methods. +See `Planet`_ for an example. Restricted Enum subclassing @@ -730,8 +730,7 @@ Some rules: 2. While :class:`Enum` can have members of any type, once you mix in an additional type, all the members must have values of that type, e.g. :class:`int` above. This restriction does not apply to mix-ins which only - add methods and don't specify another data type such as :class:`int` or - :class:`str`. + add methods and don't specify another type. 3. When another data type is mixed in, the :attr:`value` attribute is *not the same* as the enum member itself, although it is equivalent and will compare equal. @@ -1054,7 +1053,7 @@ Supported ``_sunder_`` names - ``_missing_`` -- a lookup function used when a value is not found; may be overridden -- ``_ignore_`` -- a list of names, either as a :func:`list` or a :func:`str`, +- ``_ignore_`` -- a list of names, either as a :class:`list` or a :class:`str`, that will not be transformed into members, and will be removed from the final class - ``_order_`` -- used in Python 2/3 code to ensure member order is consistent diff --git a/Misc/ACKS b/Misc/ACKS index 52a5d70e5e2d..3a796860b798 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1771,6 +1771,7 @@ Steve Weber Corran Webster Glyn Webster Phil Webster +Antoine Wecxsteen Stefan Wehr Zack Weinberg Bob Weiner From webhook-mailer at python.org Tue Aug 20 01:40:32 2019 From: webhook-mailer at python.org (Eric V. Smith) Date: Tue, 20 Aug 2019 05:40:32 -0000 Subject: [Python-checkins] bpo-37868: Improve is_dataclass for instances. (GH-15325) Message-ID: https://github.com/python/cpython/commit/b0f4dab8735f692bcfedcf0fa9a25e238a554bab commit: b0f4dab8735f692bcfedcf0fa9a25e238a554bab branch: master author: Eric V. Smith committer: GitHub date: 2019-08-20T01:40:28-04:00 summary: bpo-37868: Improve is_dataclass for instances. (GH-15325) files: A Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index f778a27912de..9020c905d117 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1015,13 +1015,14 @@ def fields(class_or_instance): def _is_dataclass_instance(obj): """Returns True if obj is an instance of a dataclass.""" - return not isinstance(obj, type) and hasattr(obj, _FIELDS) + return hasattr(type(obj), _FIELDS) def is_dataclass(obj): """Returns True if obj is a dataclass or an instance of a dataclass.""" - return hasattr(obj, _FIELDS) + cls = obj if isinstance(obj, type) else type(obj) + return hasattr(cls, _FIELDS) def asdict(obj, *, dict_factory=dict): diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index ea42904b003d..037bf4c22142 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1300,6 +1300,32 @@ class D: self.assertTrue(is_dataclass(d.d)) self.assertFalse(is_dataclass(d.e)) + def test_is_dataclass_when_getattr_always_returns(self): + # See bpo-37868. + class A: + def __getattr__(self, key): + return 0 + self.assertFalse(is_dataclass(A)) + a = A() + + # Also test for an instance attribute. + class B: + pass + b = B() + b.__dataclass_fields__ = [] + + for obj in a, b: + with self.subTest(obj=obj): + self.assertFalse(is_dataclass(obj)) + + # Indirect tests for _is_dataclass_instance(). + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + asdict(obj) + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + astuple(obj) + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + replace(obj, x=0) + def test_helper_fields_with_class_instance(self): # Check that we can call fields() on either a class or instance, # and get back the same thing. diff --git a/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst b/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst new file mode 100644 index 000000000000..7f342e1ee354 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst @@ -0,0 +1,3 @@ +Fix dataclasses.is_dataclass when given an instance that never raises +AttributeError in __getattr__. That is, an object that returns something +for __dataclass_fields__ even if it's not a dataclass. From webhook-mailer at python.org Tue Aug 20 01:59:31 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 20 Aug 2019 05:59:31 -0000 Subject: [Python-checkins] bpo-37868: Improve is_dataclass for instances. (GH-15325) Message-ID: https://github.com/python/cpython/commit/1271ee8187df31debda7c556882a51ec356ca534 commit: 1271ee8187df31debda7c556882a51ec356ca534 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-19T22:59:21-07:00 summary: bpo-37868: Improve is_dataclass for instances. (GH-15325) (cherry picked from commit b0f4dab8735f692bcfedcf0fa9a25e238a554bab) Co-authored-by: Eric V. Smith files: A Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 23712fa8709d..2f0e5ff0b6e0 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1015,13 +1015,14 @@ def fields(class_or_instance): def _is_dataclass_instance(obj): """Returns True if obj is an instance of a dataclass.""" - return not isinstance(obj, type) and hasattr(obj, _FIELDS) + return hasattr(type(obj), _FIELDS) def is_dataclass(obj): """Returns True if obj is a dataclass or an instance of a dataclass.""" - return hasattr(obj, _FIELDS) + cls = obj if isinstance(obj, type) else type(obj) + return hasattr(cls, _FIELDS) def asdict(obj, *, dict_factory=dict): diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index facf9d2e2c05..0885c9798fe6 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1300,6 +1300,32 @@ class D: self.assertTrue(is_dataclass(d.d)) self.assertFalse(is_dataclass(d.e)) + def test_is_dataclass_when_getattr_always_returns(self): + # See bpo-37868. + class A: + def __getattr__(self, key): + return 0 + self.assertFalse(is_dataclass(A)) + a = A() + + # Also test for an instance attribute. + class B: + pass + b = B() + b.__dataclass_fields__ = [] + + for obj in a, b: + with self.subTest(obj=obj): + self.assertFalse(is_dataclass(obj)) + + # Indirect tests for _is_dataclass_instance(). + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + asdict(obj) + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + astuple(obj) + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + replace(obj, x=0) + def test_helper_fields_with_class_instance(self): # Check that we can call fields() on either a class or instance, # and get back the same thing. diff --git a/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst b/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst new file mode 100644 index 000000000000..7f342e1ee354 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst @@ -0,0 +1,3 @@ +Fix dataclasses.is_dataclass when given an instance that never raises +AttributeError in __getattr__. That is, an object that returns something +for __dataclass_fields__ even if it's not a dataclass. From webhook-mailer at python.org Tue Aug 20 02:02:00 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 20 Aug 2019 06:02:00 -0000 Subject: [Python-checkins] bpo-37868: Improve is_dataclass for instances. (GH-15325) Message-ID: https://github.com/python/cpython/commit/02c1457a036c2af3e91beb952afdb66d9c806435 commit: 02c1457a036c2af3e91beb952afdb66d9c806435 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-19T23:01:55-07:00 summary: bpo-37868: Improve is_dataclass for instances. (GH-15325) (cherry picked from commit b0f4dab8735f692bcfedcf0fa9a25e238a554bab) Co-authored-by: Eric V. Smith files: A Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 7725621e0fae..33e26460c74e 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1011,13 +1011,14 @@ def fields(class_or_instance): def _is_dataclass_instance(obj): """Returns True if obj is an instance of a dataclass.""" - return not isinstance(obj, type) and hasattr(obj, _FIELDS) + return hasattr(type(obj), _FIELDS) def is_dataclass(obj): """Returns True if obj is a dataclass or an instance of a dataclass.""" - return hasattr(obj, _FIELDS) + cls = obj if isinstance(obj, type) else type(obj) + return hasattr(cls, _FIELDS) def asdict(obj, *, dict_factory=dict): diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index f36098c69339..99086e5f6d25 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1294,6 +1294,32 @@ class D: self.assertTrue(is_dataclass(d.d)) self.assertFalse(is_dataclass(d.e)) + def test_is_dataclass_when_getattr_always_returns(self): + # See bpo-37868. + class A: + def __getattr__(self, key): + return 0 + self.assertFalse(is_dataclass(A)) + a = A() + + # Also test for an instance attribute. + class B: + pass + b = B() + b.__dataclass_fields__ = [] + + for obj in a, b: + with self.subTest(obj=obj): + self.assertFalse(is_dataclass(obj)) + + # Indirect tests for _is_dataclass_instance(). + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + asdict(obj) + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + astuple(obj) + with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + replace(obj, x=0) + def test_helper_fields_with_class_instance(self): # Check that we can call fields() on either a class or instance, # and get back the same thing. diff --git a/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst b/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst new file mode 100644 index 000000000000..7f342e1ee354 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst @@ -0,0 +1,3 @@ +Fix dataclasses.is_dataclass when given an instance that never raises +AttributeError in __getattr__. That is, an object that returns something +for __dataclass_fields__ even if it's not a dataclass. From webhook-mailer at python.org Tue Aug 20 07:28:10 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 20 Aug 2019 11:28:10 -0000 Subject: [Python-checkins] bpo-37732: Fix GCC warning in _PyObject_Malloc() (GH-15333) Message-ID: https://github.com/python/cpython/commit/18f8dcfa10d8a858b152d12a9ad8fa83b7e967f0 commit: 18f8dcfa10d8a858b152d12a9ad8fa83b7e967f0 branch: master author: Victor Stinner committer: GitHub date: 2019-08-20T12:28:02+01:00 summary: bpo-37732: Fix GCC warning in _PyObject_Malloc() (GH-15333) pymalloc_alloc() now returns directly the pointer, return NULL on memory allocation error. allocate_from_new_pool() already uses NULL as marker for "allocation failed". files: M Objects/obmalloc.c diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 6ca7cd84eda8..40c098ddc30a 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1580,35 +1580,35 @@ allocate_from_new_pool(uint size) /* pymalloc allocator - Return 1 if pymalloc allocated memory and wrote the pointer into *ptr_p. + Return a pointer to newly allocated memory if pymalloc allocated memory. - Return 0 if pymalloc failed to allocate the memory block: on bigger + Return NULL if pymalloc failed to allocate the memory block: on bigger requests, on error in the code below (as a last chance to serve the request) or when the max memory limit has been reached. */ -static inline int -pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) +static inline void* +pymalloc_alloc(void *ctx, size_t nbytes) { #ifdef WITH_VALGRIND if (UNLIKELY(running_on_valgrind == -1)) { running_on_valgrind = RUNNING_ON_VALGRIND; } if (UNLIKELY(running_on_valgrind)) { - return 0; + return NULL; } #endif if (UNLIKELY(nbytes == 0)) { - return 0; + return NULL; } if (UNLIKELY(nbytes > SMALL_REQUEST_THRESHOLD)) { - return 0; + return NULL; } uint size = (uint)(nbytes - 1) >> ALIGNMENT_SHIFT; poolp pool = usedpools[size + size]; block *bp; - + if (LIKELY(pool != pool->nextpool)) { /* * There is a used pool for this size class. @@ -1616,6 +1616,7 @@ pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) */ ++pool->ref.count; bp = pool->freeblock; + assert(bp != NULL); if (UNLIKELY((pool->freeblock = *(block **)bp) == NULL)) { // Reached the end of the free list, try to extend it. @@ -1627,22 +1628,17 @@ pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) * available: use a free pool. */ bp = allocate_from_new_pool(size); - if (UNLIKELY(bp == NULL)) { - return 0; - } } - assert(bp != NULL); - *ptr_p = (void *)bp; - return 1; + return (void *)bp; } static void * _PyObject_Malloc(void *ctx, size_t nbytes) { - void* ptr; - if (LIKELY(pymalloc_alloc(ctx, &ptr, nbytes))) { + void* ptr = pymalloc_alloc(ctx, nbytes); + if (LIKELY(ptr != NULL)) { return ptr; } @@ -1657,12 +1653,11 @@ _PyObject_Malloc(void *ctx, size_t nbytes) static void * _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize) { - void* ptr; - assert(elsize == 0 || nelem <= (size_t)PY_SSIZE_T_MAX / elsize); size_t nbytes = nelem * elsize; - if (LIKELY(pymalloc_alloc(ctx, &ptr, nbytes))) { + void* ptr = pymalloc_alloc(ctx, nbytes); + if (LIKELY(ptr != NULL)) { memset(ptr, 0, nbytes); return ptr; } @@ -1711,8 +1706,8 @@ insert_to_freepool(poolp pool) * are no arenas in usable_arenas with that value. */ struct arena_object* lastnf = nfp2lasta[nf]; - assert((nf == 0 && lastnf == NULL) || - (nf > 0 && + assert((nf == 0 && lastnf == NULL) || + (nf > 0 && lastnf != NULL && lastnf->nfreepools == nf && (lastnf->nextarena == NULL || From webhook-mailer at python.org Tue Aug 20 08:44:38 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 20 Aug 2019 12:44:38 -0000 Subject: [Python-checkins] bpo-37732: Fix GCC warning in _PyObject_Malloc() (GH-15333) (GH-15342) Message-ID: https://github.com/python/cpython/commit/30e5aff5fb0e3841107ddd4539a1f5b8521c80fb commit: 30e5aff5fb0e3841107ddd4539a1f5b8521c80fb branch: 3.8 author: Victor Stinner committer: GitHub date: 2019-08-20T13:44:32+01:00 summary: bpo-37732: Fix GCC warning in _PyObject_Malloc() (GH-15333) (GH-15342) pymalloc_alloc() now returns directly the pointer, return NULL on memory allocation error. allocate_from_new_pool() already uses NULL as marker for "allocation failed". (cherry picked from commit 18f8dcfa10d8a858b152d12a9ad8fa83b7e967f0) files: M Objects/obmalloc.c diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 0501cb992008..f420e1976174 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1415,13 +1415,13 @@ address_in_range(void *p, poolp pool) block allocations typically result in a couple of instructions). Unless the optimizer reorders everything, being too smart... - Return 1 if pymalloc allocated memory and wrote the pointer into *ptr_p. + Return a pointer to newly allocated memory if pymalloc allocated memory. - Return 0 if pymalloc failed to allocate the memory block: on bigger + Return NULL if pymalloc failed to allocate the memory block: on bigger requests, on error in the code below (as a last chance to serve the request) or when the max memory limit has been reached. */ -static int -pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) +static void* +pymalloc_alloc(void *ctx, size_t nbytes) { block *bp; poolp pool; @@ -1433,15 +1433,15 @@ pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) running_on_valgrind = RUNNING_ON_VALGRIND; } if (UNLIKELY(running_on_valgrind)) { - return 0; + return NULL; } #endif if (nbytes == 0) { - return 0; + return NULL; } if (nbytes > SMALL_REQUEST_THRESHOLD) { - return 0; + return NULL; } /* @@ -1609,19 +1609,18 @@ pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) success: assert(bp != NULL); - *ptr_p = (void *)bp; - return 1; + return (void *)bp; failed: - return 0; + return NULL; } static void * _PyObject_Malloc(void *ctx, size_t nbytes) { - void* ptr; - if (pymalloc_alloc(ctx, &ptr, nbytes)) { + void* ptr = pymalloc_alloc(ctx, nbytes); + if (ptr != NULL) { _Py_AllocatedBlocks++; return ptr; } @@ -1637,12 +1636,11 @@ _PyObject_Malloc(void *ctx, size_t nbytes) static void * _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize) { - void* ptr; - assert(elsize == 0 || nelem <= (size_t)PY_SSIZE_T_MAX / elsize); size_t nbytes = nelem * elsize; - if (pymalloc_alloc(ctx, &ptr, nbytes)) { + void *ptr = pymalloc_alloc(ctx, nbytes); + if (ptr != NULL) { memset(ptr, 0, nbytes); _Py_AllocatedBlocks++; return ptr; @@ -1743,8 +1741,8 @@ pymalloc_free(void *ctx, void *p) * are no arenas in usable_arenas with that value. */ struct arena_object* lastnf = nfp2lasta[nf]; - assert((nf == 0 && lastnf == NULL) || - (nf > 0 && + assert((nf == 0 && lastnf == NULL) || + (nf > 0 && lastnf != NULL && lastnf->nfreepools == nf && (lastnf->nextarena == NULL || From webhook-mailer at python.org Tue Aug 20 10:29:27 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 20 Aug 2019 14:29:27 -0000 Subject: [Python-checkins] bpo-37732: Fix GCC warning in _PyObject_Malloc() (GH-15333) (GH-15342) (GH-15343) Message-ID: https://github.com/python/cpython/commit/c9a484a1e76384680b90454018389465760dbeae commit: c9a484a1e76384680b90454018389465760dbeae branch: 3.7 author: Victor Stinner committer: GitHub date: 2019-08-20T15:29:08+01:00 summary: bpo-37732: Fix GCC warning in _PyObject_Malloc() (GH-15333) (GH-15342) (GH-15343) pymalloc_alloc() now returns directly the pointer, return NULL on memory allocation error. allocate_from_new_pool() already uses NULL as marker for "allocation failed". (cherry picked from commit 18f8dcfa10d8a858b152d12a9ad8fa83b7e967f0) (cherry picked from commit 30e5aff5fb0e3841107ddd4539a1f5b8521c80fb) files: M Objects/obmalloc.c diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 8446efcbd440..1248a3937e0d 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1377,13 +1377,13 @@ address_in_range(void *p, poolp pool) block allocations typically result in a couple of instructions). Unless the optimizer reorders everything, being too smart... - Return 1 if pymalloc allocated memory and wrote the pointer into *ptr_p. + Return a pointer to newly allocated memory if pymalloc allocated memory. - Return 0 if pymalloc failed to allocate the memory block: on bigger + Return NULL if pymalloc failed to allocate the memory block: on bigger requests, on error in the code below (as a last chance to serve the request) or when the max memory limit has been reached. */ -static int -pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) +static void* +pymalloc_alloc(void *ctx, size_t nbytes) { block *bp; poolp pool; @@ -1395,15 +1395,15 @@ pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) running_on_valgrind = RUNNING_ON_VALGRIND; } if (UNLIKELY(running_on_valgrind)) { - return 0; + return NULL; } #endif if (nbytes == 0) { - return 0; + return NULL; } if (nbytes > SMALL_REQUEST_THRESHOLD) { - return 0; + return NULL; } LOCK(); @@ -1564,20 +1564,19 @@ pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) success: UNLOCK(); assert(bp != NULL); - *ptr_p = (void *)bp; - return 1; + return (void *)bp; failed: UNLOCK(); - return 0; + return NULL; } static void * _PyObject_Malloc(void *ctx, size_t nbytes) { - void* ptr; - if (pymalloc_alloc(ctx, &ptr, nbytes)) { + void* ptr = pymalloc_alloc(ctx, nbytes); + if (ptr != NULL) { _Py_AllocatedBlocks++; return ptr; } @@ -1593,12 +1592,11 @@ _PyObject_Malloc(void *ctx, size_t nbytes) static void * _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize) { - void* ptr; - assert(elsize == 0 || nelem <= (size_t)PY_SSIZE_T_MAX / elsize); size_t nbytes = nelem * elsize; - if (pymalloc_alloc(ctx, &ptr, nbytes)) { + void *ptr = pymalloc_alloc(ctx, nbytes); + if (ptr != NULL) { memset(ptr, 0, nbytes); _Py_AllocatedBlocks++; return ptr; From webhook-mailer at python.org Tue Aug 20 10:46:50 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 20 Aug 2019 14:46:50 -0000 Subject: [Python-checkins] bpo-15913: Implement PyBuffer_SizeFromFormat() (GH-13873) Message-ID: https://github.com/python/cpython/commit/9e66aba99925eebacfe137d9deb0ef1fdbc2d5db commit: 9e66aba99925eebacfe137d9deb0ef1fdbc2d5db branch: master author: Joannah Nanjekye <33177550+nanjekyejoannah at users.noreply.github.com> committer: Victor Stinner date: 2019-08-20T15:46:36+01:00 summary: bpo-15913: Implement PyBuffer_SizeFromFormat() (GH-13873) Implement PyBuffer_SizeFromFormat() function (previously documented but not implemented): call struct.calcsize(). files: A Misc/NEWS.d/next/Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst M Doc/c-api/buffer.rst M Include/cpython/abstract.h M Lib/test/test_buffer.py M Modules/_testcapimodule.c M Objects/abstract.c diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst old mode 100644 new mode 100755 index fdb8bd19d218..2536c743b247 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -462,10 +462,12 @@ Buffer-related functions :c:func:`PyObject_GetBuffer`. -.. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *) +.. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *format) Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. - This function is not yet implemented. + On error, raise an exception and return -1. + + .. versionadded:: 3.9 .. c:function:: int PyBuffer_IsContiguous(Py_buffer *view, char order) diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h old mode 100644 new mode 100755 index 62a113fc00e2..04e4a9e7bd27 --- a/Include/cpython/abstract.h +++ b/Include/cpython/abstract.h @@ -243,7 +243,7 @@ PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices); /* Return the implied itemsize of the data-format area from a struct-style description. */ -PyAPI_FUNC(int) PyBuffer_SizeFromFormat(const char *); +PyAPI_FUNC(Py_ssize_t) PyBuffer_SizeFromFormat(const char *format); /* Implementation in memoryobject.c */ PyAPI_FUNC(int) PyBuffer_ToContiguous(void *buf, Py_buffer *view, diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py old mode 100644 new mode 100755 index 47413c03d663..5fa52bffc22b --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -43,6 +43,11 @@ except ImportError: numpy_array = None +try: + import _testcapi +except ImportError: + _testcapi = None + SHORT_TEST = True @@ -4412,6 +4417,13 @@ def test_issue_7385(self): x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL) self.assertRaises(BufferError, memoryview, x) + @support.cpython_only + def test_pybuffer_size_from_format(self): + # basic tests + for format in ('', 'ii', '3s'): + self.assertEqual(_testcapi.PyBuffer_SizeFromFormat(format), + struct.calcsize(format)) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst b/Misc/NEWS.d/next/Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst new file mode 100644 index 000000000000..0fbfcb37abb4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst @@ -0,0 +1,3 @@ +Implement :c:func:`PyBuffer_SizeFromFormat()` function (previously +documented but not implemented): call :func:`struct.calcsize`. +Patch by Joannah Nanjekye. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c old mode 100644 new mode 100755 index 8a6e741d2810..84f2651641c7 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3363,6 +3363,26 @@ getbuffer_with_null_view(PyObject* self, PyObject *obj) Py_RETURN_NONE; } +/* PyBuffer_SizeFromFormat() */ +static PyObject * +test_PyBuffer_SizeFromFormat(PyObject *self, PyObject *args) +{ + const char *format; + Py_ssize_t result; + + if (!PyArg_ParseTuple(args, "s:test_PyBuffer_SizeFromFormat", + &format)) { + return NULL; + } + + result = PyBuffer_SizeFromFormat(format); + if (result == -1) { + return NULL; + } + + return PyLong_FromSsize_t(result); +} + /* Test that the fatal error from not having a current thread doesn't cause an infinite loop. Run via Lib/test/test_capi.py */ static PyObject * @@ -5153,6 +5173,7 @@ static PyMethodDef TestMethods[] = { {"test_pep3118_obsolete_write_locks", (PyCFunction)test_pep3118_obsolete_write_locks, METH_NOARGS}, #endif {"getbuffer_with_null_view", getbuffer_with_null_view, METH_O}, + {"PyBuffer_SizeFromFormat", test_PyBuffer_SizeFromFormat, METH_VARARGS}, {"test_buildvalue_N", test_buildvalue_N, METH_NOARGS}, {"get_args", get_args, METH_VARARGS}, {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS}, diff --git a/Objects/abstract.c b/Objects/abstract.c old mode 100644 new mode 100755 index f93d73fa7571..3db56fab2c8d --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -495,6 +495,48 @@ _Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape) } } +Py_ssize_t +PyBuffer_SizeFromFormat(const char *format) +{ + PyObject *structmodule = NULL; + PyObject *calcsize = NULL; + PyObject *res = NULL; + PyObject *fmt = NULL; + Py_ssize_t itemsize = -1; + + structmodule = PyImport_ImportModule("struct"); + if (structmodule == NULL) { + return itemsize; + } + + calcsize = PyObject_GetAttrString(structmodule, "calcsize"); + if (calcsize == NULL) { + goto done; + } + + fmt = PyUnicode_FromString(format); + if (fmt == NULL) { + goto done; + } + + res = PyObject_CallFunctionObjArgs(calcsize, fmt, NULL); + if (res == NULL) { + goto done; + } + + itemsize = PyLong_AsSsize_t(res); + if (itemsize < 0) { + goto done; + } + +done: + Py_DECREF(structmodule); + Py_XDECREF(calcsize); + Py_XDECREF(fmt); + Py_XDECREF(res); + return itemsize; +} + int PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort) { From webhook-mailer at python.org Tue Aug 20 13:52:38 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 20 Aug 2019 17:52:38 -0000 Subject: [Python-checkins] bpo-32793: Fix a duplicate debug message in smtplib (GH-15341) Message-ID: https://github.com/python/cpython/commit/46a7564578f208df1e0c54fc0520d3b7ca32c981 commit: 46a7564578f208df1e0c54fc0520d3b7ca32c981 branch: master author: Zackery Spytz committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-20T10:52:25-07:00 summary: bpo-32793: Fix a duplicate debug message in smtplib (GH-15341) _get_socket() already prints a debug message for the host and port. https://bugs.python.org/issue32793 Automerge-Triggered-By: @maxking files: A Misc/NEWS.d/next/Library/2019-08-20-05-17-32.bpo-32793.cgpXl6.rst M Lib/smtplib.py diff --git a/Lib/smtplib.py b/Lib/smtplib.py index a634f7ae7336..43a00d9a4e3c 100755 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -333,8 +333,6 @@ def connect(self, host='localhost', port=0, source_address=None): raise OSError("nonnumeric port") if not port: port = self.default_port - if self.debuglevel > 0: - self._print_debug('connect:', (host, port)) sys.audit("smtplib.connect", self, host, port) self.sock = self._get_socket(host, port, self.timeout) self.file = None diff --git a/Misc/NEWS.d/next/Library/2019-08-20-05-17-32.bpo-32793.cgpXl6.rst b/Misc/NEWS.d/next/Library/2019-08-20-05-17-32.bpo-32793.cgpXl6.rst new file mode 100644 index 000000000000..f715a816efda --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-20-05-17-32.bpo-32793.cgpXl6.rst @@ -0,0 +1 @@ +Fix a duplicated debug message when :meth:`smtplib.SMTP.connect` is called. From webhook-mailer at python.org Tue Aug 20 15:21:00 2019 From: webhook-mailer at python.org (Brett Cannon) Date: Tue, 20 Aug 2019 19:21:00 -0000 Subject: [Python-checkins] Remove a dead comment from ossaudiodev.c (#15346) Message-ID: https://github.com/python/cpython/commit/1407038e0bcd3f2543c50cd5476d2d2f15a2a9fb commit: 1407038e0bcd3f2543c50cd5476d2d2f15a2a9fb branch: master author: Brett Cannon <54418+brettcannon at users.noreply.github.com> committer: GitHub date: 2019-08-20T12:20:47-07:00 summary: Remove a dead comment from ossaudiodev.c (#15346) files: M Modules/ossaudiodev.c diff --git a/Modules/ossaudiodev.c b/Modules/ossaudiodev.c index 6e050e4bc4ca..c94ba9255acd 100644 --- a/Modules/ossaudiodev.c +++ b/Modules/ossaudiodev.c @@ -14,8 +14,6 @@ * (c) 2002 Gregory P. Ward. All Rights Reserved. * (c) 2002 Python Software Foundation. All Rights Reserved. * - * XXX need a license statement - * * $Id$ */ From webhook-mailer at python.org Tue Aug 20 22:19:50 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 21 Aug 2019 02:19:50 -0000 Subject: [Python-checkins] abstract.c should not be executable. (GH-15348) Message-ID: https://github.com/python/cpython/commit/d33e46d17d33f9b918846982c02ddc17d897c9bc commit: d33e46d17d33f9b918846982c02ddc17d897c9bc branch: master author: Benjamin Peterson committer: GitHub date: 2019-08-20T19:19:43-07:00 summary: abstract.c should not be executable. (GH-15348) files: M Objects/abstract.c diff --git a/Objects/abstract.c b/Objects/abstract.c old mode 100755 new mode 100644 From webhook-mailer at python.org Tue Aug 20 23:51:01 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 21 Aug 2019 03:51:01 -0000 Subject: [Python-checkins] bpo-35518: Skip test that relies on a deceased network service. (GH-15349) Message-ID: https://github.com/python/cpython/commit/5b95a1507e349da5adae6d2ab57deac3bdd12f15 commit: 5b95a1507e349da5adae6d2ab57deac3bdd12f15 branch: master author: Greg Price committer: Benjamin Peterson date: 2019-08-20T20:50:50-07:00 summary: bpo-35518: Skip test that relies on a deceased network service. (GH-15349) If this service had thoroughly vanished, we could just ignore the test until someone gets around to either recreating such a service or redesigning the test to somehow work locally. The `support.transient_internet` mechanism catches the failure to resolve the domain name, and skips the test. But in fact the domain snakebite.net does still exist, as do its nameservers -- and they can be quite slow to reply. As a result this test can easily take 20-30s before it gets auto-skipped. So, skip the test explicitly up front. files: M Lib/test/test_timeout.py diff --git a/Lib/test/test_timeout.py b/Lib/test/test_timeout.py index b54fc826ae0a..b07c07cbfc4d 100644 --- a/Lib/test/test_timeout.py +++ b/Lib/test/test_timeout.py @@ -150,6 +150,7 @@ def setUp(self): def tearDown(self): self.sock.close() + @unittest.skipIf(True, 'need to replace these hosts; see bpo-35518') def testConnectTimeout(self): # Testing connect timeout is tricky: we need to have IP connectivity # to a host that silently drops our packets. We can't simulate this From webhook-mailer at python.org Wed Aug 21 00:09:01 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 04:09:01 -0000 Subject: [Python-checkins] bpo-35518: Skip test that relies on a deceased network service. (GH-15349) Message-ID: https://github.com/python/cpython/commit/44f2c096804e8e3adc09400a59ef9c9ae843f339 commit: 44f2c096804e8e3adc09400a59ef9c9ae843f339 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-20T21:08:57-07:00 summary: bpo-35518: Skip test that relies on a deceased network service. (GH-15349) If this service had thoroughly vanished, we could just ignore the test until someone gets around to either recreating such a service or redesigning the test to somehow work locally. The `support.transient_internet` mechanism catches the failure to resolve the domain name, and skips the test. But in fact the domain snakebite.net does still exist, as do its nameservers -- and they can be quite slow to reply. As a result this test can easily take 20-30s before it gets auto-skipped. So, skip the test explicitly up front. (cherry picked from commit 5b95a1507e349da5adae6d2ab57deac3bdd12f15) Co-authored-by: Greg Price files: M Lib/test/test_timeout.py diff --git a/Lib/test/test_timeout.py b/Lib/test/test_timeout.py index b54fc826ae0a..b07c07cbfc4d 100644 --- a/Lib/test/test_timeout.py +++ b/Lib/test/test_timeout.py @@ -150,6 +150,7 @@ def setUp(self): def tearDown(self): self.sock.close() + @unittest.skipIf(True, 'need to replace these hosts; see bpo-35518') def testConnectTimeout(self): # Testing connect timeout is tricky: we need to have IP connectivity # to a host that silently drops our packets. We can't simulate this From webhook-mailer at python.org Wed Aug 21 00:11:29 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 04:11:29 -0000 Subject: [Python-checkins] bpo-35518: Skip test that relies on a deceased network service. (GH-15349) Message-ID: https://github.com/python/cpython/commit/b9d88e771238b5098842cad8a6ad624621f3f62e commit: b9d88e771238b5098842cad8a6ad624621f3f62e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-20T21:11:25-07:00 summary: bpo-35518: Skip test that relies on a deceased network service. (GH-15349) If this service had thoroughly vanished, we could just ignore the test until someone gets around to either recreating such a service or redesigning the test to somehow work locally. The `support.transient_internet` mechanism catches the failure to resolve the domain name, and skips the test. But in fact the domain snakebite.net does still exist, as do its nameservers -- and they can be quite slow to reply. As a result this test can easily take 20-30s before it gets auto-skipped. So, skip the test explicitly up front. (cherry picked from commit 5b95a1507e349da5adae6d2ab57deac3bdd12f15) Co-authored-by: Greg Price files: M Lib/test/test_timeout.py diff --git a/Lib/test/test_timeout.py b/Lib/test/test_timeout.py index b54fc826ae0a..b07c07cbfc4d 100644 --- a/Lib/test/test_timeout.py +++ b/Lib/test/test_timeout.py @@ -150,6 +150,7 @@ def setUp(self): def tearDown(self): self.sock.close() + @unittest.skipIf(True, 'need to replace these hosts; see bpo-35518') def testConnectTimeout(self): # Testing connect timeout is tricky: we need to have IP connectivity # to a host that silently drops our packets. We can't simulate this From webhook-mailer at python.org Wed Aug 21 00:12:21 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 04:12:21 -0000 Subject: [Python-checkins] bpo-35518: Skip test that relies on a deceased network service. (GH-15349) Message-ID: https://github.com/python/cpython/commit/198a0d622a696a4c234aa7866d6c15e38839cc76 commit: 198a0d622a696a4c234aa7866d6c15e38839cc76 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-20T21:12:18-07:00 summary: bpo-35518: Skip test that relies on a deceased network service. (GH-15349) If this service had thoroughly vanished, we could just ignore the test until someone gets around to either recreating such a service or redesigning the test to somehow work locally. The `support.transient_internet` mechanism catches the failure to resolve the domain name, and skips the test. But in fact the domain snakebite.net does still exist, as do its nameservers -- and they can be quite slow to reply. As a result this test can easily take 20-30s before it gets auto-skipped. So, skip the test explicitly up front. (cherry picked from commit 5b95a1507e349da5adae6d2ab57deac3bdd12f15) Co-authored-by: Greg Price files: M Lib/test/test_timeout.py diff --git a/Lib/test/test_timeout.py b/Lib/test/test_timeout.py index bb9252d1a433..51690335b70e 100644 --- a/Lib/test/test_timeout.py +++ b/Lib/test/test_timeout.py @@ -106,6 +106,7 @@ def setUp(self): def tearDown(self): self.sock.close() + @unittest.skipIf(True, 'need to replace these hosts; see bpo-35518') def testConnectTimeout(self): # Choose a private address that is unlikely to exist to prevent # failures due to the connect succeeding before the timeout. From webhook-mailer at python.org Wed Aug 21 00:54:03 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 04:54:03 -0000 Subject: [Python-checkins] Unmark files as executable that can't actually be executed. (GH-15353) Message-ID: https://github.com/python/cpython/commit/9ece4a5057d52c42a8a064a6c0c7f923267fb3db commit: 9ece4a5057d52c42a8a064a6c0c7f923267fb3db branch: master author: Greg Price committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-20T21:53:59-07:00 summary: Unmark files as executable that can't actually be executed. (GH-15353) There are plenty of legitimate scripts in the tree that begin with a `#!`, but also a few that seem to be marked executable by mistake. Found them with this command -- it gets executable files known to Git, filters to the ones that don't start with a `#!`, and then unmarks them as executable: $ git ls-files --stage \ | perl -lane 'print $F[3] if (!/^100644/)' \ | while read f; do head -c2 "$f" | grep -qxF '#!' \ || chmod a-x "$f"; \ done Looking at the list by hand confirms that we didn't sweep up any files that should have the executable bit after all. In particular * The `.psd` files are images from Photoshop. * The `.bat` files sure look like things that can be run. But we have lots of other `.bat` files, and they don't have this bit set, so it must not be needed for them. Automerge-Triggered-By: @benjaminp files: M .azure-pipelines/posix-deps-apt.sh M Doc/c-api/buffer.rst M Include/cpython/abstract.h M Lib/idlelib/idle.bat M Lib/test/test_buffer.py M Lib/test/test_dataclasses.py M Lib/test/test_importlib/test_abc.py M Lib/turtledemo/two_canvases.py M Mac/Resources/iconsrc/PythonCompiled.psd M Mac/Resources/iconsrc/PythonIcon.psd M Mac/Resources/iconsrc/PythonSource.psd M Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst M Modules/_decimal/tests/runall.bat M Modules/_testcapimodule.c M Modules/socketmodule.c M Modules/socketmodule.h diff --git a/.azure-pipelines/posix-deps-apt.sh b/.azure-pipelines/posix-deps-apt.sh index 4f489903ab56..e0f4ca5d8d8e 100755 --- a/.azure-pipelines/posix-deps-apt.sh +++ b/.azure-pipelines/posix-deps-apt.sh @@ -1,3 +1,4 @@ +#!/bin/sh apt-get update apt-get -yq install \ diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst old mode 100755 new mode 100644 diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h old mode 100755 new mode 100644 diff --git a/Lib/idlelib/idle.bat b/Lib/idlelib/idle.bat old mode 100755 new mode 100644 diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py old mode 100755 new mode 100644 diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py old mode 100755 new mode 100644 diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py old mode 100755 new mode 100644 diff --git a/Lib/turtledemo/two_canvases.py b/Lib/turtledemo/two_canvases.py old mode 100755 new mode 100644 diff --git a/Mac/Resources/iconsrc/PythonCompiled.psd b/Mac/Resources/iconsrc/PythonCompiled.psd old mode 100755 new mode 100644 diff --git a/Mac/Resources/iconsrc/PythonIcon.psd b/Mac/Resources/iconsrc/PythonIcon.psd old mode 100755 new mode 100644 diff --git a/Mac/Resources/iconsrc/PythonSource.psd b/Mac/Resources/iconsrc/PythonSource.psd old mode 100755 new mode 100644 diff --git a/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst b/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst old mode 100755 new mode 100644 diff --git a/Modules/_decimal/tests/runall.bat b/Modules/_decimal/tests/runall.bat old mode 100755 new mode 100644 diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c old mode 100755 new mode 100644 diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c old mode 100755 new mode 100644 diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h old mode 100755 new mode 100644 From webhook-mailer at python.org Wed Aug 21 05:59:24 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 21 Aug 2019 09:59:24 -0000 Subject: [Python-checkins] bpo-37531: Enhance regrtest multiprocess timeout (GH-15345) Message-ID: https://github.com/python/cpython/commit/de2d9eed8bc628533e1628b843cc4c7a5010f6e5 commit: de2d9eed8bc628533e1628b843cc4c7a5010f6e5 branch: master author: Victor Stinner committer: GitHub date: 2019-08-21T10:59:20+01:00 summary: bpo-37531: Enhance regrtest multiprocess timeout (GH-15345) * Write a message when killing a worker process * Put a timeout on the second popen.communicate() call (after killing the process) * Put a timeout on popen.wait() call * Catch popen.kill() and popen.wait() exceptions files: A Misc/NEWS.d/next/Tests/2019-08-20-19-24-19.bpo-37531.wRoXfU.rst M Lib/test/libregrtest/runtest_mp.py diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index eed643291162..c22479b7976f 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -126,6 +126,38 @@ def __repr__(self): info.append(f'pid={popen.pid}') return '<%s>' % ' '.join(info) + def _kill(self): + dt = time.monotonic() - self.start_time + + popen = self._popen + pid = popen.pid + print("Kill worker process %s running for %.1f sec" % (pid, dt), + file=sys.stderr, flush=True) + + try: + popen.kill() + return True + except OSError as exc: + print("WARNING: Failed to kill worker process %s: %r" % (pid, exc), + file=sys.stderr, flush=True) + return False + + def _close_wait(self): + popen = self._popen + + # stdout and stderr must be closed to ensure that communicate() + # does not hang + popen.stdout.close() + popen.stderr.close() + + try: + popen.wait(JOIN_TIMEOUT) + except (subprocess.TimeoutExpired, OSError) as exc: + print("WARNING: Failed to wait for worker process %s " + "completion (timeout=%.1f sec): %r" + % (popen.pid, JOIN_TIMEOUT, exc), + file=sys.stderr, flush=True) + def kill(self): """ Kill the current process (if any). @@ -135,15 +167,13 @@ def kill(self): """ self._killed = True - popen = self._popen - if popen is None: + if self._popen is None: return - popen.kill() - # stdout and stderr must be closed to ensure that communicate() - # does not hang - popen.stdout.close() - popen.stderr.close() - popen.wait() + + if not self._kill(): + return + + self._close_wait() def mp_result_error(self, test_name, error_type, stdout='', stderr='', err_msg=None): @@ -151,6 +181,23 @@ def mp_result_error(self, test_name, error_type, stdout='', stderr='', result = TestResult(test_name, error_type, test_time, None) return MultiprocessResult(result, stdout, stderr, err_msg) + def _timedout(self, test_name): + self._kill() + + stdout = sterr = '' + popen = self._popen + try: + stdout, stderr = popen.communicate(timeout=JOIN_TIMEOUT) + except (subprocess.TimeoutExpired, OSError) as exc: + print("WARNING: Failed to read worker process %s output " + "(timeout=%.1f sec): %r" + % (popen.pid, exc, timeout), + file=sys.stderr, flush=True) + + self._close_wait() + + return self.mp_result_error(test_name, TIMEOUT, stdout, stderr) + def _runtest(self, test_name): try: self.start_time = time.monotonic() @@ -158,7 +205,7 @@ def _runtest(self, test_name): self._popen = run_test_in_subprocess(test_name, self.ns) popen = self._popen - with popen: + try: try: if self._killed: # If kill() has been called before self._popen is set, @@ -175,12 +222,7 @@ def _runtest(self, test_name): # on reading closed stdout/stderr raise ExitThread - popen.kill() - stdout, stderr = popen.communicate() - self.kill() - - return self.mp_result_error(test_name, TIMEOUT, - stdout, stderr) + return self._timedout(test_name) except OSError: if self._killed: # kill() has been called: communicate() fails @@ -190,8 +232,10 @@ def _runtest(self, test_name): except: self.kill() raise + finally: + self._close_wait() - retcode = popen.wait() + retcode = popen.returncode finally: self.current_test_name = None self._popen = None @@ -286,10 +330,11 @@ def wait_workers(self): if not worker.is_alive(): break dt = time.monotonic() - start_time - print("Wait for regrtest worker %r for %.1f sec" % (worker, dt)) + print("Wait for regrtest worker %r for %.1f sec" % (worker, dt), + flush=True) if dt > JOIN_TIMEOUT: print("Warning -- failed to join a regrtest worker %s" - % worker) + % worker, flush=True) break def _get_result(self): diff --git a/Misc/NEWS.d/next/Tests/2019-08-20-19-24-19.bpo-37531.wRoXfU.rst b/Misc/NEWS.d/next/Tests/2019-08-20-19-24-19.bpo-37531.wRoXfU.rst new file mode 100644 index 000000000000..59500ce67a01 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-08-20-19-24-19.bpo-37531.wRoXfU.rst @@ -0,0 +1,3 @@ +Enhance regrtest multiprocess timeout: write a message when killing a worker +process, catch popen.kill() and popen.wait() exceptions, put a timeout on the +second call to popen.communicate(). From webhook-mailer at python.org Wed Aug 21 07:13:43 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 21 Aug 2019 11:13:43 -0000 Subject: [Python-checkins] bpo-37823: Fix open() link in telnetlib doc (GH-15281) Message-ID: https://github.com/python/cpython/commit/e0b6117e2723327d6741d0aa599408514add5b30 commit: e0b6117e2723327d6741d0aa599408514add5b30 branch: master author: Michael Anckaert committer: Victor Stinner date: 2019-08-21T12:13:34+01:00 summary: bpo-37823: Fix open() link in telnetlib doc (GH-15281) Fixed wrong link to Telnet.open() method in telnetlib documentation. files: M Doc/library/telnetlib.rst diff --git a/Doc/library/telnetlib.rst b/Doc/library/telnetlib.rst index 0262a9b08410..48a9aea50ddd 100644 --- a/Doc/library/telnetlib.rst +++ b/Doc/library/telnetlib.rst @@ -29,7 +29,7 @@ Character), EL (Erase Line), GA (Go Ahead), SB (Subnegotiation Begin). .. class:: Telnet(host=None, port=0[, timeout]) :class:`Telnet` represents a connection to a Telnet server. The instance is - initially not connected by default; the :meth:`open` method must be used to + initially not connected by default; the :meth:`~Telnet.open` method must be used to establish a connection. Alternatively, the host name and optional port number can be passed to the constructor too, in which case the connection to the server will be established before the constructor returns. The optional From webhook-mailer at python.org Wed Aug 21 07:38:09 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 11:38:09 -0000 Subject: [Python-checkins] bpo-37823: Fix open() link in telnetlib doc (GH-15281) Message-ID: https://github.com/python/cpython/commit/c777dec6f47ce649f3dea88d308e36e45538fdac commit: c777dec6f47ce649f3dea88d308e36e45538fdac branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-21T04:38:04-07:00 summary: bpo-37823: Fix open() link in telnetlib doc (GH-15281) Fixed wrong link to Telnet.open() method in telnetlib documentation. (cherry picked from commit e0b6117e2723327d6741d0aa599408514add5b30) Co-authored-by: Michael Anckaert files: M Doc/library/telnetlib.rst diff --git a/Doc/library/telnetlib.rst b/Doc/library/telnetlib.rst index 0262a9b08410..48a9aea50ddd 100644 --- a/Doc/library/telnetlib.rst +++ b/Doc/library/telnetlib.rst @@ -29,7 +29,7 @@ Character), EL (Erase Line), GA (Go Ahead), SB (Subnegotiation Begin). .. class:: Telnet(host=None, port=0[, timeout]) :class:`Telnet` represents a connection to a Telnet server. The instance is - initially not connected by default; the :meth:`open` method must be used to + initially not connected by default; the :meth:`~Telnet.open` method must be used to establish a connection. Alternatively, the host name and optional port number can be passed to the constructor too, in which case the connection to the server will be established before the constructor returns. The optional From webhook-mailer at python.org Wed Aug 21 07:38:29 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 11:38:29 -0000 Subject: [Python-checkins] bpo-37823: Fix open() link in telnetlib doc (GH-15281) Message-ID: https://github.com/python/cpython/commit/72088d56247ee422d8abeef94a89be463737b982 commit: 72088d56247ee422d8abeef94a89be463737b982 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-21T04:38:25-07:00 summary: bpo-37823: Fix open() link in telnetlib doc (GH-15281) Fixed wrong link to Telnet.open() method in telnetlib documentation. (cherry picked from commit e0b6117e2723327d6741d0aa599408514add5b30) Co-authored-by: Michael Anckaert files: M Doc/library/telnetlib.rst diff --git a/Doc/library/telnetlib.rst b/Doc/library/telnetlib.rst index 4ba426425277..931711963b16 100644 --- a/Doc/library/telnetlib.rst +++ b/Doc/library/telnetlib.rst @@ -29,7 +29,7 @@ Character), EL (Erase Line), GA (Go Ahead), SB (Subnegotiation Begin). .. class:: Telnet(host=None, port=0[, timeout]) :class:`Telnet` represents a connection to a Telnet server. The instance is - initially not connected by default; the :meth:`open` method must be used to + initially not connected by default; the :meth:`~Telnet.open` method must be used to establish a connection. Alternatively, the host name and optional port number can be passed to the constructor too, in which case the connection to the server will be established before the constructor returns. The optional From webhook-mailer at python.org Wed Aug 21 07:52:09 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 11:52:09 -0000 Subject: [Python-checkins] bpo-37823: Fix open() link in telnetlib doc (GH-15281) Message-ID: https://github.com/python/cpython/commit/98b11e1160a1749bfdb48bbf4c0dda177296b005 commit: 98b11e1160a1749bfdb48bbf4c0dda177296b005 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-21T04:52:05-07:00 summary: bpo-37823: Fix open() link in telnetlib doc (GH-15281) Fixed wrong link to Telnet.open() method in telnetlib documentation. (cherry picked from commit e0b6117e2723327d6741d0aa599408514add5b30) Co-authored-by: Michael Anckaert files: M Doc/library/telnetlib.rst diff --git a/Doc/library/telnetlib.rst b/Doc/library/telnetlib.rst index a3019f5fc3c9..73721f5fe153 100644 --- a/Doc/library/telnetlib.rst +++ b/Doc/library/telnetlib.rst @@ -29,7 +29,7 @@ Character), EL (Erase Line), GA (Go Ahead), SB (Subnegotiation Begin). .. class:: Telnet([host[, port[, timeout]]]) :class:`Telnet` represents a connection to a Telnet server. The instance is - initially not connected by default; the :meth:`open` method must be used to + initially not connected by default; the :meth:`~Telnet.open` method must be used to establish a connection. Alternatively, the host name and optional port number can be passed to the constructor, to, in which case the connection to the server will be established before the constructor returns. The optional From webhook-mailer at python.org Wed Aug 21 08:41:05 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 21 Aug 2019 12:41:05 -0000 Subject: [Python-checkins] bpo-37851: faulthandler allocates its stack on demand (GH-15358) Message-ID: https://github.com/python/cpython/commit/d8c5adf6f83024238545aac0bb465289cc2dde84 commit: d8c5adf6f83024238545aac0bb465289cc2dde84 branch: master author: Victor Stinner committer: GitHub date: 2019-08-21T13:40:42+01:00 summary: bpo-37851: faulthandler allocates its stack on demand (GH-15358) The faulthandler module no longer allocates its alternative stack at Python startup. Now the stack is only allocated at the first faulthandler usage. faulthandler no longer ignores memory allocation failure when allocating the stack. sigaltstack() failure now raises an OSError exception, rather than being ignored. The alternative stack is no longer used if sigaction() is not available. In practice, sigaltstack() should only be available when sigaction() is avaialble, so this change should have no effect in practice. faulthandler.dump_traceback_later() internal locks are now only allocated at the first dump_traceback_later() call, rather than always being allocated at Python startup. files: A Misc/NEWS.d/next/Library/2019-08-21-13-43-04.bpo-37851.mIIfD_.rst M Modules/faulthandler.c diff --git a/Misc/NEWS.d/next/Library/2019-08-21-13-43-04.bpo-37851.mIIfD_.rst b/Misc/NEWS.d/next/Library/2019-08-21-13-43-04.bpo-37851.mIIfD_.rst new file mode 100644 index 000000000000..997011f023f2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-21-13-43-04.bpo-37851.mIIfD_.rst @@ -0,0 +1,3 @@ +The :mod:`faulthandler` module no longer allocates its alternative stack at +Python startup. Now the stack is only allocated at the first faulthandler +usage. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 5dbbcad057e6..35e7b34c29cc 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -125,7 +125,13 @@ static fault_handler_t faulthandler_handlers[] = { static const size_t faulthandler_nsignals = \ Py_ARRAY_LENGTH(faulthandler_handlers); -#ifdef HAVE_SIGALTSTACK +/* Using an alternative stack requires sigaltstack() + and sigaction() SA_ONSTACK */ +#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION) +# define FAULTHANDLER_USE_ALT_STACK +#endif + +#ifdef FAULTHANDLER_USE_ALT_STACK static stack_t stack; static stack_t old_stack; #endif @@ -427,6 +433,36 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) } #endif + +#ifdef FAULTHANDLER_USE_ALT_STACK +static int +faulthandler_allocate_stack(void) +{ + if (stack.ss_sp != NULL) { + return 0; + } + /* Allocate an alternate stack for faulthandler() signal handler + to be able to execute a signal handler on a stack overflow error */ + stack.ss_sp = PyMem_Malloc(stack.ss_size); + if (stack.ss_sp == NULL) { + PyErr_NoMemory(); + return -1; + } + + int err = sigaltstack(&stack, &old_stack); + if (err) { + /* Release the stack to retry sigaltstack() next time */ + PyMem_Free(stack.ss_sp); + stack.ss_sp = NULL; + + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + return 0; +} +#endif + + /* Install the handler for fatal signals, faulthandler_fatal_error(). */ static int @@ -437,32 +473,35 @@ faulthandler_enable(void) } fatal_error.enabled = 1; +#ifdef FAULTHANDLER_USE_ALT_STACK + if (faulthandler_allocate_stack() < 0) { + return -1; + } +#endif + for (size_t i=0; i < faulthandler_nsignals; i++) { fault_handler_t *handler; -#ifdef HAVE_SIGACTION - struct sigaction action; -#endif int err; handler = &faulthandler_handlers[i]; assert(!handler->enabled); #ifdef HAVE_SIGACTION + struct sigaction action; action.sa_handler = faulthandler_fatal_error; sigemptyset(&action.sa_mask); /* Do not prevent the signal from being received from within its own signal handler */ action.sa_flags = SA_NODEFER; -#ifdef HAVE_SIGALTSTACK - if (stack.ss_sp != NULL) { - /* Call the signal handler on an alternate signal stack - provided by sigaltstack() */ - action.sa_flags |= SA_ONSTACK; - } +#ifdef FAULTHANDLER_USE_ALT_STACK + assert(stack.ss_sp != NULL); + /* Call the signal handler on an alternate signal stack + provided by sigaltstack() */ + action.sa_flags |= SA_ONSTACK; #endif err = sigaction(handler->signum, &action, &handler->previous); #else handler->previous = signal(handler->signum, - faulthandler_fatal_error); + faulthandler_fatal_error); err = (handler->previous == SIG_ERR); #endif if (err) { @@ -676,17 +715,37 @@ faulthandler_dump_traceback_later(PyObject *self, } tstate = get_thread_state(); - if (tstate == NULL) + if (tstate == NULL) { return NULL; + } fd = faulthandler_get_fileno(&file); - if (fd < 0) + if (fd < 0) { return NULL; + } + + if (!thread.running) { + thread.running = PyThread_allocate_lock(); + if (!thread.running) { + return PyErr_NoMemory(); + } + } + if (!thread.cancel_event) { + thread.cancel_event = PyThread_allocate_lock(); + if (!thread.cancel_event || !thread.running) { + return PyErr_NoMemory(); + } + + /* cancel_event starts to be acquired: it's only released to cancel + the thread. */ + PyThread_acquire_lock(thread.cancel_event, 1); + } /* format the timeout */ header = format_timeout(timeout_us); - if (header == NULL) + if (header == NULL) { return PyErr_NoMemory(); + } header_len = strlen(header); /* Cancel previous thread, if running */ @@ -728,9 +787,10 @@ faulthandler_cancel_dump_traceback_later_py(PyObject *self, } #endif /* FAULTHANDLER_LATER */ + #ifdef FAULTHANDLER_USER static int -faulthandler_register(int signum, int chain, _Py_sighandler_t *p_previous) +faulthandler_register(int signum, int chain, _Py_sighandler_t *previous_p) { #ifdef HAVE_SIGACTION struct sigaction action; @@ -745,19 +805,19 @@ faulthandler_register(int signum, int chain, _Py_sighandler_t *p_previous) own signal handler */ action.sa_flags = SA_NODEFER; } -#ifdef HAVE_SIGALTSTACK - if (stack.ss_sp != NULL) { - /* Call the signal handler on an alternate signal stack - provided by sigaltstack() */ - action.sa_flags |= SA_ONSTACK; - } +#ifdef FAULTHANDLER_USE_ALT_STACK + assert(stack.ss_sp != NULL); + /* Call the signal handler on an alternate signal stack + provided by sigaltstack() */ + action.sa_flags |= SA_ONSTACK; #endif - return sigaction(signum, &action, p_previous); + return sigaction(signum, &action, previous_p); #else _Py_sighandler_t previous; previous = signal(signum, faulthandler_user); - if (p_previous != NULL) - *p_previous = previous; + if (previous_p != NULL) { + *previous_p = previous; + } return (previous == SIG_ERR); #endif } @@ -861,6 +921,12 @@ faulthandler_register_py(PyObject *self, user = &user_signals[signum]; if (!user->enabled) { +#ifdef FAULTHANDLER_USE_ALT_STACK + if (faulthandler_allocate_stack() < 0) { + return NULL; + } +#endif + err = faulthandler_register(signum, chain, &previous); if (err) { PyErr_SetFromErrno(PyExc_OSError); @@ -1094,7 +1160,7 @@ faulthandler_fatal_error_py(PyObject *self, PyObject *args) Py_RETURN_NONE; } -#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION) +#if defined(FAULTHANDLER_USE_ALT_STACK) #define FAULTHANDLER_STACK_OVERFLOW #ifdef __INTEL_COMPILER @@ -1153,7 +1219,7 @@ faulthandler_stack_overflow(PyObject *self, PyObject *Py_UNUSED(ignored)) size, depth); return NULL; } -#endif /* defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION) */ +#endif /* defined(FAULTHANDLER_USE_ALT_STACK) && defined(HAVE_SIGACTION) */ static int @@ -1318,35 +1384,18 @@ faulthandler_init_enable(void) PyStatus _PyFaulthandler_Init(int enable) { -#ifdef HAVE_SIGALTSTACK - int err; - - /* Try to allocate an alternate stack for faulthandler() signal handler to - * be able to allocate memory on the stack, even on a stack overflow. If it - * fails, ignore the error. */ +#ifdef FAULTHANDLER_USE_ALT_STACK + memset(&stack, 0, sizeof(stack)); stack.ss_flags = 0; /* bpo-21131: allocate dedicated stack of SIGSTKSZ*2 bytes, instead of just SIGSTKSZ bytes. Calling the previous signal handler in faulthandler signal handler uses more than SIGSTKSZ bytes of stack memory on some platforms. */ stack.ss_size = SIGSTKSZ * 2; - stack.ss_sp = PyMem_Malloc(stack.ss_size); - if (stack.ss_sp != NULL) { - err = sigaltstack(&stack, &old_stack); - if (err) { - PyMem_Free(stack.ss_sp); - stack.ss_sp = NULL; - } - } #endif + #ifdef FAULTHANDLER_LATER - thread.file = NULL; - thread.cancel_event = PyThread_allocate_lock(); - thread.running = PyThread_allocate_lock(); - if (!thread.cancel_event || !thread.running) { - return _PyStatus_ERR("failed to allocate locks for faulthandler"); - } - PyThread_acquire_lock(thread.cancel_event, 1); + memset(&thread, 0, sizeof(thread)); #endif if (enable) { @@ -1386,7 +1435,8 @@ void _PyFaulthandler_Fini(void) /* fatal */ faulthandler_disable(); -#ifdef HAVE_SIGALTSTACK + +#ifdef FAULTHANDLER_USE_ALT_STACK if (stack.ss_sp != NULL) { /* Fetch the current alt stack */ stack_t current_stack; From webhook-mailer at python.org Wed Aug 21 09:08:51 2019 From: webhook-mailer at python.org (Carol Willing) Date: Wed, 21 Aug 2019 13:08:51 -0000 Subject: [Python-checkins] bpo-37860: Add netlify deploy preview for docs (GH-15288) Message-ID: https://github.com/python/cpython/commit/87bc3b7a0b0c41ea5da2aa137c4145f437a1c9fd commit: 87bc3b7a0b0c41ea5da2aa137c4145f437a1c9fd branch: master author: Ashwin Ramaswami committer: Carol Willing date: 2019-08-21T22:08:47+09:00 summary: bpo-37860: Add netlify deploy preview for docs (GH-15288) * add netlify deploy preview * fix publish path * install python3 venv * add sudo * try without venv * install right dependencies * use python3, not python * use pip3 * python3.7 * use requirements.txt * move requirements.txt to Doc * use python 3.7 in runtime.txt * move runtime.txt * Update requirements.txt files: A Doc/requirements.txt A Doc/runtime.txt A netlify.toml diff --git a/Doc/requirements.txt b/Doc/requirements.txt new file mode 100644 index 000000000000..e0d7ca869af8 --- /dev/null +++ b/Doc/requirements.txt @@ -0,0 +1,5 @@ +# Requirements for docs build on netlify +# Pin sphinx to version specified in .travis.yml +sphinx==2.0.1 +blurb +python-docs-theme diff --git a/Doc/runtime.txt b/Doc/runtime.txt new file mode 100644 index 000000000000..548d71365f0e --- /dev/null +++ b/Doc/runtime.txt @@ -0,0 +1 @@ +3.7 \ No newline at end of file diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 000000000000..387c8f954ada --- /dev/null +++ b/netlify.toml @@ -0,0 +1,4 @@ +[build] + base = "Doc/" + command = "make html" + publish = "Doc/build/html" \ No newline at end of file From webhook-mailer at python.org Wed Aug 21 09:26:34 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 21 Aug 2019 13:26:34 -0000 Subject: [Python-checkins] bpo-37751: Fix codecs.lookup() normalization (GH-15092) Message-ID: https://github.com/python/cpython/commit/20f59fe1f7748ae899aceee4cb560e5e1f528a1f commit: 20f59fe1f7748ae899aceee4cb560e5e1f528a1f branch: master author: Jordon Xu <46997731+qigangxu at users.noreply.github.com> committer: Victor Stinner date: 2019-08-21T14:26:20+01:00 summary: bpo-37751: Fix codecs.lookup() normalization (GH-15092) Fix codecs.lookup() to normalize the encoding name the same way than encodings.normalize_encoding(), except that codecs.lookup() also converts the name to lower case. files: A Misc/NEWS.d/next/Core and Builtins/2019-08-20-04-36-37.bpo-37751.CSFzUd.rst M Python/codecs.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-20-04-36-37.bpo-37751.CSFzUd.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-20-04-36-37.bpo-37751.CSFzUd.rst new file mode 100644 index 000000000000..4da59ff4c1c9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-20-04-36-37.bpo-37751.CSFzUd.rst @@ -0,0 +1 @@ +Fix :func:`codecs.lookup` to normalize the encoding name the same way than :func:`encodings.normalize_encoding`, except that :func:`codecs.lookup` also converts the name to lower case. diff --git a/Python/codecs.c b/Python/codecs.c index 4f38b33e0b76..08e9b916f201 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -49,15 +49,16 @@ int PyCodec_Register(PyObject *search_function) return -1; } -/* Convert a string to a normalized Python string: all characters are - converted to lower case, spaces are replaced with underscores. */ +extern int _Py_normalize_encoding(const char *, char *, size_t); + +/* Convert a string to a normalized Python string(decoded from UTF-8): all characters are + converted to lower case, spaces and hyphens are replaced with underscores. */ static PyObject *normalizestring(const char *string) { - size_t i; size_t len = strlen(string); - char *p; + char *encoding; PyObject *v; if (len > PY_SSIZE_T_MAX) { @@ -65,20 +66,19 @@ PyObject *normalizestring(const char *string) return NULL; } - p = PyMem_Malloc(len + 1); - if (p == NULL) + encoding = PyMem_Malloc(len + 1); + if (encoding == NULL) return PyErr_NoMemory(); - for (i = 0; i < len; i++) { - char ch = string[i]; - if (ch == ' ') - ch = '-'; - else - ch = Py_TOLOWER(Py_CHARMASK(ch)); - p[i] = ch; + + if (!_Py_normalize_encoding(string, encoding, len + 1)) + { + PyErr_SetString(PyExc_RuntimeError, "_Py_normalize_encoding() failed"); + PyMem_Free(encoding); + return NULL; } - p[i] = '\0'; - v = PyUnicode_FromString(p); - PyMem_Free(p); + + v = PyUnicode_FromString(encoding); + PyMem_Free(encoding); return v; } From webhook-mailer at python.org Wed Aug 21 11:59:16 2019 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 21 Aug 2019 15:59:16 -0000 Subject: [Python-checkins] Update asyncio.ensure_future() documentation (GH-15347) Message-ID: https://github.com/python/cpython/commit/092911d5c0d8f6db8a0cb02fecd73dbb650f9e2e commit: 092911d5c0d8f6db8a0cb02fecd73dbb650f9e2e branch: master author: Roger Iyengar committer: Yury Selivanov date: 2019-08-21T11:59:11-04:00 summary: Update asyncio.ensure_future() documentation (GH-15347) Added back mention that ensure_future actually scheduled obj. This documentation just mentions what ensure_future returns, so I did not realize that ensure_future also schedules obj. files: M Doc/library/asyncio-future.rst diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index 6e6e0137c1bd..c069471b519b 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -35,7 +35,9 @@ Future Functions is used for the test.) * a :class:`Task` object wrapping *obj*, if *obj* is a - coroutine (:func:`iscoroutine` is used for the test.) + coroutine (:func:`iscoroutine` is used for the test); + in this case the coroutine will be scheduled by + ``ensure_future()``. * a :class:`Task` object that would await on *obj*, if *obj* is an awaitable (:func:`inspect.isawaitable` is used for the test.) From webhook-mailer at python.org Wed Aug 21 13:01:58 2019 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 21 Aug 2019 17:01:58 -0000 Subject: [Python-checkins] Update asyncio.ensure_future() documentation (GH-15347) (GH-15361) Message-ID: https://github.com/python/cpython/commit/fb3d7423f7ee4f6413774567d04b2f98b254e5f7 commit: fb3d7423f7ee4f6413774567d04b2f98b254e5f7 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov date: 2019-08-21T13:01:53-04:00 summary: Update asyncio.ensure_future() documentation (GH-15347) (GH-15361) Added back mention that ensure_future actually scheduled obj. This documentation just mentions what ensure_future returns, so I did not realize that ensure_future also schedules obj. (cherry picked from commit 092911d5c0d8f6db8a0cb02fecd73dbb650f9e2e) Co-authored-by: Roger Iyengar files: M Doc/library/asyncio-future.rst diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index 6e6e0137c1bd..c069471b519b 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -35,7 +35,9 @@ Future Functions is used for the test.) * a :class:`Task` object wrapping *obj*, if *obj* is a - coroutine (:func:`iscoroutine` is used for the test.) + coroutine (:func:`iscoroutine` is used for the test); + in this case the coroutine will be scheduled by + ``ensure_future()``. * a :class:`Task` object that would await on *obj*, if *obj* is an awaitable (:func:`inspect.isawaitable` is used for the test.) From webhook-mailer at python.org Wed Aug 21 13:21:03 2019 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 21 Aug 2019 17:21:03 -0000 Subject: [Python-checkins] Update asyncio.ensure_future() documentation (GH-15347) (GH-15364) Message-ID: https://github.com/python/cpython/commit/349d897e0f54f2991ffe518c8ac3ef55c30c293b commit: 349d897e0f54f2991ffe518c8ac3ef55c30c293b branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov date: 2019-08-21T13:20:49-04:00 summary: Update asyncio.ensure_future() documentation (GH-15347) (GH-15364) Added back mention that ensure_future actually scheduled obj. This documentation just mentions what ensure_future returns, so I did not realize that ensure_future also schedules obj. (cherry picked from commit 092911d5c0d8f6db8a0cb02fecd73dbb650f9e2e) Co-authored-by: Roger Iyengar files: M Doc/library/asyncio-future.rst diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index 6e6e0137c1bd..c069471b519b 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -35,7 +35,9 @@ Future Functions is used for the test.) * a :class:`Task` object wrapping *obj*, if *obj* is a - coroutine (:func:`iscoroutine` is used for the test.) + coroutine (:func:`iscoroutine` is used for the test); + in this case the coroutine will be scheduled by + ``ensure_future()``. * a :class:`Task` object that would await on *obj*, if *obj* is an awaitable (:func:`inspect.isawaitable` is used for the test.) From webhook-mailer at python.org Wed Aug 21 14:59:32 2019 From: webhook-mailer at python.org (Tim Peters) Date: Wed, 21 Aug 2019 18:59:32 -0000 Subject: [Python-checkins] Fix difflib `?` hint in diff output when dealing with tabs (#15201) Message-ID: https://github.com/python/cpython/commit/e1c638da6a065af6803028ced1afcc679e63f59d commit: e1c638da6a065af6803028ced1afcc679e63f59d branch: master author: Anthony Sottile committer: Tim Peters date: 2019-08-21T13:59:25-05:00 summary: Fix difflib `?` hint in diff output when dealing with tabs (#15201) files: A Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst M Lib/difflib.py M Lib/test/test_difflib.py diff --git a/Lib/difflib.py b/Lib/difflib.py index 887c3c26cae4..3de1b3d0fcdf 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -733,20 +733,15 @@ def get_close_matches(word, possibilities, n=3, cutoff=0.6): # Strip scores for the best n matches return [x for score, x in result] -def _count_leading(line, ch): - """ - Return number of `ch` characters at the start of `line`. - Example: +def _keep_original_ws(s, tag_s): + """Replace whitespace with the original whitespace characters in `s`""" + return ''.join( + c if tag_c == " " and c.isspace() else tag_c + for c, tag_c in zip(s, tag_s) + ) - >>> _count_leading(' abc', ' ') - 3 - """ - i, n = 0, len(line) - while i < n and line[i] == ch: - i += 1 - return i class Differ: r""" @@ -1033,7 +1028,7 @@ def _fancy_helper(self, a, alo, ahi, b, blo, bhi): def _qformat(self, aline, bline, atags, btags): r""" - Format "?" output and deal with leading tabs. + Format "?" output and deal with tabs. Example: @@ -1047,22 +1042,16 @@ def _qformat(self, aline, bline, atags, btags): '+ \tabcdefGhijkl\n' '? \t ^ ^ ^\n' """ - - # Can hurt, but will probably help most of the time. - common = min(_count_leading(aline, "\t"), - _count_leading(bline, "\t")) - common = min(common, _count_leading(atags[:common], " ")) - common = min(common, _count_leading(btags[:common], " ")) - atags = atags[common:].rstrip() - btags = btags[common:].rstrip() + atags = _keep_original_ws(aline, atags).rstrip() + btags = _keep_original_ws(bline, btags).rstrip() yield "- " + aline if atags: - yield "? %s%s\n" % ("\t" * common, atags) + yield f"? {atags}\n" yield "+ " + bline if btags: - yield "? %s%s\n" % ("\t" * common, btags) + yield f"? {btags}\n" # With respect to junk, an earlier version of ndiff simply refused to # *start* a match with a junk element. The result was cases like this: diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py index 745ccbd6659e..5e2ca1a23b92 100644 --- a/Lib/test/test_difflib.py +++ b/Lib/test/test_difflib.py @@ -89,10 +89,16 @@ def test_added_tab_hint(self): # Check fix for bug #1488943 diff = list(difflib.Differ().compare(["\tI am a buggy"],["\t\tI am a bug"])) self.assertEqual("- \tI am a buggy", diff[0]) - self.assertEqual("? --\n", diff[1]) + self.assertEqual("? \t --\n", diff[1]) self.assertEqual("+ \t\tI am a bug", diff[2]) self.assertEqual("? +\n", diff[3]) + def test_hint_indented_properly_with_tabs(self): + diff = list(difflib.Differ().compare(["\t \t \t^"], ["\t \t \t^\n"])) + self.assertEqual("- \t \t \t^", diff[0]) + self.assertEqual("+ \t \t \t^\n", diff[1]) + self.assertEqual("? \t \t \t +\n", diff[2]) + def test_mdiff_catch_stop_iteration(self): # Issue #33224 self.assertEqual( diff --git a/Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst b/Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst new file mode 100644 index 000000000000..3e0b31775d07 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst @@ -0,0 +1,2 @@ +Fix :mod:`difflib` ``?`` hint in diff output when dealing with tabs. Patch +by Anthony Sottile. From webhook-mailer at python.org Wed Aug 21 15:18:32 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 19:18:32 -0000 Subject: [Python-checkins] Fix difflib `?` hint in diff output when dealing with tabs (GH-15201) Message-ID: https://github.com/python/cpython/commit/7e293f5e4c27592c6808bd7db13d7bd09dd7f5a0 commit: 7e293f5e4c27592c6808bd7db13d7bd09dd7f5a0 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-21T12:18:26-07:00 summary: Fix difflib `?` hint in diff output when dealing with tabs (GH-15201) (cherry picked from commit e1c638da6a065af6803028ced1afcc679e63f59d) Co-authored-by: Anthony Sottile files: A Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst M Lib/difflib.py M Lib/test/test_difflib.py diff --git a/Lib/difflib.py b/Lib/difflib.py index 887c3c26cae4..3de1b3d0fcdf 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -733,20 +733,15 @@ def get_close_matches(word, possibilities, n=3, cutoff=0.6): # Strip scores for the best n matches return [x for score, x in result] -def _count_leading(line, ch): - """ - Return number of `ch` characters at the start of `line`. - Example: +def _keep_original_ws(s, tag_s): + """Replace whitespace with the original whitespace characters in `s`""" + return ''.join( + c if tag_c == " " and c.isspace() else tag_c + for c, tag_c in zip(s, tag_s) + ) - >>> _count_leading(' abc', ' ') - 3 - """ - i, n = 0, len(line) - while i < n and line[i] == ch: - i += 1 - return i class Differ: r""" @@ -1033,7 +1028,7 @@ def _fancy_helper(self, a, alo, ahi, b, blo, bhi): def _qformat(self, aline, bline, atags, btags): r""" - Format "?" output and deal with leading tabs. + Format "?" output and deal with tabs. Example: @@ -1047,22 +1042,16 @@ def _qformat(self, aline, bline, atags, btags): '+ \tabcdefGhijkl\n' '? \t ^ ^ ^\n' """ - - # Can hurt, but will probably help most of the time. - common = min(_count_leading(aline, "\t"), - _count_leading(bline, "\t")) - common = min(common, _count_leading(atags[:common], " ")) - common = min(common, _count_leading(btags[:common], " ")) - atags = atags[common:].rstrip() - btags = btags[common:].rstrip() + atags = _keep_original_ws(aline, atags).rstrip() + btags = _keep_original_ws(bline, btags).rstrip() yield "- " + aline if atags: - yield "? %s%s\n" % ("\t" * common, atags) + yield f"? {atags}\n" yield "+ " + bline if btags: - yield "? %s%s\n" % ("\t" * common, btags) + yield f"? {btags}\n" # With respect to junk, an earlier version of ndiff simply refused to # *start* a match with a junk element. The result was cases like this: diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py index 745ccbd6659e..5e2ca1a23b92 100644 --- a/Lib/test/test_difflib.py +++ b/Lib/test/test_difflib.py @@ -89,10 +89,16 @@ def test_added_tab_hint(self): # Check fix for bug #1488943 diff = list(difflib.Differ().compare(["\tI am a buggy"],["\t\tI am a bug"])) self.assertEqual("- \tI am a buggy", diff[0]) - self.assertEqual("? --\n", diff[1]) + self.assertEqual("? \t --\n", diff[1]) self.assertEqual("+ \t\tI am a bug", diff[2]) self.assertEqual("? +\n", diff[3]) + def test_hint_indented_properly_with_tabs(self): + diff = list(difflib.Differ().compare(["\t \t \t^"], ["\t \t \t^\n"])) + self.assertEqual("- \t \t \t^", diff[0]) + self.assertEqual("+ \t \t \t^\n", diff[1]) + self.assertEqual("? \t \t \t +\n", diff[2]) + def test_mdiff_catch_stop_iteration(self): # Issue #33224 self.assertEqual( diff --git a/Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst b/Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst new file mode 100644 index 000000000000..3e0b31775d07 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst @@ -0,0 +1,2 @@ +Fix :mod:`difflib` ``?`` hint in diff output when dealing with tabs. Patch +by Anthony Sottile. From webhook-mailer at python.org Wed Aug 21 16:43:10 2019 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 21 Aug 2019 20:43:10 -0000 Subject: [Python-checkins] bpo-9949: Enable symlink traversal for ntpath.realpath (GH-15287) Message-ID: https://github.com/python/cpython/commit/75e064962ee0e31ec19a8081e9d9cc957baf6415 commit: 75e064962ee0e31ec19a8081e9d9cc957baf6415 branch: master author: Steve Dower committer: GitHub date: 2019-08-21T13:43:06-07:00 summary: bpo-9949: Enable symlink traversal for ntpath.realpath (GH-15287) files: A Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst M Doc/library/os.path.rst M Doc/whatsnew/3.8.rst M Lib/ntpath.py M Lib/test/test_ntpath.py M Lib/test/test_os.py M Lib/test/test_shutil.py M Lib/unittest/test/test_discovery.py diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index a673b81278ea..640ceecbc78f 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -350,11 +350,19 @@ the :mod:`glob` module.) .. function:: realpath(path) Return the canonical path of the specified filename, eliminating any symbolic - links encountered in the path (if they are supported by the operating system). + links encountered in the path (if they are supported by the operating + system). + + .. note:: + When symbolic link cycles occur, the returned path will be one member of + the cycle, but no guarantee is made about which member that will be. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: 3.8 + Symbolic links and junctions are now resolved on Windows. + .. function:: relpath(path, start=os.curdir) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index e8238251d6ea..93758e96b573 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -824,6 +824,9 @@ characters or bytes unrepresentable at the OS level. environment variable and does not use :envvar:`HOME`, which is not normally set for regular user accounts. +:func:`~os.path.realpath` on Windows now resolves reparse points, including +symlinks and directory junctions. + ncurses ------- diff --git a/Lib/ntpath.py b/Lib/ntpath.py index f3cfabf0238e..ef4999e1473a 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -519,8 +519,94 @@ def abspath(path): except (OSError, ValueError): return _abspath_fallback(path) -# realpath is a no-op on systems without islink support -realpath = abspath +try: + from nt import _getfinalpathname, readlink as _nt_readlink +except ImportError: + # realpath is a no-op on systems without _getfinalpathname support. + realpath = abspath +else: + def _readlink_deep(path, seen=None): + if seen is None: + seen = set() + + while normcase(path) not in seen: + seen.add(normcase(path)) + try: + path = _nt_readlink(path) + except OSError as ex: + # Stop on file (2) or directory (3) not found, or + # paths that are not reparse points (4390) + if ex.winerror in (2, 3, 4390): + break + raise + except ValueError: + # Stop on reparse points that are not symlinks + break + return path + + def _getfinalpathname_nonstrict(path): + # Fast path to get the final path name. If this succeeds, there + # is no need to go any further. + try: + return _getfinalpathname(path) + except OSError: + pass + + # Allow file (2) or directory (3) not found, invalid syntax (123), + # and symlinks that cannot be followed (1921) + allowed_winerror = 2, 3, 123, 1921 + + # Non-strict algorithm is to find as much of the target directory + # as we can and join the rest. + tail = '' + seen = set() + while path: + try: + path = _readlink_deep(path, seen) + path = _getfinalpathname(path) + return join(path, tail) if tail else path + except OSError as ex: + if ex.winerror not in allowed_winerror: + raise + path, name = split(path) + if path and not name: + return abspath(path + tail) + tail = join(name, tail) if tail else name + return abspath(tail) + + def realpath(path): + path = os.fspath(path) + if isinstance(path, bytes): + prefix = b'\\\\?\\' + unc_prefix = b'\\\\?\\UNC\\' + new_unc_prefix = b'\\\\' + cwd = os.getcwdb() + else: + prefix = '\\\\?\\' + unc_prefix = '\\\\?\\UNC\\' + new_unc_prefix = '\\\\' + cwd = os.getcwd() + had_prefix = path.startswith(prefix) + path = _getfinalpathname_nonstrict(path) + # The path returned by _getfinalpathname will always start with \\?\ - + # strip off that prefix unless it was already provided on the original + # path. + if not had_prefix and path.startswith(prefix): + # For UNC paths, the prefix will actually be \\?\UNC\ + # Handle that case as well. + if path.startswith(unc_prefix): + spath = new_unc_prefix + path[len(unc_prefix):] + else: + spath = path[len(prefix):] + # Ensure that the non-prefixed path resolves to the same path + try: + if _getfinalpathname(spath) == path: + path = spath + except OSError as ex: + pass + return path + + # Win9x family and earlier have no Unicode filename support. supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and sys.getwindowsversion()[3] >= 2) @@ -633,23 +719,6 @@ def commonpath(paths): raise -# determine if two files are in fact the same file -try: - # GetFinalPathNameByHandle is available starting with Windows 6.0. - # Windows XP and non-Windows OS'es will mock _getfinalpathname. - if sys.getwindowsversion()[:2] >= (6, 0): - from nt import _getfinalpathname - else: - raise ImportError -except (AttributeError, ImportError): - # On Windows XP and earlier, two files are the same if their absolute - # pathnames are the same. - # Non-Windows operating systems fake this method with an XP - # approximation. - def _getfinalpathname(f): - return normcase(abspath(f)) - - try: # The genericpath.isdir implementation uses os.stat and checks the mode # attribute to tell whether or not the path is a directory. diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 92d85ecbc4fc..74dc8c378e27 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -7,6 +7,7 @@ from test import support, test_genericpath from tempfile import TemporaryFile + try: import nt except ImportError: @@ -14,6 +15,14 @@ # but for those that require it we import here. nt = None +try: + ntpath._getfinalpathname +except AttributeError: + HAVE_GETFINALPATHNAME = False +else: + HAVE_GETFINALPATHNAME = True + + def tester(fn, wantResult): fn = fn.replace("\\", "\\\\") gotResult = eval(fn) @@ -194,6 +203,189 @@ def test_normpath(self): tester("ntpath.normpath('\\\\.\\NUL')", r'\\.\NUL') tester("ntpath.normpath('\\\\?\\D:/XY\\Z')", r'\\?\D:/XY\Z') + def test_realpath_curdir(self): + expected = ntpath.normpath(os.getcwd()) + tester("ntpath.realpath('.')", expected) + tester("ntpath.realpath('./.')", expected) + tester("ntpath.realpath('/'.join(['.'] * 100))", expected) + tester("ntpath.realpath('.\\.')", expected) + tester("ntpath.realpath('\\'.join(['.'] * 100))", expected) + + def test_realpath_pardir(self): + expected = ntpath.normpath(os.getcwd()) + tester("ntpath.realpath('..')", ntpath.dirname(expected)) + tester("ntpath.realpath('../..')", + ntpath.dirname(ntpath.dirname(expected))) + tester("ntpath.realpath('/'.join(['..'] * 50))", + ntpath.splitdrive(expected)[0] + '\\') + tester("ntpath.realpath('..\\..')", + ntpath.dirname(ntpath.dirname(expected))) + tester("ntpath.realpath('\\'.join(['..'] * 50))", + ntpath.splitdrive(expected)[0] + '\\') + + @support.skip_unless_symlink + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_basic(self): + ABSTFN = ntpath.abspath(support.TESTFN) + open(ABSTFN, "wb").close() + self.addCleanup(support.unlink, ABSTFN) + self.addCleanup(support.unlink, ABSTFN + "1") + + os.symlink(ABSTFN, ABSTFN + "1") + self.assertEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN) + self.assertEqual(ntpath.realpath(os.fsencode(ABSTFN + "1")), + os.fsencode(ABSTFN)) + + @support.skip_unless_symlink + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_relative(self): + ABSTFN = ntpath.abspath(support.TESTFN) + open(ABSTFN, "wb").close() + self.addCleanup(support.unlink, ABSTFN) + self.addCleanup(support.unlink, ABSTFN + "1") + + os.symlink(ABSTFN, ntpath.relpath(ABSTFN + "1")) + self.assertEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN) + + @support.skip_unless_symlink + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_broken_symlinks(self): + ABSTFN = ntpath.abspath(support.TESTFN) + os.mkdir(ABSTFN) + self.addCleanup(support.rmtree, ABSTFN) + + with support.change_cwd(ABSTFN): + os.mkdir("subdir") + os.chdir("subdir") + os.symlink(".", "recursive") + os.symlink("..", "parent") + os.chdir("..") + os.symlink(".", "self") + os.symlink("missing", "broken") + os.symlink(r"broken\bar", "broken1") + os.symlink(r"self\self\broken", "broken2") + os.symlink(r"subdir\parent\subdir\parent\broken", "broken3") + os.symlink(ABSTFN + r"\broken", "broken4") + os.symlink(r"recursive\..\broken", "broken5") + + self.assertEqual(ntpath.realpath("broken"), + ABSTFN + r"\missing") + self.assertEqual(ntpath.realpath(r"broken\foo"), + ABSTFN + r"\missing\foo") + self.assertEqual(ntpath.realpath(r"broken1"), + ABSTFN + r"\missing\bar") + self.assertEqual(ntpath.realpath(r"broken1\baz"), + ABSTFN + r"\missing\bar\baz") + self.assertEqual(ntpath.realpath("broken2"), + ABSTFN + r"\missing") + self.assertEqual(ntpath.realpath("broken3"), + ABSTFN + r"\missing") + self.assertEqual(ntpath.realpath("broken4"), + ABSTFN + r"\missing") + self.assertEqual(ntpath.realpath("broken5"), + ABSTFN + r"\missing") + + self.assertEqual(ntpath.realpath(b"broken"), + os.fsencode(ABSTFN + r"\missing")) + self.assertEqual(ntpath.realpath(rb"broken\foo"), + os.fsencode(ABSTFN + r"\missing\foo")) + self.assertEqual(ntpath.realpath(rb"broken1"), + os.fsencode(ABSTFN + r"\missing\bar")) + self.assertEqual(ntpath.realpath(rb"broken1\baz"), + os.fsencode(ABSTFN + r"\missing\bar\baz")) + self.assertEqual(ntpath.realpath(b"broken2"), + os.fsencode(ABSTFN + r"\missing")) + self.assertEqual(ntpath.realpath(rb"broken3"), + os.fsencode(ABSTFN + r"\missing")) + self.assertEqual(ntpath.realpath(b"broken4"), + os.fsencode(ABSTFN + r"\missing")) + self.assertEqual(ntpath.realpath(b"broken5"), + os.fsencode(ABSTFN + r"\missing")) + + @support.skip_unless_symlink + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_symlink_loops(self): + # Bug #930024, return the path unchanged if we get into an infinite + # symlink loop. + ABSTFN = ntpath.abspath(support.TESTFN) + self.addCleanup(support.unlink, ABSTFN) + self.addCleanup(support.unlink, ABSTFN + "1") + self.addCleanup(support.unlink, ABSTFN + "2") + self.addCleanup(support.unlink, ABSTFN + "y") + self.addCleanup(support.unlink, ABSTFN + "c") + self.addCleanup(support.unlink, ABSTFN + "a") + + P = "\\\\?\\" + + os.symlink(ABSTFN, ABSTFN) + self.assertEqual(ntpath.realpath(ABSTFN), P + ABSTFN) + + # cycles are non-deterministic as to which path is returned, but + # it will always be the fully resolved path of one member of the cycle + os.symlink(ABSTFN + "1", ABSTFN + "2") + os.symlink(ABSTFN + "2", ABSTFN + "1") + expected = (P + ABSTFN + "1", P + ABSTFN + "2") + self.assertIn(ntpath.realpath(ABSTFN + "1"), expected) + self.assertIn(ntpath.realpath(ABSTFN + "2"), expected) + + self.assertIn(ntpath.realpath(ABSTFN + "1\\x"), + (ntpath.join(r, "x") for r in expected)) + self.assertEqual(ntpath.realpath(ABSTFN + "1\\.."), + ntpath.dirname(ABSTFN)) + self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\x"), + ntpath.dirname(P + ABSTFN) + "\\x") + os.symlink(ABSTFN + "x", ABSTFN + "y") + self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\" + + ntpath.basename(ABSTFN) + "y"), + P + ABSTFN + "x") + self.assertIn(ntpath.realpath(ABSTFN + "1\\..\\" + + ntpath.basename(ABSTFN) + "1"), + expected) + + os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a") + self.assertEqual(ntpath.realpath(ABSTFN + "a"), P + ABSTFN + "a") + + os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN)) + + "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c") + self.assertEqual(ntpath.realpath(ABSTFN + "c"), P + ABSTFN + "c") + + # Test using relative path as well. + self.assertEqual(ntpath.realpath(ntpath.basename(ABSTFN)), P + ABSTFN) + + @support.skip_unless_symlink + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_symlink_prefix(self): + ABSTFN = ntpath.abspath(support.TESTFN) + self.addCleanup(support.unlink, ABSTFN + "3") + self.addCleanup(support.unlink, "\\\\?\\" + ABSTFN + "3.") + self.addCleanup(support.unlink, ABSTFN + "3link") + self.addCleanup(support.unlink, ABSTFN + "3.link") + + with open(ABSTFN + "3", "wb") as f: + f.write(b'0') + os.symlink(ABSTFN + "3", ABSTFN + "3link") + + with open("\\\\?\\" + ABSTFN + "3.", "wb") as f: + f.write(b'1') + os.symlink("\\\\?\\" + ABSTFN + "3.", ABSTFN + "3.link") + + self.assertEqual(ntpath.realpath(ABSTFN + "3link"), + ABSTFN + "3") + self.assertEqual(ntpath.realpath(ABSTFN + "3.link"), + "\\\\?\\" + ABSTFN + "3.") + + # Resolved paths should be usable to open target files + with open(ntpath.realpath(ABSTFN + "3link"), "rb") as f: + self.assertEqual(f.read(), b'0') + with open(ntpath.realpath(ABSTFN + "3.link"), "rb") as f: + self.assertEqual(f.read(), b'1') + + # When the prefix is included, it is not stripped + self.assertEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3link"), + "\\\\?\\" + ABSTFN + "3") + self.assertEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3.link"), + "\\\\?\\" + ABSTFN + "3.") + def test_expandvars(self): with support.EnvironmentVarGuard() as env: env.clear() @@ -288,11 +480,11 @@ def test_abspath(self): def test_relpath(self): tester('ntpath.relpath("a")', 'a') - tester('ntpath.relpath(os.path.abspath("a"))', 'a') + tester('ntpath.relpath(ntpath.abspath("a"))', 'a') tester('ntpath.relpath("a/b")', 'a\\b') tester('ntpath.relpath("../a/b")', '..\\a\\b') with support.temp_cwd(support.TESTFN) as cwd_dir: - currentdir = os.path.basename(cwd_dir) + currentdir = ntpath.basename(cwd_dir) tester('ntpath.relpath("a", "../b")', '..\\'+currentdir+'\\a') tester('ntpath.relpath("a/b", "../c")', '..\\'+currentdir+'\\a\\b') tester('ntpath.relpath("a", "b/c")', '..\\..\\a') @@ -417,7 +609,7 @@ def test_ismount(self): # locations below cannot then refer to mount points # drive, path = ntpath.splitdrive(sys.executable) - with support.change_cwd(os.path.dirname(sys.executable)): + with support.change_cwd(ntpath.dirname(sys.executable)): self.assertFalse(ntpath.ismount(drive.lower())) self.assertFalse(ntpath.ismount(drive.upper())) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index b2cd4cca5f21..15fd65b55149 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3358,10 +3358,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": - funcs.append((self.unicode_filenames, os.readlink,)) - else: - funcs.append((self.filenames, os.readlink,)) + funcs.append((self.filenames, os.readlink,)) for filenames, func, *func_args in funcs: diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index e209607f22c1..88dc4d9e195e 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1871,11 +1871,7 @@ def test_move_dangling_symlink(self): dst_link = os.path.join(self.dst_dir, 'quux') shutil.move(dst, dst_link) self.assertTrue(os.path.islink(dst_link)) - # On Windows, os.path.realpath does not follow symlinks (issue #9949) - if os.name == 'nt': - self.assertEqual(os.path.realpath(src), os.readlink(dst_link)) - else: - self.assertEqual(os.path.realpath(src), os.path.realpath(dst_link)) + self.assertEqual(os.path.realpath(src), os.path.realpath(dst_link)) @support.skip_unless_symlink @mock_rename diff --git a/Lib/unittest/test/test_discovery.py b/Lib/unittest/test/test_discovery.py index 204043b493b5..16e081e1fb76 100644 --- a/Lib/unittest/test/test_discovery.py +++ b/Lib/unittest/test/test_discovery.py @@ -723,11 +723,13 @@ class Module(object): original_listdir = os.listdir original_isfile = os.path.isfile original_isdir = os.path.isdir + original_realpath = os.path.realpath def cleanup(): os.listdir = original_listdir os.path.isfile = original_isfile os.path.isdir = original_isdir + os.path.realpath = original_realpath del sys.modules['foo'] if full_path in sys.path: sys.path.remove(full_path) @@ -742,6 +744,10 @@ def isdir(_): os.listdir = listdir os.path.isfile = isfile os.path.isdir = isdir + if os.name == 'nt': + # ntpath.realpath may inject path prefixes when failing to + # resolve real files, so we substitute abspath() here instead. + os.path.realpath = os.path.abspath return full_path def test_detect_module_clash(self): diff --git a/Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst b/Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst new file mode 100644 index 000000000000..e42169a927c7 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst @@ -0,0 +1 @@ +Enable support for following symlinks in :func:`os.realpath`. From webhook-mailer at python.org Wed Aug 21 17:00:08 2019 From: webhook-mailer at python.org (Stefan Krah) Date: Wed, 21 Aug 2019 21:00:08 -0000 Subject: [Python-checkins] Revert mode change that loses information in directory listings on Linux. (#15366) Message-ID: https://github.com/python/cpython/commit/bcc446f525421156fe693139140e7051d000592e commit: bcc446f525421156fe693139140e7051d000592e branch: master author: Stefan Krah committer: GitHub date: 2019-08-21T23:00:04+02:00 summary: Revert mode change that loses information in directory listings on Linux. (#15366) files: M Modules/_decimal/tests/runall.bat diff --git a/Modules/_decimal/tests/runall.bat b/Modules/_decimal/tests/runall.bat old mode 100644 new mode 100755 From webhook-mailer at python.org Wed Aug 21 17:09:38 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 21:09:38 -0000 Subject: [Python-checkins] bpo-9949: Enable symlink traversal for ntpath.realpath (GH-15287) Message-ID: https://github.com/python/cpython/commit/c30c869e8dec5eefdee7977943ffa11a8e3c8d75 commit: c30c869e8dec5eefdee7977943ffa11a8e3c8d75 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-21T14:09:33-07:00 summary: bpo-9949: Enable symlink traversal for ntpath.realpath (GH-15287) (cherry picked from commit 75e064962ee0e31ec19a8081e9d9cc957baf6415) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst M Doc/library/os.path.rst M Doc/whatsnew/3.8.rst M Lib/ntpath.py M Lib/test/test_ntpath.py M Lib/test/test_os.py M Lib/test/test_shutil.py M Lib/unittest/test/test_discovery.py diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index a673b81278ea..640ceecbc78f 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -350,11 +350,19 @@ the :mod:`glob` module.) .. function:: realpath(path) Return the canonical path of the specified filename, eliminating any symbolic - links encountered in the path (if they are supported by the operating system). + links encountered in the path (if they are supported by the operating + system). + + .. note:: + When symbolic link cycles occur, the returned path will be one member of + the cycle, but no guarantee is made about which member that will be. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: 3.8 + Symbolic links and junctions are now resolved on Windows. + .. function:: relpath(path, start=os.curdir) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index e8238251d6ea..93758e96b573 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -824,6 +824,9 @@ characters or bytes unrepresentable at the OS level. environment variable and does not use :envvar:`HOME`, which is not normally set for regular user accounts. +:func:`~os.path.realpath` on Windows now resolves reparse points, including +symlinks and directory junctions. + ncurses ------- diff --git a/Lib/ntpath.py b/Lib/ntpath.py index f3cfabf0238e..ef4999e1473a 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -519,8 +519,94 @@ def abspath(path): except (OSError, ValueError): return _abspath_fallback(path) -# realpath is a no-op on systems without islink support -realpath = abspath +try: + from nt import _getfinalpathname, readlink as _nt_readlink +except ImportError: + # realpath is a no-op on systems without _getfinalpathname support. + realpath = abspath +else: + def _readlink_deep(path, seen=None): + if seen is None: + seen = set() + + while normcase(path) not in seen: + seen.add(normcase(path)) + try: + path = _nt_readlink(path) + except OSError as ex: + # Stop on file (2) or directory (3) not found, or + # paths that are not reparse points (4390) + if ex.winerror in (2, 3, 4390): + break + raise + except ValueError: + # Stop on reparse points that are not symlinks + break + return path + + def _getfinalpathname_nonstrict(path): + # Fast path to get the final path name. If this succeeds, there + # is no need to go any further. + try: + return _getfinalpathname(path) + except OSError: + pass + + # Allow file (2) or directory (3) not found, invalid syntax (123), + # and symlinks that cannot be followed (1921) + allowed_winerror = 2, 3, 123, 1921 + + # Non-strict algorithm is to find as much of the target directory + # as we can and join the rest. + tail = '' + seen = set() + while path: + try: + path = _readlink_deep(path, seen) + path = _getfinalpathname(path) + return join(path, tail) if tail else path + except OSError as ex: + if ex.winerror not in allowed_winerror: + raise + path, name = split(path) + if path and not name: + return abspath(path + tail) + tail = join(name, tail) if tail else name + return abspath(tail) + + def realpath(path): + path = os.fspath(path) + if isinstance(path, bytes): + prefix = b'\\\\?\\' + unc_prefix = b'\\\\?\\UNC\\' + new_unc_prefix = b'\\\\' + cwd = os.getcwdb() + else: + prefix = '\\\\?\\' + unc_prefix = '\\\\?\\UNC\\' + new_unc_prefix = '\\\\' + cwd = os.getcwd() + had_prefix = path.startswith(prefix) + path = _getfinalpathname_nonstrict(path) + # The path returned by _getfinalpathname will always start with \\?\ - + # strip off that prefix unless it was already provided on the original + # path. + if not had_prefix and path.startswith(prefix): + # For UNC paths, the prefix will actually be \\?\UNC\ + # Handle that case as well. + if path.startswith(unc_prefix): + spath = new_unc_prefix + path[len(unc_prefix):] + else: + spath = path[len(prefix):] + # Ensure that the non-prefixed path resolves to the same path + try: + if _getfinalpathname(spath) == path: + path = spath + except OSError as ex: + pass + return path + + # Win9x family and earlier have no Unicode filename support. supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and sys.getwindowsversion()[3] >= 2) @@ -633,23 +719,6 @@ def commonpath(paths): raise -# determine if two files are in fact the same file -try: - # GetFinalPathNameByHandle is available starting with Windows 6.0. - # Windows XP and non-Windows OS'es will mock _getfinalpathname. - if sys.getwindowsversion()[:2] >= (6, 0): - from nt import _getfinalpathname - else: - raise ImportError -except (AttributeError, ImportError): - # On Windows XP and earlier, two files are the same if their absolute - # pathnames are the same. - # Non-Windows operating systems fake this method with an XP - # approximation. - def _getfinalpathname(f): - return normcase(abspath(f)) - - try: # The genericpath.isdir implementation uses os.stat and checks the mode # attribute to tell whether or not the path is a directory. diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 92d85ecbc4fc..74dc8c378e27 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -7,6 +7,7 @@ from test import support, test_genericpath from tempfile import TemporaryFile + try: import nt except ImportError: @@ -14,6 +15,14 @@ # but for those that require it we import here. nt = None +try: + ntpath._getfinalpathname +except AttributeError: + HAVE_GETFINALPATHNAME = False +else: + HAVE_GETFINALPATHNAME = True + + def tester(fn, wantResult): fn = fn.replace("\\", "\\\\") gotResult = eval(fn) @@ -194,6 +203,189 @@ def test_normpath(self): tester("ntpath.normpath('\\\\.\\NUL')", r'\\.\NUL') tester("ntpath.normpath('\\\\?\\D:/XY\\Z')", r'\\?\D:/XY\Z') + def test_realpath_curdir(self): + expected = ntpath.normpath(os.getcwd()) + tester("ntpath.realpath('.')", expected) + tester("ntpath.realpath('./.')", expected) + tester("ntpath.realpath('/'.join(['.'] * 100))", expected) + tester("ntpath.realpath('.\\.')", expected) + tester("ntpath.realpath('\\'.join(['.'] * 100))", expected) + + def test_realpath_pardir(self): + expected = ntpath.normpath(os.getcwd()) + tester("ntpath.realpath('..')", ntpath.dirname(expected)) + tester("ntpath.realpath('../..')", + ntpath.dirname(ntpath.dirname(expected))) + tester("ntpath.realpath('/'.join(['..'] * 50))", + ntpath.splitdrive(expected)[0] + '\\') + tester("ntpath.realpath('..\\..')", + ntpath.dirname(ntpath.dirname(expected))) + tester("ntpath.realpath('\\'.join(['..'] * 50))", + ntpath.splitdrive(expected)[0] + '\\') + + @support.skip_unless_symlink + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_basic(self): + ABSTFN = ntpath.abspath(support.TESTFN) + open(ABSTFN, "wb").close() + self.addCleanup(support.unlink, ABSTFN) + self.addCleanup(support.unlink, ABSTFN + "1") + + os.symlink(ABSTFN, ABSTFN + "1") + self.assertEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN) + self.assertEqual(ntpath.realpath(os.fsencode(ABSTFN + "1")), + os.fsencode(ABSTFN)) + + @support.skip_unless_symlink + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_relative(self): + ABSTFN = ntpath.abspath(support.TESTFN) + open(ABSTFN, "wb").close() + self.addCleanup(support.unlink, ABSTFN) + self.addCleanup(support.unlink, ABSTFN + "1") + + os.symlink(ABSTFN, ntpath.relpath(ABSTFN + "1")) + self.assertEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN) + + @support.skip_unless_symlink + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_broken_symlinks(self): + ABSTFN = ntpath.abspath(support.TESTFN) + os.mkdir(ABSTFN) + self.addCleanup(support.rmtree, ABSTFN) + + with support.change_cwd(ABSTFN): + os.mkdir("subdir") + os.chdir("subdir") + os.symlink(".", "recursive") + os.symlink("..", "parent") + os.chdir("..") + os.symlink(".", "self") + os.symlink("missing", "broken") + os.symlink(r"broken\bar", "broken1") + os.symlink(r"self\self\broken", "broken2") + os.symlink(r"subdir\parent\subdir\parent\broken", "broken3") + os.symlink(ABSTFN + r"\broken", "broken4") + os.symlink(r"recursive\..\broken", "broken5") + + self.assertEqual(ntpath.realpath("broken"), + ABSTFN + r"\missing") + self.assertEqual(ntpath.realpath(r"broken\foo"), + ABSTFN + r"\missing\foo") + self.assertEqual(ntpath.realpath(r"broken1"), + ABSTFN + r"\missing\bar") + self.assertEqual(ntpath.realpath(r"broken1\baz"), + ABSTFN + r"\missing\bar\baz") + self.assertEqual(ntpath.realpath("broken2"), + ABSTFN + r"\missing") + self.assertEqual(ntpath.realpath("broken3"), + ABSTFN + r"\missing") + self.assertEqual(ntpath.realpath("broken4"), + ABSTFN + r"\missing") + self.assertEqual(ntpath.realpath("broken5"), + ABSTFN + r"\missing") + + self.assertEqual(ntpath.realpath(b"broken"), + os.fsencode(ABSTFN + r"\missing")) + self.assertEqual(ntpath.realpath(rb"broken\foo"), + os.fsencode(ABSTFN + r"\missing\foo")) + self.assertEqual(ntpath.realpath(rb"broken1"), + os.fsencode(ABSTFN + r"\missing\bar")) + self.assertEqual(ntpath.realpath(rb"broken1\baz"), + os.fsencode(ABSTFN + r"\missing\bar\baz")) + self.assertEqual(ntpath.realpath(b"broken2"), + os.fsencode(ABSTFN + r"\missing")) + self.assertEqual(ntpath.realpath(rb"broken3"), + os.fsencode(ABSTFN + r"\missing")) + self.assertEqual(ntpath.realpath(b"broken4"), + os.fsencode(ABSTFN + r"\missing")) + self.assertEqual(ntpath.realpath(b"broken5"), + os.fsencode(ABSTFN + r"\missing")) + + @support.skip_unless_symlink + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_symlink_loops(self): + # Bug #930024, return the path unchanged if we get into an infinite + # symlink loop. + ABSTFN = ntpath.abspath(support.TESTFN) + self.addCleanup(support.unlink, ABSTFN) + self.addCleanup(support.unlink, ABSTFN + "1") + self.addCleanup(support.unlink, ABSTFN + "2") + self.addCleanup(support.unlink, ABSTFN + "y") + self.addCleanup(support.unlink, ABSTFN + "c") + self.addCleanup(support.unlink, ABSTFN + "a") + + P = "\\\\?\\" + + os.symlink(ABSTFN, ABSTFN) + self.assertEqual(ntpath.realpath(ABSTFN), P + ABSTFN) + + # cycles are non-deterministic as to which path is returned, but + # it will always be the fully resolved path of one member of the cycle + os.symlink(ABSTFN + "1", ABSTFN + "2") + os.symlink(ABSTFN + "2", ABSTFN + "1") + expected = (P + ABSTFN + "1", P + ABSTFN + "2") + self.assertIn(ntpath.realpath(ABSTFN + "1"), expected) + self.assertIn(ntpath.realpath(ABSTFN + "2"), expected) + + self.assertIn(ntpath.realpath(ABSTFN + "1\\x"), + (ntpath.join(r, "x") for r in expected)) + self.assertEqual(ntpath.realpath(ABSTFN + "1\\.."), + ntpath.dirname(ABSTFN)) + self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\x"), + ntpath.dirname(P + ABSTFN) + "\\x") + os.symlink(ABSTFN + "x", ABSTFN + "y") + self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\" + + ntpath.basename(ABSTFN) + "y"), + P + ABSTFN + "x") + self.assertIn(ntpath.realpath(ABSTFN + "1\\..\\" + + ntpath.basename(ABSTFN) + "1"), + expected) + + os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a") + self.assertEqual(ntpath.realpath(ABSTFN + "a"), P + ABSTFN + "a") + + os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN)) + + "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c") + self.assertEqual(ntpath.realpath(ABSTFN + "c"), P + ABSTFN + "c") + + # Test using relative path as well. + self.assertEqual(ntpath.realpath(ntpath.basename(ABSTFN)), P + ABSTFN) + + @support.skip_unless_symlink + @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname') + def test_realpath_symlink_prefix(self): + ABSTFN = ntpath.abspath(support.TESTFN) + self.addCleanup(support.unlink, ABSTFN + "3") + self.addCleanup(support.unlink, "\\\\?\\" + ABSTFN + "3.") + self.addCleanup(support.unlink, ABSTFN + "3link") + self.addCleanup(support.unlink, ABSTFN + "3.link") + + with open(ABSTFN + "3", "wb") as f: + f.write(b'0') + os.symlink(ABSTFN + "3", ABSTFN + "3link") + + with open("\\\\?\\" + ABSTFN + "3.", "wb") as f: + f.write(b'1') + os.symlink("\\\\?\\" + ABSTFN + "3.", ABSTFN + "3.link") + + self.assertEqual(ntpath.realpath(ABSTFN + "3link"), + ABSTFN + "3") + self.assertEqual(ntpath.realpath(ABSTFN + "3.link"), + "\\\\?\\" + ABSTFN + "3.") + + # Resolved paths should be usable to open target files + with open(ntpath.realpath(ABSTFN + "3link"), "rb") as f: + self.assertEqual(f.read(), b'0') + with open(ntpath.realpath(ABSTFN + "3.link"), "rb") as f: + self.assertEqual(f.read(), b'1') + + # When the prefix is included, it is not stripped + self.assertEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3link"), + "\\\\?\\" + ABSTFN + "3") + self.assertEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3.link"), + "\\\\?\\" + ABSTFN + "3.") + def test_expandvars(self): with support.EnvironmentVarGuard() as env: env.clear() @@ -288,11 +480,11 @@ def test_abspath(self): def test_relpath(self): tester('ntpath.relpath("a")', 'a') - tester('ntpath.relpath(os.path.abspath("a"))', 'a') + tester('ntpath.relpath(ntpath.abspath("a"))', 'a') tester('ntpath.relpath("a/b")', 'a\\b') tester('ntpath.relpath("../a/b")', '..\\a\\b') with support.temp_cwd(support.TESTFN) as cwd_dir: - currentdir = os.path.basename(cwd_dir) + currentdir = ntpath.basename(cwd_dir) tester('ntpath.relpath("a", "../b")', '..\\'+currentdir+'\\a') tester('ntpath.relpath("a/b", "../c")', '..\\'+currentdir+'\\a\\b') tester('ntpath.relpath("a", "b/c")', '..\\..\\a') @@ -417,7 +609,7 @@ def test_ismount(self): # locations below cannot then refer to mount points # drive, path = ntpath.splitdrive(sys.executable) - with support.change_cwd(os.path.dirname(sys.executable)): + with support.change_cwd(ntpath.dirname(sys.executable)): self.assertFalse(ntpath.ismount(drive.lower())) self.assertFalse(ntpath.ismount(drive.upper())) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index b2cd4cca5f21..15fd65b55149 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3358,10 +3358,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": - funcs.append((self.unicode_filenames, os.readlink,)) - else: - funcs.append((self.filenames, os.readlink,)) + funcs.append((self.filenames, os.readlink,)) for filenames, func, *func_args in funcs: diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index e209607f22c1..88dc4d9e195e 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1871,11 +1871,7 @@ def test_move_dangling_symlink(self): dst_link = os.path.join(self.dst_dir, 'quux') shutil.move(dst, dst_link) self.assertTrue(os.path.islink(dst_link)) - # On Windows, os.path.realpath does not follow symlinks (issue #9949) - if os.name == 'nt': - self.assertEqual(os.path.realpath(src), os.readlink(dst_link)) - else: - self.assertEqual(os.path.realpath(src), os.path.realpath(dst_link)) + self.assertEqual(os.path.realpath(src), os.path.realpath(dst_link)) @support.skip_unless_symlink @mock_rename diff --git a/Lib/unittest/test/test_discovery.py b/Lib/unittest/test/test_discovery.py index 204043b493b5..16e081e1fb76 100644 --- a/Lib/unittest/test/test_discovery.py +++ b/Lib/unittest/test/test_discovery.py @@ -723,11 +723,13 @@ class Module(object): original_listdir = os.listdir original_isfile = os.path.isfile original_isdir = os.path.isdir + original_realpath = os.path.realpath def cleanup(): os.listdir = original_listdir os.path.isfile = original_isfile os.path.isdir = original_isdir + os.path.realpath = original_realpath del sys.modules['foo'] if full_path in sys.path: sys.path.remove(full_path) @@ -742,6 +744,10 @@ def isdir(_): os.listdir = listdir os.path.isfile = isfile os.path.isdir = isdir + if os.name == 'nt': + # ntpath.realpath may inject path prefixes when failing to + # resolve real files, so we substitute abspath() here instead. + os.path.realpath = os.path.abspath return full_path def test_detect_module_clash(self): diff --git a/Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst b/Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst new file mode 100644 index 000000000000..e42169a927c7 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst @@ -0,0 +1 @@ +Enable support for following symlinks in :func:`os.realpath`. From webhook-mailer at python.org Wed Aug 21 18:27:37 2019 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 21 Aug 2019 22:27:37 -0000 Subject: [Python-checkins] bpo-37834: Normalise handling of reparse points on Windows (GH-15231) Message-ID: https://github.com/python/cpython/commit/df2d4a6f3d5da2839c4fc11d31511c8e028daf2c commit: df2d4a6f3d5da2839c4fc11d31511c8e028daf2c branch: master author: Steve Dower committer: GitHub date: 2019-08-21T15:27:33-07:00 summary: bpo-37834: Normalise handling of reparse points on Windows (GH-15231) bpo-37834: Normalise handling of reparse points on Windows * ntpath.realpath() and nt.stat() will traverse all supported reparse points (previously was mixed) * nt.lstat() will let the OS traverse reparse points that are not name surrogates (previously would not traverse any reparse point) * nt.[l]stat() will only set S_IFLNK for symlinks (previous behaviour) * nt.readlink() will read destinations for symlinks and junction points only bpo-1311: os.path.exists('nul') now returns True on Windows * nt.stat('nul').st_mode is now S_IFCHR (previously was an error) files: A Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst A Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst M Doc/library/os.rst M Doc/library/shutil.rst M Doc/library/stat.rst M Doc/whatsnew/3.8.rst M Include/fileutils.h M Lib/shutil.py M Lib/test/test_os.py M Lib/test/test_shutil.py M Lib/test/test_tools/test_lll.py M Lib/test/test_venv.py M Modules/_stat.c M Modules/clinic/posixmodule.c.h M Modules/posixmodule.c M Python/fileutils.c diff --git a/Doc/library/os.rst b/Doc/library/os.rst index c74d687f08fb..6cbfb7432841 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1858,6 +1858,12 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object` for *src* and *dst*. + .. versionchanged:: 3.8 + On Windows, now opens reparse points that represent another path + (name surrogates), including symbolic links and directory junctions. + Other kinds of reparse points are resolved by the operating system as + for :func:`~os.stat`. + .. function:: mkdir(path, mode=0o777, *, dir_fd=None) @@ -2039,6 +2045,10 @@ features: This function can also support :ref:`paths relative to directory descriptors `. + When trying to resolve a path that may contain links, use + :func:`~os.path.realpath` to properly handle recursion and platform + differences. + .. availability:: Unix, Windows. .. versionchanged:: 3.2 @@ -2053,6 +2063,11 @@ features: .. versionchanged:: 3.8 Accepts a :term:`path-like object` and a bytes object on Windows. + .. versionchanged:: 3.8 + Added support for directory junctions, and changed to return the + substitution path (which typically includes ``\\?\`` prefix) rather + than the optional "print name" field that was previously returned. + .. function:: remove(path, *, dir_fd=None) Remove (delete) the file *path*. If *path* is a directory, an @@ -2366,7 +2381,8 @@ features: On Unix, this method always requires a system call. On Windows, it only requires a system call if *follow_symlinks* is ``True`` and the - entry is a symbolic link. + entry is a reparse point (for example, a symbolic link or directory + junction). On Windows, the ``st_ino``, ``st_dev`` and ``st_nlink`` attributes of the :class:`stat_result` are always set to zero. Call :func:`os.stat` to @@ -2403,6 +2419,17 @@ features: This function can support :ref:`specifying a file descriptor ` and :ref:`not following symlinks `. + On Windows, passing ``follow_symlinks=False`` will disable following all + name-surrogate reparse points, which includes symlinks and directory + junctions. Other types of reparse points that do not resemble links or that + the operating system is unable to follow will be opened directly. When + following a chain of multiple links, this may result in the original link + being returned instead of the non-link that prevented full traversal. To + obtain stat results for the final path in this case, use the + :func:`os.path.realpath` function to resolve the path name as far as + possible and call :func:`lstat` on the result. This does not apply to + dangling symlinks or junction points, which will raise the usual exceptions. + .. index:: module: stat Example:: @@ -2427,6 +2454,14 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: 3.8 + On Windows, all reparse points that can be resolved by the operating + system are now followed, and passing ``follow_symlinks=False`` + disables following all name surrogate reparse points. If the operating + system reaches a reparse point that it is not able to follow, *stat* now + returns the information for the original path as if + ``follow_symlinks=False`` had been specified instead of raising an error. + .. class:: stat_result @@ -2578,7 +2613,7 @@ features: File type. - On Windows systems, the following attribute is also available: + On Windows systems, the following attributes are also available: .. attribute:: st_file_attributes @@ -2587,6 +2622,12 @@ features: :c:func:`GetFileInformationByHandle`. See the ``FILE_ATTRIBUTE_*`` constants in the :mod:`stat` module. + .. attribute:: st_reparse_tag + + When :attr:`st_file_attributes` has the ``FILE_ATTRIBUTE_REPARSE_POINT`` + set, this field contains the tag identifying the type of reparse point. + See the ``IO_REPARSE_TAG_*`` constants in the :mod:`stat` module. + The standard module :mod:`stat` defines functions and constants that are useful for extracting information from a :c:type:`stat` structure. (On Windows, some items are filled with dummy values.) @@ -2614,6 +2655,14 @@ features: .. versionadded:: 3.7 Added the :attr:`st_fstype` member to Solaris/derivatives. + .. versionadded:: 3.8 + Added the :attr:`st_reparse_tag` member on Windows. + + .. versionchanged:: 3.8 + On Windows, the :attr:`st_mode` member now identifies special + files as :const:`S_IFCHR`, :const:`S_IFIFO` or :const:`S_IFBLK` + as appropriate. + .. function:: statvfs(path) Perform a :c:func:`statvfs` system call on the given path. The return value is diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index eaeee8df81b8..a51e068ebd59 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -304,6 +304,10 @@ Directory and files operations Added a symlink attack resistant version that is used automatically if platform supports fd-based functions. + .. versionchanged:: 3.8 + On Windows, will no longer delete the contents of a directory junction + before removing the junction. + .. attribute:: rmtree.avoids_symlink_attacks Indicates whether the current platform and implementation provides a diff --git a/Doc/library/stat.rst b/Doc/library/stat.rst index c8f6904f9b1f..f48a0a9faa6b 100644 --- a/Doc/library/stat.rst +++ b/Doc/library/stat.rst @@ -425,3 +425,13 @@ for more detail on the meaning of these constants. FILE_ATTRIBUTE_VIRTUAL .. versionadded:: 3.5 + +On Windows, the following constants are available for comparing against the +``st_reparse_tag`` member returned by :func:`os.lstat`. These are well-known +constants, but are not an exhaustive list. + +.. data:: IO_REPARSE_TAG_SYMLINK + IO_REPARSE_TAG_MOUNT_POINT + IO_REPARSE_TAG_APPEXECLINK + + .. versionadded:: 3.8 diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 93758e96b573..0294e9a0830b 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -808,6 +808,21 @@ A new :func:`os.memfd_create` function was added to wrap the ``memfd_create()`` syscall. (Contributed by Zackery Spytz and Christian Heimes in :issue:`26836`.) +On Windows, much of the manual logic for handling reparse points (including +symlinks and directory junctions) has been delegated to the operating system. +Specifically, :func:`os.stat` will now traverse anything supported by the +operating system, while :func:`os.lstat` will only open reparse points that +identify as "name surrogates" while others are opened as for :func:`os.stat`. +In all cases, :attr:`stat_result.st_mode` will only have ``S_IFLNK`` set for +symbolic links and not other kinds of reparse points. To identify other kinds +of reparse point, check the new :attr:`stat_result.st_reparse_tag` attribute. + +On Windows, :func:`os.readlink` is now able to read directory junctions. Note +that :func:`~os.path.islink` will return ``False`` for directory junctions, +and so code that checks ``islink`` first will continue to treat junctions as +directories, while code that handles errors from :func:`os.readlink` may now +treat junctions as links. + os.path ------- @@ -824,6 +839,9 @@ characters or bytes unrepresentable at the OS level. environment variable and does not use :envvar:`HOME`, which is not normally set for regular user accounts. +:func:`~os.path.isdir` on Windows no longer returns true for a link to a +non-existent directory. + :func:`~os.path.realpath` on Windows now resolves reparse points, including symlinks and directory junctions. @@ -912,6 +930,9 @@ format for new archives to improve portability and standards conformance, inherited from the corresponding change to the :mod:`tarfile` module. (Contributed by C.A.M. Gerlach in :issue:`30661`.) +:func:`shutil.rmtree` on Windows now removes directory junctions without +recursively removing their contents first. + ssl --- diff --git a/Include/fileutils.h b/Include/fileutils.h index f081779f8aac..a9655bbf9a5f 100644 --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -84,6 +84,7 @@ struct _Py_stat_struct { time_t st_ctime; int st_ctime_nsec; unsigned long st_file_attributes; + unsigned long st_reparse_tag; }; #else # define _Py_stat_struct stat diff --git a/Lib/shutil.py b/Lib/shutil.py index ab1a7d61897a..39f793b5f3bd 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -452,7 +452,14 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function, dstname = os.path.join(dst, srcentry.name) srcobj = srcentry if use_srcentry else srcname try: - if srcentry.is_symlink(): + is_symlink = srcentry.is_symlink() + if is_symlink and os.name == 'nt': + # Special check for directory junctions, which appear as + # symlinks but we want to recurse. + lstat = srcentry.stat(follow_symlinks=False) + if lstat.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT: + is_symlink = False + if is_symlink: linkto = os.readlink(srcname) if symlinks: # We can't just leave it to `copy_function` because legacy @@ -537,6 +544,37 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=ignore_dangling_symlinks, dirs_exist_ok=dirs_exist_ok) +if hasattr(stat, 'FILE_ATTRIBUTE_REPARSE_POINT'): + # Special handling for directory junctions to make them behave like + # symlinks for shutil.rmtree, since in general they do not appear as + # regular links. + def _rmtree_isdir(entry): + try: + st = entry.stat(follow_symlinks=False) + return (stat.S_ISDIR(st.st_mode) and not + (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT + and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)) + except OSError: + return False + + def _rmtree_islink(path): + try: + st = os.lstat(path) + return (stat.S_ISLNK(st.st_mode) or + (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT + and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)) + except OSError: + return False +else: + def _rmtree_isdir(entry): + try: + return entry.is_dir(follow_symlinks=False) + except OSError: + return False + + def _rmtree_islink(path): + return os.path.islink(path) + # version vulnerable to race conditions def _rmtree_unsafe(path, onerror): try: @@ -547,11 +585,7 @@ def _rmtree_unsafe(path, onerror): entries = [] for entry in entries: fullname = entry.path - try: - is_dir = entry.is_dir(follow_symlinks=False) - except OSError: - is_dir = False - if is_dir: + if _rmtree_isdir(entry): try: if entry.is_symlink(): # This can only happen if someone replaces @@ -681,7 +715,7 @@ def onerror(*args): os.close(fd) else: try: - if os.path.islink(path): + if _rmtree_islink(path): # symlinks to directories are forbidden, see bug #1669 raise OSError("Cannot call rmtree on a symbolic link") except OSError: diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 15fd65b55149..ba9f5c35ae31 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -8,6 +8,7 @@ import contextlib import decimal import errno +import fnmatch import fractions import itertools import locale @@ -2253,6 +2254,20 @@ class ReadlinkTests(unittest.TestCase): filelinkb = os.fsencode(filelink) filelinkb_target = os.fsencode(filelink_target) + def assertPathEqual(self, left, right): + left = os.path.normcase(left) + right = os.path.normcase(right) + if sys.platform == 'win32': + # Bad practice to blindly strip the prefix as it may be required to + # correctly refer to the file, but we're only comparing paths here. + has_prefix = lambda p: p.startswith( + b'\\\\?\\' if isinstance(p, bytes) else '\\\\?\\') + if has_prefix(left): + left = left[4:] + if has_prefix(right): + right = right[4:] + self.assertEqual(left, right) + def setUp(self): self.assertTrue(os.path.exists(self.filelink_target)) self.assertTrue(os.path.exists(self.filelinkb_target)) @@ -2274,14 +2289,14 @@ def test_pathlike(self): os.symlink(self.filelink_target, self.filelink) self.addCleanup(support.unlink, self.filelink) filelink = FakePath(self.filelink) - self.assertEqual(os.readlink(filelink), self.filelink_target) + self.assertPathEqual(os.readlink(filelink), self.filelink_target) @support.skip_unless_symlink def test_pathlike_bytes(self): os.symlink(self.filelinkb_target, self.filelinkb) self.addCleanup(support.unlink, self.filelinkb) path = os.readlink(FakePath(self.filelinkb)) - self.assertEqual(path, self.filelinkb_target) + self.assertPathEqual(path, self.filelinkb_target) self.assertIsInstance(path, bytes) @support.skip_unless_symlink @@ -2289,7 +2304,7 @@ def test_bytes(self): os.symlink(self.filelinkb_target, self.filelinkb) self.addCleanup(support.unlink, self.filelinkb) path = os.readlink(self.filelinkb) - self.assertEqual(path, self.filelinkb_target) + self.assertPathEqual(path, self.filelinkb_target) self.assertIsInstance(path, bytes) @@ -2348,16 +2363,12 @@ def test_remove_directory_link_to_missing_target(self): # was created with target_is_dir==True. os.remove(self.missing_link) - @unittest.skip("currently fails; consider for improvement") def test_isdir_on_directory_link_to_missing_target(self): self._create_missing_dir_link() - # consider having isdir return true for directory links - self.assertTrue(os.path.isdir(self.missing_link)) + self.assertFalse(os.path.isdir(self.missing_link)) - @unittest.skip("currently fails; consider for improvement") def test_rmdir_on_directory_link_to_missing_target(self): self._create_missing_dir_link() - # consider allowing rmdir to remove directory links os.rmdir(self.missing_link) def check_stat(self, link, target): @@ -2453,6 +2464,24 @@ def test_buffer_overflow(self): except OSError: pass + def test_appexeclink(self): + root = os.path.expandvars(r'%LOCALAPPDATA%\Microsoft\WindowsApps') + aliases = [os.path.join(root, a) + for a in fnmatch.filter(os.listdir(root), '*.exe')] + + for alias in aliases: + if support.verbose: + print() + print("Testing with", alias) + st = os.lstat(alias) + self.assertEqual(st, os.stat(alias)) + self.assertFalse(stat.S_ISLNK(st.st_mode)) + self.assertEqual(st.st_reparse_tag, stat.IO_REPARSE_TAG_APPEXECLINK) + # testing the first one we see is sufficient + break + else: + self.skipTest("test requires an app execution alias") + @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") class Win32JunctionTests(unittest.TestCase): junction = 'junctiontest' @@ -2460,25 +2489,29 @@ class Win32JunctionTests(unittest.TestCase): def setUp(self): assert os.path.exists(self.junction_target) - assert not os.path.exists(self.junction) + assert not os.path.lexists(self.junction) def tearDown(self): - if os.path.exists(self.junction): - # os.rmdir delegates to Windows' RemoveDirectoryW, - # which removes junction points safely. - os.rmdir(self.junction) + if os.path.lexists(self.junction): + os.unlink(self.junction) def test_create_junction(self): _winapi.CreateJunction(self.junction_target, self.junction) + self.assertTrue(os.path.lexists(self.junction)) self.assertTrue(os.path.exists(self.junction)) self.assertTrue(os.path.isdir(self.junction)) + self.assertNotEqual(os.stat(self.junction), os.lstat(self.junction)) + self.assertEqual(os.stat(self.junction), os.stat(self.junction_target)) - # Junctions are not recognized as links. + # bpo-37834: Junctions are not recognized as links. self.assertFalse(os.path.islink(self.junction)) + self.assertEqual(os.path.normcase("\\\\?\\" + self.junction_target), + os.path.normcase(os.readlink(self.junction))) def test_unlink_removes_junction(self): _winapi.CreateJunction(self.junction_target, self.junction) self.assertTrue(os.path.exists(self.junction)) + self.assertTrue(os.path.lexists(self.junction)) os.unlink(self.junction) self.assertFalse(os.path.exists(self.junction)) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 88dc4d9e195e..636e3bd97955 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -42,6 +42,11 @@ except ImportError: UID_GID_SUPPORT = False +try: + import _winapi +except ImportError: + _winapi = None + def _fake_rename(*args, **kwargs): # Pretend the destination path is on a different filesystem. raise OSError(getattr(errno, 'EXDEV', 18), "Invalid cross-device link") @@ -226,6 +231,47 @@ def test_rmtree_works_on_symlinks(self): self.assertTrue(os.path.exists(dir3)) self.assertTrue(os.path.exists(file1)) + @unittest.skipUnless(_winapi, 'only relevant on Windows') + def test_rmtree_fails_on_junctions(self): + tmp = self.mkdtemp() + dir_ = os.path.join(tmp, 'dir') + os.mkdir(dir_) + link = os.path.join(tmp, 'link') + _winapi.CreateJunction(dir_, link) + self.assertRaises(OSError, shutil.rmtree, link) + self.assertTrue(os.path.exists(dir_)) + self.assertTrue(os.path.lexists(link)) + errors = [] + def onerror(*args): + errors.append(args) + shutil.rmtree(link, onerror=onerror) + self.assertEqual(len(errors), 1) + self.assertIs(errors[0][0], os.path.islink) + self.assertEqual(errors[0][1], link) + self.assertIsInstance(errors[0][2][1], OSError) + + @unittest.skipUnless(_winapi, 'only relevant on Windows') + def test_rmtree_works_on_junctions(self): + tmp = self.mkdtemp() + dir1 = os.path.join(tmp, 'dir1') + dir2 = os.path.join(dir1, 'dir2') + dir3 = os.path.join(tmp, 'dir3') + for d in dir1, dir2, dir3: + os.mkdir(d) + file1 = os.path.join(tmp, 'file1') + write_file(file1, 'foo') + link1 = os.path.join(dir1, 'link1') + _winapi.CreateJunction(dir2, link1) + link2 = os.path.join(dir1, 'link2') + _winapi.CreateJunction(dir3, link2) + link3 = os.path.join(dir1, 'link3') + _winapi.CreateJunction(file1, link3) + # make sure junctions are removed but not followed + shutil.rmtree(dir1) + self.assertFalse(os.path.exists(dir1)) + self.assertTrue(os.path.exists(dir3)) + self.assertTrue(os.path.exists(file1)) + def test_rmtree_errors(self): # filename is guaranteed not to exist filename = tempfile.mktemp() @@ -754,8 +800,12 @@ def test_copytree_symlinks(self): src_stat = os.lstat(src_link) shutil.copytree(src_dir, dst_dir, symlinks=True) self.assertTrue(os.path.islink(os.path.join(dst_dir, 'sub', 'link'))) - self.assertEqual(os.readlink(os.path.join(dst_dir, 'sub', 'link')), - os.path.join(src_dir, 'file.txt')) + actual = os.readlink(os.path.join(dst_dir, 'sub', 'link')) + # Bad practice to blindly strip the prefix as it may be required to + # correctly refer to the file, but we're only comparing paths here. + if os.name == 'nt' and actual.startswith('\\\\?\\'): + actual = actual[4:] + self.assertEqual(actual, os.path.join(src_dir, 'file.txt')) dst_stat = os.lstat(dst_link) if hasattr(os, 'lchmod'): self.assertEqual(dst_stat.st_mode, src_stat.st_mode) @@ -886,7 +936,6 @@ def custom_cpfun(a, b): shutil.copytree(src, dst, copy_function=custom_cpfun) self.assertEqual(len(flag), 1) - @unittest.skipIf(os.name == 'nt', 'temporarily disabled on Windows') @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link') def test_dont_copy_file_onto_link_to_itself(self): # bug 851123. @@ -941,6 +990,20 @@ def test_rmtree_on_symlink(self): finally: shutil.rmtree(TESTFN, ignore_errors=True) + @unittest.skipUnless(_winapi, 'only relevant on Windows') + def test_rmtree_on_junction(self): + os.mkdir(TESTFN) + try: + src = os.path.join(TESTFN, 'cheese') + dst = os.path.join(TESTFN, 'shop') + os.mkdir(src) + open(os.path.join(src, 'spam'), 'wb').close() + _winapi.CreateJunction(src, dst) + self.assertRaises(OSError, shutil.rmtree, dst) + shutil.rmtree(dst, ignore_errors=True) + finally: + shutil.rmtree(TESTFN, ignore_errors=True) + # Issue #3002: copyfile and copytree block indefinitely on named pipes @unittest.skipUnless(hasattr(os, "mkfifo"), 'requires os.mkfifo()') def test_copyfile_named_pipe(self): diff --git a/Lib/test/test_tools/test_lll.py b/Lib/test/test_tools/test_lll.py index f3fbe961eee5..b01e2188e1cf 100644 --- a/Lib/test/test_tools/test_lll.py +++ b/Lib/test/test_tools/test_lll.py @@ -1,6 +1,7 @@ """Tests for the lll script in the Tools/script directory.""" import os +import sys import tempfile from test import support from test.test_tools import skip_if_missing, import_tool @@ -26,12 +27,13 @@ def test_lll_multiple_dirs(self): with support.captured_stdout() as output: self.lll.main([dir1, dir2]) + prefix = '\\\\?\\' if os.name == 'nt' else '' self.assertEqual(output.getvalue(), f'{dir1}:\n' - f'symlink -> {fn1}\n' + f'symlink -> {prefix}{fn1}\n' f'\n' f'{dir2}:\n' - f'symlink -> {fn2}\n' + f'symlink -> {prefix}{fn2}\n' ) diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 9724d9ef57bc..de93d9539c2c 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -394,11 +394,7 @@ def test_devnull(self): with open(os.devnull, "rb") as f: self.assertEqual(f.read(), b"") - # Issue #20541: os.path.exists('nul') is False on Windows - if os.devnull.lower() == 'nul': - self.assertFalse(os.path.exists(os.devnull)) - else: - self.assertTrue(os.path.exists(os.devnull)) + self.assertTrue(os.path.exists(os.devnull)) def do_test_with_pip(self, system_site_packages): rmtree(self.env_dir) diff --git a/Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst b/Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst new file mode 100644 index 000000000000..f2a654cac911 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst @@ -0,0 +1,2 @@ +Treat all name surrogate reparse points on Windows in :func:`os.lstat` and +other reparse points as regular files in :func:`os.stat`. diff --git a/Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst b/Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst new file mode 100644 index 000000000000..2ee98e450fae --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst @@ -0,0 +1,2 @@ +The ``nul`` file on Windows now returns True from :func:`~os.path.exists` +and a valid result from :func:`os.stat` with ``S_IFCHR`` set. diff --git a/Modules/_stat.c b/Modules/_stat.c index f6cb303500cd..6a3020a00d11 100644 --- a/Modules/_stat.c +++ b/Modules/_stat.c @@ -589,6 +589,13 @@ PyInit__stat(void) if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_SYSTEM)) return NULL; if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_TEMPORARY)) return NULL; if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_VIRTUAL)) return NULL; + + if (PyModule_AddObject(m, "IO_REPARSE_TAG_SYMLINK", + PyLong_FromUnsignedLong(IO_REPARSE_TAG_SYMLINK))) return NULL; + if (PyModule_AddObject(m, "IO_REPARSE_TAG_MOUNT_POINT", + PyLong_FromUnsignedLong(IO_REPARSE_TAG_MOUNT_POINT))) return NULL; + if (PyModule_AddObject(m, "IO_REPARSE_TAG_APPEXECLINK", + PyLong_FromUnsignedLong(IO_REPARSE_TAG_APPEXECLINK))) return NULL; #endif return m; diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index aa1ab79bd96a..c4ebe3996aa7 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1272,19 +1272,6 @@ os__getfinalpathname(PyObject *module, PyObject *arg) #if defined(MS_WINDOWS) -PyDoc_STRVAR(os__isdir__doc__, -"_isdir($module, path, /)\n" -"--\n" -"\n" -"Return true if the pathname refers to an existing directory."); - -#define OS__ISDIR_METHODDEF \ - {"_isdir", (PyCFunction)os__isdir, METH_O, os__isdir__doc__}, - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - PyDoc_STRVAR(os__getvolumepathname__doc__, "_getvolumepathname($module, /, path)\n" "--\n" @@ -8274,10 +8261,6 @@ os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nar #define OS__GETFINALPATHNAME_METHODDEF #endif /* !defined(OS__GETFINALPATHNAME_METHODDEF) */ -#ifndef OS__ISDIR_METHODDEF - #define OS__ISDIR_METHODDEF -#endif /* !defined(OS__ISDIR_METHODDEF) */ - #ifndef OS__GETVOLUMEPATHNAME_METHODDEF #define OS__GETVOLUMEPATHNAME_METHODDEF #endif /* !defined(OS__GETVOLUMEPATHNAME_METHODDEF) */ @@ -8741,4 +8724,4 @@ os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF #define OS__REMOVE_DLL_DIRECTORY_METHODDEF #endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */ -/*[clinic end generated code: output=1e001c855e011720 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b71eff00b91f5e43 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 4f8c074a6716..2302678ccc14 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1625,6 +1625,7 @@ win32_wchdir(LPCWSTR path) */ #define HAVE_STAT_NSEC 1 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 +#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1 static void find_data_to_file_info(WIN32_FIND_DATAW *pFileData, @@ -1658,136 +1659,178 @@ attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *re return TRUE; } -static BOOL -get_target_path(HANDLE hdl, wchar_t **target_path) -{ - int buf_size, result_length; - wchar_t *buf; - - /* We have a good handle to the target, use it to determine - the target path name (then we'll call lstat on it). */ - buf_size = GetFinalPathNameByHandleW(hdl, 0, 0, - VOLUME_NAME_DOS); - if(!buf_size) - return FALSE; - - buf = (wchar_t *)PyMem_RawMalloc((buf_size + 1) * sizeof(wchar_t)); - if (!buf) { - SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - - result_length = GetFinalPathNameByHandleW(hdl, - buf, buf_size, VOLUME_NAME_DOS); - - if(!result_length) { - PyMem_RawFree(buf); - return FALSE; - } - - buf[result_length] = 0; - - *target_path = buf; - return TRUE; -} - static int win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) { - int code; - HANDLE hFile, hFile2; - BY_HANDLE_FILE_INFORMATION info; - ULONG reparse_tag = 0; - wchar_t *target_path; - const wchar_t *dot; + HANDLE hFile; + BY_HANDLE_FILE_INFORMATION fileInfo; + FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 }; + DWORD fileType, error; + BOOL isUnhandledTag = FALSE; + int retval = 0; - hFile = CreateFileW( - path, - FILE_READ_ATTRIBUTES, /* desired access */ - 0, /* share mode */ - NULL, /* security attributes */ - OPEN_EXISTING, - /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ - /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink. - Because of this, calls like GetFinalPathNameByHandle will return - the symlink path again and not the actual final path. */ - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS| - FILE_FLAG_OPEN_REPARSE_POINT, - NULL); + DWORD access = FILE_READ_ATTRIBUTES; + DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */ + if (!traverse) { + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + } + hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL); if (hFile == INVALID_HANDLE_VALUE) { - /* Either the target doesn't exist, or we don't have access to - get a handle to it. If the former, we need to return an error. - If the latter, we can use attributes_from_dir. */ - DWORD lastError = GetLastError(); - if (lastError != ERROR_ACCESS_DENIED && - lastError != ERROR_SHARING_VIOLATION) - return -1; - /* Could not get attributes on open file. Fall back to - reading the directory. */ - if (!attributes_from_dir(path, &info, &reparse_tag)) - /* Very strange. This should not fail now */ - return -1; - if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (traverse) { - /* Should traverse, but could not open reparse point handle */ - SetLastError(lastError); + /* Either the path doesn't exist, or the caller lacks access. */ + error = GetLastError(); + switch (error) { + case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */ + case ERROR_SHARING_VIOLATION: /* It's a paging file. */ + /* Try reading the parent directory. */ + if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) { + /* Cannot read the parent directory. */ + SetLastError(error); return -1; } - } - } else { - if (!GetFileInformationByHandle(hFile, &info)) { - CloseHandle(hFile); - return -1; - } - if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (!win32_get_reparse_tag(hFile, &reparse_tag)) { - CloseHandle(hFile); - return -1; + if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + if (traverse || + !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { + /* The stat call has to traverse but cannot, so fail. */ + SetLastError(error); + return -1; + } } - /* Close the outer open file handle now that we're about to - reopen it with different flags. */ - if (!CloseHandle(hFile)) + break; + + case ERROR_INVALID_PARAMETER: + /* \\.\con requires read or write access. */ + hFile = CreateFileW(path, access | GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, flags, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + SetLastError(error); return -1; + } + break; + case ERROR_CANT_ACCESS_FILE: + /* bpo37834: open unhandled reparse points if traverse fails. */ if (traverse) { - /* In order to call GetFinalPathNameByHandle we need to open - the file without the reparse handling flag set. */ - hFile2 = CreateFileW( - path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, - NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if (hFile2 == INVALID_HANDLE_VALUE) - return -1; + traverse = FALSE; + isUnhandledTag = TRUE; + hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, + flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + } + if (hFile == INVALID_HANDLE_VALUE) { + SetLastError(error); + return -1; + } + break; - if (!get_target_path(hFile2, &target_path)) { - CloseHandle(hFile2); - return -1; - } + default: + return -1; + } + } - if (!CloseHandle(hFile2)) { - return -1; + if (hFile != INVALID_HANDLE_VALUE) { + /* Handle types other than files on disk. */ + fileType = GetFileType(hFile); + if (fileType != FILE_TYPE_DISK) { + if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) { + retval = -1; + goto cleanup; + } + DWORD fileAttributes = GetFileAttributesW(path); + memset(result, 0, sizeof(*result)); + if (fileAttributes != INVALID_FILE_ATTRIBUTES && + fileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + /* \\.\pipe\ or \\.\mailslot\ */ + result->st_mode = _S_IFDIR; + } else if (fileType == FILE_TYPE_CHAR) { + /* \\.\nul */ + result->st_mode = _S_IFCHR; + } else if (fileType == FILE_TYPE_PIPE) { + /* \\.\pipe\spam */ + result->st_mode = _S_IFIFO; + } + /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */ + goto cleanup; + } + + /* Query the reparse tag, and traverse a non-link. */ + if (!traverse) { + if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo, + &tagInfo, sizeof(tagInfo))) { + /* Allow devices that do not support FileAttributeTagInfo. */ + switch (GetLastError()) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_NOT_SUPPORTED: + tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; + tagInfo.ReparseTag = 0; + break; + default: + retval = -1; + goto cleanup; } + } else if (tagInfo.FileAttributes & + FILE_ATTRIBUTE_REPARSE_POINT) { + if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { + if (isUnhandledTag) { + /* Traversing previously failed for either this link + or its target. */ + SetLastError(ERROR_CANT_ACCESS_FILE); + retval = -1; + goto cleanup; + } + /* Traverse a non-link, but not if traversing already failed + for an unhandled tag. */ + } else if (!isUnhandledTag) { + CloseHandle(hFile); + return win32_xstat_impl(path, result, TRUE); + } + } + } - code = win32_xstat_impl(target_path, result, FALSE); - PyMem_RawFree(target_path); - return code; + if (!GetFileInformationByHandle(hFile, &fileInfo)) { + switch (GetLastError()) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_NOT_SUPPORTED: + retval = -1; + goto cleanup; } - } else - CloseHandle(hFile); + /* Volumes and physical disks are block devices, e.g. + \\.\C: and \\.\PhysicalDrive0. */ + memset(result, 0, sizeof(*result)); + result->st_mode = 0x6000; /* S_IFBLK */ + goto cleanup; + } } - _Py_attribute_data_to_stat(&info, reparse_tag, result); - /* Set S_IEXEC if it is an .exe, .bat, ... */ - dot = wcsrchr(path, '.'); - if (dot) { - if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 || - _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0) - result->st_mode |= 0111; + _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result); + + if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + /* Fix the file execute permissions. This hack sets S_IEXEC if + the filename has an extension that is commonly used by files + that CreateProcessW can execute. A real implementation calls + GetSecurityInfo, OpenThreadToken/OpenProcessToken, and + AccessCheck to check for generic read, write, and execute + access. */ + const wchar_t *fileExtension = wcsrchr(path, '.'); + if (fileExtension) { + if (_wcsicmp(fileExtension, L".exe") == 0 || + _wcsicmp(fileExtension, L".bat") == 0 || + _wcsicmp(fileExtension, L".cmd") == 0 || + _wcsicmp(fileExtension, L".com") == 0) { + result->st_mode |= 0111; + } + } } - return 0; + +cleanup: + if (hFile != INVALID_HANDLE_VALUE) { + CloseHandle(hFile); + } + + return retval; } static int @@ -1806,9 +1849,8 @@ win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) default does not traverse symlinks and instead returns attributes for the symlink. - Therefore, win32_lstat will get the attributes traditionally, and - win32_stat will first explicitly resolve the symlink target and then will - call win32_lstat on that result. */ + Instead, we will open the file (which *does* traverse symlinks by default) + and GetFileInformationByHandle(). */ static int win32_lstat(const wchar_t* path, struct _Py_stat_struct *result) @@ -1876,6 +1918,9 @@ static PyStructSequence_Field stat_result_fields[] = { #endif #ifdef HAVE_STRUCT_STAT_ST_FSTYPE {"st_fstype", "Type of filesystem"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG + {"st_reparse_tag", "Windows reparse tag"}, #endif {0} }; @@ -1928,6 +1973,12 @@ static PyStructSequence_Field stat_result_fields[] = { #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX #endif +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG +#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1) +#else +#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX +#endif + static PyStructSequence_Desc stat_result_desc = { "stat_result", /* name */ stat_result__doc__, /* doc */ @@ -2155,6 +2206,10 @@ _pystat_fromstructstat(STRUCT_STAT *st) PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype)); #endif +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG + PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX, + PyLong_FromUnsignedLong(st->st_reparse_tag)); +#endif if (PyErr_Occurred()) { Py_DECREF(v); @@ -3877,8 +3932,9 @@ os__getfinalpathname_impl(PyObject *module, path_t *path) } result = PyUnicode_FromWideChar(target_path, result_length); - if (path->narrow) + if (result && path->narrow) { Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + } cleanup: if (target_path != buf) { @@ -3888,44 +3944,6 @@ os__getfinalpathname_impl(PyObject *module, path_t *path) return result; } -/*[clinic input] -os._isdir - - path as arg: object - / - -Return true if the pathname refers to an existing directory. -[clinic start generated code]*/ - -static PyObject * -os__isdir(PyObject *module, PyObject *arg) -/*[clinic end generated code: output=404f334d85d4bf25 input=36cb6785874d479e]*/ -{ - DWORD attributes; - path_t path = PATH_T_INITIALIZE("_isdir", "path", 0, 0); - - if (!path_converter(arg, &path)) { - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - attributes = GetFileAttributesW(path.wide); - Py_END_ALLOW_THREADS - - path_cleanup(&path); - if (attributes == INVALID_FILE_ATTRIBUTES) - Py_RETURN_FALSE; - - if (attributes & FILE_ATTRIBUTE_DIRECTORY) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - /*[clinic input] os._getvolumepathname @@ -7796,11 +7814,10 @@ os_readlink_impl(PyObject *module, path_t *path, int dir_fd) return PyBytes_FromStringAndSize(buffer, length); #elif defined(MS_WINDOWS) DWORD n_bytes_returned; - DWORD io_result; + DWORD io_result = 0; HANDLE reparse_point_handle; char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; - const wchar_t *print_name; PyObject *result; /* First get a handle to the reparse point */ @@ -7813,42 +7830,51 @@ os_readlink_impl(PyObject *module, path_t *path, int dir_fd) OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0); - Py_END_ALLOW_THREADS - - if (reparse_point_handle == INVALID_HANDLE_VALUE) { - return path_error(path); + if (reparse_point_handle != INVALID_HANDLE_VALUE) { + /* New call DeviceIoControl to read the reparse point */ + io_result = DeviceIoControl( + reparse_point_handle, + FSCTL_GET_REPARSE_POINT, + 0, 0, /* in buffer */ + target_buffer, sizeof(target_buffer), + &n_bytes_returned, + 0 /* we're not using OVERLAPPED_IO */ + ); + CloseHandle(reparse_point_handle); } - - Py_BEGIN_ALLOW_THREADS - /* New call DeviceIoControl to read the reparse point */ - io_result = DeviceIoControl( - reparse_point_handle, - FSCTL_GET_REPARSE_POINT, - 0, 0, /* in buffer */ - target_buffer, sizeof(target_buffer), - &n_bytes_returned, - 0 /* we're not using OVERLAPPED_IO */ - ); - CloseHandle(reparse_point_handle); Py_END_ALLOW_THREADS if (io_result == 0) { return path_error(path); } - if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) + wchar_t *name = NULL; + Py_ssize_t nameLen = 0; + if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { - PyErr_SetString(PyExc_ValueError, - "not a symbolic link"); - return NULL; + name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + + rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset); + nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); } - print_name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + - rdb->SymbolicLinkReparseBuffer.PrintNameOffset); - - result = PyUnicode_FromWideChar(print_name, - rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); - if (path->narrow) { - Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) + { + name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer + + rdb->MountPointReparseBuffer.SubstituteNameOffset); + nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + } + else + { + PyErr_SetString(PyExc_ValueError, "not a symbolic link"); + } + if (name) { + if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) { + /* Our buffer is mutable, so this is okay */ + name[1] = L'\\'; + } + result = PyUnicode_FromWideChar(name, nameLen); + if (path->narrow) { + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + } } return result; #endif @@ -13647,7 +13673,6 @@ static PyMethodDef posix_methods[] = { OS_PATHCONF_METHODDEF OS_ABORT_METHODDEF OS__GETFULLPATHNAME_METHODDEF - OS__ISDIR_METHODDEF OS__GETDISKUSAGE_METHODDEF OS__GETFINALPATHNAME_METHODDEF OS__GETVOLUMEPATHNAME_METHODDEF diff --git a/Python/fileutils.c b/Python/fileutils.c index 55bc1940aeb8..36a3c995a98a 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -878,7 +878,12 @@ _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec); result->st_nlink = info->nNumberOfLinks; result->st_ino = (((uint64_t)info->nFileIndexHigh) << 32) + info->nFileIndexLow; - if (reparse_tag == IO_REPARSE_TAG_SYMLINK) { + /* bpo-37834: Only actual symlinks set the S_IFLNK flag. But lstat() will + open other name surrogate reparse points without traversing them. To + detect/handle these, check st_file_attributes and st_reparse_tag. */ + result->st_reparse_tag = reparse_tag; + if (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && + reparse_tag == IO_REPARSE_TAG_SYMLINK) { /* first clear the S_IFMT bits */ result->st_mode ^= (result->st_mode & S_IFMT); /* now set the bits that make this a symlink */ From webhook-mailer at python.org Wed Aug 21 18:52:46 2019 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 21 Aug 2019 22:52:46 -0000 Subject: [Python-checkins] bpo-37834: Normalise handling of reparse points on Windows (GH-15370) Message-ID: https://github.com/python/cpython/commit/9eb3d5463976068900e94b860ced7e035885835c commit: 9eb3d5463976068900e94b860ced7e035885835c branch: 3.8 author: Steve Dower committer: GitHub date: 2019-08-21T15:52:42-07:00 summary: bpo-37834: Normalise handling of reparse points on Windows (GH-15370) bpo-37834: Normalise handling of reparse points on Windows * ntpath.realpath() and nt.stat() will traverse all supported reparse points (previously was mixed) * nt.lstat() will let the OS traverse reparse points that are not name surrogates (previously would not traverse any reparse point) * nt.[l]stat() will only set S_IFLNK for symlinks (previous behaviour) * nt.readlink() will read destinations for symlinks and junction points only bpo-1311: os.path.exists('nul') now returns True on Windows * nt.stat('nul').st_mode is now S_IFCHR (previously was an error) files: A Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst A Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst M Doc/library/os.rst M Doc/library/shutil.rst M Doc/library/stat.rst M Doc/whatsnew/3.8.rst M Include/fileutils.h M Lib/shutil.py M Lib/test/test_os.py M Lib/test/test_shutil.py M Lib/test/test_tools/test_lll.py M Lib/test/test_venv.py M Modules/_stat.c M Modules/clinic/posixmodule.c.h M Modules/posixmodule.c M Python/fileutils.c diff --git a/Doc/library/os.rst b/Doc/library/os.rst index c74d687f08fb..6cbfb7432841 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1858,6 +1858,12 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object` for *src* and *dst*. + .. versionchanged:: 3.8 + On Windows, now opens reparse points that represent another path + (name surrogates), including symbolic links and directory junctions. + Other kinds of reparse points are resolved by the operating system as + for :func:`~os.stat`. + .. function:: mkdir(path, mode=0o777, *, dir_fd=None) @@ -2039,6 +2045,10 @@ features: This function can also support :ref:`paths relative to directory descriptors `. + When trying to resolve a path that may contain links, use + :func:`~os.path.realpath` to properly handle recursion and platform + differences. + .. availability:: Unix, Windows. .. versionchanged:: 3.2 @@ -2053,6 +2063,11 @@ features: .. versionchanged:: 3.8 Accepts a :term:`path-like object` and a bytes object on Windows. + .. versionchanged:: 3.8 + Added support for directory junctions, and changed to return the + substitution path (which typically includes ``\\?\`` prefix) rather + than the optional "print name" field that was previously returned. + .. function:: remove(path, *, dir_fd=None) Remove (delete) the file *path*. If *path* is a directory, an @@ -2366,7 +2381,8 @@ features: On Unix, this method always requires a system call. On Windows, it only requires a system call if *follow_symlinks* is ``True`` and the - entry is a symbolic link. + entry is a reparse point (for example, a symbolic link or directory + junction). On Windows, the ``st_ino``, ``st_dev`` and ``st_nlink`` attributes of the :class:`stat_result` are always set to zero. Call :func:`os.stat` to @@ -2403,6 +2419,17 @@ features: This function can support :ref:`specifying a file descriptor ` and :ref:`not following symlinks `. + On Windows, passing ``follow_symlinks=False`` will disable following all + name-surrogate reparse points, which includes symlinks and directory + junctions. Other types of reparse points that do not resemble links or that + the operating system is unable to follow will be opened directly. When + following a chain of multiple links, this may result in the original link + being returned instead of the non-link that prevented full traversal. To + obtain stat results for the final path in this case, use the + :func:`os.path.realpath` function to resolve the path name as far as + possible and call :func:`lstat` on the result. This does not apply to + dangling symlinks or junction points, which will raise the usual exceptions. + .. index:: module: stat Example:: @@ -2427,6 +2454,14 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: 3.8 + On Windows, all reparse points that can be resolved by the operating + system are now followed, and passing ``follow_symlinks=False`` + disables following all name surrogate reparse points. If the operating + system reaches a reparse point that it is not able to follow, *stat* now + returns the information for the original path as if + ``follow_symlinks=False`` had been specified instead of raising an error. + .. class:: stat_result @@ -2578,7 +2613,7 @@ features: File type. - On Windows systems, the following attribute is also available: + On Windows systems, the following attributes are also available: .. attribute:: st_file_attributes @@ -2587,6 +2622,12 @@ features: :c:func:`GetFileInformationByHandle`. See the ``FILE_ATTRIBUTE_*`` constants in the :mod:`stat` module. + .. attribute:: st_reparse_tag + + When :attr:`st_file_attributes` has the ``FILE_ATTRIBUTE_REPARSE_POINT`` + set, this field contains the tag identifying the type of reparse point. + See the ``IO_REPARSE_TAG_*`` constants in the :mod:`stat` module. + The standard module :mod:`stat` defines functions and constants that are useful for extracting information from a :c:type:`stat` structure. (On Windows, some items are filled with dummy values.) @@ -2614,6 +2655,14 @@ features: .. versionadded:: 3.7 Added the :attr:`st_fstype` member to Solaris/derivatives. + .. versionadded:: 3.8 + Added the :attr:`st_reparse_tag` member on Windows. + + .. versionchanged:: 3.8 + On Windows, the :attr:`st_mode` member now identifies special + files as :const:`S_IFCHR`, :const:`S_IFIFO` or :const:`S_IFBLK` + as appropriate. + .. function:: statvfs(path) Perform a :c:func:`statvfs` system call on the given path. The return value is diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index eaeee8df81b8..a51e068ebd59 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -304,6 +304,10 @@ Directory and files operations Added a symlink attack resistant version that is used automatically if platform supports fd-based functions. + .. versionchanged:: 3.8 + On Windows, will no longer delete the contents of a directory junction + before removing the junction. + .. attribute:: rmtree.avoids_symlink_attacks Indicates whether the current platform and implementation provides a diff --git a/Doc/library/stat.rst b/Doc/library/stat.rst index c8f6904f9b1f..f48a0a9faa6b 100644 --- a/Doc/library/stat.rst +++ b/Doc/library/stat.rst @@ -425,3 +425,13 @@ for more detail on the meaning of these constants. FILE_ATTRIBUTE_VIRTUAL .. versionadded:: 3.5 + +On Windows, the following constants are available for comparing against the +``st_reparse_tag`` member returned by :func:`os.lstat`. These are well-known +constants, but are not an exhaustive list. + +.. data:: IO_REPARSE_TAG_SYMLINK + IO_REPARSE_TAG_MOUNT_POINT + IO_REPARSE_TAG_APPEXECLINK + + .. versionadded:: 3.8 diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 93758e96b573..0294e9a0830b 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -808,6 +808,21 @@ A new :func:`os.memfd_create` function was added to wrap the ``memfd_create()`` syscall. (Contributed by Zackery Spytz and Christian Heimes in :issue:`26836`.) +On Windows, much of the manual logic for handling reparse points (including +symlinks and directory junctions) has been delegated to the operating system. +Specifically, :func:`os.stat` will now traverse anything supported by the +operating system, while :func:`os.lstat` will only open reparse points that +identify as "name surrogates" while others are opened as for :func:`os.stat`. +In all cases, :attr:`stat_result.st_mode` will only have ``S_IFLNK`` set for +symbolic links and not other kinds of reparse points. To identify other kinds +of reparse point, check the new :attr:`stat_result.st_reparse_tag` attribute. + +On Windows, :func:`os.readlink` is now able to read directory junctions. Note +that :func:`~os.path.islink` will return ``False`` for directory junctions, +and so code that checks ``islink`` first will continue to treat junctions as +directories, while code that handles errors from :func:`os.readlink` may now +treat junctions as links. + os.path ------- @@ -824,6 +839,9 @@ characters or bytes unrepresentable at the OS level. environment variable and does not use :envvar:`HOME`, which is not normally set for regular user accounts. +:func:`~os.path.isdir` on Windows no longer returns true for a link to a +non-existent directory. + :func:`~os.path.realpath` on Windows now resolves reparse points, including symlinks and directory junctions. @@ -912,6 +930,9 @@ format for new archives to improve portability and standards conformance, inherited from the corresponding change to the :mod:`tarfile` module. (Contributed by C.A.M. Gerlach in :issue:`30661`.) +:func:`shutil.rmtree` on Windows now removes directory junctions without +recursively removing their contents first. + ssl --- diff --git a/Include/fileutils.h b/Include/fileutils.h index 0be8b0ae3b31..359dd0ad4ead 100644 --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -84,6 +84,7 @@ struct _Py_stat_struct { time_t st_ctime; int st_ctime_nsec; unsigned long st_file_attributes; + unsigned long st_reparse_tag; }; #else # define _Py_stat_struct stat diff --git a/Lib/shutil.py b/Lib/shutil.py index ab1a7d61897a..39f793b5f3bd 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -452,7 +452,14 @@ def _copytree(entries, src, dst, symlinks, ignore, copy_function, dstname = os.path.join(dst, srcentry.name) srcobj = srcentry if use_srcentry else srcname try: - if srcentry.is_symlink(): + is_symlink = srcentry.is_symlink() + if is_symlink and os.name == 'nt': + # Special check for directory junctions, which appear as + # symlinks but we want to recurse. + lstat = srcentry.stat(follow_symlinks=False) + if lstat.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT: + is_symlink = False + if is_symlink: linkto = os.readlink(srcname) if symlinks: # We can't just leave it to `copy_function` because legacy @@ -537,6 +544,37 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=ignore_dangling_symlinks, dirs_exist_ok=dirs_exist_ok) +if hasattr(stat, 'FILE_ATTRIBUTE_REPARSE_POINT'): + # Special handling for directory junctions to make them behave like + # symlinks for shutil.rmtree, since in general they do not appear as + # regular links. + def _rmtree_isdir(entry): + try: + st = entry.stat(follow_symlinks=False) + return (stat.S_ISDIR(st.st_mode) and not + (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT + and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)) + except OSError: + return False + + def _rmtree_islink(path): + try: + st = os.lstat(path) + return (stat.S_ISLNK(st.st_mode) or + (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT + and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)) + except OSError: + return False +else: + def _rmtree_isdir(entry): + try: + return entry.is_dir(follow_symlinks=False) + except OSError: + return False + + def _rmtree_islink(path): + return os.path.islink(path) + # version vulnerable to race conditions def _rmtree_unsafe(path, onerror): try: @@ -547,11 +585,7 @@ def _rmtree_unsafe(path, onerror): entries = [] for entry in entries: fullname = entry.path - try: - is_dir = entry.is_dir(follow_symlinks=False) - except OSError: - is_dir = False - if is_dir: + if _rmtree_isdir(entry): try: if entry.is_symlink(): # This can only happen if someone replaces @@ -681,7 +715,7 @@ def onerror(*args): os.close(fd) else: try: - if os.path.islink(path): + if _rmtree_islink(path): # symlinks to directories are forbidden, see bug #1669 raise OSError("Cannot call rmtree on a symbolic link") except OSError: diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 15fd65b55149..ba9f5c35ae31 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -8,6 +8,7 @@ import contextlib import decimal import errno +import fnmatch import fractions import itertools import locale @@ -2253,6 +2254,20 @@ class ReadlinkTests(unittest.TestCase): filelinkb = os.fsencode(filelink) filelinkb_target = os.fsencode(filelink_target) + def assertPathEqual(self, left, right): + left = os.path.normcase(left) + right = os.path.normcase(right) + if sys.platform == 'win32': + # Bad practice to blindly strip the prefix as it may be required to + # correctly refer to the file, but we're only comparing paths here. + has_prefix = lambda p: p.startswith( + b'\\\\?\\' if isinstance(p, bytes) else '\\\\?\\') + if has_prefix(left): + left = left[4:] + if has_prefix(right): + right = right[4:] + self.assertEqual(left, right) + def setUp(self): self.assertTrue(os.path.exists(self.filelink_target)) self.assertTrue(os.path.exists(self.filelinkb_target)) @@ -2274,14 +2289,14 @@ def test_pathlike(self): os.symlink(self.filelink_target, self.filelink) self.addCleanup(support.unlink, self.filelink) filelink = FakePath(self.filelink) - self.assertEqual(os.readlink(filelink), self.filelink_target) + self.assertPathEqual(os.readlink(filelink), self.filelink_target) @support.skip_unless_symlink def test_pathlike_bytes(self): os.symlink(self.filelinkb_target, self.filelinkb) self.addCleanup(support.unlink, self.filelinkb) path = os.readlink(FakePath(self.filelinkb)) - self.assertEqual(path, self.filelinkb_target) + self.assertPathEqual(path, self.filelinkb_target) self.assertIsInstance(path, bytes) @support.skip_unless_symlink @@ -2289,7 +2304,7 @@ def test_bytes(self): os.symlink(self.filelinkb_target, self.filelinkb) self.addCleanup(support.unlink, self.filelinkb) path = os.readlink(self.filelinkb) - self.assertEqual(path, self.filelinkb_target) + self.assertPathEqual(path, self.filelinkb_target) self.assertIsInstance(path, bytes) @@ -2348,16 +2363,12 @@ def test_remove_directory_link_to_missing_target(self): # was created with target_is_dir==True. os.remove(self.missing_link) - @unittest.skip("currently fails; consider for improvement") def test_isdir_on_directory_link_to_missing_target(self): self._create_missing_dir_link() - # consider having isdir return true for directory links - self.assertTrue(os.path.isdir(self.missing_link)) + self.assertFalse(os.path.isdir(self.missing_link)) - @unittest.skip("currently fails; consider for improvement") def test_rmdir_on_directory_link_to_missing_target(self): self._create_missing_dir_link() - # consider allowing rmdir to remove directory links os.rmdir(self.missing_link) def check_stat(self, link, target): @@ -2453,6 +2464,24 @@ def test_buffer_overflow(self): except OSError: pass + def test_appexeclink(self): + root = os.path.expandvars(r'%LOCALAPPDATA%\Microsoft\WindowsApps') + aliases = [os.path.join(root, a) + for a in fnmatch.filter(os.listdir(root), '*.exe')] + + for alias in aliases: + if support.verbose: + print() + print("Testing with", alias) + st = os.lstat(alias) + self.assertEqual(st, os.stat(alias)) + self.assertFalse(stat.S_ISLNK(st.st_mode)) + self.assertEqual(st.st_reparse_tag, stat.IO_REPARSE_TAG_APPEXECLINK) + # testing the first one we see is sufficient + break + else: + self.skipTest("test requires an app execution alias") + @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") class Win32JunctionTests(unittest.TestCase): junction = 'junctiontest' @@ -2460,25 +2489,29 @@ class Win32JunctionTests(unittest.TestCase): def setUp(self): assert os.path.exists(self.junction_target) - assert not os.path.exists(self.junction) + assert not os.path.lexists(self.junction) def tearDown(self): - if os.path.exists(self.junction): - # os.rmdir delegates to Windows' RemoveDirectoryW, - # which removes junction points safely. - os.rmdir(self.junction) + if os.path.lexists(self.junction): + os.unlink(self.junction) def test_create_junction(self): _winapi.CreateJunction(self.junction_target, self.junction) + self.assertTrue(os.path.lexists(self.junction)) self.assertTrue(os.path.exists(self.junction)) self.assertTrue(os.path.isdir(self.junction)) + self.assertNotEqual(os.stat(self.junction), os.lstat(self.junction)) + self.assertEqual(os.stat(self.junction), os.stat(self.junction_target)) - # Junctions are not recognized as links. + # bpo-37834: Junctions are not recognized as links. self.assertFalse(os.path.islink(self.junction)) + self.assertEqual(os.path.normcase("\\\\?\\" + self.junction_target), + os.path.normcase(os.readlink(self.junction))) def test_unlink_removes_junction(self): _winapi.CreateJunction(self.junction_target, self.junction) self.assertTrue(os.path.exists(self.junction)) + self.assertTrue(os.path.lexists(self.junction)) os.unlink(self.junction) self.assertFalse(os.path.exists(self.junction)) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 88dc4d9e195e..636e3bd97955 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -42,6 +42,11 @@ except ImportError: UID_GID_SUPPORT = False +try: + import _winapi +except ImportError: + _winapi = None + def _fake_rename(*args, **kwargs): # Pretend the destination path is on a different filesystem. raise OSError(getattr(errno, 'EXDEV', 18), "Invalid cross-device link") @@ -226,6 +231,47 @@ def test_rmtree_works_on_symlinks(self): self.assertTrue(os.path.exists(dir3)) self.assertTrue(os.path.exists(file1)) + @unittest.skipUnless(_winapi, 'only relevant on Windows') + def test_rmtree_fails_on_junctions(self): + tmp = self.mkdtemp() + dir_ = os.path.join(tmp, 'dir') + os.mkdir(dir_) + link = os.path.join(tmp, 'link') + _winapi.CreateJunction(dir_, link) + self.assertRaises(OSError, shutil.rmtree, link) + self.assertTrue(os.path.exists(dir_)) + self.assertTrue(os.path.lexists(link)) + errors = [] + def onerror(*args): + errors.append(args) + shutil.rmtree(link, onerror=onerror) + self.assertEqual(len(errors), 1) + self.assertIs(errors[0][0], os.path.islink) + self.assertEqual(errors[0][1], link) + self.assertIsInstance(errors[0][2][1], OSError) + + @unittest.skipUnless(_winapi, 'only relevant on Windows') + def test_rmtree_works_on_junctions(self): + tmp = self.mkdtemp() + dir1 = os.path.join(tmp, 'dir1') + dir2 = os.path.join(dir1, 'dir2') + dir3 = os.path.join(tmp, 'dir3') + for d in dir1, dir2, dir3: + os.mkdir(d) + file1 = os.path.join(tmp, 'file1') + write_file(file1, 'foo') + link1 = os.path.join(dir1, 'link1') + _winapi.CreateJunction(dir2, link1) + link2 = os.path.join(dir1, 'link2') + _winapi.CreateJunction(dir3, link2) + link3 = os.path.join(dir1, 'link3') + _winapi.CreateJunction(file1, link3) + # make sure junctions are removed but not followed + shutil.rmtree(dir1) + self.assertFalse(os.path.exists(dir1)) + self.assertTrue(os.path.exists(dir3)) + self.assertTrue(os.path.exists(file1)) + def test_rmtree_errors(self): # filename is guaranteed not to exist filename = tempfile.mktemp() @@ -754,8 +800,12 @@ def test_copytree_symlinks(self): src_stat = os.lstat(src_link) shutil.copytree(src_dir, dst_dir, symlinks=True) self.assertTrue(os.path.islink(os.path.join(dst_dir, 'sub', 'link'))) - self.assertEqual(os.readlink(os.path.join(dst_dir, 'sub', 'link')), - os.path.join(src_dir, 'file.txt')) + actual = os.readlink(os.path.join(dst_dir, 'sub', 'link')) + # Bad practice to blindly strip the prefix as it may be required to + # correctly refer to the file, but we're only comparing paths here. + if os.name == 'nt' and actual.startswith('\\\\?\\'): + actual = actual[4:] + self.assertEqual(actual, os.path.join(src_dir, 'file.txt')) dst_stat = os.lstat(dst_link) if hasattr(os, 'lchmod'): self.assertEqual(dst_stat.st_mode, src_stat.st_mode) @@ -886,7 +936,6 @@ def custom_cpfun(a, b): shutil.copytree(src, dst, copy_function=custom_cpfun) self.assertEqual(len(flag), 1) - @unittest.skipIf(os.name == 'nt', 'temporarily disabled on Windows') @unittest.skipUnless(hasattr(os, 'link'), 'requires os.link') def test_dont_copy_file_onto_link_to_itself(self): # bug 851123. @@ -941,6 +990,20 @@ def test_rmtree_on_symlink(self): finally: shutil.rmtree(TESTFN, ignore_errors=True) + @unittest.skipUnless(_winapi, 'only relevant on Windows') + def test_rmtree_on_junction(self): + os.mkdir(TESTFN) + try: + src = os.path.join(TESTFN, 'cheese') + dst = os.path.join(TESTFN, 'shop') + os.mkdir(src) + open(os.path.join(src, 'spam'), 'wb').close() + _winapi.CreateJunction(src, dst) + self.assertRaises(OSError, shutil.rmtree, dst) + shutil.rmtree(dst, ignore_errors=True) + finally: + shutil.rmtree(TESTFN, ignore_errors=True) + # Issue #3002: copyfile and copytree block indefinitely on named pipes @unittest.skipUnless(hasattr(os, "mkfifo"), 'requires os.mkfifo()') def test_copyfile_named_pipe(self): diff --git a/Lib/test/test_tools/test_lll.py b/Lib/test/test_tools/test_lll.py index f3fbe961eee5..b01e2188e1cf 100644 --- a/Lib/test/test_tools/test_lll.py +++ b/Lib/test/test_tools/test_lll.py @@ -1,6 +1,7 @@ """Tests for the lll script in the Tools/script directory.""" import os +import sys import tempfile from test import support from test.test_tools import skip_if_missing, import_tool @@ -26,12 +27,13 @@ def test_lll_multiple_dirs(self): with support.captured_stdout() as output: self.lll.main([dir1, dir2]) + prefix = '\\\\?\\' if os.name == 'nt' else '' self.assertEqual(output.getvalue(), f'{dir1}:\n' - f'symlink -> {fn1}\n' + f'symlink -> {prefix}{fn1}\n' f'\n' f'{dir2}:\n' - f'symlink -> {fn2}\n' + f'symlink -> {prefix}{fn2}\n' ) diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index e7adbeebe960..7130dc6f8309 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -372,11 +372,7 @@ def test_devnull(self): with open(os.devnull, "rb") as f: self.assertEqual(f.read(), b"") - # Issue #20541: os.path.exists('nul') is False on Windows - if os.devnull.lower() == 'nul': - self.assertFalse(os.path.exists(os.devnull)) - else: - self.assertTrue(os.path.exists(os.devnull)) + self.assertTrue(os.path.exists(os.devnull)) def do_test_with_pip(self, system_site_packages): rmtree(self.env_dir) diff --git a/Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst b/Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst new file mode 100644 index 000000000000..f2a654cac911 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst @@ -0,0 +1,2 @@ +Treat all name surrogate reparse points on Windows in :func:`os.lstat` and +other reparse points as regular files in :func:`os.stat`. diff --git a/Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst b/Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst new file mode 100644 index 000000000000..2ee98e450fae --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst @@ -0,0 +1,2 @@ +The ``nul`` file on Windows now returns True from :func:`~os.path.exists` +and a valid result from :func:`os.stat` with ``S_IFCHR`` set. diff --git a/Modules/_stat.c b/Modules/_stat.c index f6cb303500cd..6a3020a00d11 100644 --- a/Modules/_stat.c +++ b/Modules/_stat.c @@ -589,6 +589,13 @@ PyInit__stat(void) if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_SYSTEM)) return NULL; if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_TEMPORARY)) return NULL; if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_VIRTUAL)) return NULL; + + if (PyModule_AddObject(m, "IO_REPARSE_TAG_SYMLINK", + PyLong_FromUnsignedLong(IO_REPARSE_TAG_SYMLINK))) return NULL; + if (PyModule_AddObject(m, "IO_REPARSE_TAG_MOUNT_POINT", + PyLong_FromUnsignedLong(IO_REPARSE_TAG_MOUNT_POINT))) return NULL; + if (PyModule_AddObject(m, "IO_REPARSE_TAG_APPEXECLINK", + PyLong_FromUnsignedLong(IO_REPARSE_TAG_APPEXECLINK))) return NULL; #endif return m; diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 22cb94761de5..5c674db3c3a5 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1272,19 +1272,6 @@ os__getfinalpathname(PyObject *module, PyObject *arg) #if defined(MS_WINDOWS) -PyDoc_STRVAR(os__isdir__doc__, -"_isdir($module, path, /)\n" -"--\n" -"\n" -"Return true if the pathname refers to an existing directory."); - -#define OS__ISDIR_METHODDEF \ - {"_isdir", (PyCFunction)os__isdir, METH_O, os__isdir__doc__}, - -#endif /* defined(MS_WINDOWS) */ - -#if defined(MS_WINDOWS) - PyDoc_STRVAR(os__getvolumepathname__doc__, "_getvolumepathname($module, /, path)\n" "--\n" @@ -8274,10 +8261,6 @@ os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nar #define OS__GETFINALPATHNAME_METHODDEF #endif /* !defined(OS__GETFINALPATHNAME_METHODDEF) */ -#ifndef OS__ISDIR_METHODDEF - #define OS__ISDIR_METHODDEF -#endif /* !defined(OS__ISDIR_METHODDEF) */ - #ifndef OS__GETVOLUMEPATHNAME_METHODDEF #define OS__GETVOLUMEPATHNAME_METHODDEF #endif /* !defined(OS__GETVOLUMEPATHNAME_METHODDEF) */ @@ -8741,4 +8724,4 @@ os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF #define OS__REMOVE_DLL_DIRECTORY_METHODDEF #endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */ -/*[clinic end generated code: output=b3ae8afd275ea5cd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=366a1de4c9c61a30 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index bceee89917cb..c178facc4bee 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1624,6 +1624,7 @@ win32_wchdir(LPCWSTR path) */ #define HAVE_STAT_NSEC 1 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 +#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1 static void find_data_to_file_info(WIN32_FIND_DATAW *pFileData, @@ -1657,136 +1658,178 @@ attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *re return TRUE; } -static BOOL -get_target_path(HANDLE hdl, wchar_t **target_path) -{ - int buf_size, result_length; - wchar_t *buf; - - /* We have a good handle to the target, use it to determine - the target path name (then we'll call lstat on it). */ - buf_size = GetFinalPathNameByHandleW(hdl, 0, 0, - VOLUME_NAME_DOS); - if(!buf_size) - return FALSE; - - buf = (wchar_t *)PyMem_RawMalloc((buf_size + 1) * sizeof(wchar_t)); - if (!buf) { - SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - - result_length = GetFinalPathNameByHandleW(hdl, - buf, buf_size, VOLUME_NAME_DOS); - - if(!result_length) { - PyMem_RawFree(buf); - return FALSE; - } - - buf[result_length] = 0; - - *target_path = buf; - return TRUE; -} - static int win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) { - int code; - HANDLE hFile, hFile2; - BY_HANDLE_FILE_INFORMATION info; - ULONG reparse_tag = 0; - wchar_t *target_path; - const wchar_t *dot; + HANDLE hFile; + BY_HANDLE_FILE_INFORMATION fileInfo; + FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 }; + DWORD fileType, error; + BOOL isUnhandledTag = FALSE; + int retval = 0; - hFile = CreateFileW( - path, - FILE_READ_ATTRIBUTES, /* desired access */ - 0, /* share mode */ - NULL, /* security attributes */ - OPEN_EXISTING, - /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ - /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink. - Because of this, calls like GetFinalPathNameByHandle will return - the symlink path again and not the actual final path. */ - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS| - FILE_FLAG_OPEN_REPARSE_POINT, - NULL); + DWORD access = FILE_READ_ATTRIBUTES; + DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */ + if (!traverse) { + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + } + hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL); if (hFile == INVALID_HANDLE_VALUE) { - /* Either the target doesn't exist, or we don't have access to - get a handle to it. If the former, we need to return an error. - If the latter, we can use attributes_from_dir. */ - DWORD lastError = GetLastError(); - if (lastError != ERROR_ACCESS_DENIED && - lastError != ERROR_SHARING_VIOLATION) - return -1; - /* Could not get attributes on open file. Fall back to - reading the directory. */ - if (!attributes_from_dir(path, &info, &reparse_tag)) - /* Very strange. This should not fail now */ - return -1; - if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (traverse) { - /* Should traverse, but could not open reparse point handle */ - SetLastError(lastError); + /* Either the path doesn't exist, or the caller lacks access. */ + error = GetLastError(); + switch (error) { + case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */ + case ERROR_SHARING_VIOLATION: /* It's a paging file. */ + /* Try reading the parent directory. */ + if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) { + /* Cannot read the parent directory. */ + SetLastError(error); return -1; } - } - } else { - if (!GetFileInformationByHandle(hFile, &info)) { - CloseHandle(hFile); - return -1; - } - if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (!win32_get_reparse_tag(hFile, &reparse_tag)) { - CloseHandle(hFile); - return -1; + if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + if (traverse || + !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { + /* The stat call has to traverse but cannot, so fail. */ + SetLastError(error); + return -1; + } } - /* Close the outer open file handle now that we're about to - reopen it with different flags. */ - if (!CloseHandle(hFile)) + break; + + case ERROR_INVALID_PARAMETER: + /* \\.\con requires read or write access. */ + hFile = CreateFileW(path, access | GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, flags, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + SetLastError(error); return -1; + } + break; + case ERROR_CANT_ACCESS_FILE: + /* bpo37834: open unhandled reparse points if traverse fails. */ if (traverse) { - /* In order to call GetFinalPathNameByHandle we need to open - the file without the reparse handling flag set. */ - hFile2 = CreateFileW( - path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, - NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if (hFile2 == INVALID_HANDLE_VALUE) - return -1; + traverse = FALSE; + isUnhandledTag = TRUE; + hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, + flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + } + if (hFile == INVALID_HANDLE_VALUE) { + SetLastError(error); + return -1; + } + break; - if (!get_target_path(hFile2, &target_path)) { - CloseHandle(hFile2); - return -1; - } + default: + return -1; + } + } - if (!CloseHandle(hFile2)) { - return -1; + if (hFile != INVALID_HANDLE_VALUE) { + /* Handle types other than files on disk. */ + fileType = GetFileType(hFile); + if (fileType != FILE_TYPE_DISK) { + if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) { + retval = -1; + goto cleanup; + } + DWORD fileAttributes = GetFileAttributesW(path); + memset(result, 0, sizeof(*result)); + if (fileAttributes != INVALID_FILE_ATTRIBUTES && + fileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + /* \\.\pipe\ or \\.\mailslot\ */ + result->st_mode = _S_IFDIR; + } else if (fileType == FILE_TYPE_CHAR) { + /* \\.\nul */ + result->st_mode = _S_IFCHR; + } else if (fileType == FILE_TYPE_PIPE) { + /* \\.\pipe\spam */ + result->st_mode = _S_IFIFO; + } + /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */ + goto cleanup; + } + + /* Query the reparse tag, and traverse a non-link. */ + if (!traverse) { + if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo, + &tagInfo, sizeof(tagInfo))) { + /* Allow devices that do not support FileAttributeTagInfo. */ + switch (GetLastError()) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_NOT_SUPPORTED: + tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; + tagInfo.ReparseTag = 0; + break; + default: + retval = -1; + goto cleanup; } + } else if (tagInfo.FileAttributes & + FILE_ATTRIBUTE_REPARSE_POINT) { + if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { + if (isUnhandledTag) { + /* Traversing previously failed for either this link + or its target. */ + SetLastError(ERROR_CANT_ACCESS_FILE); + retval = -1; + goto cleanup; + } + /* Traverse a non-link, but not if traversing already failed + for an unhandled tag. */ + } else if (!isUnhandledTag) { + CloseHandle(hFile); + return win32_xstat_impl(path, result, TRUE); + } + } + } - code = win32_xstat_impl(target_path, result, FALSE); - PyMem_RawFree(target_path); - return code; + if (!GetFileInformationByHandle(hFile, &fileInfo)) { + switch (GetLastError()) { + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_NOT_SUPPORTED: + retval = -1; + goto cleanup; } - } else - CloseHandle(hFile); + /* Volumes and physical disks are block devices, e.g. + \\.\C: and \\.\PhysicalDrive0. */ + memset(result, 0, sizeof(*result)); + result->st_mode = 0x6000; /* S_IFBLK */ + goto cleanup; + } } - _Py_attribute_data_to_stat(&info, reparse_tag, result); - /* Set S_IEXEC if it is an .exe, .bat, ... */ - dot = wcsrchr(path, '.'); - if (dot) { - if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 || - _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0) - result->st_mode |= 0111; + _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result); + + if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + /* Fix the file execute permissions. This hack sets S_IEXEC if + the filename has an extension that is commonly used by files + that CreateProcessW can execute. A real implementation calls + GetSecurityInfo, OpenThreadToken/OpenProcessToken, and + AccessCheck to check for generic read, write, and execute + access. */ + const wchar_t *fileExtension = wcsrchr(path, '.'); + if (fileExtension) { + if (_wcsicmp(fileExtension, L".exe") == 0 || + _wcsicmp(fileExtension, L".bat") == 0 || + _wcsicmp(fileExtension, L".cmd") == 0 || + _wcsicmp(fileExtension, L".com") == 0) { + result->st_mode |= 0111; + } + } } - return 0; + +cleanup: + if (hFile != INVALID_HANDLE_VALUE) { + CloseHandle(hFile); + } + + return retval; } static int @@ -1805,9 +1848,8 @@ win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) default does not traverse symlinks and instead returns attributes for the symlink. - Therefore, win32_lstat will get the attributes traditionally, and - win32_stat will first explicitly resolve the symlink target and then will - call win32_lstat on that result. */ + Instead, we will open the file (which *does* traverse symlinks by default) + and GetFileInformationByHandle(). */ static int win32_lstat(const wchar_t* path, struct _Py_stat_struct *result) @@ -1875,6 +1917,9 @@ static PyStructSequence_Field stat_result_fields[] = { #endif #ifdef HAVE_STRUCT_STAT_ST_FSTYPE {"st_fstype", "Type of filesystem"}, +#endif +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG + {"st_reparse_tag", "Windows reparse tag"}, #endif {0} }; @@ -1927,6 +1972,12 @@ static PyStructSequence_Field stat_result_fields[] = { #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX #endif +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG +#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1) +#else +#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX +#endif + static PyStructSequence_Desc stat_result_desc = { "stat_result", /* name */ stat_result__doc__, /* doc */ @@ -2154,6 +2205,10 @@ _pystat_fromstructstat(STRUCT_STAT *st) PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype)); #endif +#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG + PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX, + PyLong_FromUnsignedLong(st->st_reparse_tag)); +#endif if (PyErr_Occurred()) { Py_DECREF(v); @@ -3880,8 +3935,9 @@ os__getfinalpathname_impl(PyObject *module, path_t *path) } result = PyUnicode_FromWideChar(target_path, result_length); - if (path->narrow) + if (result && path->narrow) { Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + } cleanup: if (target_path != buf) { @@ -3891,44 +3947,6 @@ os__getfinalpathname_impl(PyObject *module, path_t *path) return result; } -/*[clinic input] -os._isdir - - path as arg: object - / - -Return true if the pathname refers to an existing directory. -[clinic start generated code]*/ - -static PyObject * -os__isdir(PyObject *module, PyObject *arg) -/*[clinic end generated code: output=404f334d85d4bf25 input=36cb6785874d479e]*/ -{ - DWORD attributes; - path_t path = PATH_T_INITIALIZE("_isdir", "path", 0, 0); - - if (!path_converter(arg, &path)) { - if (PyErr_ExceptionMatches(PyExc_ValueError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - attributes = GetFileAttributesW(path.wide); - Py_END_ALLOW_THREADS - - path_cleanup(&path); - if (attributes == INVALID_FILE_ATTRIBUTES) - Py_RETURN_FALSE; - - if (attributes & FILE_ATTRIBUTE_DIRECTORY) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - /*[clinic input] os._getvolumepathname @@ -7799,11 +7817,10 @@ os_readlink_impl(PyObject *module, path_t *path, int dir_fd) return PyBytes_FromStringAndSize(buffer, length); #elif defined(MS_WINDOWS) DWORD n_bytes_returned; - DWORD io_result; + DWORD io_result = 0; HANDLE reparse_point_handle; char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; - const wchar_t *print_name; PyObject *result; /* First get a handle to the reparse point */ @@ -7816,42 +7833,51 @@ os_readlink_impl(PyObject *module, path_t *path, int dir_fd) OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0); - Py_END_ALLOW_THREADS - - if (reparse_point_handle == INVALID_HANDLE_VALUE) { - return path_error(path); + if (reparse_point_handle != INVALID_HANDLE_VALUE) { + /* New call DeviceIoControl to read the reparse point */ + io_result = DeviceIoControl( + reparse_point_handle, + FSCTL_GET_REPARSE_POINT, + 0, 0, /* in buffer */ + target_buffer, sizeof(target_buffer), + &n_bytes_returned, + 0 /* we're not using OVERLAPPED_IO */ + ); + CloseHandle(reparse_point_handle); } - - Py_BEGIN_ALLOW_THREADS - /* New call DeviceIoControl to read the reparse point */ - io_result = DeviceIoControl( - reparse_point_handle, - FSCTL_GET_REPARSE_POINT, - 0, 0, /* in buffer */ - target_buffer, sizeof(target_buffer), - &n_bytes_returned, - 0 /* we're not using OVERLAPPED_IO */ - ); - CloseHandle(reparse_point_handle); Py_END_ALLOW_THREADS if (io_result == 0) { return path_error(path); } - if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) + wchar_t *name = NULL; + Py_ssize_t nameLen = 0; + if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { - PyErr_SetString(PyExc_ValueError, - "not a symbolic link"); - return NULL; + name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + + rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset); + nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); } - print_name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + - rdb->SymbolicLinkReparseBuffer.PrintNameOffset); - - result = PyUnicode_FromWideChar(print_name, - rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); - if (path->narrow) { - Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) + { + name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer + + rdb->MountPointReparseBuffer.SubstituteNameOffset); + nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + } + else + { + PyErr_SetString(PyExc_ValueError, "not a symbolic link"); + } + if (name) { + if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) { + /* Our buffer is mutable, so this is okay */ + name[1] = L'\\'; + } + result = PyUnicode_FromWideChar(name, nameLen); + if (path->narrow) { + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + } } return result; #endif @@ -13650,7 +13676,6 @@ static PyMethodDef posix_methods[] = { OS_PATHCONF_METHODDEF OS_ABORT_METHODDEF OS__GETFULLPATHNAME_METHODDEF - OS__ISDIR_METHODDEF OS__GETDISKUSAGE_METHODDEF OS__GETFINALPATHNAME_METHODDEF OS__GETVOLUMEPATHNAME_METHODDEF diff --git a/Python/fileutils.c b/Python/fileutils.c index 93c093f89b4b..30ddd037e65a 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -878,7 +878,12 @@ _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec); result->st_nlink = info->nNumberOfLinks; result->st_ino = (((uint64_t)info->nFileIndexHigh) << 32) + info->nFileIndexLow; - if (reparse_tag == IO_REPARSE_TAG_SYMLINK) { + /* bpo-37834: Only actual symlinks set the S_IFLNK flag. But lstat() will + open other name surrogate reparse points without traversing them. To + detect/handle these, check st_file_attributes and st_reparse_tag. */ + result->st_reparse_tag = reparse_tag; + if (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && + reparse_tag == IO_REPARSE_TAG_SYMLINK) { /* first clear the S_IFMT bits */ result->st_mode ^= (result->st_mode & S_IFMT); /* now set the bits that make this a symlink */ From webhook-mailer at python.org Wed Aug 21 18:58:06 2019 From: webhook-mailer at python.org (Brett Cannon) Date: Wed, 21 Aug 2019 22:58:06 -0000 Subject: [Python-checkins] bpo-37663: have venv activation scripts all consistently use __VENV_PROMPT__ for prompt customization (GH-14941) Message-ID: https://github.com/python/cpython/commit/48ede6b8f685669f53d26ae8456647af42ae3dae commit: 48ede6b8f685669f53d26ae8456647af42ae3dae branch: master author: Brett Cannon <54418+brettcannon at users.noreply.github.com> committer: GitHub date: 2019-08-21T15:58:01-07:00 summary: bpo-37663: have venv activation scripts all consistently use __VENV_PROMPT__ for prompt customization (GH-14941) The activation scripts generated by venv were inconsistent in how they changed the shell's prompt. Some used `__VENV_PROMPT__` exclusively, some used `__VENV_PROMPT__` if it was set even though by default `__VENV_PROMPT__` is always set and the fallback matched the default, and one ignored `__VENV_PROMPT__` and used `__VENV_NAME__` instead (and even used a differing format to the default prompt). This change now has all activation scripts use `__VENV_PROMPT__` only and relies on the fact that venv sets that value by default. The color of the customization is also now set in fish to the blue from the Python logo for as hex color support is built into that shell (much like PowerShell where the built-in green color is used). files: A Misc/NEWS.d/next/Library/2019-07-24-14-38-53.bpo-37663.h4-9-1.rst M Doc/whatsnew/3.9.rst M Lib/venv/scripts/common/activate M Lib/venv/scripts/posix/activate.csh M Lib/venv/scripts/posix/activate.fish diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index f09e09c2b905..6615a2e28eff 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -118,6 +118,16 @@ finalization crashed with a Python fatal error if a daemon thread was still running. (Contributed by Victor Stinner in :issue:`37266`.) +venv +---- + +The activation scripts provided by :mod:`venv` now all specify their prompt +customization consistently by always using the value specified by +``__VENV_PROMPT__``. Previously some scripts unconditionally used +``__VENV_PROMPT__``, others only if it happened to be set (which was the default +case), and one used ``__VENV_NAME__`` instead. +(Contributed by Brett Cannon in :issue:`37663`.) + pprint ------ @@ -191,12 +201,14 @@ Removed Use :meth:`~threading.Thread.is_alive()` instead. (Contributed by Dong-hee Na in :issue:`37804`.) + Porting to Python 3.9 ===================== This section lists previously described changes and other bugfixes that may require changes to your code. + Changes in the Python API ------------------------- @@ -205,3 +217,6 @@ Changes in the Python API catching the specific exception type and supporting both Python 3.9 and earlier versions will need to catch both: ``except (ImportError, ValueError):`` + +* The :mod:`venv` activation scripts no longer special-case when + ``__VENV_PROMPT__`` is set to ``""``. diff --git a/Lib/venv/scripts/common/activate b/Lib/venv/scripts/common/activate index fff0765af53b..6a2320a369cb 100644 --- a/Lib/venv/scripts/common/activate +++ b/Lib/venv/scripts/common/activate @@ -54,17 +54,7 @@ fi if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then _OLD_VIRTUAL_PS1="${PS1:-}" - if [ "x__VENV_PROMPT__" != x ] ; then - PS1="__VENV_PROMPT__${PS1:-}" - else - if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then - # special case for Aspen magic directories - # see http://www.zetadev.com/software/aspen/ - PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1" - else - PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1" - fi - fi + PS1="__VENV_PROMPT__${PS1:-}" export PS1 fi diff --git a/Lib/venv/scripts/posix/activate.csh b/Lib/venv/scripts/posix/activate.csh index b0c7028a9295..68a0dc74e1a3 100644 --- a/Lib/venv/scripts/posix/activate.csh +++ b/Lib/venv/scripts/posix/activate.csh @@ -17,19 +17,7 @@ setenv PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH" set _OLD_VIRTUAL_PROMPT="$prompt" if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then - if ("__VENV_NAME__" != "") then - set env_name = "__VENV_NAME__" - else - if (`basename "VIRTUAL_ENV"` == "__") then - # special case for Aspen magic directories - # see http://www.zetadev.com/software/aspen/ - set env_name = `basename \`dirname "$VIRTUAL_ENV"\`` - else - set env_name = `basename "$VIRTUAL_ENV"` - endif - endif - set prompt = "[$env_name] $prompt" - unset env_name + set prompt = "__VENV_PROMPT__$prompt" endif alias pydoc python -m pydoc diff --git a/Lib/venv/scripts/posix/activate.fish b/Lib/venv/scripts/posix/activate.fish index b40105825ead..777d51cb69b0 100644 --- a/Lib/venv/scripts/posix/activate.fish +++ b/Lib/venv/scripts/posix/activate.fish @@ -1,5 +1,5 @@ -# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org) -# you cannot run it directly +# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org); +# you cannot run it directly. function deactivate -d "Exit virtualenv and return to normal shell environment" # reset old environment variables @@ -21,12 +21,12 @@ function deactivate -d "Exit virtualenv and return to normal shell environment" set -e VIRTUAL_ENV if test "$argv[1]" != "nondestructive" - # Self destruct! + # Self-destruct! functions -e deactivate end end -# unset irrelevant variables +# Unset irrelevant variables. deactivate nondestructive set -gx VIRTUAL_ENV "__VENV_DIR__" @@ -34,7 +34,7 @@ set -gx VIRTUAL_ENV "__VENV_DIR__" set -gx _OLD_VIRTUAL_PATH $PATH set -gx PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__" $PATH -# unset PYTHONHOME if set +# Unset PYTHONHOME if set. if set -q PYTHONHOME set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME set -e PYTHONHOME @@ -43,31 +43,20 @@ end if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" # fish uses a function instead of an env var to generate the prompt. - # save the current fish_prompt function as the function _old_fish_prompt + # Save the current fish_prompt function as the function _old_fish_prompt. functions -c fish_prompt _old_fish_prompt - # with the original prompt function renamed, we can override with our own. + # With the original prompt function renamed, we can override with our own. function fish_prompt - # Save the return status of the last command + # Save the return status of the last command. set -l old_status $status - # Prompt override? - if test -n "__VENV_PROMPT__" - printf "%s%s" "__VENV_PROMPT__" (set_color normal) - else - # ...Otherwise, prepend env - set -l _checkbase (basename "$VIRTUAL_ENV") - if test $_checkbase = "__" - # special case for Aspen magic directories - # see http://www.zetadev.com/software/aspen/ - printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal) - else - printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal) - end - end + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) "__VENV_PROMPT__" (set_color normal) # Restore the return status of the previous command. echo "exit $old_status" | . + # Output the original/"old" prompt. _old_fish_prompt end diff --git a/Misc/NEWS.d/next/Library/2019-07-24-14-38-53.bpo-37663.h4-9-1.rst b/Misc/NEWS.d/next/Library/2019-07-24-14-38-53.bpo-37663.h4-9-1.rst new file mode 100644 index 000000000000..1f9f9d9e44a7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-24-14-38-53.bpo-37663.h4-9-1.rst @@ -0,0 +1,2 @@ +Bring consistency to venv shell activation scripts by always using +__VENV_PROMPT__. From webhook-mailer at python.org Wed Aug 21 19:00:43 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 23:00:43 -0000 Subject: [Python-checkins] bpo-37482: Fix email address name with encoded words and special chars (GH-14561) Message-ID: https://github.com/python/cpython/commit/df0c21ff46c5c37b6913828ef8c7651f523432f8 commit: df0c21ff46c5c37b6913828ef8c7651f523432f8 branch: master author: bsiem <52461103+bsiem at users.noreply.github.com> committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-21T16:00:39-07:00 summary: bpo-37482: Fix email address name with encoded words and special chars (GH-14561) Special characters in email address header display names are normally put within double quotes. However, encoded words (=?charset?x?...?=) are not allowed withing double quotes. When the header contains a word with special characters and another word that must be encoded, the first one must also be encoded. In the next example, the display name in the From header is quoted and therefore the comma is allowed; in the To header, the comma is not within quotes and not encoded, which is not allowed and therefore rejected by some mail servers. From: "Foo Bar, France" To: Foo Bar, =?utf-8?q?Espa=C3=B1a?= https://bugs.python.org/issue37482 files: A Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst M Lib/email/_header_value_parser.py M Lib/test/test_email/test_headerregistry.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index ea33bd8eda7d..b5003943ab0d 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2743,6 +2743,9 @@ def _refold_parse_tree(parse_tree, *, policy): wrap_as_ew_blocked -= 1 continue tstr = str(part) + if part.token_type == 'ptext' and set(tstr) & SPECIALS: + # Encode if tstr contains special characters. + want_encoding = True try: tstr.encode(encoding) charset = encoding diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index 4758f4b1c52e..38f7ddbf06d5 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1547,6 +1547,30 @@ def test_group_comparison(self): class TestFolding(TestHeaderBase): + def test_address_display_names(self): + """Test the folding and encoding of address headers.""" + for name, result in ( + ('Foo Bar, France', '"Foo Bar, France"'), + ('Foo Bar (France)', '"Foo Bar (France)"'), + ('Foo Bar, Espa?a', 'Foo =?utf-8?q?Bar=2C_Espa=C3=B1a?='), + ('Foo Bar (Espa?a)', 'Foo Bar =?utf-8?b?KEVzcGHDsWEp?='), + ('Foo, Bar Espa?a', '=?utf-8?q?Foo=2C_Bar_Espa=C3=B1a?='), + ('Foo, Bar [Espa?a]', '=?utf-8?q?Foo=2C_Bar_=5BEspa=C3=B1a=5D?='), + ('Foo B?r, France', 'Foo =?utf-8?q?B=C3=A4r=2C?= France'), + ('Foo B?r ', 'Foo =?utf-8?q?B=C3=A4r_=3CFrance=3E?='), + ( + 'L?rem ipsum d?l?r sit amet, c?nsectetuer adipiscing. ' + 'Suspendisse p?tenti. Aliquam nibh. Suspendisse p?tenti.', + '=?utf-8?q?L=C3=B4rem_ipsum_d=C3=B4l=C3=B4r_sit_amet=2C_c' + '=C3=B4nsectetuer?=\n =?utf-8?q?adipiscing=2E_Suspendisse' + '_p=C3=B4tenti=2E_Aliquam_nibh=2E?=\n Suspendisse =?utf-8' + '?q?p=C3=B4tenti=2E?=', + ), + ): + h = self.make_header('To', Address(name, addr_spec='a at b.com')) + self.assertEqual(h.fold(policy=policy.default), + 'To: %s \n' % result) + def test_short_unstructured(self): h = self.make_header('subject', 'this is a test') self.assertEqual(h.fold(policy=policy.default), diff --git a/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst b/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst new file mode 100644 index 000000000000..e09ff63eedc4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst @@ -0,0 +1 @@ +Fix serialization of display name in originator or destination address fields with both encoded words and special chars. From webhook-mailer at python.org Wed Aug 21 19:21:53 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 23:21:53 -0000 Subject: [Python-checkins] bpo-37482: Fix email address name with encoded words and special chars (GH-14561) Message-ID: https://github.com/python/cpython/commit/c5bba853d5e7836f6d4340e18721d3fb3a6ee0f7 commit: c5bba853d5e7836f6d4340e18721d3fb3a6ee0f7 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-21T16:21:48-07:00 summary: bpo-37482: Fix email address name with encoded words and special chars (GH-14561) Special characters in email address header display names are normally put within double quotes. However, encoded words (=?charset?x?...?=) are not allowed withing double quotes. When the header contains a word with special characters and another word that must be encoded, the first one must also be encoded. In the next example, the display name in the From header is quoted and therefore the comma is allowed; in the To header, the comma is not within quotes and not encoded, which is not allowed and therefore rejected by some mail servers. From: "Foo Bar, France" To: Foo Bar, =?utf-8?q?Espa=C3=B1a?= https://bugs.python.org/issue37482 (cherry picked from commit df0c21ff46c5c37b6913828ef8c7651f523432f8) Co-authored-by: bsiem <52461103+bsiem at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst M Lib/email/_header_value_parser.py M Lib/test/test_email/test_headerregistry.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 666be034420e..2306879fc9d7 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2637,6 +2637,9 @@ def _refold_parse_tree(parse_tree, *, policy): wrap_as_ew_blocked -= 1 continue tstr = str(part) + if part.token_type == 'ptext' and set(tstr) & SPECIALS: + # Encode if tstr contains special characters. + want_encoding = True try: tstr.encode(encoding) charset = encoding diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index e6db3acedcc1..b54df3ebc61a 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1528,6 +1528,30 @@ def test_set_message_header_from_group(self): class TestFolding(TestHeaderBase): + def test_address_display_names(self): + """Test the folding and encoding of address headers.""" + for name, result in ( + ('Foo Bar, France', '"Foo Bar, France"'), + ('Foo Bar (France)', '"Foo Bar (France)"'), + ('Foo Bar, Espa?a', 'Foo =?utf-8?q?Bar=2C_Espa=C3=B1a?='), + ('Foo Bar (Espa?a)', 'Foo Bar =?utf-8?b?KEVzcGHDsWEp?='), + ('Foo, Bar Espa?a', '=?utf-8?q?Foo=2C_Bar_Espa=C3=B1a?='), + ('Foo, Bar [Espa?a]', '=?utf-8?q?Foo=2C_Bar_=5BEspa=C3=B1a=5D?='), + ('Foo B?r, France', 'Foo =?utf-8?q?B=C3=A4r=2C?= France'), + ('Foo B?r ', 'Foo =?utf-8?q?B=C3=A4r_=3CFrance=3E?='), + ( + 'L?rem ipsum d?l?r sit amet, c?nsectetuer adipiscing. ' + 'Suspendisse p?tenti. Aliquam nibh. Suspendisse p?tenti.', + '=?utf-8?q?L=C3=B4rem_ipsum_d=C3=B4l=C3=B4r_sit_amet=2C_c' + '=C3=B4nsectetuer?=\n =?utf-8?q?adipiscing=2E_Suspendisse' + '_p=C3=B4tenti=2E_Aliquam_nibh=2E?=\n Suspendisse =?utf-8' + '?q?p=C3=B4tenti=2E?=', + ), + ): + h = self.make_header('To', Address(name, addr_spec='a at b.com')) + self.assertEqual(h.fold(policy=policy.default), + 'To: %s \n' % result) + def test_short_unstructured(self): h = self.make_header('subject', 'this is a test') self.assertEqual(h.fold(policy=policy.default), diff --git a/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst b/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst new file mode 100644 index 000000000000..e09ff63eedc4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst @@ -0,0 +1 @@ +Fix serialization of display name in originator or destination address fields with both encoded words and special chars. From webhook-mailer at python.org Wed Aug 21 19:22:37 2019 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 21 Aug 2019 23:22:37 -0000 Subject: [Python-checkins] bpo-36311: Fixes decoding multibyte characters around chunk boundaries and improves decoding performance (GH-15083) Message-ID: https://github.com/python/cpython/commit/7ebdda0dbee7df6f0c945a7e1e623e47676e112d commit: 7ebdda0dbee7df6f0c945a7e1e623e47676e112d branch: master author: Steve Dower committer: GitHub date: 2019-08-21T16:22:33-07:00 summary: bpo-36311: Fixes decoding multibyte characters around chunk boundaries and improves decoding performance (GH-15083) files: A Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst M Lib/test/test_codecs.py M Objects/unicodeobject.c diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index b187ca650dc6..ba7f4847468a 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -3075,13 +3075,13 @@ def test_mbcs_alias(self): self.assertEqual(codec.name, 'mbcs') @support.bigmemtest(size=2**31, memuse=7, dry_run=False) - def test_large_input(self): + def test_large_input(self, size): # Test input longer than INT_MAX. # Input should contain undecodable bytes before and after # the INT_MAX limit. - encoded = (b'01234567' * (2**28-1) + + encoded = (b'01234567' * ((size//8)-1) + b'\x85\x86\xea\xeb\xec\xef\xfc\xfd\xfe\xff') - self.assertEqual(len(encoded), 2**31+2) + self.assertEqual(len(encoded), size+2) decoded = codecs.code_page_decode(932, encoded, 'surrogateescape', True) self.assertEqual(decoded[1], len(encoded)) del encoded @@ -3092,6 +3092,20 @@ def test_large_input(self): '\udc85\udc86\udcea\udceb\udcec' '\udcef\udcfc\udcfd\udcfe\udcff') + @support.bigmemtest(size=2**31, memuse=6, dry_run=False) + def test_large_utf8_input(self, size): + # Test input longer than INT_MAX. + # Input should contain a decodable multi-byte character + # surrounding INT_MAX + encoded = (b'0123456\xed\x84\x80' * (size//8)) + self.assertEqual(len(encoded), size // 8 * 10) + decoded = codecs.code_page_decode(65001, encoded, 'ignore', True) + self.assertEqual(decoded[1], len(encoded)) + del encoded + self.assertEqual(len(decoded[0]), size) + self.assertEqual(decoded[0][:10], '0123456\ud10001') + self.assertEqual(decoded[0][-11:], '56\ud1000123456\ud100') + class ASCIITest(unittest.TestCase): def test_encode(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst new file mode 100644 index 000000000000..c45f2224237b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst @@ -0,0 +1,2 @@ +Decoding bytes objects larger than 2GiB is faster and no longer fails when a +multibyte characters spans a chunk boundary. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 5545eae79505..aa933773233b 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -7186,6 +7186,12 @@ PyUnicode_AsASCIIString(PyObject *unicode) #define NEED_RETRY #endif +/* INT_MAX is the theoretical largest chunk (or INT_MAX / 2 when + transcoding from UTF-16), but INT_MAX / 4 perfoms better in + both cases also and avoids partial characters overrunning the + length limit in MultiByteToWideChar on Windows */ +#define DECODING_CHUNK_SIZE (INT_MAX/4) + #ifndef WC_ERR_INVALID_CHARS # define WC_ERR_INVALID_CHARS 0x0080 #endif @@ -7422,8 +7428,8 @@ decode_code_page_stateful(int code_page, do { #ifdef NEED_RETRY - if (size > INT_MAX) { - chunk_size = INT_MAX; + if (size > DECODING_CHUNK_SIZE) { + chunk_size = DECODING_CHUNK_SIZE; final = 0; done = 0; } @@ -7827,10 +7833,8 @@ encode_code_page(int code_page, do { #ifdef NEED_RETRY - /* UTF-16 encoding may double the size, so use only INT_MAX/2 - chunks. */ - if (len > INT_MAX/2) { - chunk_len = INT_MAX/2; + if (len > DECODING_CHUNK_SIZE) { + chunk_len = DECODING_CHUNK_SIZE; done = 0; } else From jeremy.kloth at gmail.com Wed Aug 21 19:26:25 2019 From: jeremy.kloth at gmail.com (Jeremy Kloth) Date: Wed, 21 Aug 2019 17:26:25 -0600 Subject: [Python-checkins] bpo-9949: Enable symlink traversal for ntpath.realpath (GH-15287) In-Reply-To: <46DKPM3LmBzpBgc@mail.python.org> References: <46DKPM3LmBzpBgc@mail.python.org> Message-ID: On Wed, Aug 21, 2019 at 2:43 PM Steve Dower wrote: > > https://github.com/python/cpython/commit/75e064962ee0e31ec19a8081e9d9cc957baf6415 > commit: 75e064962ee0e31ec19a8081e9d9cc957baf6415 > branch: master > author: Steve Dower > committer: GitHub > date: 2019-08-21T13:43:06-07:00 > summary: > > bpo-9949: Enable symlink traversal for ntpath.realpath (GH-15287) > > files: > A Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst > M Doc/library/os.path.rst > M Doc/whatsnew/3.8.rst > M Lib/ntpath.py > M Lib/test/test_ntpath.py > M Lib/test/test_os.py > M Lib/test/test_shutil.py > M Lib/unittest/test/test_discovery.py > This change seems to have broken the windows buildbots. -- Jeremy Kloth From webhook-mailer at python.org Wed Aug 21 19:45:06 2019 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 21 Aug 2019 23:45:06 -0000 Subject: [Python-checkins] bpo-9949: Call normpath() in realpath() and avoid unnecessary prefixes (GH-15369) Message-ID: https://github.com/python/cpython/commit/06be2c7f357d12249445e95def1fb708a087b357 commit: 06be2c7f357d12249445e95def1fb708a087b357 branch: master author: Steve Dower committer: GitHub date: 2019-08-21T16:45:02-07:00 summary: bpo-9949: Call normpath() in realpath() and avoid unnecessary prefixes (GH-15369) files: M Lib/ntpath.py M Lib/test/test_ntpath.py diff --git a/Lib/ntpath.py b/Lib/ntpath.py index ef4999e1473a..1d22d5f1dc2a 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -458,7 +458,8 @@ def normpath(path): # in the case of paths with these prefixes: # \\.\ -> device names # \\?\ -> literal paths - # do not do any normalization, but return the path unchanged + # do not do any normalization, but return the path + # unchanged apart from the call to os.fspath() return path path = path.replace(altsep, sep) prefix, path = splitdrive(path) @@ -575,7 +576,7 @@ def _getfinalpathname_nonstrict(path): return abspath(tail) def realpath(path): - path = os.fspath(path) + path = normpath(path) if isinstance(path, bytes): prefix = b'\\\\?\\' unc_prefix = b'\\\\?\\UNC\\' @@ -586,6 +587,7 @@ def realpath(path): unc_prefix = '\\\\?\\UNC\\' new_unc_prefix = '\\\\' cwd = os.getcwd() + did_not_exist = not exists(path) had_prefix = path.startswith(prefix) path = _getfinalpathname_nonstrict(path) # The path returned by _getfinalpathname will always start with \\?\ - @@ -603,7 +605,10 @@ def realpath(path): if _getfinalpathname(spath) == path: path = spath except OSError as ex: - pass + # If the path does not exist and originally did not exist, then + # strip the prefix anyway. + if ex.winerror in {2, 3} and did_not_exist: + path = spath return path diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 74dc8c378e27..285fb69dc1e8 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -333,11 +333,11 @@ def test_realpath_symlink_loops(self): self.assertEqual(ntpath.realpath(ABSTFN + "1\\.."), ntpath.dirname(ABSTFN)) self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\x"), - ntpath.dirname(P + ABSTFN) + "\\x") + ntpath.dirname(ABSTFN) + "\\x") os.symlink(ABSTFN + "x", ABSTFN + "y") self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\" + ntpath.basename(ABSTFN) + "y"), - P + ABSTFN + "x") + ABSTFN + "x") self.assertIn(ntpath.realpath(ABSTFN + "1\\..\\" + ntpath.basename(ABSTFN) + "1"), expected) From webhook-mailer at python.org Wed Aug 21 19:54:00 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 23:54:00 -0000 Subject: [Python-checkins] bpo-36311: Fixes decoding multibyte characters around chunk boundaries and improves decoding performance (GH-15083) Message-ID: https://github.com/python/cpython/commit/f93c15aedc2ea2cb8b56fc9dbb0d412918992e86 commit: f93c15aedc2ea2cb8b56fc9dbb0d412918992e86 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-21T16:53:56-07:00 summary: bpo-36311: Fixes decoding multibyte characters around chunk boundaries and improves decoding performance (GH-15083) (cherry picked from commit 7ebdda0dbee7df6f0c945a7e1e623e47676e112d) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst M Lib/test/test_codecs.py M Objects/unicodeobject.c diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index b187ca650dc6..ba7f4847468a 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -3075,13 +3075,13 @@ def test_mbcs_alias(self): self.assertEqual(codec.name, 'mbcs') @support.bigmemtest(size=2**31, memuse=7, dry_run=False) - def test_large_input(self): + def test_large_input(self, size): # Test input longer than INT_MAX. # Input should contain undecodable bytes before and after # the INT_MAX limit. - encoded = (b'01234567' * (2**28-1) + + encoded = (b'01234567' * ((size//8)-1) + b'\x85\x86\xea\xeb\xec\xef\xfc\xfd\xfe\xff') - self.assertEqual(len(encoded), 2**31+2) + self.assertEqual(len(encoded), size+2) decoded = codecs.code_page_decode(932, encoded, 'surrogateescape', True) self.assertEqual(decoded[1], len(encoded)) del encoded @@ -3092,6 +3092,20 @@ def test_large_input(self): '\udc85\udc86\udcea\udceb\udcec' '\udcef\udcfc\udcfd\udcfe\udcff') + @support.bigmemtest(size=2**31, memuse=6, dry_run=False) + def test_large_utf8_input(self, size): + # Test input longer than INT_MAX. + # Input should contain a decodable multi-byte character + # surrounding INT_MAX + encoded = (b'0123456\xed\x84\x80' * (size//8)) + self.assertEqual(len(encoded), size // 8 * 10) + decoded = codecs.code_page_decode(65001, encoded, 'ignore', True) + self.assertEqual(decoded[1], len(encoded)) + del encoded + self.assertEqual(len(decoded[0]), size) + self.assertEqual(decoded[0][:10], '0123456\ud10001') + self.assertEqual(decoded[0][-11:], '56\ud1000123456\ud100') + class ASCIITest(unittest.TestCase): def test_encode(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst new file mode 100644 index 000000000000..c45f2224237b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst @@ -0,0 +1,2 @@ +Decoding bytes objects larger than 2GiB is faster and no longer fails when a +multibyte characters spans a chunk boundary. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 132f57aa6c90..c28f36fb4618 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -7118,6 +7118,12 @@ PyUnicode_AsASCIIString(PyObject *unicode) #define NEED_RETRY #endif +/* INT_MAX is the theoretical largest chunk (or INT_MAX / 2 when + transcoding from UTF-16), but INT_MAX / 4 perfoms better in + both cases also and avoids partial characters overrunning the + length limit in MultiByteToWideChar on Windows */ +#define DECODING_CHUNK_SIZE (INT_MAX/4) + #ifndef WC_ERR_INVALID_CHARS # define WC_ERR_INVALID_CHARS 0x0080 #endif @@ -7354,8 +7360,8 @@ decode_code_page_stateful(int code_page, do { #ifdef NEED_RETRY - if (size > INT_MAX) { - chunk_size = INT_MAX; + if (size > DECODING_CHUNK_SIZE) { + chunk_size = DECODING_CHUNK_SIZE; final = 0; done = 0; } @@ -7759,10 +7765,8 @@ encode_code_page(int code_page, do { #ifdef NEED_RETRY - /* UTF-16 encoding may double the size, so use only INT_MAX/2 - chunks. */ - if (len > INT_MAX/2) { - chunk_len = INT_MAX/2; + if (len > DECODING_CHUNK_SIZE) { + chunk_len = DECODING_CHUNK_SIZE; done = 0; } else From webhook-mailer at python.org Wed Aug 21 19:56:01 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Aug 2019 23:56:01 -0000 Subject: [Python-checkins] bpo-36311: Fixes decoding multibyte characters around chunk boundaries and improves decoding performance (GH-15083) Message-ID: https://github.com/python/cpython/commit/735a960ac98cf414caf910565220ab2761fa542a commit: 735a960ac98cf414caf910565220ab2761fa542a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-21T16:55:57-07:00 summary: bpo-36311: Fixes decoding multibyte characters around chunk boundaries and improves decoding performance (GH-15083) (cherry picked from commit 7ebdda0dbee7df6f0c945a7e1e623e47676e112d) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst M Lib/test/test_codecs.py M Objects/unicodeobject.c diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index b39ea54e4b2a..cd2761353490 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -3229,13 +3229,13 @@ def test_mbcs_alias(self): self.assertEqual(codec.name, 'mbcs') @support.bigmemtest(size=2**31, memuse=7, dry_run=False) - def test_large_input(self): + def test_large_input(self, size): # Test input longer than INT_MAX. # Input should contain undecodable bytes before and after # the INT_MAX limit. - encoded = (b'01234567' * (2**28-1) + + encoded = (b'01234567' * ((size//8)-1) + b'\x85\x86\xea\xeb\xec\xef\xfc\xfd\xfe\xff') - self.assertEqual(len(encoded), 2**31+2) + self.assertEqual(len(encoded), size+2) decoded = codecs.code_page_decode(932, encoded, 'surrogateescape', True) self.assertEqual(decoded[1], len(encoded)) del encoded @@ -3246,6 +3246,20 @@ def test_large_input(self): '\udc85\udc86\udcea\udceb\udcec' '\udcef\udcfc\udcfd\udcfe\udcff') + @support.bigmemtest(size=2**31, memuse=6, dry_run=False) + def test_large_utf8_input(self, size): + # Test input longer than INT_MAX. + # Input should contain a decodable multi-byte character + # surrounding INT_MAX + encoded = (b'0123456\xed\x84\x80' * (size//8)) + self.assertEqual(len(encoded), size // 8 * 10) + decoded = codecs.code_page_decode(65001, encoded, 'ignore', True) + self.assertEqual(decoded[1], len(encoded)) + del encoded + self.assertEqual(len(decoded[0]), size) + self.assertEqual(decoded[0][:10], '0123456\ud10001') + self.assertEqual(decoded[0][-11:], '56\ud1000123456\ud100') + class ASCIITest(unittest.TestCase): def test_encode(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst new file mode 100644 index 000000000000..c45f2224237b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst @@ -0,0 +1,2 @@ +Decoding bytes objects larger than 2GiB is faster and no longer fails when a +multibyte characters spans a chunk boundary. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index c0e9c2d112ab..9e0731bf2ba2 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -7085,6 +7085,12 @@ PyUnicode_AsASCIIString(PyObject *unicode) #define NEED_RETRY #endif +/* INT_MAX is the theoretical largest chunk (or INT_MAX / 2 when + transcoding from UTF-16), but INT_MAX / 4 perfoms better in + both cases also and avoids partial characters overrunning the + length limit in MultiByteToWideChar on Windows */ +#define DECODING_CHUNK_SIZE (INT_MAX/4) + #ifndef WC_ERR_INVALID_CHARS # define WC_ERR_INVALID_CHARS 0x0080 #endif @@ -7345,8 +7351,8 @@ decode_code_page_stateful(int code_page, do { #ifdef NEED_RETRY - if (size > INT_MAX) { - chunk_size = INT_MAX; + if (size > DECODING_CHUNK_SIZE) { + chunk_size = DECODING_CHUNK_SIZE; final = 0; done = 0; } @@ -7748,10 +7754,8 @@ encode_code_page(int code_page, do { #ifdef NEED_RETRY - /* UTF-16 encoding may double the size, so use only INT_MAX/2 - chunks. */ - if (len > INT_MAX/2) { - chunk_len = INT_MAX/2; + if (len > DECODING_CHUNK_SIZE) { + chunk_len = DECODING_CHUNK_SIZE; done = 0; } else From webhook-mailer at python.org Wed Aug 21 20:23:42 2019 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 22 Aug 2019 00:23:42 -0000 Subject: [Python-checkins] bpo-9949: Call normpath() in realpath() and avoid unnecessary prefixes (GH-15376) Message-ID: https://github.com/python/cpython/commit/a50d2f7e199f3be60c70c1586ee60ec60bf36642 commit: a50d2f7e199f3be60c70c1586ee60ec60bf36642 branch: 3.8 author: Steve Dower committer: GitHub date: 2019-08-21T17:23:38-07:00 summary: bpo-9949: Call normpath() in realpath() and avoid unnecessary prefixes (GH-15376) files: M Lib/ntpath.py M Lib/test/test_ntpath.py diff --git a/Lib/ntpath.py b/Lib/ntpath.py index ef4999e1473a..1d22d5f1dc2a 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -458,7 +458,8 @@ def normpath(path): # in the case of paths with these prefixes: # \\.\ -> device names # \\?\ -> literal paths - # do not do any normalization, but return the path unchanged + # do not do any normalization, but return the path + # unchanged apart from the call to os.fspath() return path path = path.replace(altsep, sep) prefix, path = splitdrive(path) @@ -575,7 +576,7 @@ def _getfinalpathname_nonstrict(path): return abspath(tail) def realpath(path): - path = os.fspath(path) + path = normpath(path) if isinstance(path, bytes): prefix = b'\\\\?\\' unc_prefix = b'\\\\?\\UNC\\' @@ -586,6 +587,7 @@ def realpath(path): unc_prefix = '\\\\?\\UNC\\' new_unc_prefix = '\\\\' cwd = os.getcwd() + did_not_exist = not exists(path) had_prefix = path.startswith(prefix) path = _getfinalpathname_nonstrict(path) # The path returned by _getfinalpathname will always start with \\?\ - @@ -603,7 +605,10 @@ def realpath(path): if _getfinalpathname(spath) == path: path = spath except OSError as ex: - pass + # If the path does not exist and originally did not exist, then + # strip the prefix anyway. + if ex.winerror in {2, 3} and did_not_exist: + path = spath return path diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 74dc8c378e27..285fb69dc1e8 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -333,11 +333,11 @@ def test_realpath_symlink_loops(self): self.assertEqual(ntpath.realpath(ABSTFN + "1\\.."), ntpath.dirname(ABSTFN)) self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\x"), - ntpath.dirname(P + ABSTFN) + "\\x") + ntpath.dirname(ABSTFN) + "\\x") os.symlink(ABSTFN + "x", ABSTFN + "y") self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\" + ntpath.basename(ABSTFN) + "y"), - P + ABSTFN + "x") + ABSTFN + "x") self.assertIn(ntpath.realpath(ABSTFN + "1\\..\\" + ntpath.basename(ABSTFN) + "1"), expected) From webhook-mailer at python.org Wed Aug 21 20:43:00 2019 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 22 Aug 2019 00:43:00 -0000 Subject: [Python-checkins] bpo-37834: Fix test on Windows 7 (GH-15377) Message-ID: https://github.com/python/cpython/commit/374be59b8e479afa8c7a8ae6e77e98915e2f6d45 commit: 374be59b8e479afa8c7a8ae6e77e98915e2f6d45 branch: master author: Steve Dower committer: GitHub date: 2019-08-21T17:42:56-07:00 summary: bpo-37834: Fix test on Windows 7 (GH-15377) files: M Lib/test/test_os.py diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index ba9f5c35ae31..428593151208 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2466,6 +2466,9 @@ def test_buffer_overflow(self): def test_appexeclink(self): root = os.path.expandvars(r'%LOCALAPPDATA%\Microsoft\WindowsApps') + if not os.path.isdir(root): + self.skipTest("test requires a WindowsApps directory") + aliases = [os.path.join(root, a) for a in fnmatch.filter(os.listdir(root), '*.exe')] From webhook-mailer at python.org Wed Aug 21 21:01:26 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Aug 2019 01:01:26 -0000 Subject: [Python-checkins] bpo-37834: Fix test on Windows 7 (GH-15377) Message-ID: https://github.com/python/cpython/commit/967d625a6df27fb490f035045ec8fe4675001d63 commit: 967d625a6df27fb490f035045ec8fe4675001d63 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-21T18:01:22-07:00 summary: bpo-37834: Fix test on Windows 7 (GH-15377) (cherry picked from commit 374be59b8e479afa8c7a8ae6e77e98915e2f6d45) Co-authored-by: Steve Dower files: M Lib/test/test_os.py diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index ba9f5c35ae31..428593151208 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2466,6 +2466,9 @@ def test_buffer_overflow(self): def test_appexeclink(self): root = os.path.expandvars(r'%LOCALAPPDATA%\Microsoft\WindowsApps') + if not os.path.isdir(root): + self.skipTest("test requires a WindowsApps directory") + aliases = [os.path.join(root, a) for a in fnmatch.filter(os.listdir(root), '*.exe')] From webhook-mailer at python.org Wed Aug 21 21:38:43 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Thu, 22 Aug 2019 01:38:43 -0000 Subject: [Python-checkins] Refactor Parser/pgen and add documentation and explanations (GH-15373) Message-ID: https://github.com/python/cpython/commit/71876fa438f706b211360d8c205cb985906212ee commit: 71876fa438f706b211360d8c205cb985906212ee branch: master author: Pablo Galindo committer: GitHub date: 2019-08-22T02:38:39+01:00 summary: Refactor Parser/pgen and add documentation and explanations (GH-15373) * Refactor Parser/pgen and add documentation and explanations To improve the readability and maintainability of the parser generator perform the following transformations: * Separate the metagrammar parser in its own class to simplify the parser generator logic. * Create separate classes for DFAs and NFAs and move methods that act exclusively on them from the parser generator to these classes. * Add docstrings and comment documenting the process to go from the grammar file into NFAs and then DFAs. Detail some of the algorithms and give some background explanations of some concepts that will helps readers not familiar with the parser generation process. * Select more descriptive names for some variables and variables. * PEP8 formatting and quote-style homogenization. The output of the parser generator remains the same (Include/graminit.h and Python/graminit.c remain untouched by running the new parser generator). files: A Parser/pgen/automata.py A Parser/pgen/metaparser.py M Parser/pgen/__main__.py M Parser/pgen/grammar.py M Parser/pgen/keywordgen.py M Parser/pgen/pgen.py M Parser/pgen/token.py diff --git a/Parser/pgen/__main__.py b/Parser/pgen/__main__.py index eea52618422e..bb96e75beea5 100644 --- a/Parser/pgen/__main__.py +++ b/Parser/pgen/__main__.py @@ -8,17 +8,15 @@ def main(): parser.add_argument( "grammar", type=str, help="The file with the grammar definition in EBNF format" ) - parser.add_argument( - "tokens", type=str, help="The file with the token definitions" - ) + parser.add_argument("tokens", type=str, help="The file with the token definitions") parser.add_argument( "graminit_h", - type=argparse.FileType('w'), + type=argparse.FileType("w"), help="The path to write the grammar's non-terminals as #defines", ) parser.add_argument( "graminit_c", - type=argparse.FileType('w'), + type=argparse.FileType("w"), help="The path to write the grammar as initialized data", ) diff --git a/Parser/pgen/automata.py b/Parser/pgen/automata.py new file mode 100644 index 000000000000..3147d8636ff3 --- /dev/null +++ b/Parser/pgen/automata.py @@ -0,0 +1,371 @@ +"""Classes representing state-machine concepts""" + +class NFA: + """A non deterministic finite automata + + A non deterministic automata is a form of a finite state + machine. An NFA's rules are less restrictive than a DFA. + The NFA rules are: + + * A transition can be non-deterministic and can result in + nothing, one, or two or more states. + + * An epsilon transition consuming empty input is valid. + Transitions consuming labeled symbols are also permitted. + + This class assumes that there is only one starting state and one + accepting (ending) state. + + Attributes: + name (str): The name of the rule the NFA is representing. + start (NFAState): The starting state. + end (NFAState): The ending state + """ + + def __init__(self, start, end): + self.name = start.rule_name + self.start = start + self.end = end + + def __repr__(self): + return "NFA(start={}, end={})".format(self.start, self.end) + + def dump(self, writer=print): + """Dump a graphical representation of the NFA""" + todo = [self.start] + for i, state in enumerate(todo): + writer(" State", i, state is self.end and "(final)" or "") + for arc in state.arcs: + label = arc.label + next = arc.target + if next in todo: + j = todo.index(next) + else: + j = len(todo) + todo.append(next) + if label is None: + writer(" -> %d" % j) + else: + writer(" %s -> %d" % (label, j)) + + +class NFAArc: + """An arc representing a transition between two NFA states. + + NFA states can be connected via two ways: + + * A label transition: An input equal to the label must + be consumed to perform the transition. + * An epsilon transition: The transition can be taken without + consuming any input symbol. + + Attributes: + target (NFAState): The ending state of the transition arc. + label (Optional[str]): The label that must be consumed to make + the transition. An epsilon transition is represented + using `None`. + """ + + def __init__(self, target, label): + self.target = target + self.label = label + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self.label) + + +class NFAState: + """A state of a NFA, non deterministic finite automata. + + Attributes: + target (rule_name): The name of the rule used to represent the NFA's + ending state after a transition. + arcs (Dict[Optional[str], NFAState]): A mapping representing transitions + between the current NFA state and another NFA state via following + a label. + """ + + def __init__(self, rule_name): + self.rule_name = rule_name + self.arcs = [] + + def add_arc(self, target, label=None): + """Add a new arc to connect the state to a target state within the NFA + + The method adds a new arc to the list of arcs available as transitions + from the present state. An optional label indicates a named transition + that consumes an input while the absence of a label represents an epsilon + transition. + + Attributes: + target (NFAState): The end of the transition that the arc represents. + label (Optional[str]): The label that must be consumed for making + the transition. If the label is not provided the transition is assumed + to be an epsilon-transition. + """ + assert label is None or isinstance(label, str) + assert isinstance(target, NFAState) + self.arcs.append(NFAArc(target, label)) + + def __repr__(self): + return "<%s: from %s>" % (self.__class__.__name__, self.rule_name) + + +class DFA: + """A deterministic finite automata + + A deterministic finite automata is a form of a finite state machine + that obeys the following rules: + + * Each of the transitions is uniquely determined by + the source state and input symbol + * Reading an input symbol is required for each state + transition (no epsilon transitions). + + The finite-state machine will accept or reject a string of symbols + and only produces a unique computation of the automaton for each input + string. The DFA must have a unique starting state (represented as the first + element in the list of states) but can have multiple final states. + + Attributes: + name (str): The name of the rule the DFA is representing. + states (List[DFAState]): A collection of DFA states. + """ + + def __init__(self, name, states): + self.name = name + self.states = states + + @classmethod + def from_nfa(cls, nfa): + """Constructs a DFA from a NFA using the Rabin?Scott construction algorithm. + + To simulate the operation of a DFA on a given input string, it's + necessary to keep track of a single state at any time, or more precisely, + the state that the automaton will reach after seeing a prefix of the + input. In contrast, to simulate an NFA, it's necessary to keep track of + a set of states: all of the states that the automaton could reach after + seeing the same prefix of the input, according to the nondeterministic + choices made by the automaton. There are two possible sources of + non-determinism: + + 1) Multiple (one or more) transitions with the same label + + 'A' +-------+ + +----------->+ State +----------->+ + | | 2 | + +-------+ +-------+ + | State | + | 1 | +-------+ + +-------+ | State | + +----------->+ 3 +----------->+ + 'A' +-------+ + + 2) Epsilon transitions (transitions that can be taken without consuming any input) + + +-------+ +-------+ + | State | ? | State | + | 1 +----------->+ 2 +----------->+ + +-------+ +-------+ + + Looking at the first case above, we can't determine which transition should be + followed when given an input A. We could choose whether or not to follow the + transition while in the second case the problem is that we can choose both to + follow the transition or not doing it. To solve this problem we can imagine that + we follow all possibilities at the same time and we construct new states from the + set of all possible reachable states. For every case in the previous example: + + + 1) For multiple transitions with the same label we colapse all of the + final states under the same one + + +-------+ +-------+ + | State | 'A' | State | + | 1 +----------->+ 2-3 +----------->+ + +-------+ +-------+ + + 2) For epsilon transitions we collapse all epsilon-reachable states + into the same one + + +-------+ + | State | + | 1-2 +-----------> + +-------+ + + Because the DFA states consist of sets of NFA states, an n-state NFA + may be converted to a DFA with at most 2**n states. Notice that the + constructed DFA is not minimal and can be simplified or reduced + afterwards. + + Parameters: + name (NFA): The NFA to transform to DFA. + """ + assert isinstance(nfa, NFA) + + def add_closure(nfa_state, base_nfa_set): + """Calculate the epsilon-closure of a given state + + Add to the *base_nfa_set* all the states that are + reachable from *nfa_state* via epsilon-transitions. + """ + assert isinstance(nfa_state, NFAState) + if nfa_state in base_nfa_set: + return + base_nfa_set.add(nfa_state) + for nfa_arc in nfa_state.arcs: + if nfa_arc.label is None: + add_closure(nfa_arc.target, base_nfa_set) + + # Calculte the epsilon-closure of the starting state + base_nfa_set = set() + add_closure(nfa.start, base_nfa_set) + + # Start by visiting the NFA starting state (there is only one). + states = [DFAState(nfa.name, base_nfa_set, nfa.end)] + + for state in states: # NB states grow while we're iterating + + # Find transitions from the current state to other reachable states + # and store them in mapping that correlates the label to all the + # possible reachable states that can be obtained by consuming a + # token equal to the label. Each set of all the states that can + # be reached after following a label will be the a DFA state. + arcs = {} + for nfa_state in state.nfa_set: + for nfa_arc in nfa_state.arcs: + if nfa_arc.label is not None: + nfa_set = arcs.setdefault(nfa_arc.label, set()) + # All states that can be reached by epsilon-transitions + # are also included in the set of reachable states. + add_closure(nfa_arc.target, nfa_set) + + # Now create new DFAs by visiting all posible transitions between + # the current DFA state and the new power-set states (each nfa_set) + # via the different labels. As the nodes are appended to *states* this + # is performing a deep-first search traversal over the power-set of + # the states of the original NFA. + for label, nfa_set in sorted(arcs.items()): + for exisisting_state in states: + if exisisting_state.nfa_set == nfa_set: + # The DFA state already exists for this rule. + next_state = exisisting_state + break + else: + next_state = DFAState(nfa.name, nfa_set, nfa.end) + states.append(next_state) + + # Add a transition between the current DFA state and the new + # DFA state (the power-set state) via the current label. + state.add_arc(next_state, label) + + return cls(nfa.name, states) + + def __iter__(self): + return iter(self.states) + + def simplify(self): + """Attempt to reduce the number of states of the DFA + + Transform the DFA into an equivalent DFA that has fewer states. Two + classes of states can be removed or merged from the original DFA without + affecting the language it accepts to minimize it: + + * Unreachable states can not be reached from the initial + state of the DFA, for any input string. + * Nondistinguishable states are those that cannot be distinguished + from one another for any input string. + + This algorithm does not achieve the optimal fully-reduced solution, but it + works well enough for the particularities of the Python grammar. The + algorithm repeatedly looks for two states that have the same set of + arcs (same labels pointing to the same nodes) and unifies them, until + things stop changing. + """ + changes = True + while changes: + changes = False + for i, state_i in enumerate(self.states): + for j in range(i + 1, len(self.states)): + state_j = self.states[j] + if state_i == state_j: + del self.states[j] + for state in self.states: + state.unifystate(state_j, state_i) + changes = True + break + + def dump(self, writer=print): + """Dump a graphical representation of the DFA""" + for i, state in enumerate(self.states): + writer(" State", i, state.is_final and "(final)" or "") + for label, next in sorted(state.arcs.items()): + writer(" %s -> %d" % (label, self.states.index(next))) + + +class DFAState(object): + """A state of a DFA + + Attributes: + rule_name (rule_name): The name of the DFA rule containing the represented state. + nfa_set (Set[NFAState]): The set of NFA states used to create this state. + final (bool): True if the state represents an accepting state of the DFA + containing this state. + arcs (Dict[label, DFAState]): A mapping representing transitions between + the current DFA state and another DFA state via following a label. + """ + + def __init__(self, rule_name, nfa_set, final): + assert isinstance(nfa_set, set) + assert isinstance(next(iter(nfa_set)), NFAState) + assert isinstance(final, NFAState) + self.rule_name = rule_name + self.nfa_set = nfa_set + self.arcs = {} # map from terminals/nonterminals to DFAState + self.is_final = final in nfa_set + + def add_arc(self, target, label): + """Add a new arc to the current state. + + Parameters: + target (DFAState): The DFA state at the end of the arc. + label (str): The label respresenting the token that must be consumed + to perform this transition. + """ + assert isinstance(label, str) + assert label not in self.arcs + assert isinstance(target, DFAState) + self.arcs[label] = target + + def unifystate(self, old, new): + """Replace all arcs from the current node to *old* with *new*. + + Parameters: + old (DFAState): The DFA state to remove from all existing arcs. + new (DFAState): The DFA state to replace in all existing arcs. + """ + for label, next_ in self.arcs.items(): + if next_ is old: + self.arcs[label] = new + + def __eq__(self, other): + # The nfa_set does not matter for equality + assert isinstance(other, DFAState) + if self.is_final != other.is_final: + return False + # We cannot just return self.arcs == other.arcs because that + # would invoke this method recursively if there are any cycles. + if len(self.arcs) != len(other.arcs): + return False + for label, next_ in self.arcs.items(): + if next_ is not other.arcs.get(label): + return False + return True + + __hash__ = None # For Py3 compatibility. + + def __repr__(self): + return "<%s: %s is_final=%s>" % ( + self.__class__.__name__, + self.rule_name, + self.is_final, + ) diff --git a/Parser/pgen/grammar.py b/Parser/pgen/grammar.py index 5cd652426b47..56188db775a8 100644 --- a/Parser/pgen/grammar.py +++ b/Parser/pgen/grammar.py @@ -76,12 +76,14 @@ def produce_graminit_c(self, writer): def print_labels(self, writer): writer( - "static const 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 writer( - ' {{{label}, {label_name}}},\n'.format( + " {{{label}, {label_name}}},\n".format( label=label, label_name=label_name ) ) diff --git a/Parser/pgen/keywordgen.py b/Parser/pgen/keywordgen.py index eeb3ef739fad..f0234a81b62d 100644 --- a/Parser/pgen/keywordgen.py +++ b/Parser/pgen/keywordgen.py @@ -32,17 +32,16 @@ def main(): - parser = argparse.ArgumentParser(description="Generate the Lib/keywords.py " - "file from the grammar.") - parser.add_argument( - "grammar", type=str, help="The file with the grammar definition in EBNF format" + parser = argparse.ArgumentParser( + description="Generate the Lib/keywords.py " "file from the grammar." ) parser.add_argument( - "tokens", type=str, help="The file with the token definitions" + "grammar", type=str, help="The file with the grammar definition in EBNF format" ) + parser.add_argument("tokens", type=str, help="The file with the token definitions") parser.add_argument( "keyword_file", - type=argparse.FileType('w'), + type=argparse.FileType("w"), help="The path to write the keyword definitions", ) args = parser.parse_args() diff --git a/Parser/pgen/metaparser.py b/Parser/pgen/metaparser.py new file mode 100644 index 000000000000..074a083fb74b --- /dev/null +++ b/Parser/pgen/metaparser.py @@ -0,0 +1,152 @@ +"""Parser for the Python metagrammar""" + +import io +import tokenize # from stdlib + +from .automata import NFA, NFAState + + +class GrammarParser: + """Parser for Python grammar files.""" + + _translation_table = { + tokenize.NAME: "NAME", + tokenize.STRING: "STRING", + tokenize.NEWLINE: "NEWLINE", + tokenize.NL: "NL", + tokenize.OP: "OP", + tokenize.ENDMARKER: "ENDMARKER", + tokenize.COMMENT: "COMMENT", + } + + def __init__(self, grammar): + self.grammar = grammar + grammar_adaptor = io.StringIO(grammar) + self.generator = tokenize.generate_tokens(grammar_adaptor.readline) + self._gettoken() # Initialize lookahead + self._current_rule_name = None + + def parse(self): + """Turn the grammar into a collection of NFAs""" + # grammar: (NEWLINE | rule)* ENDMARKER + while self.type != tokenize.ENDMARKER: + while self.type == tokenize.NEWLINE: + self._gettoken() + # rule: NAME ':' rhs NEWLINE + self._current_rule_name = self._expect(tokenize.NAME) + self._expect(tokenize.OP, ":") + a, z = self._parse_rhs() + self._expect(tokenize.NEWLINE) + + yield NFA(a, z) + + def _parse_rhs(self): + # rhs: items ('|' items)* + a, z = self._parse_items() + if self.value != "|": + return a, z + else: + aa = NFAState(self._current_rule_name) + zz = NFAState(self._current_rule_name) + while True: + # Allow to transit directly to the previous state and connect the end of the + # previous state to the end of the current one, effectively allowing to skip + # the current state. + aa.add_arc(a) + z.add_arc(zz) + if self.value != "|": + break + + self._gettoken() + a, z = self._parse_items() + return aa, zz + + def _parse_items(self): + # items: item+ + a, b = self._parse_item() + while self.type in (tokenize.NAME, tokenize.STRING) or self.value in ("(", "["): + c, d = self._parse_item() + # Allow a transition between the end of the previous state + # and the beginning of the new one, connecting all the items + # together. In this way we can only reach the end if we visit + # all the items. + b.add_arc(c) + b = d + return a, b + + def _parse_item(self): + # item: '[' rhs ']' | atom ['+' | '*'] + if self.value == "[": + self._gettoken() + a, z = self._parse_rhs() + self._expect(tokenize.OP, "]") + # Make a transition from the beginning to the end so it is possible to + # advance for free to the next state of this item # without consuming + # anything from the rhs. + a.add_arc(z) + return a, z + else: + a, z = self._parse_atom() + value = self.value + if value not in ("+", "*"): + return a, z + self._gettoken() + z.add_arc(a) + if value == "+": + # Create a cycle to the beginning so we go back to the old state in this + # item and repeat. + return a, z + else: + # The end state is the same as the beginning, so we can cycle arbitrarily + # and end in the beginning if necessary. + return a, a + + def _parse_atom(self): + # atom: '(' rhs ')' | NAME | STRING + if self.value == "(": + self._gettoken() + a, z = self._parse_rhs() + self._expect(tokenize.OP, ")") + return a, z + elif self.type in (tokenize.NAME, tokenize.STRING): + a = NFAState(self._current_rule_name) + z = NFAState(self._current_rule_name) + # We can transit to the next state only if we consume the value. + a.add_arc(z, self.value) + self._gettoken() + return a, z + else: + self._raise_error( + "expected (...) or NAME or STRING, got {} ({})", + self._translation_table.get(self.type, self.type), + self.value, + ) + + def _expect(self, type_, value=None): + if self.type != type_: + self._raise_error( + "expected {}, got {} ({})", + self._translation_table.get(type_, type_), + self._translation_table.get(self.type, self.type), + self.value, + ) + if value is not None and self.value != value: + self._raise_error("expected {}, got {}", value, self.value) + value = self.value + self._gettoken() + return value + + def _gettoken(self): + tup = next(self.generator) + while tup[0] in (tokenize.COMMENT, tokenize.NL): + tup = next(self.generator) + self.type, self.value, self.begin, self.end, self.line = tup + + def _raise_error(self, msg, *args): + if args: + try: + msg = msg.format(*args) + except Exception: + msg = " ".join([msg] + list(map(str, args))) + line = self.grammar.splitlines()[self.begin[0] - 1] + raise SyntaxError(msg, ("", self.begin[0], self.begin[1], line)) diff --git a/Parser/pgen/pgen.py b/Parser/pgen/pgen.py index d52d58f64e41..d7dcb769334c 100644 --- a/Parser/pgen/pgen.py +++ b/Parser/pgen/pgen.py @@ -1,42 +1,180 @@ +"""Python parser generator + + +This parser generator transforms a Python grammar file into parsing tables +that can be consumed by Python's LL(1) parser written in C. + +Concepts +-------- + +* An LL(1) parser (Left-to-right, Leftmost derivation, 1 token-lookahead) is a + top-down parser for a subset of context-free languages. It parses the input + from Left to right, performing Leftmost derivation of the sentence, and can + only use 1 tokens of lookahead when parsing a sentence. + +* A parsing table is a collection of data that a generic implementation of the + LL(1) parser consumes to know how to parse a given context-free grammar. In + this case the collection of thata involves Deterministic Finite Automatons, + calculated first sets, keywords and transition labels. + +* A grammar is defined by production rules (or just 'productions') that specify + which symbols may replace which other symbols; these rules may be used to + generate strings, or to parse them. Each such rule has a head, or left-hand + side, which consists of the string that may be replaced, and a body, or + right-hand side, which consists of a string that may replace it. In the + Python grammar, rules are written in the form + + rule_name: rule_description; + + meaning the rule 'a: b' specifies that a can be replaced by b. A Context-free + grammars is a grammars in which the left-hand side of each production rule + consists of only a single nonterminal symbol. Context free grammars can + always be recognized by a Non-Deterministic Automatons. + +* Terminal symbols are literal symbols which may appear in the outputs of the + production rules of the grammar and which cannot be changed using the rules + of the grammar. Applying the rules recursively to a source string of symbols + will usually terminate in a final output string consisting only of terminal + symbols. + +* Nonterminal symbols are those symbols which can be replaced. The grammar + includes a start symbol a designated member of the set of nonterminals from + which all the strings in the language may be derived by successive + applications of the production rules. + +* The language defined by the grammar is defined as the set of terminal strings + that can be derived using the production rules. + +* The first sets of a rule (FIRST(rule)) are defined to be the set of terminals + that can appear in the first position of any string derived from the rule. + This is useful for LL(1) parsers as the parser is only allow to look at the + next token in the input to know which rule needs to parse. For example given + this grammar: + + start: '(' A | B ')' + A: 'a' '<' + B: 'b' '<' + + and the input '(b<)' the parser can only look at 'b' to know if it needs + to parse A o B. Because FIRST(A) = {'a'} and FIRST(B) = {'b'} it knows + that needs to continue parsing rule B because only that rule can start + with 'b'. + +Description +----------- + +The input for the parser generator is a grammar in extended BNF form (using * +for repetition, + for at-least-once repetition, [] for optional parts, | for +alternatives and () for grouping). + +Each rule in the grammar file is considered as a regular expression in its +own right. It is turned into a Non-deterministic Finite Automaton (NFA), +which is then turned into a Deterministic Finite Automaton (DFA), which is +then optimized to reduce the number of states. See [Aho&Ullman 77] chapter 3, +or similar compiler books (this technique is more often used for lexical +analyzers). + +The DFA's are used by the parser as parsing tables in a special way that's +probably unique. Before they are usable, the FIRST sets of all non-terminals +are computed so the LL(1) parser consuming the parsing tables can distinguish +between different transitions. +Reference +--------- + +[Aho&Ullman 77] + Aho&Ullman, Principles of Compiler Design, Addison-Wesley 1977 + (first edition) +""" + +from ast import literal_eval import collections -import tokenize # from stdlib from . import grammar, token +from .automata import DFA +from .metaparser import GrammarParser +import enum -class ParserGenerator(object): - def __init__(self, grammar_file, token_file, stream=None, verbose=False): - close_stream = None - if stream is None: - stream = open(grammar_file) - close_stream = stream.close +class LabelType(enum.Enum): + NONTERMINAL = 0 + NAMED_TOKEN = 1 + KEYWORD = 2 + OPERATOR = 3 + NONE = 4 + + +class Label(str): + def __init__(self, value): + self.type = self._get_type() + + def _get_type(self): + if self[0].isalpha(): + if self.upper() == self: + # NAMED tokens (ASYNC, NAME...) are all uppercase by convention + return LabelType.NAMED_TOKEN + else: + # If is not uppercase it must be a non terminal. + return LabelType.NONTERMINAL + else: + # Keywords and operators are wrapped in quotes + assert self[0] == self[-1] in ('"', "'"), self + value = literal_eval(self) + if value[0].isalpha(): + return LabelType.KEYWORD + else: + return LabelType.OPERATOR + + def __repr__(self): + return "{}({})".format(self.type, super().__repr__()) + + +class ParserGenerator(object): + def __init__(self, grammar_file, token_file, verbose=False): + with open(grammar_file) as f: + self.grammar = f.read() with open(token_file) as tok_file: token_lines = tok_file.readlines() self.tokens = dict(token.generate_tokens(token_lines)) self.opmap = dict(token.generate_opmap(token_lines)) # Manually add <> so it does not collide with != - self.opmap['<>'] = "NOTEQUAL" + self.opmap["<>"] = "NOTEQUAL" self.verbose = verbose self.filename = grammar_file - self.stream = stream - self.generator = tokenize.generate_tokens(stream.readline) - self.gettoken() # Initialize lookahead - self.dfas, self.startsymbol = self.parse() - if close_stream is not None: - close_stream() - self.first = {} # map from symbol name to set of tokens - self.addfirstsets() + self.dfas, self.startsymbol = self.create_dfas() + self.first = {} # map from symbol name to set of tokens + self.calculate_first_sets() + + def create_dfas(self): + rule_to_dfas = collections.OrderedDict() + start_nonterminal = None + for nfa in GrammarParser(self.grammar).parse(): + if self.verbose: + print("Dump of NFA for", nfa.name) + nfa.dump() + dfa = DFA.from_nfa(nfa) + if self.verbose: + print("Dump of DFA for", dfa.name) + dfa.dump() + dfa.simplify() + rule_to_dfas[dfa.name] = dfa + + if start_nonterminal is None: + start_nonterminal = dfa.name + + return rule_to_dfas, start_nonterminal def make_grammar(self): c = grammar.Grammar() + c.all_labels = set() names = list(self.dfas.keys()) names.remove(self.startsymbol) names.insert(0, self.startsymbol) for name in names: i = 256 + len(c.symbol2number) - c.symbol2number[name] = i - c.number2symbol[i] = name + c.symbol2number[Label(name)] = i + c.number2symbol[i] = Label(name) + c.all_labels.add(name) for name in names: self.make_label(c, name) dfa = self.dfas[name] @@ -44,12 +182,13 @@ def make_grammar(self): for state in dfa: arcs = [] for label, next in sorted(state.arcs.items()): - arcs.append((self.make_label(c, label), dfa.index(next))) - if state.isfinal: - arcs.append((0, dfa.index(state))) + c.all_labels.add(label) + arcs.append((self.make_label(c, label), dfa.states.index(next))) + if state.is_final: + arcs.append((0, dfa.states.index(state))) states.append(arcs) c.states.append(states) - c.dfas[c.symbol2number[name]] = (states, self.make_first(c, name)) + c.dfas[c.symbol2number[name]] = (states, self.make_first_sets(c, name)) c.start = c.symbol2number[self.startsymbol] if self.verbose: @@ -68,7 +207,7 @@ def make_grammar(self): ) return c - def make_first(self, c, name): + def make_first_sets(self, c, name): rawfirst = self.first[name] first = set() for label in sorted(rawfirst): @@ -78,67 +217,65 @@ def make_first(self, c, name): return first def make_label(self, c, label): - # XXX Maybe this should be a method on a subclass of converter? + label = Label(label) ilabel = len(c.labels) - if label[0].isalpha(): - # Either a symbol name or a named token - if label in c.symbol2number: - # A symbol name (a non-terminal) - if label in c.symbol2label: - return c.symbol2label[label] - else: - c.labels.append((c.symbol2number[label], None)) - c.symbol2label[label] = ilabel - return ilabel + + if label.type == LabelType.NONTERMINAL: + if label in c.symbol2label: + return c.symbol2label[label] else: - # A named token (NAME, NUMBER, STRING) - itoken = self.tokens.get(label, None) - assert isinstance(itoken, int), label - assert itoken in self.tokens.values(), label - if itoken in c.tokens: - return c.tokens[itoken] - else: - c.labels.append((itoken, None)) - c.tokens[itoken] = ilabel - return ilabel - else: - # Either a keyword or an operator - assert label[0] in ('"', "'"), label - value = eval(label) - if value[0].isalpha(): - # A keyword - if value in c.keywords: - return c.keywords[value] - else: - c.labels.append((self.tokens["NAME"], value)) - c.keywords[value] = ilabel - return ilabel + c.labels.append((c.symbol2number[label], None)) + c.symbol2label[label] = ilabel + return ilabel + elif label.type == LabelType.NAMED_TOKEN: + # A named token (NAME, NUMBER, STRING) + itoken = self.tokens.get(label, None) + assert isinstance(itoken, int), label + assert itoken in self.tokens.values(), label + if itoken in c.tokens: + return c.tokens[itoken] else: - # An operator (any non-numeric token) - tok_name = self.opmap[value] # Fails if unknown token - itoken = self.tokens[tok_name] - if itoken in c.tokens: - return c.tokens[itoken] - else: - c.labels.append((itoken, None)) - c.tokens[itoken] = ilabel - return ilabel + c.labels.append((itoken, None)) + c.tokens[itoken] = ilabel + return ilabel + elif label.type == LabelType.KEYWORD: + # A keyword + value = literal_eval(label) + if value in c.keywords: + return c.keywords[value] + else: + c.labels.append((self.tokens["NAME"], value)) + c.keywords[value] = ilabel + return ilabel + elif label.type == LabelType.OPERATOR: + # An operator (any non-numeric token) + value = literal_eval(label) + tok_name = self.opmap[value] # Fails if unknown token + itoken = self.tokens[tok_name] + if itoken in c.tokens: + return c.tokens[itoken] + else: + c.labels.append((itoken, None)) + c.tokens[itoken] = ilabel + return ilabel + else: + raise ValueError("Cannot categorize label {}".format(label)) - def addfirstsets(self): + def calculate_first_sets(self): names = list(self.dfas.keys()) for name in names: if name not in self.first: - self.calcfirst(name) + self.calculate_first_sets_for_rule(name) if self.verbose: print("First set for {dfa_name}".format(dfa_name=name)) for item in self.first[name]: print(" - {terminal}".format(terminal=item)) - def calcfirst(self, name): + def calculate_first_sets_for_rule(self, name): dfa = self.dfas[name] - self.first[name] = None # dummy to detect left recursion - state = dfa[0] + self.first[name] = None # dummy to detect left recursion + state = dfa.states[0] totalset = set() overlapcheck = {} for label, next in state.arcs.items(): @@ -148,7 +285,7 @@ def calcfirst(self, name): if fset is None: raise ValueError("recursion for rule %r" % name) else: - self.calcfirst(label) + self.calculate_first_sets_for_rule(label) fset = self.first[label] totalset.update(fset) overlapcheck[label] = fset @@ -159,248 +296,10 @@ def calcfirst(self, name): for label, itsfirst in overlapcheck.items(): for symbol in itsfirst: if symbol in inverse: - raise ValueError("rule %s is ambiguous; %s is in the" - " first sets of %s as well as %s" % - (name, symbol, label, inverse[symbol])) + raise ValueError( + "rule %s is ambiguous; %s is in the" + " first sets of %s as well as %s" + % (name, symbol, label, inverse[symbol]) + ) inverse[symbol] = label self.first[name] = totalset - - def parse(self): - dfas = collections.OrderedDict() - startsymbol = None - # MSTART: (NEWLINE | RULE)* ENDMARKER - while self.type != tokenize.ENDMARKER: - while self.type == tokenize.NEWLINE: - self.gettoken() - # RULE: NAME ':' RHS NEWLINE - name = self.expect(tokenize.NAME) - if self.verbose: - print("Processing rule {dfa_name}".format(dfa_name=name)) - self.expect(tokenize.OP, ":") - a, z = self.parse_rhs() - self.expect(tokenize.NEWLINE) - if self.verbose: - self.dump_nfa(name, a, z) - dfa = self.make_dfa(a, z) - if self.verbose: - self.dump_dfa(name, dfa) - self.simplify_dfa(dfa) - dfas[name] = dfa - if startsymbol is None: - startsymbol = name - return dfas, startsymbol - - def make_dfa(self, start, finish): - # To turn an NFA into a DFA, we define the states of the DFA - # to correspond to *sets* of states of the NFA. Then do some - # state reduction. Let's represent sets as dicts with 1 for - # values. - assert isinstance(start, NFAState) - assert isinstance(finish, NFAState) - def closure(state): - base = set() - addclosure(state, base) - return base - def addclosure(state, base): - assert isinstance(state, NFAState) - if state in base: - return - base.add(state) - for label, next in state.arcs: - if label is None: - addclosure(next, base) - states = [DFAState(closure(start), finish)] - for state in states: # NB states grows while we're iterating - arcs = {} - for nfastate in state.nfaset: - for label, next in nfastate.arcs: - if label is not None: - addclosure(next, arcs.setdefault(label, set())) - for label, nfaset in sorted(arcs.items()): - for st in states: - if st.nfaset == nfaset: - break - else: - st = DFAState(nfaset, finish) - states.append(st) - state.addarc(st, label) - return states # List of DFAState instances; first one is start - - def dump_nfa(self, name, start, finish): - print("Dump of NFA for", name) - todo = [start] - for i, state in enumerate(todo): - print(" State", i, state is finish and "(final)" or "") - for label, next in state.arcs: - if next in todo: - j = todo.index(next) - else: - j = len(todo) - todo.append(next) - if label is None: - print(" -> %d" % j) - else: - print(" %s -> %d" % (label, j)) - - def dump_dfa(self, name, dfa): - print("Dump of DFA for", name) - for i, state in enumerate(dfa): - print(" State", i, state.isfinal and "(final)" or "") - for label, next in sorted(state.arcs.items()): - print(" %s -> %d" % (label, dfa.index(next))) - - def simplify_dfa(self, dfa): - # This is not theoretically optimal, but works well enough. - # Algorithm: repeatedly look for two states that have the same - # set of arcs (same labels pointing to the same nodes) and - # unify them, until things stop changing. - - # dfa is a list of DFAState instances - changes = True - while changes: - changes = False - for i, state_i in enumerate(dfa): - for j in range(i+1, len(dfa)): - state_j = dfa[j] - if state_i == state_j: - #print " unify", i, j - del dfa[j] - for state in dfa: - state.unifystate(state_j, state_i) - changes = True - break - - def parse_rhs(self): - # RHS: ALT ('|' ALT)* - a, z = self.parse_alt() - if self.value != "|": - return a, z - else: - aa = NFAState() - zz = NFAState() - aa.addarc(a) - z.addarc(zz) - while self.value == "|": - self.gettoken() - a, z = self.parse_alt() - aa.addarc(a) - z.addarc(zz) - return aa, zz - - def parse_alt(self): - # ALT: ITEM+ - a, b = self.parse_item() - while (self.value in ("(", "[") or - self.type in (tokenize.NAME, tokenize.STRING)): - c, d = self.parse_item() - b.addarc(c) - b = d - return a, b - - def parse_item(self): - # ITEM: '[' RHS ']' | ATOM ['+' | '*'] - if self.value == "[": - self.gettoken() - a, z = self.parse_rhs() - self.expect(tokenize.OP, "]") - a.addarc(z) - return a, z - else: - a, z = self.parse_atom() - value = self.value - if value not in ("+", "*"): - return a, z - self.gettoken() - z.addarc(a) - if value == "+": - return a, z - else: - return a, a - - def parse_atom(self): - # ATOM: '(' RHS ')' | NAME | STRING - if self.value == "(": - self.gettoken() - a, z = self.parse_rhs() - self.expect(tokenize.OP, ")") - return a, z - elif self.type in (tokenize.NAME, tokenize.STRING): - a = NFAState() - z = NFAState() - a.addarc(z, self.value) - self.gettoken() - return a, z - else: - self.raise_error("expected (...) or NAME or STRING, got %s/%s", - self.type, self.value) - - def expect(self, type, value=None): - if self.type != type or (value is not None and self.value != value): - self.raise_error("expected %s/%s, got %s/%s", - type, value, self.type, self.value) - value = self.value - self.gettoken() - return value - - def gettoken(self): - tup = next(self.generator) - while tup[0] in (tokenize.COMMENT, tokenize.NL): - tup = next(self.generator) - self.type, self.value, self.begin, self.end, self.line = tup - # print(getattr(tokenize, 'tok_name')[self.type], repr(self.value)) - - def raise_error(self, msg, *args): - if args: - try: - msg = msg % args - except Exception: - msg = " ".join([msg] + list(map(str, args))) - raise SyntaxError(msg, (self.filename, self.end[0], - self.end[1], self.line)) - -class NFAState(object): - - def __init__(self): - self.arcs = [] # list of (label, NFAState) pairs - - def addarc(self, next, label=None): - assert label is None or isinstance(label, str) - assert isinstance(next, NFAState) - self.arcs.append((label, next)) - -class DFAState(object): - - def __init__(self, nfaset, final): - assert isinstance(nfaset, set) - assert isinstance(next(iter(nfaset)), NFAState) - assert isinstance(final, NFAState) - self.nfaset = nfaset - self.isfinal = final in nfaset - self.arcs = {} # map from label to DFAState - - def addarc(self, next, label): - assert isinstance(label, str) - assert label not in self.arcs - assert isinstance(next, DFAState) - self.arcs[label] = next - - def unifystate(self, old, new): - for label, next in self.arcs.items(): - if next is old: - self.arcs[label] = new - - def __eq__(self, other): - # Equality test -- ignore the nfaset instance variable - assert isinstance(other, DFAState) - if self.isfinal != other.isfinal: - return False - # Can't just return self.arcs == other.arcs, because that - # would invoke this method recursively, with cycles... - if len(self.arcs) != len(other.arcs): - return False - for label, next in self.arcs.items(): - if next is not other.arcs.get(label): - return False - return True - - __hash__ = None # For Py3 compatibility. diff --git a/Parser/pgen/token.py b/Parser/pgen/token.py index e7e8f3f1b661..2cff62ce3b23 100644 --- a/Parser/pgen/token.py +++ b/Parser/pgen/token.py @@ -6,21 +6,21 @@ def generate_tokens(tokens): for line in tokens: line = line.strip() - if not line or line.startswith('#'): + if not line or line.startswith("#"): continue name = line.split()[0] yield (name, next(numbers)) - yield ('N_TOKENS', next(numbers)) - yield ('NT_OFFSET', 256) + yield ("N_TOKENS", next(numbers)) + yield ("NT_OFFSET", 256) def generate_opmap(tokens): for line in tokens: line = line.strip() - if not line or line.startswith('#'): + if not line or line.startswith("#"): continue pieces = line.split() @@ -35,4 +35,4 @@ def generate_opmap(tokens): # with the token generation in "generate_tokens" because if this # symbol is included in Grammar/Tokens, it will collide with != # as it has the same name (NOTEQUAL). - yield ('<>', 'NOTEQUAL') + yield ("<>", "NOTEQUAL") From webhook-mailer at python.org Thu Aug 22 02:06:58 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 22 Aug 2019 06:06:58 -0000 Subject: [Python-checkins] Add missing space to warning message (GH-14915) Message-ID: https://github.com/python/cpython/commit/c4106af38bbcb180725fe0d9478e6a11f7a5e7b9 commit: c4106af38bbcb180725fe0d9478e6a11f7a5e7b9 branch: master author: Florian Bruhin committer: Raymond Hettinger date: 2019-08-21T23:06:51-07:00 summary: Add missing space to warning message (GH-14915) This typo was introduced in GH-13409 when changing the message text. files: M Lib/collections/__init__.py diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 75d797579d94..6a3e599a91e6 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -47,7 +47,7 @@ def __getattr__(name): obj = getattr(_collections_abc, name) import warnings warnings.warn("Using or importing the ABCs from 'collections' instead " - "of from 'collections.abc' is deprecated since Python 3.3," + "of from 'collections.abc' is deprecated since Python 3.3, " "and in 3.9 it will stop working", DeprecationWarning, stacklevel=2) globals()[name] = obj From webhook-mailer at python.org Thu Aug 22 02:30:41 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 22 Aug 2019 06:30:41 -0000 Subject: [Python-checkins] Add missing space to warning message (GH-14915) (GH-15379) Message-ID: https://github.com/python/cpython/commit/8ede9676bb8350e6d0206158f795d48075e33081 commit: 8ede9676bb8350e6d0206158f795d48075e33081 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-21T23:30:26-07:00 summary: Add missing space to warning message (GH-14915) (GH-15379) This typo was introduced in GH-13409 when changing the message text. (cherry picked from commit c4106af38bbcb180725fe0d9478e6a11f7a5e7b9) Co-authored-by: Florian Bruhin files: M Lib/collections/__init__.py diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 3d1d93e113fd..469690be8c8e 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -47,7 +47,7 @@ def __getattr__(name): obj = getattr(_collections_abc, name) import warnings warnings.warn("Using or importing the ABCs from 'collections' instead " - "of from 'collections.abc' is deprecated since Python 3.3," + "of from 'collections.abc' is deprecated since Python 3.3, " "and in 3.9 it will stop working", DeprecationWarning, stacklevel=2) globals()[name] = obj From webhook-mailer at python.org Thu Aug 22 11:28:33 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Thu, 22 Aug 2019 15:28:33 -0000 Subject: [Python-checkins] bpo-27961: Remove leftovers from the times when long long wasn't required (GH-15388) Message-ID: https://github.com/python/cpython/commit/a38e9d139929a227e3899fbb638bc46c6cc6d8ba commit: a38e9d139929a227e3899fbb638bc46c6cc6d8ba branch: master author: Sergey Fedoseev committer: Pablo Galindo date: 2019-08-22T16:28:28+01:00 summary: bpo-27961: Remove leftovers from the times when long long wasn't required (GH-15388) files: M Doc/library/array.rst M Doc/library/posix.rst M Doc/library/struct.rst M PC/pyconfig.h M pyconfig.h.in diff --git a/Doc/library/array.rst b/Doc/library/array.rst index 59b94f10b43e..2ae2a071262a 100644 --- a/Doc/library/array.rst +++ b/Doc/library/array.rst @@ -36,9 +36,9 @@ defined: +-----------+--------------------+-------------------+-----------------------+-------+ | ``'L'`` | unsigned long | int | 4 | | +-----------+--------------------+-------------------+-----------------------+-------+ -| ``'q'`` | signed long long | int | 8 | \(2) | +| ``'q'`` | signed long long | int | 8 | | +-----------+--------------------+-------------------+-----------------------+-------+ -| ``'Q'`` | unsigned long long | int | 8 | \(2) | +| ``'Q'`` | unsigned long long | int | 8 | | +-----------+--------------------+-------------------+-----------------------+-------+ | ``'f'`` | float | float | 4 | | +-----------+--------------------+-------------------+-----------------------+-------+ @@ -57,13 +57,6 @@ Notes: .. deprecated-removed:: 3.3 4.0 -(2) - The ``'q'`` and ``'Q'`` type codes are available only if - the platform C compiler used to build Python supports C :c:type:`long long`, - or, on Windows, :c:type:`__int64`. - - .. versionadded:: 3.3 - The actual representation of values is determined by the machine architecture (strictly speaking, by the C implementation). The actual size can be accessed through the :attr:`itemsize` attribute. diff --git a/Doc/library/posix.rst b/Doc/library/posix.rst index 9cbc5505aee6..2105af9215f7 100644 --- a/Doc/library/posix.rst +++ b/Doc/library/posix.rst @@ -44,8 +44,8 @@ by defining the relevant size and offset types as 64-bit values. Such files are sometimes referred to as :dfn:`large files`. Large file support is enabled in Python when the size of an :c:type:`off_t` is -larger than a :c:type:`long` and the :c:type:`long long` type is available and is -at least as large as an :c:type:`off_t`. +larger than a :c:type:`long` and the :c:type:`long long` is at least as large +as an :c:type:`off_t`. It may be necessary to configure and compile Python with certain compiler flags to enable this mode. For example, it is enabled by default with recent versions of Irix, but with Solaris 2.6 and 2.7 you need to do something like:: diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index a06d90344ba3..1f90e3d1ba85 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -197,44 +197,44 @@ platform-dependent. +--------+--------------------------+--------------------+----------------+------------+ | ``c`` | :c:type:`char` | bytes of length 1 | 1 | | +--------+--------------------------+--------------------+----------------+------------+ -| ``b`` | :c:type:`signed char` | integer | 1 | \(1),\(3) | +| ``b`` | :c:type:`signed char` | integer | 1 | \(1), \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``B`` | :c:type:`unsigned char` | integer | 1 | \(3) | +| ``B`` | :c:type:`unsigned char` | integer | 1 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ | ``?`` | :c:type:`_Bool` | bool | 1 | \(1) | +--------+--------------------------+--------------------+----------------+------------+ -| ``h`` | :c:type:`short` | integer | 2 | \(3) | +| ``h`` | :c:type:`short` | integer | 2 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``H`` | :c:type:`unsigned short` | integer | 2 | \(3) | +| ``H`` | :c:type:`unsigned short` | integer | 2 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``i`` | :c:type:`int` | integer | 4 | \(3) | +| ``i`` | :c:type:`int` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``I`` | :c:type:`unsigned int` | integer | 4 | \(3) | +| ``I`` | :c:type:`unsigned int` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``l`` | :c:type:`long` | integer | 4 | \(3) | +| ``l`` | :c:type:`long` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``L`` | :c:type:`unsigned long` | integer | 4 | \(3) | +| ``L`` | :c:type:`unsigned long` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``q`` | :c:type:`long long` | integer | 8 | \(2), \(3) | +| ``q`` | :c:type:`long long` | integer | 8 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``Q`` | :c:type:`unsigned long | integer | 8 | \(2), \(3) | +| ``Q`` | :c:type:`unsigned long | integer | 8 | \(2) | | | long` | | | | +--------+--------------------------+--------------------+----------------+------------+ -| ``n`` | :c:type:`ssize_t` | integer | | \(4) | +| ``n`` | :c:type:`ssize_t` | integer | | \(3) | +--------+--------------------------+--------------------+----------------+------------+ -| ``N`` | :c:type:`size_t` | integer | | \(4) | +| ``N`` | :c:type:`size_t` | integer | | \(3) | +--------+--------------------------+--------------------+----------------+------------+ -| ``e`` | \(7) | float | 2 | \(5) | +| ``e`` | \(6) | float | 2 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ -| ``f`` | :c:type:`float` | float | 4 | \(5) | +| ``f`` | :c:type:`float` | float | 4 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ -| ``d`` | :c:type:`double` | float | 8 | \(5) | +| ``d`` | :c:type:`double` | float | 8 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ | ``s`` | :c:type:`char[]` | bytes | | | +--------+--------------------------+--------------------+----------------+------------+ | ``p`` | :c:type:`char[]` | bytes | | | +--------+--------------------------+--------------------+----------------+------------+ -| ``P`` | :c:type:`void \*` | integer | | \(6) | +| ``P`` | :c:type:`void \*` | integer | | \(5) | +--------+--------------------------+--------------------+----------------+------------+ .. versionchanged:: 3.3 @@ -254,11 +254,6 @@ Notes: standard mode, it is always represented by one byte. (2) - The ``'q'`` and ``'Q'`` conversion codes are available in native mode only if - the platform C compiler supports C :c:type:`long long`, or, on Windows, - :c:type:`__int64`. They are always available in standard modes. - -(3) When attempting to pack a non-integer using any of the integer conversion codes, if the non-integer has a :meth:`__index__` method then that method is called to convert the argument to an integer before packing. @@ -266,26 +261,26 @@ Notes: .. versionchanged:: 3.2 Use of the :meth:`__index__` method for non-integers is new in 3.2. -(4) +(3) The ``'n'`` and ``'N'`` conversion codes are only available for the native size (selected as the default or with the ``'@'`` byte order character). For the standard size, you can use whichever of the other integer formats fits your application. -(5) +(4) For the ``'f'``, ``'d'`` and ``'e'`` conversion codes, the packed representation uses the IEEE 754 binary32, binary64 or binary16 format (for ``'f'``, ``'d'`` or ``'e'`` respectively), regardless of the floating-point format used by the platform. -(6) +(5) The ``'P'`` format character is only available for the native byte ordering (selected as the default or with the ``'@'`` byte order character). The byte order character ``'='`` chooses to use little- or big-endian ordering based on the host system. The struct module does not interpret this as native ordering, so the ``'P'`` format is not available. -(7) +(6) The IEEE 754 binary16 "half precision" type was introduced in the 2008 revision of the `IEEE 754 standard `_. It has a sign bit, a 5-bit exponent and 11-bit precision (with 10 bits explicitly stored), diff --git a/PC/pyconfig.h b/PC/pyconfig.h index 9228923cbea8..9304c7257c66 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -295,7 +295,7 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ # define SIZEOF_FPOS_T 8 # define SIZEOF_HKEY 8 # define SIZEOF_SIZE_T 8 -/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff HAVE_LONG_LONG, +/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff sizeof(off_t) > sizeof(long), and sizeof(PY_LONG_LONG) >= sizeof(off_t). On Win64 the second condition is not true, but if fpos_t replaces off_t then this is true. The uses of HAVE_LARGEFILE_SUPPORT imply that Win64 diff --git a/pyconfig.h.in b/pyconfig.h.in index 20cc901e473b..ffdc49514e29 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -569,7 +569,7 @@ #undef HAVE_LANGINFO_H /* Defined to enable large file support when an off_t is bigger than a long - and long long is available and at least as big as an off_t. You may need to + and long long is at least as big as an off_t. You may need to add some flags for configuration and compilation to enable this mode. (For Solaris and Linux, the necessary defines are already defined.) */ #undef HAVE_LARGEFILE_SUPPORT From webhook-mailer at python.org Thu Aug 22 11:59:22 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Aug 2019 15:59:22 -0000 Subject: [Python-checkins] bpo-27961: Remove leftovers from the times when long long wasn't required (GH-15388) Message-ID: https://github.com/python/cpython/commit/2878f378e02990303a8fe4bedd5386bd90efc26d commit: 2878f378e02990303a8fe4bedd5386bd90efc26d branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-22T08:59:18-07:00 summary: bpo-27961: Remove leftovers from the times when long long wasn't required (GH-15388) (cherry picked from commit a38e9d139929a227e3899fbb638bc46c6cc6d8ba) Co-authored-by: Sergey Fedoseev files: M Doc/library/array.rst M Doc/library/posix.rst M Doc/library/struct.rst M PC/pyconfig.h M pyconfig.h.in diff --git a/Doc/library/array.rst b/Doc/library/array.rst index 59b94f10b43e..2ae2a071262a 100644 --- a/Doc/library/array.rst +++ b/Doc/library/array.rst @@ -36,9 +36,9 @@ defined: +-----------+--------------------+-------------------+-----------------------+-------+ | ``'L'`` | unsigned long | int | 4 | | +-----------+--------------------+-------------------+-----------------------+-------+ -| ``'q'`` | signed long long | int | 8 | \(2) | +| ``'q'`` | signed long long | int | 8 | | +-----------+--------------------+-------------------+-----------------------+-------+ -| ``'Q'`` | unsigned long long | int | 8 | \(2) | +| ``'Q'`` | unsigned long long | int | 8 | | +-----------+--------------------+-------------------+-----------------------+-------+ | ``'f'`` | float | float | 4 | | +-----------+--------------------+-------------------+-----------------------+-------+ @@ -57,13 +57,6 @@ Notes: .. deprecated-removed:: 3.3 4.0 -(2) - The ``'q'`` and ``'Q'`` type codes are available only if - the platform C compiler used to build Python supports C :c:type:`long long`, - or, on Windows, :c:type:`__int64`. - - .. versionadded:: 3.3 - The actual representation of values is determined by the machine architecture (strictly speaking, by the C implementation). The actual size can be accessed through the :attr:`itemsize` attribute. diff --git a/Doc/library/posix.rst b/Doc/library/posix.rst index 9cbc5505aee6..2105af9215f7 100644 --- a/Doc/library/posix.rst +++ b/Doc/library/posix.rst @@ -44,8 +44,8 @@ by defining the relevant size and offset types as 64-bit values. Such files are sometimes referred to as :dfn:`large files`. Large file support is enabled in Python when the size of an :c:type:`off_t` is -larger than a :c:type:`long` and the :c:type:`long long` type is available and is -at least as large as an :c:type:`off_t`. +larger than a :c:type:`long` and the :c:type:`long long` is at least as large +as an :c:type:`off_t`. It may be necessary to configure and compile Python with certain compiler flags to enable this mode. For example, it is enabled by default with recent versions of Irix, but with Solaris 2.6 and 2.7 you need to do something like:: diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index 1a0fd73c6758..56b0a3614df5 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -197,44 +197,44 @@ platform-dependent. +--------+--------------------------+--------------------+----------------+------------+ | ``c`` | :c:type:`char` | bytes of length 1 | 1 | | +--------+--------------------------+--------------------+----------------+------------+ -| ``b`` | :c:type:`signed char` | integer | 1 | \(1),\(3) | +| ``b`` | :c:type:`signed char` | integer | 1 | \(1), \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``B`` | :c:type:`unsigned char` | integer | 1 | \(3) | +| ``B`` | :c:type:`unsigned char` | integer | 1 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ | ``?`` | :c:type:`_Bool` | bool | 1 | \(1) | +--------+--------------------------+--------------------+----------------+------------+ -| ``h`` | :c:type:`short` | integer | 2 | \(3) | +| ``h`` | :c:type:`short` | integer | 2 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``H`` | :c:type:`unsigned short` | integer | 2 | \(3) | +| ``H`` | :c:type:`unsigned short` | integer | 2 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``i`` | :c:type:`int` | integer | 4 | \(3) | +| ``i`` | :c:type:`int` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``I`` | :c:type:`unsigned int` | integer | 4 | \(3) | +| ``I`` | :c:type:`unsigned int` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``l`` | :c:type:`long` | integer | 4 | \(3) | +| ``l`` | :c:type:`long` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``L`` | :c:type:`unsigned long` | integer | 4 | \(3) | +| ``L`` | :c:type:`unsigned long` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``q`` | :c:type:`long long` | integer | 8 | \(2), \(3) | +| ``q`` | :c:type:`long long` | integer | 8 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``Q`` | :c:type:`unsigned long | integer | 8 | \(2), \(3) | +| ``Q`` | :c:type:`unsigned long | integer | 8 | \(2) | | | long` | | | | +--------+--------------------------+--------------------+----------------+------------+ -| ``n`` | :c:type:`ssize_t` | integer | | \(4) | +| ``n`` | :c:type:`ssize_t` | integer | | \(3) | +--------+--------------------------+--------------------+----------------+------------+ -| ``N`` | :c:type:`size_t` | integer | | \(4) | +| ``N`` | :c:type:`size_t` | integer | | \(3) | +--------+--------------------------+--------------------+----------------+------------+ -| ``e`` | \(7) | float | 2 | \(5) | +| ``e`` | \(6) | float | 2 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ -| ``f`` | :c:type:`float` | float | 4 | \(5) | +| ``f`` | :c:type:`float` | float | 4 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ -| ``d`` | :c:type:`double` | float | 8 | \(5) | +| ``d`` | :c:type:`double` | float | 8 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ | ``s`` | :c:type:`char[]` | bytes | | | +--------+--------------------------+--------------------+----------------+------------+ | ``p`` | :c:type:`char[]` | bytes | | | +--------+--------------------------+--------------------+----------------+------------+ -| ``P`` | :c:type:`void \*` | integer | | \(6) | +| ``P`` | :c:type:`void \*` | integer | | \(5) | +--------+--------------------------+--------------------+----------------+------------+ .. versionchanged:: 3.3 @@ -254,11 +254,6 @@ Notes: standard mode, it is always represented by one byte. (2) - The ``'q'`` and ``'Q'`` conversion codes are available in native mode only if - the platform C compiler supports C :c:type:`long long`, or, on Windows, - :c:type:`__int64`. They are always available in standard modes. - -(3) When attempting to pack a non-integer using any of the integer conversion codes, if the non-integer has a :meth:`__index__` method then that method is called to convert the argument to an integer before packing. @@ -266,26 +261,26 @@ Notes: .. versionchanged:: 3.2 Use of the :meth:`__index__` method for non-integers is new in 3.2. -(4) +(3) The ``'n'`` and ``'N'`` conversion codes are only available for the native size (selected as the default or with the ``'@'`` byte order character). For the standard size, you can use whichever of the other integer formats fits your application. -(5) +(4) For the ``'f'``, ``'d'`` and ``'e'`` conversion codes, the packed representation uses the IEEE 754 binary32, binary64 or binary16 format (for ``'f'``, ``'d'`` or ``'e'`` respectively), regardless of the floating-point format used by the platform. -(6) +(5) The ``'P'`` format character is only available for the native byte ordering (selected as the default or with the ``'@'`` byte order character). The byte order character ``'='`` chooses to use little- or big-endian ordering based on the host system. The struct module does not interpret this as native ordering, so the ``'P'`` format is not available. -(7) +(6) The IEEE 754 binary16 "half precision" type was introduced in the 2008 revision of the `IEEE 754 standard `_. It has a sign bit, a 5-bit exponent and 11-bit precision (with 10 bits explicitly stored), diff --git a/PC/pyconfig.h b/PC/pyconfig.h index 3d7425a5a2c1..b40e24f438ef 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -295,7 +295,7 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ # define SIZEOF_FPOS_T 8 # define SIZEOF_HKEY 8 # define SIZEOF_SIZE_T 8 -/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff HAVE_LONG_LONG, +/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff sizeof(off_t) > sizeof(long), and sizeof(PY_LONG_LONG) >= sizeof(off_t). On Win64 the second condition is not true, but if fpos_t replaces off_t then this is true. The uses of HAVE_LARGEFILE_SUPPORT imply that Win64 diff --git a/pyconfig.h.in b/pyconfig.h.in index 20cc901e473b..ffdc49514e29 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -569,7 +569,7 @@ #undef HAVE_LANGINFO_H /* Defined to enable large file support when an off_t is bigger than a long - and long long is available and at least as big as an off_t. You may need to + and long long is at least as big as an off_t. You may need to add some flags for configuration and compilation to enable this mode. (For Solaris and Linux, the necessary defines are already defined.) */ #undef HAVE_LARGEFILE_SUPPORT From webhook-mailer at python.org Thu Aug 22 12:06:12 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Aug 2019 16:06:12 -0000 Subject: [Python-checkins] bpo-27961: Remove leftovers from the times when long long wasn't required (GH-15388) Message-ID: https://github.com/python/cpython/commit/d0da97de65985ea4fc69cade2343d931f8b9efcd commit: d0da97de65985ea4fc69cade2343d931f8b9efcd branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-22T09:06:08-07:00 summary: bpo-27961: Remove leftovers from the times when long long wasn't required (GH-15388) (cherry picked from commit a38e9d139929a227e3899fbb638bc46c6cc6d8ba) Co-authored-by: Sergey Fedoseev files: M Doc/library/array.rst M Doc/library/posix.rst M Doc/library/struct.rst M PC/pyconfig.h M pyconfig.h.in diff --git a/Doc/library/array.rst b/Doc/library/array.rst index 4ac7bb5391a7..0da6b48721fb 100644 --- a/Doc/library/array.rst +++ b/Doc/library/array.rst @@ -36,9 +36,9 @@ defined: +-----------+--------------------+-------------------+-----------------------+-------+ | ``'L'`` | unsigned long | int | 4 | | +-----------+--------------------+-------------------+-----------------------+-------+ -| ``'q'`` | signed long long | int | 8 | \(2) | +| ``'q'`` | signed long long | int | 8 | | +-----------+--------------------+-------------------+-----------------------+-------+ -| ``'Q'`` | unsigned long long | int | 8 | \(2) | +| ``'Q'`` | unsigned long long | int | 8 | | +-----------+--------------------+-------------------+-----------------------+-------+ | ``'f'`` | float | float | 4 | | +-----------+--------------------+-------------------+-----------------------+-------+ @@ -57,13 +57,6 @@ Notes: .. deprecated-removed:: 3.3 4.0 -(2) - The ``'q'`` and ``'Q'`` type codes are available only if - the platform C compiler used to build Python supports C :c:type:`long long`, - or, on Windows, :c:type:`__int64`. - - .. versionadded:: 3.3 - The actual representation of values is determined by the machine architecture (strictly speaking, by the C implementation). The actual size can be accessed through the :attr:`itemsize` attribute. diff --git a/Doc/library/posix.rst b/Doc/library/posix.rst index 9cbc5505aee6..2105af9215f7 100644 --- a/Doc/library/posix.rst +++ b/Doc/library/posix.rst @@ -44,8 +44,8 @@ by defining the relevant size and offset types as 64-bit values. Such files are sometimes referred to as :dfn:`large files`. Large file support is enabled in Python when the size of an :c:type:`off_t` is -larger than a :c:type:`long` and the :c:type:`long long` type is available and is -at least as large as an :c:type:`off_t`. +larger than a :c:type:`long` and the :c:type:`long long` is at least as large +as an :c:type:`off_t`. It may be necessary to configure and compile Python with certain compiler flags to enable this mode. For example, it is enabled by default with recent versions of Irix, but with Solaris 2.6 and 2.7 you need to do something like:: diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index df2416e5bc92..48885d14f4f4 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -197,44 +197,44 @@ platform-dependent. +--------+--------------------------+--------------------+----------------+------------+ | ``c`` | :c:type:`char` | bytes of length 1 | 1 | | +--------+--------------------------+--------------------+----------------+------------+ -| ``b`` | :c:type:`signed char` | integer | 1 | \(1),\(3) | +| ``b`` | :c:type:`signed char` | integer | 1 | \(1), \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``B`` | :c:type:`unsigned char` | integer | 1 | \(3) | +| ``B`` | :c:type:`unsigned char` | integer | 1 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ | ``?`` | :c:type:`_Bool` | bool | 1 | \(1) | +--------+--------------------------+--------------------+----------------+------------+ -| ``h`` | :c:type:`short` | integer | 2 | \(3) | +| ``h`` | :c:type:`short` | integer | 2 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``H`` | :c:type:`unsigned short` | integer | 2 | \(3) | +| ``H`` | :c:type:`unsigned short` | integer | 2 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``i`` | :c:type:`int` | integer | 4 | \(3) | +| ``i`` | :c:type:`int` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``I`` | :c:type:`unsigned int` | integer | 4 | \(3) | +| ``I`` | :c:type:`unsigned int` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``l`` | :c:type:`long` | integer | 4 | \(3) | +| ``l`` | :c:type:`long` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``L`` | :c:type:`unsigned long` | integer | 4 | \(3) | +| ``L`` | :c:type:`unsigned long` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``q`` | :c:type:`long long` | integer | 8 | \(2), \(3) | +| ``q`` | :c:type:`long long` | integer | 8 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``Q`` | :c:type:`unsigned long | integer | 8 | \(2), \(3) | +| ``Q`` | :c:type:`unsigned long | integer | 8 | \(2) | | | long` | | | | +--------+--------------------------+--------------------+----------------+------------+ -| ``n`` | :c:type:`ssize_t` | integer | | \(4) | +| ``n`` | :c:type:`ssize_t` | integer | | \(3) | +--------+--------------------------+--------------------+----------------+------------+ -| ``N`` | :c:type:`size_t` | integer | | \(4) | +| ``N`` | :c:type:`size_t` | integer | | \(3) | +--------+--------------------------+--------------------+----------------+------------+ -| ``e`` | \(7) | float | 2 | \(5) | +| ``e`` | \(6) | float | 2 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ -| ``f`` | :c:type:`float` | float | 4 | \(5) | +| ``f`` | :c:type:`float` | float | 4 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ -| ``d`` | :c:type:`double` | float | 8 | \(5) | +| ``d`` | :c:type:`double` | float | 8 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ | ``s`` | :c:type:`char[]` | bytes | | | +--------+--------------------------+--------------------+----------------+------------+ | ``p`` | :c:type:`char[]` | bytes | | | +--------+--------------------------+--------------------+----------------+------------+ -| ``P`` | :c:type:`void \*` | integer | | \(6) | +| ``P`` | :c:type:`void \*` | integer | | \(5) | +--------+--------------------------+--------------------+----------------+------------+ .. versionchanged:: 3.3 @@ -254,11 +254,6 @@ Notes: standard mode, it is always represented by one byte. (2) - The ``'q'`` and ``'Q'`` conversion codes are available in native mode only if - the platform C compiler supports C :c:type:`long long`, or, on Windows, - :c:type:`__int64`. They are always available in standard modes. - -(3) When attempting to pack a non-integer using any of the integer conversion codes, if the non-integer has a :meth:`__index__` method then that method is called to convert the argument to an integer before packing. @@ -266,26 +261,26 @@ Notes: .. versionchanged:: 3.2 Use of the :meth:`__index__` method for non-integers is new in 3.2. -(4) +(3) The ``'n'`` and ``'N'`` conversion codes are only available for the native size (selected as the default or with the ``'@'`` byte order character). For the standard size, you can use whichever of the other integer formats fits your application. -(5) +(4) For the ``'f'``, ``'d'`` and ``'e'`` conversion codes, the packed representation uses the IEEE 754 binary32, binary64 or binary16 format (for ``'f'``, ``'d'`` or ``'e'`` respectively), regardless of the floating-point format used by the platform. -(6) +(5) The ``'P'`` format character is only available for the native byte ordering (selected as the default or with the ``'@'`` byte order character). The byte order character ``'='`` chooses to use little- or big-endian ordering based on the host system. The struct module does not interpret this as native ordering, so the ``'P'`` format is not available. -(7) +(6) The IEEE 754 binary16 "half precision" type was introduced in the 2008 revision of the `IEEE 754 standard `_. It has a sign bit, a 5-bit exponent and 11-bit precision (with 10 bits explicitly stored), diff --git a/PC/pyconfig.h b/PC/pyconfig.h index 46fc84e92f29..6e33f12e0df6 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -292,7 +292,7 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ # define SIZEOF_FPOS_T 8 # define SIZEOF_HKEY 8 # define SIZEOF_SIZE_T 8 -/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff HAVE_LONG_LONG, +/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff sizeof(off_t) > sizeof(long), and sizeof(PY_LONG_LONG) >= sizeof(off_t). On Win64 the second condition is not true, but if fpos_t replaces off_t then this is true. The uses of HAVE_LARGEFILE_SUPPORT imply that Win64 diff --git a/pyconfig.h.in b/pyconfig.h.in index 4032fa519f8a..1ed9479ee474 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -540,7 +540,7 @@ #undef HAVE_LANGINFO_H /* Defined to enable large file support when an off_t is bigger than a long - and long long is available and at least as big as an off_t. You may need to + and long long is at least as big as an off_t. You may need to add some flags for configuration and compilation to enable this mode. (For Solaris and Linux, the necessary defines are already defined.) */ #undef HAVE_LARGEFILE_SUPPORT From webhook-mailer at python.org Thu Aug 22 12:11:39 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 22 Aug 2019 16:11:39 -0000 Subject: [Python-checkins] bpo-14050: Note that not all data can be sorted (GH-15381) Message-ID: https://github.com/python/cpython/commit/4109263a7edce11194e301138cf66fa2d07f7ce4 commit: 4109263a7edce11194e301138cf66fa2d07f7ce4 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-22T09:11:35-07:00 summary: bpo-14050: Note that not all data can be sorted (GH-15381) files: M Doc/tutorial/datastructures.rst diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst index 01e437bb5da8..a0d56274fd7e 100644 --- a/Doc/tutorial/datastructures.rst +++ b/Doc/tutorial/datastructures.rst @@ -125,6 +125,13 @@ only modify the list have no return value printed -- they return the default ``None``. [1]_ This is a design principle for all mutable data structures in Python. +Another thing you might notice is that not all data can be sorted or +compared. For instance, ``[None, 'hello', 10]`` doesn't sort because +integers can't be compared to strings and *None* can't be compared to +other types. Also, there are some types that don't have a defined +ordering relation. For example, ``3+4j < 5+7j`` isn't a valid +comparison. + .. _tut-lists-as-stacks: From webhook-mailer at python.org Thu Aug 22 12:19:40 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 22 Aug 2019 16:19:40 -0000 Subject: [Python-checkins] bpo-32554: Deprecate hashing arbitrary types in random.seed() (GH-15382) Message-ID: https://github.com/python/cpython/commit/d0cdeaab76fef8a6e5a04665df226b6659111e4e commit: d0cdeaab76fef8a6e5a04665df226b6659111e4e branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-22T09:19:36-07:00 summary: bpo-32554: Deprecate hashing arbitrary types in random.seed() (GH-15382) files: A Misc/NEWS.d/next/Library/2019-08-22-01-49-05.bpo-32554.4xiXyM.rst M Doc/library/random.rst M Doc/whatsnew/3.9.rst M Lib/random.py diff --git a/Doc/library/random.rst b/Doc/library/random.rst index 90b86248e6e1..1bd1856937be 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -86,6 +86,11 @@ Bookkeeping functions .. versionchanged:: 3.2 Moved to the version 2 scheme which uses all of the bits in a string seed. + .. deprecated:: 3.9 + In the future, the *seed* must be one of the following types: + *NoneType*, :class:`int`, :class:`float`, :class:`str`, + :class:`bytes`, or :class:`bytearray`. + .. function:: getstate() Return an object capturing the current internal state of the generator. This @@ -316,6 +321,11 @@ Alternative Generator Class that implements the default pseudo-random number generator used by the :mod:`random` module. + .. deprecated:: 3.9 + In the future, the *seed* must be one of the following types: + :class:`NoneType`, :class:`int`, :class:`float`, :class:`str`, + :class:`bytes`, or :class:`bytearray`. + .. class:: SystemRandom([seed]) Class that uses the :func:`os.urandom` function for generating random numbers diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 6615a2e28eff..05a17a5c7390 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -169,6 +169,12 @@ Deprecated of Python. For the majority of use cases users can leverage the Abstract Syntax Tree (AST) generation and compilation stage, using the :mod:`ast` module. +* The :mod:`random` module currently accepts any hashable type as a + possible seed value. Unfortunately, some of those types are not + guaranteed to have a deterministic hash value. After Python 3.9, + the module will restrict its seeds to *None*, :class:`int`, + :class:`float`, :class:`str`, :class:`bytes`, and :class:`bytearray`. + Removed ======= diff --git a/Lib/random.py b/Lib/random.py index 365a01957203..be4401c554d7 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -121,7 +121,10 @@ def __init_subclass__(cls, /, **kwargs): break def seed(self, a=None, version=2): - """Initialize internal state from hashable object. + """Initialize internal state from a seed. + + The only supported seed types are None, int, float, + str, bytes, and bytearray. None or no argument seeds from current time or from an operating system specific randomness source if available. @@ -143,12 +146,20 @@ def seed(self, a=None, version=2): x ^= len(a) a = -2 if x == -1 else x - if version == 2 and isinstance(a, (str, bytes, bytearray)): + elif version == 2 and isinstance(a, (str, bytes, bytearray)): if isinstance(a, str): a = a.encode() a += _sha512(a).digest() a = int.from_bytes(a, 'big') + elif not isinstance(a, (type(None), int, float, str, bytes, bytearray)): + _warn('Seeding based on hashing is deprecated\n' + 'since Python 3.9 and will be removed in a subsequent ' + 'version. The only \n' + 'supported seed types are: None, ' + 'int, float, str, bytes, and bytearray.', + DeprecationWarning, 2) + super().seed(a) self.gauss_next = None diff --git a/Misc/NEWS.d/next/Library/2019-08-22-01-49-05.bpo-32554.4xiXyM.rst b/Misc/NEWS.d/next/Library/2019-08-22-01-49-05.bpo-32554.4xiXyM.rst new file mode 100644 index 000000000000..752cf48a4543 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-22-01-49-05.bpo-32554.4xiXyM.rst @@ -0,0 +1 @@ +Deprecate having random.seed() call hash on arbitrary types. From webhook-mailer at python.org Thu Aug 22 12:40:00 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 22 Aug 2019 16:40:00 -0000 Subject: [Python-checkins] bpo-14050: Note that not all data can be sorted (GH-15381) (GH-15395) Message-ID: https://github.com/python/cpython/commit/cb8de91dadf15925fb95069cb190398e1d485f56 commit: cb8de91dadf15925fb95069cb190398e1d485f56 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-22T09:39:52-07:00 summary: bpo-14050: Note that not all data can be sorted (GH-15381) (GH-15395) (cherry picked from commit 4109263a7edce11194e301138cf66fa2d07f7ce4) Co-authored-by: Raymond Hettinger files: M Doc/tutorial/datastructures.rst diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst index 01e437bb5da8..a0d56274fd7e 100644 --- a/Doc/tutorial/datastructures.rst +++ b/Doc/tutorial/datastructures.rst @@ -125,6 +125,13 @@ only modify the list have no return value printed -- they return the default ``None``. [1]_ This is a design principle for all mutable data structures in Python. +Another thing you might notice is that not all data can be sorted or +compared. For instance, ``[None, 'hello', 10]`` doesn't sort because +integers can't be compared to strings and *None* can't be compared to +other types. Also, there are some types that don't have a defined +ordering relation. For example, ``3+4j < 5+7j`` isn't a valid +comparison. + .. _tut-lists-as-stacks: From webhook-mailer at python.org Thu Aug 22 13:48:14 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Aug 2019 17:48:14 -0000 Subject: [Python-checkins] bpo-28556: Add a regression test to typing (GH-15396) Message-ID: https://github.com/python/cpython/commit/8889627b53e1eea2e32590f1867fbb0b0fc7407f commit: 8889627b53e1eea2e32590f1867fbb0b0fc7407f branch: master author: Ivan Levkivskyi committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-22T10:48:01-07:00 summary: bpo-28556: Add a regression test to typing (GH-15396) This adds a regression test for the issue found in the Python 2 backport, see https://github.com/python/typing/issues/656 https://bugs.python.org/issue28556 files: M Lib/test/test_typing.py diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index ba001c3462fc..ba0800fae90e 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -961,6 +961,23 @@ def __init__(self, x): self.assertIsInstance(C(1), P) self.assertIsInstance(C(1), PG) + def test_protocol_checks_after_subscript(self): + class P(Protocol[T]): pass + class C(P[T]): pass + class Other1: pass + class Other2: pass + CA = C[Any] + + self.assertNotIsInstance(Other1(), C) + self.assertNotIsSubclass(Other2, C) + + class D1(C[Any]): pass + class D2(C[Any]): pass + CI = C[int] + + self.assertIsInstance(D1(), C) + self.assertIsSubclass(D2, C) + def test_protocols_support_register(self): @runtime_checkable class P(Protocol): From webhook-mailer at python.org Thu Aug 22 14:11:32 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Aug 2019 18:11:32 -0000 Subject: [Python-checkins] bpo-28556: Add a regression test to typing (GH-15396) Message-ID: https://github.com/python/cpython/commit/5fda09cc1ebcb364a660bc5a831ef8f6463d810b commit: 5fda09cc1ebcb364a660bc5a831ef8f6463d810b branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-22T11:11:27-07:00 summary: bpo-28556: Add a regression test to typing (GH-15396) This adds a regression test for the issue found in the Python 2 backport, see https://github.com/python/typing/issues/656 https://bugs.python.org/issue28556 (cherry picked from commit 8889627b53e1eea2e32590f1867fbb0b0fc7407f) Co-authored-by: Ivan Levkivskyi files: M Lib/test/test_typing.py diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index ba001c3462fc..ba0800fae90e 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -961,6 +961,23 @@ def __init__(self, x): self.assertIsInstance(C(1), P) self.assertIsInstance(C(1), PG) + def test_protocol_checks_after_subscript(self): + class P(Protocol[T]): pass + class C(P[T]): pass + class Other1: pass + class Other2: pass + CA = C[Any] + + self.assertNotIsInstance(Other1(), C) + self.assertNotIsSubclass(Other2, C) + + class D1(C[Any]): pass + class D2(C[Any]): pass + CI = C[int] + + self.assertIsInstance(D1(), C) + self.assertIsSubclass(D2, C) + def test_protocols_support_register(self): @runtime_checkable class P(Protocol): From webhook-mailer at python.org Thu Aug 22 15:24:32 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Aug 2019 19:24:32 -0000 Subject: [Python-checkins] bpo-37915: Fix comparison between tzinfo objects and timezone objects (GH-15390) Message-ID: https://github.com/python/cpython/commit/4be11c009abe88175fa164b45e4838e7267dfa97 commit: 4be11c009abe88175fa164b45e4838e7267dfa97 branch: master author: Pablo Galindo committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-22T12:24:25-07:00 summary: bpo-37915: Fix comparison between tzinfo objects and timezone objects (GH-15390) https://bugs.python.org/issue37915 Automerge-Triggered-By: @pablogsal files: A Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst M Lib/test/datetimetester.py M Modules/_datetimemodule.c diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index d0101c98bc76..58004870a00f 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -413,6 +413,11 @@ def test_offset_boundaries(self): with self.assertRaises(ValueError): timezone(delta) + def test_comparison_with_tzinfo(self): + # Constructing tzinfo objects directly should not be done by users + # and serves only to check the bug described in bpo-37915 + self.assertNotEqual(timezone.utc, tzinfo()) + self.assertNotEqual(timezone(timedelta(hours=1)), tzinfo()) ############################################################################# # Base class for testing a particular aspect of timedelta, time, date and diff --git a/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst b/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst new file mode 100644 index 000000000000..1dc9ea4b8cf8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst @@ -0,0 +1,3 @@ +Fix a segmentation fault that appeared when comparing instances of +``datetime.timezone`` and ``datetime.tzinfo`` objects. Patch by Pablo +Galindo. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 6d28b3e511c2..56eaccdf1723 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -32,6 +32,7 @@ #define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType) #define PyTZInfo_CheckExact(op) (Py_TYPE(op) == &PyDateTime_TZInfoType) +#define PyTimezone_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeZoneType) /*[clinic input] module datetime @@ -3745,7 +3746,7 @@ timezone_richcompare(PyDateTime_TimeZone *self, { if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED; - if (!PyTZInfo_Check(other)) { + if (!PyTimezone_Check(other)) { Py_RETURN_NOTIMPLEMENTED; } return delta_richcompare(self->offset, other->offset, op); From webhook-mailer at python.org Thu Aug 22 18:14:48 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 22 Aug 2019 22:14:48 -0000 Subject: [Python-checkins] bpo-30550: Clarify JSON ordering guarantees (GH-15397) Message-ID: https://github.com/python/cpython/commit/657008ea0336ff4f275ed3f0c2b6dd2e52de2bba commit: 657008ea0336ff4f275ed3f0c2b6dd2e52de2bba branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-22T15:14:42-07:00 summary: bpo-30550: Clarify JSON ordering guarantees (GH-15397) files: M Doc/library/json.rst diff --git a/Doc/library/json.rst b/Doc/library/json.rst index b476c372370d..56c16f5d296a 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -120,6 +120,18 @@ See :ref:`json-commandline` for detailed documentation. value) is also a subset of YAML 1.0 and 1.1. This module can thus also be used as a YAML serializer. +.. note:: + + This module's encoders and decoders preserve input and output order by + default. Order is only lost if the underlying containers are unordered. + + Prior to Python 3.7, :class:`dict` was not guaranteed to be ordered, so + inputs and outputs were typically scrambled unless + :class:`collections.OrderedDict` was specifically requested. Starting + with Python 3.7, the regular :class:`dict` became order preserving, so + it is no longer necessary specify :class:`collections.OrderedDict` for + JSON generation and parsing. + Basic Usage ----------- From webhook-mailer at python.org Thu Aug 22 18:50:38 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 22 Aug 2019 22:50:38 -0000 Subject: [Python-checkins] bpo-30550: Clarify JSON ordering guarantees (GH-15397) (GH-15403) Message-ID: https://github.com/python/cpython/commit/4a40498ea96a3c606952712c7951b2ea4ab258e4 commit: 4a40498ea96a3c606952712c7951b2ea4ab258e4 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-22T15:50:32-07:00 summary: bpo-30550: Clarify JSON ordering guarantees (GH-15397) (GH-15403) (cherry picked from commit 657008ea0336ff4f275ed3f0c2b6dd2e52de2bba) Co-authored-by: Raymond Hettinger files: M Doc/library/json.rst diff --git a/Doc/library/json.rst b/Doc/library/json.rst index b476c372370d..56c16f5d296a 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -120,6 +120,18 @@ See :ref:`json-commandline` for detailed documentation. value) is also a subset of YAML 1.0 and 1.1. This module can thus also be used as a YAML serializer. +.. note:: + + This module's encoders and decoders preserve input and output order by + default. Order is only lost if the underlying containers are unordered. + + Prior to Python 3.7, :class:`dict` was not guaranteed to be ordered, so + inputs and outputs were typically scrambled unless + :class:`collections.OrderedDict` was specifically requested. Starting + with Python 3.7, the regular :class:`dict` became order preserving, so + it is no longer necessary specify :class:`collections.OrderedDict` for + JSON generation and parsing. + Basic Usage ----------- From webhook-mailer at python.org Fri Aug 23 02:27:26 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 23 Aug 2019 06:27:26 -0000 Subject: [Python-checkins] bpo-12634: Clarify an awkward section of the tutorial (GH-15406) Message-ID: https://github.com/python/cpython/commit/483ae0cf1dcf46f8b71c4bf32419dd138e908553 commit: 483ae0cf1dcf46f8b71c4bf32419dd138e908553 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-22T23:27:04-07:00 summary: bpo-12634: Clarify an awkward section of the tutorial (GH-15406) files: M Doc/tutorial/classes.rst diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst index 7619ccbc1f36..0c0dca99f21f 100644 --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -475,12 +475,20 @@ Random Remarks .. These should perhaps be placed more carefully... -Data attributes override method attributes with the same name; to avoid -accidental name conflicts, which may cause hard-to-find bugs in large programs, -it is wise to use some kind of convention that minimizes the chance of -conflicts. Possible conventions include capitalizing method names, prefixing -data attribute names with a small unique string (perhaps just an underscore), or -using verbs for methods and nouns for data attributes. +If the same attribute name occurs in both an instance and in a class, +then attribute lookup prioritizes the instance:: + + >>> class Warehouse: + purpose = 'storage' + region = 'west' + + >>> w1 = Warehouse() + >>> print(w1.purpose, w1.region) + storage west + >>> w2 = Warehouse() + >>> w2.region = 'east' + >>> print(w2.purpose, w2.region) + storage east Data attributes may be referenced by methods as well as by ordinary users ("clients") of an object. In other words, classes are not usable to implement From webhook-mailer at python.org Fri Aug 23 02:44:23 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 23 Aug 2019 06:44:23 -0000 Subject: [Python-checkins] bpo-30826: Improve control flow examples (GH-15407) Message-ID: https://github.com/python/cpython/commit/6fcb6cfb139ade1aac6dbee0b18ca72b18cbe0d2 commit: 6fcb6cfb139ade1aac6dbee0b18ca72b18cbe0d2 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-22T23:44:19-07:00 summary: bpo-30826: Improve control flow examples (GH-15407) files: M Doc/tutorial/controlflow.rst diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index 92c042e26dfb..b7e003c55018 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -66,20 +66,20 @@ they appear in the sequence. For example (no pun intended): window 6 defenestrate 12 -If you need to modify the sequence you are iterating over while inside the loop -(for example to duplicate selected items), it is recommended that you first -make a copy. Iterating over a sequence does not implicitly make a copy. The -slice notation makes this especially convenient:: - - >>> for w in words[:]: # Loop over a slice copy of the entire list. - ... if len(w) > 6: - ... words.insert(0, w) - ... - >>> words - ['defenestrate', 'cat', 'window', 'defenestrate'] - -With ``for w in words:``, the example would attempt to create an infinite list, -inserting ``defenestrate`` over and over again. +Code that modifies a collection while iterating over that same collection can +be tricky to get right. Instead, it is usually more straight-forward to loop +over a copy of the collection or to create a new collection:: + + # Strategy: Iterate over a copy + for user, status in users.copy().items(): + if status == 'inactive': + del users[user] + + # Strategy: Create a new collection + active_users = {} + for user, status in users.items(): + if status == 'active': + active_users[user] = status .. _tut-range: From webhook-mailer at python.org Fri Aug 23 02:46:00 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 23 Aug 2019 06:46:00 -0000 Subject: [Python-checkins] bpo-12634: Clarify an awkward section of the tutorial (GH-15406) (GH-15409) Message-ID: https://github.com/python/cpython/commit/f6a7f5bc50f4267cfb7fe0c4ea16d5359c009cbd commit: f6a7f5bc50f4267cfb7fe0c4ea16d5359c009cbd branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-22T23:45:57-07:00 summary: bpo-12634: Clarify an awkward section of the tutorial (GH-15406) (GH-15409) (cherry picked from commit 483ae0cf1dcf46f8b71c4bf32419dd138e908553) Co-authored-by: Raymond Hettinger files: M Doc/tutorial/classes.rst diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst index 7619ccbc1f36..0c0dca99f21f 100644 --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -475,12 +475,20 @@ Random Remarks .. These should perhaps be placed more carefully... -Data attributes override method attributes with the same name; to avoid -accidental name conflicts, which may cause hard-to-find bugs in large programs, -it is wise to use some kind of convention that minimizes the chance of -conflicts. Possible conventions include capitalizing method names, prefixing -data attribute names with a small unique string (perhaps just an underscore), or -using verbs for methods and nouns for data attributes. +If the same attribute name occurs in both an instance and in a class, +then attribute lookup prioritizes the instance:: + + >>> class Warehouse: + purpose = 'storage' + region = 'west' + + >>> w1 = Warehouse() + >>> print(w1.purpose, w1.region) + storage west + >>> w2 = Warehouse() + >>> w2.region = 'east' + >>> print(w2.purpose, w2.region) + storage east Data attributes may be referenced by methods as well as by ordinary users ("clients") of an object. In other words, classes are not usable to implement From webhook-mailer at python.org Fri Aug 23 02:52:18 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 23 Aug 2019 06:52:18 -0000 Subject: [Python-checkins] bpo-30826: Improve control flow examples (GH-15407) (GH-15410) Message-ID: https://github.com/python/cpython/commit/b6341e676af2f58f3ad9b51a0d2fb7db5a3428e3 commit: b6341e676af2f58f3ad9b51a0d2fb7db5a3428e3 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-22T23:52:12-07:00 summary: bpo-30826: Improve control flow examples (GH-15407) (GH-15410) (cherry picked from commit 6fcb6cfb139ade1aac6dbee0b18ca72b18cbe0d2) Co-authored-by: Raymond Hettinger files: M Doc/tutorial/controlflow.rst diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index 92c042e26dfb..b7e003c55018 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -66,20 +66,20 @@ they appear in the sequence. For example (no pun intended): window 6 defenestrate 12 -If you need to modify the sequence you are iterating over while inside the loop -(for example to duplicate selected items), it is recommended that you first -make a copy. Iterating over a sequence does not implicitly make a copy. The -slice notation makes this especially convenient:: - - >>> for w in words[:]: # Loop over a slice copy of the entire list. - ... if len(w) > 6: - ... words.insert(0, w) - ... - >>> words - ['defenestrate', 'cat', 'window', 'defenestrate'] - -With ``for w in words:``, the example would attempt to create an infinite list, -inserting ``defenestrate`` over and over again. +Code that modifies a collection while iterating over that same collection can +be tricky to get right. Instead, it is usually more straight-forward to loop +over a copy of the collection or to create a new collection:: + + # Strategy: Iterate over a copy + for user, status in users.copy().items(): + if status == 'inactive': + del users[user] + + # Strategy: Create a new collection + active_users = {} + for user, status in users.items(): + if status == 'active': + active_users[user] = status .. _tut-range: From webhook-mailer at python.org Fri Aug 23 04:48:46 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Aug 2019 08:48:46 -0000 Subject: [Python-checkins] bpo-37915: Fix comparison between tzinfo objects and timezone objects (GH-15390) Message-ID: https://github.com/python/cpython/commit/5c77730300c0358d7bebd2bb39ea5d10222a3d9a commit: 5c77730300c0358d7bebd2bb39ea5d10222a3d9a branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-23T01:48:40-07:00 summary: bpo-37915: Fix comparison between tzinfo objects and timezone objects (GH-15390) https://bugs.python.org/issue37915 Automerge-Triggered-By: @pablogsal (cherry picked from commit 4be11c009abe88175fa164b45e4838e7267dfa97) Co-authored-by: Pablo Galindo files: A Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst M Lib/test/datetimetester.py M Modules/_datetimemodule.c diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index d0101c98bc76..58004870a00f 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -413,6 +413,11 @@ def test_offset_boundaries(self): with self.assertRaises(ValueError): timezone(delta) + def test_comparison_with_tzinfo(self): + # Constructing tzinfo objects directly should not be done by users + # and serves only to check the bug described in bpo-37915 + self.assertNotEqual(timezone.utc, tzinfo()) + self.assertNotEqual(timezone(timedelta(hours=1)), tzinfo()) ############################################################################# # Base class for testing a particular aspect of timedelta, time, date and diff --git a/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst b/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst new file mode 100644 index 000000000000..1dc9ea4b8cf8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst @@ -0,0 +1,3 @@ +Fix a segmentation fault that appeared when comparing instances of +``datetime.timezone`` and ``datetime.tzinfo`` objects. Patch by Pablo +Galindo. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index beb1c3cfbca9..e6abfc2cb223 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -32,6 +32,7 @@ #define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType) #define PyTZInfo_CheckExact(op) (Py_TYPE(op) == &PyDateTime_TZInfoType) +#define PyTimezone_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeZoneType) /*[clinic input] module datetime @@ -3748,7 +3749,7 @@ timezone_richcompare(PyDateTime_TimeZone *self, { if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED; - if (!PyTZInfo_Check(other)) { + if (!PyTimezone_Check(other)) { Py_RETURN_NOTIMPLEMENTED; } return delta_richcompare(self->offset, other->offset, op); From webhook-mailer at python.org Fri Aug 23 05:58:32 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Fri, 23 Aug 2019 09:58:32 -0000 Subject: [Python-checkins] Correct minor grammar mistake (GH-15404) Message-ID: https://github.com/python/cpython/commit/d288b29fc652d27191bde3b3c9145c2eb8169929 commit: d288b29fc652d27191bde3b3c9145c2eb8169929 branch: master author: Andre Delfino committer: Pablo Galindo date: 2019-08-23T10:58:27+01:00 summary: Correct minor grammar mistake (GH-15404) files: M Doc/library/json.rst diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 56c16f5d296a..23e39e95f783 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -129,7 +129,7 @@ See :ref:`json-commandline` for detailed documentation. inputs and outputs were typically scrambled unless :class:`collections.OrderedDict` was specifically requested. Starting with Python 3.7, the regular :class:`dict` became order preserving, so - it is no longer necessary specify :class:`collections.OrderedDict` for + it is no longer necessary to specify :class:`collections.OrderedDict` for JSON generation and parsing. From webhook-mailer at python.org Fri Aug 23 06:04:20 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 10:04:20 -0000 Subject: [Python-checkins] bpo-37926: Fix PySys_SetArgvEx(0, NULL, 0) crash (GH-15415) Message-ID: https://github.com/python/cpython/commit/c48682509dc49b43fe914fe6c502bc390345d1c2 commit: c48682509dc49b43fe914fe6c502bc390345d1c2 branch: master author: Victor Stinner committer: GitHub date: 2019-08-23T11:04:16+01:00 summary: bpo-37926: Fix PySys_SetArgvEx(0, NULL, 0) crash (GH-15415) empty_argv is no longer static in Python 3.8, but it is declared in a temporary scope, whereas argv keeps a reference to it. empty_argv memory (allocated on the stack) is reused by make_sys_argv() code which is inlined when using gcc -O3. Define empty_argv in PySys_SetArgvEx() body, to ensure that it remains valid for the whole lifetime of the PySys_SetArgvEx() call. files: A Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst M Python/sysmodule.c diff --git a/Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst b/Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst new file mode 100644 index 000000000000..20185330a8f4 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst @@ -0,0 +1 @@ +Fix a crash in ``PySys_SetArgvEx(0, NULL, 0)``. diff --git a/Python/sysmodule.c b/Python/sysmodule.c index a89ebceb66c5..738bbc826f5e 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -3058,11 +3058,11 @@ make_sys_argv(int argc, wchar_t * const * argv) void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) { + wchar_t* empty_argv[1] = {L""}; PyThreadState *tstate = _PyThreadState_GET(); if (argc < 1 || argv == NULL) { /* Ensure at least one (empty) argument is seen */ - wchar_t* empty_argv[1] = {L""}; argv = empty_argv; argc = 1; } From webhook-mailer at python.org Fri Aug 23 06:06:31 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Aug 2019 10:06:31 -0000 Subject: [Python-checkins] Correct minor grammar mistake (GH-15404) Message-ID: https://github.com/python/cpython/commit/994925b2cb28d5a77c9bdf056b6fdf99838fd848 commit: 994925b2cb28d5a77c9bdf056b6fdf99838fd848 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-23T03:06:27-07:00 summary: Correct minor grammar mistake (GH-15404) (cherry picked from commit d288b29fc652d27191bde3b3c9145c2eb8169929) Co-authored-by: Andre Delfino files: M Doc/library/json.rst diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 56c16f5d296a..23e39e95f783 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -129,7 +129,7 @@ See :ref:`json-commandline` for detailed documentation. inputs and outputs were typically scrambled unless :class:`collections.OrderedDict` was specifically requested. Starting with Python 3.7, the regular :class:`dict` became order preserving, so - it is no longer necessary specify :class:`collections.OrderedDict` for + it is no longer necessary to specify :class:`collections.OrderedDict` for JSON generation and parsing. From webhook-mailer at python.org Fri Aug 23 06:12:35 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Fri, 23 Aug 2019 10:12:35 -0000 Subject: [Python-checkins] [3.7] bpo-37915: Fix comparison between tzinfo objects and timezone objects (GH-15390) (GH-15417) Message-ID: https://github.com/python/cpython/commit/1b1796df3a4292067a174faa11b1a852f79e98e3 commit: 1b1796df3a4292067a174faa11b1a852f79e98e3 branch: 3.7 author: Pablo Galindo committer: GitHub date: 2019-08-23T11:12:31+01:00 summary: [3.7] bpo-37915: Fix comparison between tzinfo objects and timezone objects (GH-15390) (GH-15417) https://bugs.python.org/issue37915 Automerge-Triggered-By: @pablogsal. (cherry picked from commit 4be11c009abe88175fa164b45e4838e7267dfa97) Co-authored-by: Pablo Galindo files: A Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst M Lib/test/datetimetester.py M Modules/_datetimemodule.c diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 025e71de7872..0c621f0f47c7 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -413,6 +413,11 @@ def test_offset_boundaries(self): with self.assertRaises(ValueError): timezone(delta) + def test_comparison_with_tzinfo(self): + # Constructing tzinfo objects directly should not be done by users + # and serves only to check the bug described in bpo-37915 + self.assertNotEqual(timezone.utc, tzinfo()) + self.assertNotEqual(timezone(timedelta(hours=1)), tzinfo()) ############################################################################# # Base class for testing a particular aspect of timedelta, time, date and diff --git a/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst b/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst new file mode 100644 index 000000000000..1dc9ea4b8cf8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst @@ -0,0 +1,3 @@ +Fix a segmentation fault that appeared when comparing instances of +``datetime.timezone`` and ``datetime.tzinfo`` objects. Patch by Pablo +Galindo. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 655be364d9cb..6bed29ee5cf3 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -20,6 +20,8 @@ #include "datetime.h" #undef Py_BUILD_CORE +#define PyTimezone_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeZoneType) + /*[clinic input] module datetime class datetime.datetime "PyDateTime_DateTime *" "&PyDateTime_DateTimeType" @@ -3648,7 +3650,7 @@ timezone_richcompare(PyDateTime_TimeZone *self, { if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED; - if (!PyTZInfo_Check(other)) { + if (!PyTimezone_Check(other)) { Py_RETURN_NOTIMPLEMENTED; } return delta_richcompare(self->offset, other->offset, op); From webhook-mailer at python.org Fri Aug 23 06:27:28 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 10:27:28 -0000 Subject: [Python-checkins] bpo-37531: Fix regrtest _timedout() function on timeout (GH-15419) Message-ID: https://github.com/python/cpython/commit/767434c39c8f3c6a8af1b3282d8382ccf809fe21 commit: 767434c39c8f3c6a8af1b3282d8382ccf809fe21 branch: master author: Victor Stinner committer: GitHub date: 2019-08-23T11:27:24+01:00 summary: bpo-37531: Fix regrtest _timedout() function on timeout (GH-15419) Fix code handling TimeoutExpired exception in _timedout(). files: M Lib/test/libregrtest/runtest_mp.py diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index c22479b7976f..c5ac6e090376 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -184,14 +184,14 @@ def mp_result_error(self, test_name, error_type, stdout='', stderr='', def _timedout(self, test_name): self._kill() - stdout = sterr = '' + stdout = stderr = '' popen = self._popen try: stdout, stderr = popen.communicate(timeout=JOIN_TIMEOUT) except (subprocess.TimeoutExpired, OSError) as exc: print("WARNING: Failed to read worker process %s output " "(timeout=%.1f sec): %r" - % (popen.pid, exc, timeout), + % (popen.pid, JOIN_TIMEOUT, exc), file=sys.stderr, flush=True) self._close_wait() From webhook-mailer at python.org Fri Aug 23 06:28:31 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 10:28:31 -0000 Subject: [Python-checkins] test_gdb: use unittest test discovery (GH-15405) Message-ID: https://github.com/python/cpython/commit/81446fd0d4fa60042ac2752350f31004324510f9 commit: 81446fd0d4fa60042ac2752350f31004324510f9 branch: master author: Victor Stinner committer: GitHub date: 2019-08-23T11:28:27+01:00 summary: test_gdb: use unittest test discovery (GH-15405) Replace test.support.run_unittest() with unittest.main() to automatically discover test cases, instead of having an maintaing manually a list which may be incomplete. Remove also an unused variable. files: M Lib/test/test_gdb.py diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py index e07d3273a455..a2aa16c62b7d 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 findfile, python_is_optimized def get_gdb_version(): try: @@ -348,7 +348,6 @@ def test_strings(self): def check_repr(text): try: text.encode(encoding) - printable = True except UnicodeEncodeError: self.assertGdbRepr(text, ascii(text)) else: @@ -960,18 +959,13 @@ def test_locals_after_up(self): self.assertMultilineMatches(bt, r".*\na = 1\nb = 2\nc = 3\n.*") -def test_main(): + +def setUpModule(): if support.verbose: print("GDB version %s.%s:" % (gdb_major_version, gdb_minor_version)) for line in gdb_version.splitlines(): print(" " * 4 + line) - run_unittest(PrettyPrintTests, - PyListTests, - StackNavigationTests, - PyBtTests, - PyPrintTests, - PyLocalsTests - ) + if __name__ == "__main__": - test_main() + unittest.main() From webhook-mailer at python.org Fri Aug 23 07:22:21 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 11:22:21 -0000 Subject: [Python-checkins] bpo-37926: Fix PySys_SetArgvEx(0, NULL, 0) crash (GH-15415) (GH-15420) Message-ID: https://github.com/python/cpython/commit/ca9ae94a2aba35d94ac1ec081f9bcac3a13aebd3 commit: ca9ae94a2aba35d94ac1ec081f9bcac3a13aebd3 branch: 3.8 author: Victor Stinner committer: GitHub date: 2019-08-23T12:22:14+01:00 summary: bpo-37926: Fix PySys_SetArgvEx(0, NULL, 0) crash (GH-15415) (GH-15420) empty_argv is no longer static in Python 3.8, but it is declared in a temporary scope, whereas argv keeps a reference to it. empty_argv memory (allocated on the stack) is reused by make_sys_argv() code which is inlined when using gcc -O3. Define empty_argv in PySys_SetArgvEx() body, to ensure that it remains valid for the whole lifetime of the PySys_SetArgvEx() call. (cherry picked from commit c48682509dc49b43fe914fe6c502bc390345d1c2) files: A Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst M Python/sysmodule.c diff --git a/Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst b/Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst new file mode 100644 index 000000000000..20185330a8f4 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst @@ -0,0 +1 @@ +Fix a crash in ``PySys_SetArgvEx(0, NULL, 0)``. diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 6a49d8992324..577b6fbbc752 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -3080,9 +3080,10 @@ make_sys_argv(int argc, wchar_t * const * argv) void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) { + wchar_t* empty_argv[1] = {L""}; + if (argc < 1 || argv == NULL) { /* Ensure at least one (empty) argument is seen */ - wchar_t* empty_argv[1] = {L""}; argv = empty_argv; argc = 1; } From webhook-mailer at python.org Fri Aug 23 08:59:44 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 12:59:44 -0000 Subject: [Python-checkins] test_multiprocessing removes temporary files (GH-15421) Message-ID: https://github.com/python/cpython/commit/3b26f734c0c96d267f23f59b42fcbb193fbf146b commit: 3b26f734c0c96d267f23f59b42fcbb193fbf146b branch: 2.7 author: Victor Stinner committer: GitHub date: 2019-08-23T13:59:40+01:00 summary: test_multiprocessing removes temporary files (GH-15421) (cherry picked from commit d0b10a64351069aa9246d40cb8bd207cc9209cee) files: M Lib/test/test_multiprocessing.py diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py index ff299feed894..c82ccfa7f0bf 100644 --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -1809,6 +1809,7 @@ def test_fd_transfer(self): p = self.Process(target=self._writefd, args=(child_conn, b"foo")) p.daemon = True p.start() + self.addCleanup(support.unlink, support.TESTFN) with open(support.TESTFN, "wb") as f: fd = f.fileno() if msvcrt: @@ -1834,6 +1835,7 @@ def test_large_fd_transfer(self): p = self.Process(target=self._writefd, args=(child_conn, b"bar", True)) p.daemon = True p.start() + self.addCleanup(support.unlink, support.TESTFN) with open(support.TESTFN, "wb") as f: fd = f.fileno() for newfd in range(256, MAXFD): From webhook-mailer at python.org Fri Aug 23 09:00:42 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 13:00:42 -0000 Subject: [Python-checkins] bpo-34521: Fix FD transfer in multiprocessing on FreeBSD (GH-15422) Message-ID: https://github.com/python/cpython/commit/c3642219090f2564c1790330cbf0ba31f19dcaf4 commit: c3642219090f2564c1790330cbf0ba31f19dcaf4 branch: 2.7 author: Victor Stinner committer: GitHub date: 2019-08-23T14:00:38+01:00 summary: bpo-34521: Fix FD transfer in multiprocessing on FreeBSD (GH-15422) Fix file descriptors transfer in multiprocessing on FreeBSD: use CMSG_SPACE() rather than CMSG_LEN(); see RFC 3542. files: A Misc/NEWS.d/next/Library/2019-08-23-14-47-09.bpo-34521.Y2BYu5.rst M Modules/_multiprocessing/multiprocessing.c diff --git a/Misc/NEWS.d/next/Library/2019-08-23-14-47-09.bpo-34521.Y2BYu5.rst b/Misc/NEWS.d/next/Library/2019-08-23-14-47-09.bpo-34521.Y2BYu5.rst new file mode 100644 index 000000000000..06f42a841ea1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-23-14-47-09.bpo-34521.Y2BYu5.rst @@ -0,0 +1,2 @@ +Fix file descriptors transfer in multiprocessing on FreeBSD: use +``CMSG_SPACE()`` rather than ``CMSG_LEN()``; see :rfc:`3542`. diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c index d192a074ba55..eecace887e62 100644 --- a/Modules/_multiprocessing/multiprocessing.c +++ b/Modules/_multiprocessing/multiprocessing.c @@ -167,7 +167,7 @@ multiprocessing_recvfd(PyObject *self, PyObject *args) cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_len = CMSG_SPACE(sizeof(int)); msg.msg_controllen = cmsg->cmsg_len; Py_BEGIN_ALLOW_THREADS From webhook-mailer at python.org Fri Aug 23 10:44:38 2019 From: webhook-mailer at python.org (Stefan Behnel) Date: Fri, 23 Aug 2019 14:44:38 -0000 Subject: [Python-checkins] bpo-14465: Add an indent() function to xml.etree.ElementTree to pretty-print XML trees (GH-15200) Message-ID: https://github.com/python/cpython/commit/b5d3ceea48c181b3e2c6c67424317afed606bd39 commit: b5d3ceea48c181b3e2c6c67424317afed606bd39 branch: master author: Stefan Behnel committer: GitHub date: 2019-08-23T16:44:25+02:00 summary: bpo-14465: Add an indent() function to xml.etree.ElementTree to pretty-print XML trees (GH-15200) files: A Misc/NEWS.d/next/Library/2019-08-10-18-50-04.bpo-14465.qZGC4g.rst M Doc/library/xml.etree.elementtree.rst M Lib/test/test_xml_etree.py M Lib/xml/etree/ElementTree.py diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 9f46755c2685..6047e6e29b92 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -572,6 +572,18 @@ Functions .. versionadded:: 3.2 +.. function:: indent(tree, space=" ", level=0) + + Appends whitespace to the subtree to indent the tree visually. + This can be used to generate pretty-printed XML output. + *tree* can be an Element or ElementTree. *space* is the whitespace + string that will be inserted for each indentation level, two space + characters by default. For indenting partial subtrees inside of an + already indented tree, pass the initial indentation level as *level*. + + .. versionadded:: 3.9 + + .. function:: iselement(element) Checks if an object appears to be a valid element object. *element* is an diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index b2492cda848f..db06aceb1461 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -788,6 +788,123 @@ def test_writestring(self): elem = ET.fromstring("text") self.assertEqual(ET.tostring(elem), b'text') + def test_indent(self): + elem = ET.XML("") + ET.indent(elem) + self.assertEqual(ET.tostring(elem), b'') + + elem = ET.XML("text") + ET.indent(elem) + self.assertEqual(ET.tostring(elem), b'\n text\n') + + elem = ET.XML(" text ") + ET.indent(elem) + self.assertEqual(ET.tostring(elem), b'\n text\n') + + elem = ET.XML("texttail") + ET.indent(elem) + self.assertEqual(ET.tostring(elem), b'\n texttail') + + elem = ET.XML("

par

\n

text

\t


") + ET.indent(elem) + self.assertEqual( + ET.tostring(elem), + b'\n' + b' \n' + b'

par

\n' + b'

text

\n' + b'

\n' + b'
\n' + b'

\n' + b' \n' + b'' + ) + + elem = ET.XML("

pre
post

text

") + ET.indent(elem) + self.assertEqual( + ET.tostring(elem), + b'\n' + b' \n' + b'

pre
post

\n' + b'

text

\n' + b' \n' + b'' + ) + + def test_indent_space(self): + elem = ET.XML("

pre
post

text

") + ET.indent(elem, space='\t') + self.assertEqual( + ET.tostring(elem), + b'\n' + b'\t\n' + b'\t\t

pre
post

\n' + b'\t\t

text

\n' + b'\t\n' + b'' + ) + + elem = ET.XML("

pre
post

text

") + ET.indent(elem, space='') + self.assertEqual( + ET.tostring(elem), + b'\n' + b'\n' + b'

pre
post

\n' + b'

text

\n' + b'\n' + b'' + ) + + def test_indent_space_caching(self): + elem = ET.XML("

par

text


") + ET.indent(elem) + self.assertEqual( + {el.tail for el in elem.iter()}, + {None, "\n", "\n ", "\n "} + ) + self.assertEqual( + {el.text for el in elem.iter()}, + {None, "\n ", "\n ", "\n ", "par", "text"} + ) + self.assertEqual( + len({el.tail for el in elem.iter()}), + len({id(el.tail) for el in elem.iter()}), + ) + + def test_indent_level(self): + elem = ET.XML("

pre
post

text

") + with self.assertRaises(ValueError): + ET.indent(elem, level=-1) + self.assertEqual( + ET.tostring(elem), + b"

pre
post

text

" + ) + + ET.indent(elem, level=2) + self.assertEqual( + ET.tostring(elem), + b'\n' + b' \n' + b'

pre
post

\n' + b'

text

\n' + b' \n' + b' ' + ) + + elem = ET.XML("

pre
post

text

") + ET.indent(elem, level=1, space=' ') + self.assertEqual( + ET.tostring(elem), + b'\n' + b' \n' + b'

pre
post

\n' + b'

text

\n' + b' \n' + b' ' + ) + def test_tostring_default_namespace(self): elem = ET.XML('') self.assertEqual( diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index 645e999a0be6..431ecd0dddf1 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -76,7 +76,7 @@ "dump", "Element", "ElementTree", "fromstring", "fromstringlist", - "iselement", "iterparse", + "indent", "iselement", "iterparse", "parse", "ParseError", "PI", "ProcessingInstruction", "QName", @@ -1185,6 +1185,57 @@ def dump(elem): if not tail or tail[-1] != "\n": sys.stdout.write("\n") + +def indent(tree, space=" ", level=0): + """Indent an XML document by inserting newlines and indentation space + after elements. + + *tree* is the ElementTree or Element to modify. The (root) element + itself will not be changed, but the tail text of all elements in its + subtree will be adapted. + + *space* is the whitespace to insert for each indentation level, two + space characters by default. + + *level* is the initial indentation level. Setting this to a higher + value than 0 can be used for indenting subtrees that are more deeply + nested inside of a document. + """ + if isinstance(tree, ElementTree): + tree = tree.getroot() + if level < 0: + raise ValueError(f"Initial indentation level must be >= 0, got {level}") + if not len(tree): + return + + # Reduce the memory consumption by reusing indentation strings. + indentations = ["\n" + level * space] + + def _indent_children(elem, level): + # Start a new indentation level for the first child. + child_level = level + 1 + try: + child_indentation = indentations[child_level] + except IndexError: + child_indentation = indentations[level] + space + indentations.append(child_indentation) + + if not elem.text or not elem.text.strip(): + elem.text = child_indentation + + for child in elem: + if len(child): + _indent_children(child, child_level) + if not child.tail or not child.tail.strip(): + child.tail = child_indentation + + # Dedent after the last child by overwriting the previous indentation. + if not child.tail.strip(): + child.tail = indentations[level] + + _indent_children(tree, 0) + + # -------------------------------------------------------------------- # parsing diff --git a/Misc/NEWS.d/next/Library/2019-08-10-18-50-04.bpo-14465.qZGC4g.rst b/Misc/NEWS.d/next/Library/2019-08-10-18-50-04.bpo-14465.qZGC4g.rst new file mode 100644 index 000000000000..5f8b7a0934d3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-10-18-50-04.bpo-14465.qZGC4g.rst @@ -0,0 +1,2 @@ +Add an xml.etree.ElementTree.indent() function for pretty-printing XML trees. +Contributed by Stefan Behnel. From webhook-mailer at python.org Fri Aug 23 11:39:13 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 15:39:13 -0000 Subject: [Python-checkins] Fix _PyTime_MIN/MAX values (GH-15384) Message-ID: https://github.com/python/cpython/commit/8e76c456226438f2e4931ce7baf05ac8faae34a1 commit: 8e76c456226438f2e4931ce7baf05ac8faae34a1 branch: master author: Sergey Fedoseev committer: Victor Stinner date: 2019-08-23T16:39:09+01:00 summary: Fix _PyTime_MIN/MAX values (GH-15384) _PyTime_t type is defined as int64_t, and so min/max are INT64_MIN/INT64_MAX, not PY_LLONG_MIN/PY_LLONG_MAX. files: M Include/pytime.h diff --git a/Include/pytime.h b/Include/pytime.h index 4870a9df5b46..bdda1da2e6b8 100644 --- a/Include/pytime.h +++ b/Include/pytime.h @@ -17,8 +17,8 @@ extern "C" { store a duration, and so indirectly a date (related to another date, like UNIX epoch). */ typedef int64_t _PyTime_t; -#define _PyTime_MIN PY_LLONG_MIN -#define _PyTime_MAX PY_LLONG_MAX +#define _PyTime_MIN INT64_MIN +#define _PyTime_MAX INT64_MAX typedef enum { /* Round towards minus infinity (-inf). From webhook-mailer at python.org Fri Aug 23 11:56:55 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Aug 2019 15:56:55 -0000 Subject: [Python-checkins] Fix _PyTime_MIN/MAX values (GH-15384) Message-ID: https://github.com/python/cpython/commit/8fac472436cccaf936732273eeb11649e2d8355d commit: 8fac472436cccaf936732273eeb11649e2d8355d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-23T08:56:51-07:00 summary: Fix _PyTime_MIN/MAX values (GH-15384) _PyTime_t type is defined as int64_t, and so min/max are INT64_MIN/INT64_MAX, not PY_LLONG_MIN/PY_LLONG_MAX. (cherry picked from commit 8e76c456226438f2e4931ce7baf05ac8faae34a1) Co-authored-by: Sergey Fedoseev files: M Include/pytime.h diff --git a/Include/pytime.h b/Include/pytime.h index 4870a9df5b46..bdda1da2e6b8 100644 --- a/Include/pytime.h +++ b/Include/pytime.h @@ -17,8 +17,8 @@ extern "C" { store a duration, and so indirectly a date (related to another date, like UNIX epoch). */ typedef int64_t _PyTime_t; -#define _PyTime_MIN PY_LLONG_MIN -#define _PyTime_MAX PY_LLONG_MAX +#define _PyTime_MIN INT64_MIN +#define _PyTime_MAX INT64_MAX typedef enum { /* Round towards minus infinity (-inf). From webhook-mailer at python.org Fri Aug 23 11:57:58 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 15:57:58 -0000 Subject: [Python-checkins] bpo-36763: Implement PyWideStringList_Insert() of PEP 587 (GH-15423) Message-ID: https://github.com/python/cpython/commit/3842f2997fbd4dc840986aad2bb94656815e243b commit: 3842f2997fbd4dc840986aad2bb94656815e243b branch: master author: Victor Stinner committer: GitHub date: 2019-08-23T16:57:54+01:00 summary: bpo-36763: Implement PyWideStringList_Insert() of PEP 587 (GH-15423) files: M Doc/c-api/init_config.rst M Include/cpython/initconfig.h M Lib/test/test_embed.py M Programs/_testembed.c M Python/initconfig.c diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index d2c1f9a2f3e3..5fd836d77b81 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -72,8 +72,12 @@ PyWideStringList .. c:function:: PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item) - Insert *item* into *list* at *index*. If *index* is greater than *list* - length, just append *item* to *list*. + Insert *item* into *list* at *index*. + + If *index* is greater than or equal to *list* length, append *item* to + *list*. + + *index* must be greater than or equal to 0. Python must be preinitialized to call this function. diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index bd07a4829b47..047f511f3104 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -37,6 +37,9 @@ typedef struct { PyAPI_FUNC(PyStatus) PyWideStringList_Append(PyWideStringList *list, const wchar_t *item); +PyAPI_FUNC(PyStatus) PyWideStringList_Insert(PyWideStringList *list, + Py_ssize_t index, + const wchar_t *item); /* --- PyPreConfig ----------------------------------------------- */ diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 37f542b29540..6fb401200380 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -500,7 +500,7 @@ def _get_expected_config(self, env): self.fail(f"fail to decode stdout: {stdout!r}") def get_expected_config(self, expected_preconfig, expected, env, api, - add_path=None): + modify_path_cb=None): cls = self.__class__ if cls.EXPECTED_CONFIG is None: cls.EXPECTED_CONFIG = self._get_expected_config(env) @@ -556,8 +556,9 @@ def get_expected_config(self, expected_preconfig, expected, env, api, prepend_path = expected['pythonpath_env'] if prepend_path is not None: expected['module_search_paths'] = [prepend_path, *expected['module_search_paths']] - if add_path is not None: - expected['module_search_paths'] = [*expected['module_search_paths'], add_path] + if modify_path_cb is not None: + expected['module_search_paths'] = expected['module_search_paths'].copy() + modify_path_cb(expected['module_search_paths']) for key in self.COPY_PRE_CONFIG: if key not in expected_preconfig: @@ -602,7 +603,7 @@ def check_global_config(self, configs): self.assertEqual(configs['global_config'], expected) def check_all_configs(self, testname, expected_config=None, - expected_preconfig=None, add_path=None, stderr=None, + expected_preconfig=None, modify_path_cb=None, stderr=None, *, api): env = remove_python_envvars() @@ -628,7 +629,7 @@ def check_all_configs(self, testname, expected_config=None, self.get_expected_config(expected_preconfig, expected_config, env, - api, add_path) + api, modify_path_cb) out, err = self.run_embedded_interpreter(testname, env=env) if stderr is None and not expected_config['verbose']: @@ -894,9 +895,12 @@ def test_init_read_set(self): 'program_name': './init_read_set', 'executable': 'my_executable', } + def modify_path(path): + path.insert(1, "test_path_insert1") + path.append("test_path_append") self.check_all_configs("test_init_read_set", config, api=API_PYTHON, - add_path="init_read_set_path") + modify_path_cb=modify_path) def test_init_run_main(self): code = ('import _testinternalcapi, json; ' diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 3d27ed2a4003..38730095dab0 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -1350,8 +1350,14 @@ static int test_init_read_set(void) goto fail; } + status = PyWideStringList_Insert(&config.module_search_paths, + 1, L"test_path_insert1"); + if (PyStatus_Exception(status)) { + goto fail; + } + status = PyWideStringList_Append(&config.module_search_paths, - L"init_read_set_path"); + L"test_path_append"); if (PyStatus_Exception(status)) { goto fail; } diff --git a/Python/initconfig.c b/Python/initconfig.c index 5bd7d4fcf889..b706f4cb8512 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -297,32 +297,53 @@ _PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2) PyStatus -PyWideStringList_Append(PyWideStringList *list, const wchar_t *item) +PyWideStringList_Insert(PyWideStringList *list, + Py_ssize_t index, const wchar_t *item) { - if (list->length == PY_SSIZE_T_MAX) { + Py_ssize_t len = list->length; + if (len == PY_SSIZE_T_MAX) { /* length+1 would overflow */ return _PyStatus_NO_MEMORY(); } + if (index < 0) { + return _PyStatus_ERR("PyWideStringList_Insert index must be >= 0"); + } + if (index > len) { + index = len; + } wchar_t *item2 = _PyMem_RawWcsdup(item); if (item2 == NULL) { return _PyStatus_NO_MEMORY(); } - size_t size = (list->length + 1) * sizeof(list->items[0]); + size_t size = (len + 1) * sizeof(list->items[0]); wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size); if (items2 == NULL) { PyMem_RawFree(item2); return _PyStatus_NO_MEMORY(); } - items2[list->length] = item2; + if (index < len) { + memmove(&items2[index + 1], + &items2[index], + (len - index) * sizeof(items2[0])); + } + + items2[index] = item2; list->items = items2; list->length++; return _PyStatus_OK(); } +PyStatus +PyWideStringList_Append(PyWideStringList *list, const wchar_t *item) +{ + return PyWideStringList_Insert(list, list->length, item); +} + + PyStatus _PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2) { From webhook-mailer at python.org Fri Aug 23 12:17:57 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 16:17:57 -0000 Subject: [Python-checkins] Fix _PyTime_MIN/MAX values (GH-15384) (GH-15426) Message-ID: https://github.com/python/cpython/commit/944aa01a81b17f844b77936d3ed6dd4e2d728841 commit: 944aa01a81b17f844b77936d3ed6dd4e2d728841 branch: 3.8 author: Victor Stinner committer: GitHub date: 2019-08-23T17:17:52+01:00 summary: Fix _PyTime_MIN/MAX values (GH-15384) (GH-15426) _PyTime_t type is defined as int64_t, and so min/max are INT64_MIN/INT64_MAX, not PY_LLONG_MIN/PY_LLONG_MAX. (cherry picked from commit 8e76c456226438f2e4931ce7baf05ac8faae34a1) files: M Include/pytime.h diff --git a/Include/pytime.h b/Include/pytime.h index 4870a9df5b46..bdda1da2e6b8 100644 --- a/Include/pytime.h +++ b/Include/pytime.h @@ -17,8 +17,8 @@ extern "C" { store a duration, and so indirectly a date (related to another date, like UNIX epoch). */ typedef int64_t _PyTime_t; -#define _PyTime_MIN PY_LLONG_MIN -#define _PyTime_MAX PY_LLONG_MAX +#define _PyTime_MIN INT64_MIN +#define _PyTime_MAX INT64_MAX typedef enum { /* Round towards minus infinity (-inf). From webhook-mailer at python.org Fri Aug 23 12:23:48 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Aug 2019 16:23:48 -0000 Subject: [Python-checkins] [3.8] Fix typo (inifite -> infinite) (GH-15429) Message-ID: https://github.com/python/cpython/commit/fe64ba611b587cf6e609679d40f0cdb8b7c93ca0 commit: fe64ba611b587cf6e609679d40f0cdb8b7c93ca0 branch: 3.8 author: GeeTransit committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-23T09:23:43-07:00 summary: [3.8] Fix typo (inifite -> infinite) (GH-15429) The same typo exists in the changelogs of 3.6 and 3.7. Automerge-Triggered-By: @Mariatta files: M Misc/NEWS.d/3.8.0b3.rst diff --git a/Misc/NEWS.d/3.8.0b3.rst b/Misc/NEWS.d/3.8.0b3.rst index 5a35160970ad..5e5225294ad8 100644 --- a/Misc/NEWS.d/3.8.0b3.rst +++ b/Misc/NEWS.d/3.8.0b3.rst @@ -4,7 +4,7 @@ .. release date: 2019-07-29 .. section: Security -Fix an inifite loop when parsing specially crafted email headers. Patch by +Fix an infinite loop when parsing specially crafted email headers. Patch by Abhilash Raj. .. From webhook-mailer at python.org Fri Aug 23 12:24:46 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Aug 2019 16:24:46 -0000 Subject: [Python-checkins] bpo-36763: Implement PyWideStringList_Insert() of PEP 587 (GH-15423) Message-ID: https://github.com/python/cpython/commit/a6427cb2a279c4125dc26d468bcbb3374cdc5f41 commit: a6427cb2a279c4125dc26d468bcbb3374cdc5f41 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-23T09:24:42-07:00 summary: bpo-36763: Implement PyWideStringList_Insert() of PEP 587 (GH-15423) (cherry picked from commit 3842f2997fbd4dc840986aad2bb94656815e243b) Co-authored-by: Victor Stinner files: M Doc/c-api/init_config.rst M Include/cpython/initconfig.h M Lib/test/test_embed.py M Programs/_testembed.c M Python/initconfig.c diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index d2c1f9a2f3e3..5fd836d77b81 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -72,8 +72,12 @@ PyWideStringList .. c:function:: PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item) - Insert *item* into *list* at *index*. If *index* is greater than *list* - length, just append *item* to *list*. + Insert *item* into *list* at *index*. + + If *index* is greater than or equal to *list* length, append *item* to + *list*. + + *index* must be greater than or equal to 0. Python must be preinitialized to call this function. diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index bd07a4829b47..047f511f3104 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -37,6 +37,9 @@ typedef struct { PyAPI_FUNC(PyStatus) PyWideStringList_Append(PyWideStringList *list, const wchar_t *item); +PyAPI_FUNC(PyStatus) PyWideStringList_Insert(PyWideStringList *list, + Py_ssize_t index, + const wchar_t *item); /* --- PyPreConfig ----------------------------------------------- */ diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index f3696c31b603..ef2ef645629e 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -500,7 +500,7 @@ def _get_expected_config(self, env): self.fail(f"fail to decode stdout: {stdout!r}") def get_expected_config(self, expected_preconfig, expected, env, api, - add_path=None): + modify_path_cb=None): cls = self.__class__ if cls.EXPECTED_CONFIG is None: cls.EXPECTED_CONFIG = self._get_expected_config(env) @@ -556,8 +556,9 @@ def get_expected_config(self, expected_preconfig, expected, env, api, prepend_path = expected['pythonpath_env'] if prepend_path is not None: expected['module_search_paths'] = [prepend_path, *expected['module_search_paths']] - if add_path is not None: - expected['module_search_paths'] = [*expected['module_search_paths'], add_path] + if modify_path_cb is not None: + expected['module_search_paths'] = expected['module_search_paths'].copy() + modify_path_cb(expected['module_search_paths']) for key in self.COPY_PRE_CONFIG: if key not in expected_preconfig: @@ -602,7 +603,7 @@ def check_global_config(self, configs): self.assertEqual(configs['global_config'], expected) def check_all_configs(self, testname, expected_config=None, - expected_preconfig=None, add_path=None, stderr=None, + expected_preconfig=None, modify_path_cb=None, stderr=None, *, api): env = remove_python_envvars() @@ -628,7 +629,7 @@ def check_all_configs(self, testname, expected_config=None, self.get_expected_config(expected_preconfig, expected_config, env, - api, add_path) + api, modify_path_cb) out, err = self.run_embedded_interpreter(testname, env=env) if stderr is None and not expected_config['verbose']: @@ -893,9 +894,12 @@ def test_init_read_set(self): 'program_name': './init_read_set', 'executable': 'my_executable', } + def modify_path(path): + path.insert(1, "test_path_insert1") + path.append("test_path_append") self.check_all_configs("test_init_read_set", config, api=API_PYTHON, - add_path="init_read_set_path") + modify_path_cb=modify_path) def test_init_run_main(self): code = ('import _testinternalcapi, json; ' diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 3d27ed2a4003..38730095dab0 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -1350,8 +1350,14 @@ static int test_init_read_set(void) goto fail; } + status = PyWideStringList_Insert(&config.module_search_paths, + 1, L"test_path_insert1"); + if (PyStatus_Exception(status)) { + goto fail; + } + status = PyWideStringList_Append(&config.module_search_paths, - L"init_read_set_path"); + L"test_path_append"); if (PyStatus_Exception(status)) { goto fail; } diff --git a/Python/initconfig.c b/Python/initconfig.c index dd8dd7aeefc6..8a6ad7c34ebf 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -297,32 +297,53 @@ _PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2) PyStatus -PyWideStringList_Append(PyWideStringList *list, const wchar_t *item) +PyWideStringList_Insert(PyWideStringList *list, + Py_ssize_t index, const wchar_t *item) { - if (list->length == PY_SSIZE_T_MAX) { + Py_ssize_t len = list->length; + if (len == PY_SSIZE_T_MAX) { /* length+1 would overflow */ return _PyStatus_NO_MEMORY(); } + if (index < 0) { + return _PyStatus_ERR("PyWideStringList_Insert index must be >= 0"); + } + if (index > len) { + index = len; + } wchar_t *item2 = _PyMem_RawWcsdup(item); if (item2 == NULL) { return _PyStatus_NO_MEMORY(); } - size_t size = (list->length + 1) * sizeof(list->items[0]); + size_t size = (len + 1) * sizeof(list->items[0]); wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size); if (items2 == NULL) { PyMem_RawFree(item2); return _PyStatus_NO_MEMORY(); } - items2[list->length] = item2; + if (index < len) { + memmove(&items2[index + 1], + &items2[index], + (len - index) * sizeof(items2[0])); + } + + items2[index] = item2; list->items = items2; list->length++; return _PyStatus_OK(); } +PyStatus +PyWideStringList_Append(PyWideStringList *list, const wchar_t *item) +{ + return PyWideStringList_Insert(list, list->length, item); +} + + PyStatus _PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2) { From webhook-mailer at python.org Fri Aug 23 12:59:16 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 16:59:16 -0000 Subject: [Python-checkins] bpo-36763, doc: Add links in the new C API init doc (GH-15433) Message-ID: https://github.com/python/cpython/commit/1beb7c3de9c3d0e802e4267a11d937e8f024d661 commit: 1beb7c3de9c3d0e802e4267a11d937e8f024d661 branch: master author: Victor Stinner committer: GitHub date: 2019-08-23T17:59:12+01:00 summary: bpo-36763, doc: Add links in the new C API init doc (GH-15433) files: M Doc/c-api/init.rst M Doc/c-api/init_config.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 4985a1d867e2..e0558f426dce 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -7,6 +7,8 @@ Initialization, Finalization, and Threads ***************************************** +See also :ref:`Python Initialization Configuration `. + .. _pre-init-safe: Before Python Initialization diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 5fd836d77b81..72bd8c37b435 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -48,6 +48,8 @@ The preconfiguration (``PyPreConfig`` type) is stored in ``_PyRuntime.preconfig`` and the configuration (``PyConfig`` type) is stored in ``PyInterpreterState.config``. +See also :ref:`Initialization, Finalization, and Threads `. + .. seealso:: :pep:`587` "Python Initialization Configuration". From webhook-mailer at python.org Fri Aug 23 13:03:12 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 17:03:12 -0000 Subject: [Python-checkins] bpo-36763: PyConfig_Read() handles PySys_AddXOption() (GH-15431) Message-ID: https://github.com/python/cpython/commit/120b707a6d43452e067daa55a8fdca69f9424abc commit: 120b707a6d43452e067daa55a8fdca69f9424abc branch: master author: Victor Stinner committer: GitHub date: 2019-08-23T18:03:08+01:00 summary: bpo-36763: PyConfig_Read() handles PySys_AddXOption() (GH-15431) PyConfig_Read() is now responsible to handle early calls to PySys_AddXOption() and PySys_AddWarnOption(). Options added by PySys_AddXOption() are now handled the same way than PyConfig.xoptions and command line -X options. For example, PySys_AddXOption(L"faulthandler") enables faulthandler as expected. files: A Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst M Include/internal/pycore_pylifecycle.h M Lib/test/test_embed.py M Programs/_testembed.c M Python/initconfig.c M Python/sysmodule.c diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index da4af4732968..bdc4bf5a46d4 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -43,6 +43,8 @@ extern PyStatus _PySys_Create( PyThreadState *tstate, PyObject **sysmod_p); extern PyStatus _PySys_SetPreliminaryStderr(PyObject *sysdict); +extern PyStatus _PySys_ReadPreinitWarnOptions(PyConfig *config); +extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config); extern int _PySys_InitMain( _PyRuntimeState *runtime, PyThreadState *tstate); diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 6fb401200380..2a5ace0bad76 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -902,6 +902,23 @@ def modify_path(path): api=API_PYTHON, modify_path_cb=modify_path) + def test_init_sys_add(self): + config = { + 'faulthandler': 1, + 'xoptions': [ + 'config_xoption', + 'cmdline_xoption', + 'sysadd_xoption', + 'faulthandler', + ], + 'warnoptions': [ + 'ignore:::config_warnoption', + 'ignore:::cmdline_warnoption', + 'ignore:::sysadd_warnoption', + ], + } + self.check_all_configs("test_init_sys_add", config, api=API_PYTHON) + def test_init_run_main(self): code = ('import _testinternalcapi, json; ' 'print(json.dumps(_testinternalcapi.get_configs()))') diff --git a/Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst b/Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst new file mode 100644 index 000000000000..500cdbf34117 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst @@ -0,0 +1,2 @@ +Options added by ``PySys_AddXOption()`` are now handled the same way than +``PyConfig.xoptions`` and command line ``-X`` options. diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 38730095dab0..c3ccc0ec325b 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -1375,6 +1375,54 @@ static int test_init_read_set(void) } +static int test_init_sys_add(void) +{ + PySys_AddXOption(L"sysadd_xoption"); + PySys_AddXOption(L"faulthandler"); + PySys_AddWarnOption(L"ignore:::sysadd_warnoption"); + + PyConfig config; + PyStatus status; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + goto fail; + } + + wchar_t* argv[] = { + L"python3", + L"-W", + L"ignore:::cmdline_warnoption", + L"-X", + L"cmdline_xoption", + }; + config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv); + config.parse_argv = 1; + + status = PyWideStringList_Append(&config.xoptions, + L"config_xoption"); + if (PyStatus_Exception(status)) { + goto fail; + } + + status = PyWideStringList_Append(&config.warnoptions, + L"ignore:::config_warnoption"); + if (PyStatus_Exception(status)) { + goto fail; + } + + config_set_program_name(&config); + init_from_config_clear(&config); + + dump_config(); + Py_Finalize(); + return 0; + +fail: + PyConfig_Clear(&config); + Py_ExitStatusException(status); +} + + static void configure_init_main(PyConfig *config) { wchar_t* argv[] = { @@ -1510,6 +1558,7 @@ static struct TestCase TestCases[] = { {"test_init_read_set", test_init_read_set}, {"test_init_run_main", test_init_run_main}, {"test_init_main", test_init_main}, + {"test_init_sys_add", test_init_sys_add}, {"test_run_main", test_run_main}, {"test_open_code_hook", test_open_code_hook}, {"test_audit", test_audit}, diff --git a/Python/initconfig.c b/Python/initconfig.c index b706f4cb8512..87dea5ee050e 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -2069,6 +2069,7 @@ config_init_warnoptions(PyConfig *config, /* The priority order for warnings configuration is (highest precedence * first): * + * - early PySys_AddWarnOption() calls * - the BytesWarning filter, if needed ('-b', '-bb') * - any '-W' command line options; then * - the 'PYTHONWARNINGS' environment variable; then @@ -2124,6 +2125,13 @@ config_init_warnoptions(PyConfig *config, return status; } } + + /* Handle early PySys_AddWarnOption() calls */ + status = _PySys_ReadPreinitWarnOptions(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); } @@ -2293,7 +2301,8 @@ config_read_cmdline(PyConfig *config) } status = config_init_warnoptions(config, - &cmdline_warnoptions, &env_warnoptions); + &cmdline_warnoptions, + &env_warnoptions); if (_PyStatus_EXCEPTION(status)) { goto done; } @@ -2403,6 +2412,12 @@ PyConfig_Read(PyConfig *config) goto done; } + /* Handle early PySys_AddXOption() calls */ + status = _PySys_ReadPreinitXOptions(config); + if (_PyStatus_EXCEPTION(status)) { + goto done; + } + status = config_read(config); if (_PyStatus_EXCEPTION(status)) { goto done; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 738bbc826f5e..0635e9d834cd 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2037,36 +2037,43 @@ _clear_preinit_entries(_Py_PreInitEntry *optionlist) PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } -static void -_clear_all_preinit_options(void) + +PyStatus +_PySys_ReadPreinitWarnOptions(PyConfig *config) { + PyStatus status; + _Py_PreInitEntry entry; + + for (entry = _preinit_warnoptions; entry != NULL; entry = entry->next) { + status = PyWideStringList_Append(&config->warnoptions, entry->value); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + _clear_preinit_entries(&_preinit_warnoptions); - _clear_preinit_entries(&_preinit_xoptions); + return _PyStatus_OK(); } -static int -sys_read_preinit_options(PyThreadState *tstate) + +PyStatus +_PySys_ReadPreinitXOptions(PyConfig *config) { - /* Rerun the add commands with the actual sys module available */ - if (tstate == NULL) { - /* Still don't have a thread state, so something is wrong! */ - return -1; - } - _Py_PreInitEntry entry = _preinit_warnoptions; - while (entry != NULL) { - PySys_AddWarnOption(entry->value); - entry = entry->next; - } - entry = _preinit_xoptions; - while (entry != NULL) { - PySys_AddXOption(entry->value); - entry = entry->next; + PyStatus status; + _Py_PreInitEntry entry; + + for (entry = _preinit_xoptions; entry != NULL; entry = entry->next) { + status = PyWideStringList_Append(&config->xoptions, entry->value); + if (_PyStatus_EXCEPTION(status)) { + return status; + } } - _clear_all_preinit_options(); - return 0; + _clear_preinit_entries(&_preinit_xoptions); + return _PyStatus_OK(); } + static PyObject * get_warnoptions(PyThreadState *tstate) { @@ -2235,9 +2242,7 @@ PySys_AddXOption(const wchar_t *s) } if (_PySys_AddXOptionWithError(s) < 0) { /* No return value, therefore clear error state if possible */ - if (tstate) { - _PyErr_Clear(tstate); - } + _PyErr_Clear(tstate); } } @@ -2898,11 +2903,6 @@ _PySys_InitMain(_PyRuntimeState *runtime, PyThreadState *tstate) if (get_xoptions(tstate) == NULL) return -1; - /* Transfer any sys.warnoptions and sys._xoptions set directly - * by an embedding application from the linked list to the module. */ - if (sys_read_preinit_options(tstate) != 0) - return -1; - if (_PyErr_Occurred(tstate)) { goto err_occurred; } From webhook-mailer at python.org Fri Aug 23 13:06:03 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Aug 2019 17:06:03 -0000 Subject: [Python-checkins] bpo-36763, doc: Add links in the new C API init doc (GH-15433) Message-ID: https://github.com/python/cpython/commit/9cbdce3917ab41856b61ac5c0f3c4ac0e203f320 commit: 9cbdce3917ab41856b61ac5c0f3c4ac0e203f320 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-23T10:05:59-07:00 summary: bpo-36763, doc: Add links in the new C API init doc (GH-15433) (cherry picked from commit 1beb7c3de9c3d0e802e4267a11d937e8f024d661) Co-authored-by: Victor Stinner files: M Doc/c-api/init.rst M Doc/c-api/init_config.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 4985a1d867e2..e0558f426dce 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -7,6 +7,8 @@ Initialization, Finalization, and Threads ***************************************** +See also :ref:`Python Initialization Configuration `. + .. _pre-init-safe: Before Python Initialization diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 5fd836d77b81..72bd8c37b435 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -48,6 +48,8 @@ The preconfiguration (``PyPreConfig`` type) is stored in ``_PyRuntime.preconfig`` and the configuration (``PyConfig`` type) is stored in ``PyInterpreterState.config``. +See also :ref:`Initialization, Finalization, and Threads `. + .. seealso:: :pep:`587` "Python Initialization Configuration". From webhook-mailer at python.org Fri Aug 23 13:19:20 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 23 Aug 2019 17:19:20 -0000 Subject: [Python-checkins] bpo-26589: Add http status code 451 (GH-15413) Message-ID: https://github.com/python/cpython/commit/8f080b09953a2d862de5c74edf414a54ea3dbea5 commit: 8f080b09953a2d862de5c74edf414a54ea3dbea5 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-23T10:19:15-07:00 summary: bpo-26589: Add http status code 451 (GH-15413) files: A Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst M Doc/library/http.rst M Lib/http/__init__.py M Lib/test/test_httplib.py diff --git a/Doc/library/http.rst b/Doc/library/http.rst index 88d62cca3f90..8df14578de1f 100644 --- a/Doc/library/http.rst +++ b/Doc/library/http.rst @@ -106,6 +106,7 @@ Code Enum Name Details ``428`` ``PRECONDITION_REQUIRED`` Additional HTTP Status Codes :rfc:`6585` ``429`` ``TOO_MANY_REQUESTS`` Additional HTTP Status Codes :rfc:`6585` ``431`` ``REQUEST_HEADER_FIELDS_TOO_LARGE`` Additional HTTP Status Codes :rfc:`6585` +``451`` ``UNAVAILABLE_FOR_LEGAL_REASONS`` An HTTP Status Code to Report Legal Obstacles :rfc:`7725` ``500`` ``INTERNAL_SERVER_ERROR`` HTTP/1.1 :rfc:`7231`, Section 6.6.1 ``501`` ``NOT_IMPLEMENTED`` HTTP/1.1 :rfc:`7231`, Section 6.6.2 ``502`` ``BAD_GATEWAY`` HTTP/1.1 :rfc:`7231`, Section 6.6.3 @@ -126,3 +127,6 @@ equal to the constant name (i.e. ``http.HTTPStatus.OK`` is also available as .. versionchanged:: 3.7 Added ``421 MISDIRECTED_REQUEST`` status code. + +.. versionadded:: 3.8 + Added ``451 UNAVAILABLE_FOR_LEGAL_REASONS`` status code. diff --git a/Lib/http/__init__.py b/Lib/http/__init__.py index e14a1eb074c5..350afe77926b 100644 --- a/Lib/http/__init__.py +++ b/Lib/http/__init__.py @@ -15,6 +15,7 @@ class HTTPStatus(IntEnum): * RFC 7238: Permanent Redirect * RFC 2295: Transparent Content Negotiation in HTTP * RFC 2774: An HTTP Extension Framework + * RFC 7725: An HTTP Status Code to Report Legal Obstacles * RFC 7540: Hypertext Transfer Protocol Version 2 (HTTP/2) """ def __new__(cls, value, phrase, description=''): @@ -114,6 +115,10 @@ def __new__(cls, value, phrase, description=''): 'Request Header Fields Too Large', 'The server is unwilling to process the request because its header ' 'fields are too large') + UNAVAILABLE_FOR_LEGAL_REASONS = (451, + 'Unavailable For Legal Reasons', + 'The server is denying access to the ' + 'resource as a consequence of a legal demand') # server errors INTERNAL_SERVER_ERROR = (500, 'Internal Server Error', diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 656932fbaab7..1121224da443 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -1401,6 +1401,7 @@ def test_client_constants(self): 'PRECONDITION_REQUIRED', 'TOO_MANY_REQUESTS', 'REQUEST_HEADER_FIELDS_TOO_LARGE', + 'UNAVAILABLE_FOR_LEGAL_REASONS', 'INTERNAL_SERVER_ERROR', 'NOT_IMPLEMENTED', 'BAD_GATEWAY', diff --git a/Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst b/Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst new file mode 100644 index 000000000000..ef132dcceb2c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst @@ -0,0 +1,2 @@ +Added a new status code to the http module: 451 +UNAVAILABLE_FOR_LEGAL_REASONS From webhook-mailer at python.org Fri Aug 23 13:56:50 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 23 Aug 2019 17:56:50 -0000 Subject: [Python-checkins] bpo-26589: Add http status code 451 (GH-15413) (GH-15436) Message-ID: https://github.com/python/cpython/commit/761e5a7c7f57cf2a09106c0afa038f04de6a9ed2 commit: 761e5a7c7f57cf2a09106c0afa038f04de6a9ed2 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-23T10:56:44-07:00 summary: bpo-26589: Add http status code 451 (GH-15413) (GH-15436) (cherry picked from commit 8f080b09953a2d862de5c74edf414a54ea3dbea5) Co-authored-by: Raymond Hettinger files: A Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst M Doc/library/http.rst M Lib/http/__init__.py M Lib/test/test_httplib.py diff --git a/Doc/library/http.rst b/Doc/library/http.rst index 88d62cca3f90..8df14578de1f 100644 --- a/Doc/library/http.rst +++ b/Doc/library/http.rst @@ -106,6 +106,7 @@ Code Enum Name Details ``428`` ``PRECONDITION_REQUIRED`` Additional HTTP Status Codes :rfc:`6585` ``429`` ``TOO_MANY_REQUESTS`` Additional HTTP Status Codes :rfc:`6585` ``431`` ``REQUEST_HEADER_FIELDS_TOO_LARGE`` Additional HTTP Status Codes :rfc:`6585` +``451`` ``UNAVAILABLE_FOR_LEGAL_REASONS`` An HTTP Status Code to Report Legal Obstacles :rfc:`7725` ``500`` ``INTERNAL_SERVER_ERROR`` HTTP/1.1 :rfc:`7231`, Section 6.6.1 ``501`` ``NOT_IMPLEMENTED`` HTTP/1.1 :rfc:`7231`, Section 6.6.2 ``502`` ``BAD_GATEWAY`` HTTP/1.1 :rfc:`7231`, Section 6.6.3 @@ -126,3 +127,6 @@ equal to the constant name (i.e. ``http.HTTPStatus.OK`` is also available as .. versionchanged:: 3.7 Added ``421 MISDIRECTED_REQUEST`` status code. + +.. versionadded:: 3.8 + Added ``451 UNAVAILABLE_FOR_LEGAL_REASONS`` status code. diff --git a/Lib/http/__init__.py b/Lib/http/__init__.py index e14a1eb074c5..350afe77926b 100644 --- a/Lib/http/__init__.py +++ b/Lib/http/__init__.py @@ -15,6 +15,7 @@ class HTTPStatus(IntEnum): * RFC 7238: Permanent Redirect * RFC 2295: Transparent Content Negotiation in HTTP * RFC 2774: An HTTP Extension Framework + * RFC 7725: An HTTP Status Code to Report Legal Obstacles * RFC 7540: Hypertext Transfer Protocol Version 2 (HTTP/2) """ def __new__(cls, value, phrase, description=''): @@ -114,6 +115,10 @@ def __new__(cls, value, phrase, description=''): 'Request Header Fields Too Large', 'The server is unwilling to process the request because its header ' 'fields are too large') + UNAVAILABLE_FOR_LEGAL_REASONS = (451, + 'Unavailable For Legal Reasons', + 'The server is denying access to the ' + 'resource as a consequence of a legal demand') # server errors INTERNAL_SERVER_ERROR = (500, 'Internal Server Error', diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 656932fbaab7..1121224da443 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -1401,6 +1401,7 @@ def test_client_constants(self): 'PRECONDITION_REQUIRED', 'TOO_MANY_REQUESTS', 'REQUEST_HEADER_FIELDS_TOO_LARGE', + 'UNAVAILABLE_FOR_LEGAL_REASONS', 'INTERNAL_SERVER_ERROR', 'NOT_IMPLEMENTED', 'BAD_GATEWAY', diff --git a/Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst b/Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst new file mode 100644 index 000000000000..ef132dcceb2c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst @@ -0,0 +1,2 @@ +Added a new status code to the http module: 451 +UNAVAILABLE_FOR_LEGAL_REASONS From webhook-mailer at python.org Fri Aug 23 14:38:45 2019 From: webhook-mailer at python.org (Steve Dower) Date: Fri, 23 Aug 2019 18:38:45 -0000 Subject: [Python-checkins] bpo-37549: os.dup() fails for standard streams on Windows 7 (GH-15389) Message-ID: https://github.com/python/cpython/commit/5be666010e4df65dc4d831435cc92340ea369f94 commit: 5be666010e4df65dc4d831435cc92340ea369f94 branch: master author: Zackery Spytz committer: Steve Dower date: 2019-08-23T11:38:41-07:00 summary: bpo-37549: os.dup() fails for standard streams on Windows 7 (GH-15389) files: A Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst M Lib/test/test_os.py M Python/fileutils.c diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 428593151208..440cd6c1cf73 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3476,6 +3476,11 @@ def test_dup(self): self.addCleanup(os.close, fd2) self.assertEqual(os.get_inheritable(fd2), False) + def test_dup_standard_stream(self): + fd = os.dup(1) + self.addCleanup(os.close, fd) + self.assertGreater(fd, 0) + @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test') def test_dup_nul(self): # os.dup() was creating inheritable fds for character files. diff --git a/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst b/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst new file mode 100644 index 000000000000..5345da80781d --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst @@ -0,0 +1 @@ +:func:`os.dup` no longer fails for standard streams on Windows 7. diff --git a/Python/fileutils.c b/Python/fileutils.c index 36a3c995a98a..0c05424143af 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1134,11 +1134,18 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) flags = HANDLE_FLAG_INHERIT; else flags = 0; - if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) { + + /* This check can be removed once support for Windows 7 ends. */ +#define CONSOLE_PSEUDOHANDLE(handle) (((ULONG_PTR)(handle) & 0x3) == 0x3 && \ + GetFileType(handle) == FILE_TYPE_CHAR) + + if (!CONSOLE_PSEUDOHANDLE(handle) && + !SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) { if (raise) PyErr_SetFromWindowsErr(0); return -1; } +#undef CONSOLE_PSEUDOHANDLE return 0; #else From webhook-mailer at python.org Fri Aug 23 15:01:44 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Aug 2019 19:01:44 -0000 Subject: [Python-checkins] bpo-37549: os.dup() fails for standard streams on Windows 7 (GH-15389) Message-ID: https://github.com/python/cpython/commit/f8dc3e85ab01e1b0345738670dcb3993da7ec436 commit: f8dc3e85ab01e1b0345738670dcb3993da7ec436 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-23T12:01:38-07:00 summary: bpo-37549: os.dup() fails for standard streams on Windows 7 (GH-15389) (cherry picked from commit 5be666010e4df65dc4d831435cc92340ea369f94) Co-authored-by: Zackery Spytz files: A Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst M Lib/test/test_os.py M Python/fileutils.c diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 8032da053067..df4bad7a8cf7 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3237,6 +3237,11 @@ def test_dup(self): self.addCleanup(os.close, fd2) self.assertEqual(os.get_inheritable(fd2), False) + def test_dup_standard_stream(self): + fd = os.dup(1) + self.addCleanup(os.close, fd) + self.assertGreater(fd, 0) + @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test') def test_dup_nul(self): # os.dup() was creating inheritable fds for character files. diff --git a/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst b/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst new file mode 100644 index 000000000000..5345da80781d --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst @@ -0,0 +1 @@ +:func:`os.dup` no longer fails for standard streams on Windows 7. diff --git a/Python/fileutils.c b/Python/fileutils.c index 868fbf910312..b2c634db23bf 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1037,11 +1037,18 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) flags = HANDLE_FLAG_INHERIT; else flags = 0; - if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) { + + /* This check can be removed once support for Windows 7 ends. */ +#define CONSOLE_PSEUDOHANDLE(handle) (((ULONG_PTR)(handle) & 0x3) == 0x3 && \ + GetFileType(handle) == FILE_TYPE_CHAR) + + if (!CONSOLE_PSEUDOHANDLE(handle) && + !SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) { if (raise) PyErr_SetFromWindowsErr(0); return -1; } +#undef CONSOLE_PSEUDOHANDLE return 0; #else From webhook-mailer at python.org Fri Aug 23 15:04:31 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Aug 2019 19:04:31 -0000 Subject: [Python-checkins] bpo-37549: os.dup() fails for standard streams on Windows 7 (GH-15389) Message-ID: https://github.com/python/cpython/commit/3921d12174c1998d9df7a08d036a7fef2d587a64 commit: 3921d12174c1998d9df7a08d036a7fef2d587a64 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-23T12:04:27-07:00 summary: bpo-37549: os.dup() fails for standard streams on Windows 7 (GH-15389) (cherry picked from commit 5be666010e4df65dc4d831435cc92340ea369f94) Co-authored-by: Zackery Spytz files: A Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst M Lib/test/test_os.py M Python/fileutils.c diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 428593151208..440cd6c1cf73 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3476,6 +3476,11 @@ def test_dup(self): self.addCleanup(os.close, fd2) self.assertEqual(os.get_inheritable(fd2), False) + def test_dup_standard_stream(self): + fd = os.dup(1) + self.addCleanup(os.close, fd) + self.assertGreater(fd, 0) + @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test') def test_dup_nul(self): # os.dup() was creating inheritable fds for character files. diff --git a/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst b/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst new file mode 100644 index 000000000000..5345da80781d --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst @@ -0,0 +1 @@ +:func:`os.dup` no longer fails for standard streams on Windows 7. diff --git a/Python/fileutils.c b/Python/fileutils.c index 30ddd037e65a..e79e732d1f55 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1134,11 +1134,18 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) flags = HANDLE_FLAG_INHERIT; else flags = 0; - if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) { + + /* This check can be removed once support for Windows 7 ends. */ +#define CONSOLE_PSEUDOHANDLE(handle) (((ULONG_PTR)(handle) & 0x3) == 0x3 && \ + GetFileType(handle) == FILE_TYPE_CHAR) + + if (!CONSOLE_PSEUDOHANDLE(handle) && + !SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) { if (raise) PyErr_SetFromWindowsErr(0); return -1; } +#undef CONSOLE_PSEUDOHANDLE return 0; #else From webhook-mailer at python.org Fri Aug 23 15:16:55 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 23 Aug 2019 19:16:55 -0000 Subject: [Python-checkins] bpo-36763: PyConfig_Read() handles PySys_AddXOption() (GH-15431) (GH-15435) Message-ID: https://github.com/python/cpython/commit/af84a88ef8b3288da528d2f52b7d3fbafb8dc8a6 commit: af84a88ef8b3288da528d2f52b7d3fbafb8dc8a6 branch: 3.8 author: Victor Stinner committer: GitHub date: 2019-08-23T21:16:51+02:00 summary: bpo-36763: PyConfig_Read() handles PySys_AddXOption() (GH-15431) (GH-15435) PyConfig_Read() is now responsible to handle early calls to PySys_AddXOption() and PySys_AddWarnOption(). Options added by PySys_AddXOption() are now handled the same way than PyConfig.xoptions and command line -X options. For example, PySys_AddXOption(L"faulthandler") enables faulthandler as expected. (cherry picked from commit 120b707a6d43452e067daa55a8fdca69f9424abc) files: A Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst M Include/internal/pycore_pylifecycle.h M Lib/test/test_embed.py M Programs/_testembed.c M Python/initconfig.c M Python/sysmodule.c diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 8a692ea16495..51f05b389e35 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -43,6 +43,8 @@ extern PyStatus _PySys_Create( PyInterpreterState *interp, PyObject **sysmod_p); extern PyStatus _PySys_SetPreliminaryStderr(PyObject *sysdict); +extern PyStatus _PySys_ReadPreinitWarnOptions(PyConfig *config); +extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config); extern int _PySys_InitMain( _PyRuntimeState *runtime, PyInterpreterState *interp); diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index ef2ef645629e..e02acbc6befe 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -901,6 +901,23 @@ def modify_path(path): api=API_PYTHON, modify_path_cb=modify_path) + def test_init_sys_add(self): + config = { + 'faulthandler': 1, + 'xoptions': [ + 'config_xoption', + 'cmdline_xoption', + 'sysadd_xoption', + 'faulthandler', + ], + 'warnoptions': [ + 'ignore:::config_warnoption', + 'ignore:::cmdline_warnoption', + 'ignore:::sysadd_warnoption', + ], + } + self.check_all_configs("test_init_sys_add", config, api=API_PYTHON) + def test_init_run_main(self): code = ('import _testinternalcapi, json; ' 'print(json.dumps(_testinternalcapi.get_configs()))') diff --git a/Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst b/Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst new file mode 100644 index 000000000000..500cdbf34117 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst @@ -0,0 +1,2 @@ +Options added by ``PySys_AddXOption()`` are now handled the same way than +``PyConfig.xoptions`` and command line ``-X`` options. diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 38730095dab0..c3ccc0ec325b 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -1375,6 +1375,54 @@ static int test_init_read_set(void) } +static int test_init_sys_add(void) +{ + PySys_AddXOption(L"sysadd_xoption"); + PySys_AddXOption(L"faulthandler"); + PySys_AddWarnOption(L"ignore:::sysadd_warnoption"); + + PyConfig config; + PyStatus status; + status = PyConfig_InitPythonConfig(&config); + if (PyStatus_Exception(status)) { + goto fail; + } + + wchar_t* argv[] = { + L"python3", + L"-W", + L"ignore:::cmdline_warnoption", + L"-X", + L"cmdline_xoption", + }; + config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv); + config.parse_argv = 1; + + status = PyWideStringList_Append(&config.xoptions, + L"config_xoption"); + if (PyStatus_Exception(status)) { + goto fail; + } + + status = PyWideStringList_Append(&config.warnoptions, + L"ignore:::config_warnoption"); + if (PyStatus_Exception(status)) { + goto fail; + } + + config_set_program_name(&config); + init_from_config_clear(&config); + + dump_config(); + Py_Finalize(); + return 0; + +fail: + PyConfig_Clear(&config); + Py_ExitStatusException(status); +} + + static void configure_init_main(PyConfig *config) { wchar_t* argv[] = { @@ -1510,6 +1558,7 @@ static struct TestCase TestCases[] = { {"test_init_read_set", test_init_read_set}, {"test_init_run_main", test_init_run_main}, {"test_init_main", test_init_main}, + {"test_init_sys_add", test_init_sys_add}, {"test_run_main", test_run_main}, {"test_open_code_hook", test_open_code_hook}, {"test_audit", test_audit}, diff --git a/Python/initconfig.c b/Python/initconfig.c index 8a6ad7c34ebf..a87d8ae74860 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -2069,6 +2069,7 @@ config_init_warnoptions(PyConfig *config, /* The priority order for warnings configuration is (highest precedence * first): * + * - early PySys_AddWarnOption() calls * - the BytesWarning filter, if needed ('-b', '-bb') * - any '-W' command line options; then * - the 'PYTHONWARNINGS' environment variable; then @@ -2124,6 +2125,13 @@ config_init_warnoptions(PyConfig *config, return status; } } + + /* Handle early PySys_AddWarnOption() calls */ + status = _PySys_ReadPreinitWarnOptions(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); } @@ -2246,7 +2254,8 @@ config_read_cmdline(PyConfig *config) } status = config_init_warnoptions(config, - &cmdline_warnoptions, &env_warnoptions); + &cmdline_warnoptions, + &env_warnoptions); if (_PyStatus_EXCEPTION(status)) { goto done; } @@ -2356,6 +2365,12 @@ PyConfig_Read(PyConfig *config) goto done; } + /* Handle early PySys_AddXOption() calls */ + status = _PySys_ReadPreinitXOptions(config); + if (_PyStatus_EXCEPTION(status)) { + goto done; + } + status = config_read(config); if (_PyStatus_EXCEPTION(status)) { goto done; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 577b6fbbc752..93ffce2a4783 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2071,37 +2071,43 @@ _clear_preinit_entries(_Py_PreInitEntry *optionlist) PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } -static void -_clear_all_preinit_options(void) + +PyStatus +_PySys_ReadPreinitWarnOptions(PyConfig *config) { + PyStatus status; + _Py_PreInitEntry entry; + + for (entry = _preinit_warnoptions; entry != NULL; entry = entry->next) { + status = PyWideStringList_Append(&config->warnoptions, entry->value); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + _clear_preinit_entries(&_preinit_warnoptions); - _clear_preinit_entries(&_preinit_xoptions); + return _PyStatus_OK(); } -static int -_PySys_ReadPreInitOptions(void) + +PyStatus +_PySys_ReadPreinitXOptions(PyConfig *config) { - /* Rerun the add commands with the actual sys module available */ - PyThreadState *tstate = _PyThreadState_GET(); - if (tstate == NULL) { - /* Still don't have a thread state, so something is wrong! */ - return -1; - } - _Py_PreInitEntry entry = _preinit_warnoptions; - while (entry != NULL) { - PySys_AddWarnOption(entry->value); - entry = entry->next; - } - entry = _preinit_xoptions; - while (entry != NULL) { - PySys_AddXOption(entry->value); - entry = entry->next; + PyStatus status; + _Py_PreInitEntry entry; + + for (entry = _preinit_xoptions; entry != NULL; entry = entry->next) { + status = PyWideStringList_Append(&config->xoptions, entry->value); + if (_PyStatus_EXCEPTION(status)) { + return status; + } } - _clear_all_preinit_options(); - return 0; + _clear_preinit_entries(&_preinit_xoptions); + return _PyStatus_OK(); } + static PyObject * get_warnoptions(void) { @@ -2265,9 +2271,7 @@ PySys_AddXOption(const wchar_t *s) } if (_PySys_AddXOptionWithError(s) < 0) { /* No return value, therefore clear error state if possible */ - if (_PyThreadState_UncheckedGet()) { - PyErr_Clear(); - } + PyErr_Clear(); } } @@ -2926,13 +2930,9 @@ _PySys_InitMain(_PyRuntimeState *runtime, PyInterpreterState *interp) if (get_xoptions() == NULL) return -1; - /* Transfer any sys.warnoptions and sys._xoptions set directly - * by an embedding application from the linked list to the module. */ - if (_PySys_ReadPreInitOptions() != 0) - return -1; - if (PyErr_Occurred()) return -1; + return 0; err_occurred: From webhook-mailer at python.org Fri Aug 23 18:20:36 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 23 Aug 2019 22:20:36 -0000 Subject: [Python-checkins] bpo-37798: Add C fastpath for statistics.NormalDist.inv_cdf() (GH-15266) Message-ID: https://github.com/python/cpython/commit/0a18ee4be7ba215f414bef04598e0849504f9f1e commit: 0a18ee4be7ba215f414bef04598e0849504f9f1e branch: master author: Dong-hee Na committer: Raymond Hettinger date: 2019-08-23T15:20:30-07:00 summary: bpo-37798: Add C fastpath for statistics.NormalDist.inv_cdf() (GH-15266) files: A Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst A Modules/_statisticsmodule.c A Modules/clinic/_statisticsmodule.c.h M Lib/statistics.py M Modules/Setup M PC/config.c M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M setup.py diff --git a/Lib/statistics.py b/Lib/statistics.py index 77291dd62cb9..c7d6568145e0 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -824,6 +824,81 @@ def pstdev(data, mu=None): ## Normal Distribution ##################################################### + +def _normal_dist_inv_cdf(p, mu, sigma): + # There is no closed-form solution to the inverse CDF for the normal + # distribution, so we use a rational approximation instead: + # Wichura, M.J. (1988). "Algorithm AS241: The Percentage Points of the + # Normal Distribution". Applied Statistics. Blackwell Publishing. 37 + # (3): 477?484. doi:10.2307/2347330. JSTOR 2347330. + q = p - 0.5 + if fabs(q) <= 0.425: + r = 0.180625 - q * q + # Hash sum: 55.88319_28806_14901_4439 + num = (((((((2.50908_09287_30122_6727e+3 * r + + 3.34305_75583_58812_8105e+4) * r + + 6.72657_70927_00870_0853e+4) * r + + 4.59219_53931_54987_1457e+4) * r + + 1.37316_93765_50946_1125e+4) * r + + 1.97159_09503_06551_4427e+3) * r + + 1.33141_66789_17843_7745e+2) * r + + 3.38713_28727_96366_6080e+0) * q + den = (((((((5.22649_52788_52854_5610e+3 * r + + 2.87290_85735_72194_2674e+4) * r + + 3.93078_95800_09271_0610e+4) * r + + 2.12137_94301_58659_5867e+4) * r + + 5.39419_60214_24751_1077e+3) * r + + 6.87187_00749_20579_0830e+2) * r + + 4.23133_30701_60091_1252e+1) * r + + 1.0) + x = num / den + return mu + (x * sigma) + r = p if q <= 0.0 else 1.0 - p + r = sqrt(-log(r)) + if r <= 5.0: + r = r - 1.6 + # Hash sum: 49.33206_50330_16102_89036 + num = (((((((7.74545_01427_83414_07640e-4 * r + + 2.27238_44989_26918_45833e-2) * r + + 2.41780_72517_74506_11770e-1) * r + + 1.27045_82524_52368_38258e+0) * r + + 3.64784_83247_63204_60504e+0) * r + + 5.76949_72214_60691_40550e+0) * r + + 4.63033_78461_56545_29590e+0) * r + + 1.42343_71107_49683_57734e+0) + den = (((((((1.05075_00716_44416_84324e-9 * r + + 5.47593_80849_95344_94600e-4) * r + + 1.51986_66563_61645_71966e-2) * r + + 1.48103_97642_74800_74590e-1) * r + + 6.89767_33498_51000_04550e-1) * r + + 1.67638_48301_83803_84940e+0) * r + + 2.05319_16266_37758_82187e+0) * r + + 1.0) + else: + r = r - 5.0 + # Hash sum: 47.52583_31754_92896_71629 + num = (((((((2.01033_43992_92288_13265e-7 * r + + 2.71155_55687_43487_57815e-5) * r + + 1.24266_09473_88078_43860e-3) * r + + 2.65321_89526_57612_30930e-2) * r + + 2.96560_57182_85048_91230e-1) * r + + 1.78482_65399_17291_33580e+0) * r + + 5.46378_49111_64114_36990e+0) * r + + 6.65790_46435_01103_77720e+0) + den = (((((((2.04426_31033_89939_78564e-15 * r + + 1.42151_17583_16445_88870e-7) * r + + 1.84631_83175_10054_68180e-5) * r + + 7.86869_13114_56132_59100e-4) * r + + 1.48753_61290_85061_48525e-2) * r + + 1.36929_88092_27358_05310e-1) * r + + 5.99832_20655_58879_37690e-1) * r + + 1.0) + x = num / den + if q < 0.0: + x = -x + return mu + (x * sigma) + + class NormalDist: "Normal distribution of a random variable" # https://en.wikipedia.org/wiki/Normal_distribution @@ -882,79 +957,7 @@ def inv_cdf(self, p): raise StatisticsError('p must be in the range 0.0 < p < 1.0') if self._sigma <= 0.0: raise StatisticsError('cdf() not defined when sigma at or below zero') - - # There is no closed-form solution to the inverse CDF for the normal - # distribution, so we use a rational approximation instead: - # Wichura, M.J. (1988). "Algorithm AS241: The Percentage Points of the - # Normal Distribution". Applied Statistics. Blackwell Publishing. 37 - # (3): 477?484. doi:10.2307/2347330. JSTOR 2347330. - - q = p - 0.5 - if fabs(q) <= 0.425: - r = 0.180625 - q * q - # Hash sum: 55.88319_28806_14901_4439 - num = (((((((2.50908_09287_30122_6727e+3 * r + - 3.34305_75583_58812_8105e+4) * r + - 6.72657_70927_00870_0853e+4) * r + - 4.59219_53931_54987_1457e+4) * r + - 1.37316_93765_50946_1125e+4) * r + - 1.97159_09503_06551_4427e+3) * r + - 1.33141_66789_17843_7745e+2) * r + - 3.38713_28727_96366_6080e+0) * q - den = (((((((5.22649_52788_52854_5610e+3 * r + - 2.87290_85735_72194_2674e+4) * r + - 3.93078_95800_09271_0610e+4) * r + - 2.12137_94301_58659_5867e+4) * r + - 5.39419_60214_24751_1077e+3) * r + - 6.87187_00749_20579_0830e+2) * r + - 4.23133_30701_60091_1252e+1) * r + - 1.0) - x = num / den - return self._mu + (x * self._sigma) - r = p if q <= 0.0 else 1.0 - p - r = sqrt(-log(r)) - if r <= 5.0: - r = r - 1.6 - # Hash sum: 49.33206_50330_16102_89036 - num = (((((((7.74545_01427_83414_07640e-4 * r + - 2.27238_44989_26918_45833e-2) * r + - 2.41780_72517_74506_11770e-1) * r + - 1.27045_82524_52368_38258e+0) * r + - 3.64784_83247_63204_60504e+0) * r + - 5.76949_72214_60691_40550e+0) * r + - 4.63033_78461_56545_29590e+0) * r + - 1.42343_71107_49683_57734e+0) - den = (((((((1.05075_00716_44416_84324e-9 * r + - 5.47593_80849_95344_94600e-4) * r + - 1.51986_66563_61645_71966e-2) * r + - 1.48103_97642_74800_74590e-1) * r + - 6.89767_33498_51000_04550e-1) * r + - 1.67638_48301_83803_84940e+0) * r + - 2.05319_16266_37758_82187e+0) * r + - 1.0) - else: - r = r - 5.0 - # Hash sum: 47.52583_31754_92896_71629 - num = (((((((2.01033_43992_92288_13265e-7 * r + - 2.71155_55687_43487_57815e-5) * r + - 1.24266_09473_88078_43860e-3) * r + - 2.65321_89526_57612_30930e-2) * r + - 2.96560_57182_85048_91230e-1) * r + - 1.78482_65399_17291_33580e+0) * r + - 5.46378_49111_64114_36990e+0) * r + - 6.65790_46435_01103_77720e+0) - den = (((((((2.04426_31033_89939_78564e-15 * r + - 1.42151_17583_16445_88870e-7) * r + - 1.84631_83175_10054_68180e-5) * r + - 7.86869_13114_56132_59100e-4) * r + - 1.48753_61290_85061_48525e-2) * r + - 1.36929_88092_27358_05310e-1) * r + - 5.99832_20655_58879_37690e-1) * r + - 1.0) - x = num / den - if q < 0.0: - x = -x - return self._mu + (x * self._sigma) + return _normal_dist_inv_cdf(p, self._mu, self._sigma) def overlap(self, other): """Compute the overlapping coefficient (OVL) between two normal distributions. @@ -1078,6 +1081,12 @@ def __hash__(self): def __repr__(self): return f'{type(self).__name__}(mu={self._mu!r}, sigma={self._sigma!r})' +# If available, use C implementation +try: + from _statistics import _normal_dist_inv_cdf +except ImportError: + pass + if __name__ == '__main__': diff --git a/Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst b/Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst new file mode 100644 index 000000000000..620f0ecdf41a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst @@ -0,0 +1 @@ +Add C fastpath for statistics.NormalDist.inv_cdf() Patch by Dong-hee Na diff --git a/Modules/Setup b/Modules/Setup index ed5ee6c5033b..983fa014ecb2 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -182,6 +182,7 @@ _symtable symtablemodule.c #_heapq _heapqmodule.c # Heap queue algorithm #_asyncio _asynciomodule.c # Fast asyncio Future #_json -I$(srcdir)/Include/internal -DPy_BUILD_CORE_BUILTIN _json.c # _json speedups +#_statistics _statisticsmodule.c # statistics accelerator #unicodedata unicodedata.c # static Unicode character database diff --git a/Modules/_statisticsmodule.c b/Modules/_statisticsmodule.c new file mode 100644 index 000000000000..78ec90a66b0f --- /dev/null +++ b/Modules/_statisticsmodule.c @@ -0,0 +1,122 @@ +/* statistics accelerator C extensor: _statistics module. */ + +#include "Python.h" +#include "structmember.h" +#include "clinic/_statisticsmodule.c.h" + +/*[clinic input] +module _statistics + +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=864a6f59b76123b2]*/ + + +static PyMethodDef speedups_methods[] = { + _STATISTICS__NORMAL_DIST_INV_CDF_METHODDEF + {NULL, NULL, 0, NULL} +}; + +/*[clinic input] +_statistics._normal_dist_inv_cdf -> double + p: double + mu: double + sigma: double + / +[clinic start generated code]*/ + +static double +_statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, + double sigma) +/*[clinic end generated code: output=02fd19ddaab36602 input=24715a74be15296a]*/ +{ + double q, num, den, r, x; + q = p - 0.5; + // Algorithm AS 241: The Percentage Points of the Normal Distribution + if(fabs(q) <= 0.425) { + r = 0.180625 - q * q; + // Hash sum AB: 55.88319 28806 14901 4439 + num = (((((((2.5090809287301226727e+3 * r + + 3.3430575583588128105e+4) * r + + 6.7265770927008700853e+4) * r + + 4.5921953931549871457e+4) * r + + 1.3731693765509461125e+4) * r + + 1.9715909503065514427e+3) * r + + 1.3314166789178437745e+2) * r + + 3.3871328727963666080e+0) * q; + den = (((((((5.2264952788528545610e+3 * r + + 2.8729085735721942674e+4) * r + + 3.9307895800092710610e+4) * r + + 2.1213794301586595867e+4) * r + + 5.3941960214247511077e+3) * r + + 6.8718700749205790830e+2) * r + + 4.2313330701600911252e+1) * r + + 1.0); + x = num / den; + return mu + (x * sigma); + } + r = q <= 0.0? p : 1.0-p; + r = sqrt(-log(r)); + if (r <= 5.0) { + r = r - 1.6; + // Hash sum CD: 49.33206 50330 16102 89036 + num = (((((((7.74545014278341407640e-4 * r + + 2.27238449892691845833e-2) * r + + 2.41780725177450611770e-1) * r + + 1.27045825245236838258e+0) * r + + 3.64784832476320460504e+0) * r + + 5.76949722146069140550e+0) * r + + 4.63033784615654529590e+0) * r + + 1.42343711074968357734e+0); + den = (((((((1.05075007164441684324e-9 * r + + 5.47593808499534494600e-4) * r + + 1.51986665636164571966e-2) * r + + 1.48103976427480074590e-1) * r + + 6.89767334985100004550e-1) * r + + 1.67638483018380384940e+0) * r + + 2.05319162663775882187e+0) * r + + 1.0); + } else { + r -= 5.0; + // Hash sum EF: 47.52583 31754 92896 71629 + num = (((((((2.01033439929228813265e-7 * r + + 2.71155556874348757815e-5) * r + + 1.24266094738807843860e-3) * r + + 2.65321895265761230930e-2) * r + + 2.96560571828504891230e-1) * r + + 1.78482653991729133580e+0) * r + + 5.46378491116411436990e+0) * r + + 6.65790464350110377720e+0); + den = (((((((2.04426310338993978564e-15 * r + + 1.42151175831644588870e-7) * r + + 1.84631831751005468180e-5) * r + + 7.86869131145613259100e-4) * r + + 1.48753612908506148525e-2) * r + + 1.36929880922735805310e-1) * r + + 5.99832206555887937690e-1) * r + + 1.0); + } + x = num / den; + if (q < 0.0) x = -x; + return mu + (x * sigma); +} + +static struct PyModuleDef statisticsmodule = { + PyModuleDef_HEAD_INIT, + "_statistics", + _statistics__normal_dist_inv_cdf__doc__, + -1, + speedups_methods, + NULL, + NULL, + NULL, + NULL +}; + + +PyMODINIT_FUNC +PyInit__statistics(void) +{ + PyObject *m = PyModule_Create(&statisticsmodule); + if (!m) return NULL; + return m; +} diff --git a/Modules/clinic/_statisticsmodule.c.h b/Modules/clinic/_statisticsmodule.c.h new file mode 100644 index 000000000000..f5a2e4678f30 --- /dev/null +++ b/Modules/clinic/_statisticsmodule.c.h @@ -0,0 +1,50 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_statistics__normal_dist_inv_cdf__doc__, +"_normal_dist_inv_cdf($module, p, mu, sigma, /)\n" +"--\n" +"\n"); + +#define _STATISTICS__NORMAL_DIST_INV_CDF_METHODDEF \ + {"_normal_dist_inv_cdf", (PyCFunction)(void(*)(void))_statistics__normal_dist_inv_cdf, METH_FASTCALL, _statistics__normal_dist_inv_cdf__doc__}, + +static double +_statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, + double sigma); + +static PyObject * +_statistics__normal_dist_inv_cdf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + double p; + double mu; + double sigma; + double _return_value; + + if (!_PyArg_CheckPositional("_normal_dist_inv_cdf", nargs, 3, 3)) { + goto exit; + } + p = PyFloat_AsDouble(args[0]); + if (PyErr_Occurred()) { + goto exit; + } + mu = PyFloat_AsDouble(args[1]); + if (PyErr_Occurred()) { + goto exit; + } + sigma = PyFloat_AsDouble(args[2]); + if (PyErr_Occurred()) { + goto exit; + } + _return_value = _statistics__normal_dist_inv_cdf_impl(module, p, mu, sigma); + if ((_return_value == -1.0) && PyErr_Occurred()) { + goto exit; + } + return_value = PyFloat_FromDouble(_return_value); + +exit: + return return_value; +} +/*[clinic end generated code: output=ba6af124acd34732 input=a9049054013a1b77]*/ diff --git a/PC/config.c b/PC/config.c index 6f34962bd72d..8eaeb31c9b93 100644 --- a/PC/config.c +++ b/PC/config.c @@ -23,6 +23,7 @@ extern PyObject* PyInit__sha1(void); extern PyObject* PyInit__sha256(void); extern PyObject* PyInit__sha512(void); extern PyObject* PyInit__sha3(void); +extern PyObject* PyInit__statistics(void); extern PyObject* PyInit__blake2(void); extern PyObject* PyInit_time(void); extern PyObject* PyInit__thread(void); @@ -103,6 +104,7 @@ struct _inittab _PyImport_Inittab[] = { {"_blake2", PyInit__blake2}, {"time", PyInit_time}, {"_thread", PyInit__thread}, + {"_statistics", PyInit__statistics}, #ifdef WIN32 {"msvcrt", PyInit_msvcrt}, {"_locale", PyInit__locale}, diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 4fd2607060ca..1c055b6a3343 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -333,6 +333,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 2d09e9f994bd..dbff89fbff62 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -611,6 +611,9 @@ Modules + + Modules + Modules diff --git a/setup.py b/setup.py index 7cd77257ae35..02f523c42d35 100644 --- a/setup.py +++ b/setup.py @@ -785,6 +785,8 @@ def detect_simple_extensions(self): self.add(Extension("_abc", ["_abc.c"])) # _queue module self.add(Extension("_queue", ["_queuemodule.c"])) + # _statistics module + self.add(Extension("_statistics", ["_statisticsmodule.c"])) # Modules with some UNIX dependencies -- on by default: # (If you have a really backward UNIX, select and socket may not be From webhook-mailer at python.org Fri Aug 23 18:39:31 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 23 Aug 2019 22:39:31 -0000 Subject: [Python-checkins] bpo-37798: Add C fastpath for statistics.NormalDist.inv_cdf() (GH-15266) (GH-15441) Message-ID: https://github.com/python/cpython/commit/5779c536321e1405b4c17654a85b8f9221be765e commit: 5779c536321e1405b4c17654a85b8f9221be765e branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-23T15:39:27-07:00 summary: bpo-37798: Add C fastpath for statistics.NormalDist.inv_cdf() (GH-15266) (GH-15441) (cherry picked from commit 0a18ee4be7ba215f414bef04598e0849504f9f1e) Co-authored-by: Dong-hee Na files: A Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst A Modules/_statisticsmodule.c A Modules/clinic/_statisticsmodule.c.h M Lib/statistics.py M Modules/Setup M PC/config.c M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M setup.py diff --git a/Lib/statistics.py b/Lib/statistics.py index 77291dd62cb9..c7d6568145e0 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -824,6 +824,81 @@ def pstdev(data, mu=None): ## Normal Distribution ##################################################### + +def _normal_dist_inv_cdf(p, mu, sigma): + # There is no closed-form solution to the inverse CDF for the normal + # distribution, so we use a rational approximation instead: + # Wichura, M.J. (1988). "Algorithm AS241: The Percentage Points of the + # Normal Distribution". Applied Statistics. Blackwell Publishing. 37 + # (3): 477?484. doi:10.2307/2347330. JSTOR 2347330. + q = p - 0.5 + if fabs(q) <= 0.425: + r = 0.180625 - q * q + # Hash sum: 55.88319_28806_14901_4439 + num = (((((((2.50908_09287_30122_6727e+3 * r + + 3.34305_75583_58812_8105e+4) * r + + 6.72657_70927_00870_0853e+4) * r + + 4.59219_53931_54987_1457e+4) * r + + 1.37316_93765_50946_1125e+4) * r + + 1.97159_09503_06551_4427e+3) * r + + 1.33141_66789_17843_7745e+2) * r + + 3.38713_28727_96366_6080e+0) * q + den = (((((((5.22649_52788_52854_5610e+3 * r + + 2.87290_85735_72194_2674e+4) * r + + 3.93078_95800_09271_0610e+4) * r + + 2.12137_94301_58659_5867e+4) * r + + 5.39419_60214_24751_1077e+3) * r + + 6.87187_00749_20579_0830e+2) * r + + 4.23133_30701_60091_1252e+1) * r + + 1.0) + x = num / den + return mu + (x * sigma) + r = p if q <= 0.0 else 1.0 - p + r = sqrt(-log(r)) + if r <= 5.0: + r = r - 1.6 + # Hash sum: 49.33206_50330_16102_89036 + num = (((((((7.74545_01427_83414_07640e-4 * r + + 2.27238_44989_26918_45833e-2) * r + + 2.41780_72517_74506_11770e-1) * r + + 1.27045_82524_52368_38258e+0) * r + + 3.64784_83247_63204_60504e+0) * r + + 5.76949_72214_60691_40550e+0) * r + + 4.63033_78461_56545_29590e+0) * r + + 1.42343_71107_49683_57734e+0) + den = (((((((1.05075_00716_44416_84324e-9 * r + + 5.47593_80849_95344_94600e-4) * r + + 1.51986_66563_61645_71966e-2) * r + + 1.48103_97642_74800_74590e-1) * r + + 6.89767_33498_51000_04550e-1) * r + + 1.67638_48301_83803_84940e+0) * r + + 2.05319_16266_37758_82187e+0) * r + + 1.0) + else: + r = r - 5.0 + # Hash sum: 47.52583_31754_92896_71629 + num = (((((((2.01033_43992_92288_13265e-7 * r + + 2.71155_55687_43487_57815e-5) * r + + 1.24266_09473_88078_43860e-3) * r + + 2.65321_89526_57612_30930e-2) * r + + 2.96560_57182_85048_91230e-1) * r + + 1.78482_65399_17291_33580e+0) * r + + 5.46378_49111_64114_36990e+0) * r + + 6.65790_46435_01103_77720e+0) + den = (((((((2.04426_31033_89939_78564e-15 * r + + 1.42151_17583_16445_88870e-7) * r + + 1.84631_83175_10054_68180e-5) * r + + 7.86869_13114_56132_59100e-4) * r + + 1.48753_61290_85061_48525e-2) * r + + 1.36929_88092_27358_05310e-1) * r + + 5.99832_20655_58879_37690e-1) * r + + 1.0) + x = num / den + if q < 0.0: + x = -x + return mu + (x * sigma) + + class NormalDist: "Normal distribution of a random variable" # https://en.wikipedia.org/wiki/Normal_distribution @@ -882,79 +957,7 @@ def inv_cdf(self, p): raise StatisticsError('p must be in the range 0.0 < p < 1.0') if self._sigma <= 0.0: raise StatisticsError('cdf() not defined when sigma at or below zero') - - # There is no closed-form solution to the inverse CDF for the normal - # distribution, so we use a rational approximation instead: - # Wichura, M.J. (1988). "Algorithm AS241: The Percentage Points of the - # Normal Distribution". Applied Statistics. Blackwell Publishing. 37 - # (3): 477?484. doi:10.2307/2347330. JSTOR 2347330. - - q = p - 0.5 - if fabs(q) <= 0.425: - r = 0.180625 - q * q - # Hash sum: 55.88319_28806_14901_4439 - num = (((((((2.50908_09287_30122_6727e+3 * r + - 3.34305_75583_58812_8105e+4) * r + - 6.72657_70927_00870_0853e+4) * r + - 4.59219_53931_54987_1457e+4) * r + - 1.37316_93765_50946_1125e+4) * r + - 1.97159_09503_06551_4427e+3) * r + - 1.33141_66789_17843_7745e+2) * r + - 3.38713_28727_96366_6080e+0) * q - den = (((((((5.22649_52788_52854_5610e+3 * r + - 2.87290_85735_72194_2674e+4) * r + - 3.93078_95800_09271_0610e+4) * r + - 2.12137_94301_58659_5867e+4) * r + - 5.39419_60214_24751_1077e+3) * r + - 6.87187_00749_20579_0830e+2) * r + - 4.23133_30701_60091_1252e+1) * r + - 1.0) - x = num / den - return self._mu + (x * self._sigma) - r = p if q <= 0.0 else 1.0 - p - r = sqrt(-log(r)) - if r <= 5.0: - r = r - 1.6 - # Hash sum: 49.33206_50330_16102_89036 - num = (((((((7.74545_01427_83414_07640e-4 * r + - 2.27238_44989_26918_45833e-2) * r + - 2.41780_72517_74506_11770e-1) * r + - 1.27045_82524_52368_38258e+0) * r + - 3.64784_83247_63204_60504e+0) * r + - 5.76949_72214_60691_40550e+0) * r + - 4.63033_78461_56545_29590e+0) * r + - 1.42343_71107_49683_57734e+0) - den = (((((((1.05075_00716_44416_84324e-9 * r + - 5.47593_80849_95344_94600e-4) * r + - 1.51986_66563_61645_71966e-2) * r + - 1.48103_97642_74800_74590e-1) * r + - 6.89767_33498_51000_04550e-1) * r + - 1.67638_48301_83803_84940e+0) * r + - 2.05319_16266_37758_82187e+0) * r + - 1.0) - else: - r = r - 5.0 - # Hash sum: 47.52583_31754_92896_71629 - num = (((((((2.01033_43992_92288_13265e-7 * r + - 2.71155_55687_43487_57815e-5) * r + - 1.24266_09473_88078_43860e-3) * r + - 2.65321_89526_57612_30930e-2) * r + - 2.96560_57182_85048_91230e-1) * r + - 1.78482_65399_17291_33580e+0) * r + - 5.46378_49111_64114_36990e+0) * r + - 6.65790_46435_01103_77720e+0) - den = (((((((2.04426_31033_89939_78564e-15 * r + - 1.42151_17583_16445_88870e-7) * r + - 1.84631_83175_10054_68180e-5) * r + - 7.86869_13114_56132_59100e-4) * r + - 1.48753_61290_85061_48525e-2) * r + - 1.36929_88092_27358_05310e-1) * r + - 5.99832_20655_58879_37690e-1) * r + - 1.0) - x = num / den - if q < 0.0: - x = -x - return self._mu + (x * self._sigma) + return _normal_dist_inv_cdf(p, self._mu, self._sigma) def overlap(self, other): """Compute the overlapping coefficient (OVL) between two normal distributions. @@ -1078,6 +1081,12 @@ def __hash__(self): def __repr__(self): return f'{type(self).__name__}(mu={self._mu!r}, sigma={self._sigma!r})' +# If available, use C implementation +try: + from _statistics import _normal_dist_inv_cdf +except ImportError: + pass + if __name__ == '__main__': diff --git a/Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst b/Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst new file mode 100644 index 000000000000..620f0ecdf41a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst @@ -0,0 +1 @@ +Add C fastpath for statistics.NormalDist.inv_cdf() Patch by Dong-hee Na diff --git a/Modules/Setup b/Modules/Setup index ed5ee6c5033b..983fa014ecb2 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -182,6 +182,7 @@ _symtable symtablemodule.c #_heapq _heapqmodule.c # Heap queue algorithm #_asyncio _asynciomodule.c # Fast asyncio Future #_json -I$(srcdir)/Include/internal -DPy_BUILD_CORE_BUILTIN _json.c # _json speedups +#_statistics _statisticsmodule.c # statistics accelerator #unicodedata unicodedata.c # static Unicode character database diff --git a/Modules/_statisticsmodule.c b/Modules/_statisticsmodule.c new file mode 100644 index 000000000000..78ec90a66b0f --- /dev/null +++ b/Modules/_statisticsmodule.c @@ -0,0 +1,122 @@ +/* statistics accelerator C extensor: _statistics module. */ + +#include "Python.h" +#include "structmember.h" +#include "clinic/_statisticsmodule.c.h" + +/*[clinic input] +module _statistics + +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=864a6f59b76123b2]*/ + + +static PyMethodDef speedups_methods[] = { + _STATISTICS__NORMAL_DIST_INV_CDF_METHODDEF + {NULL, NULL, 0, NULL} +}; + +/*[clinic input] +_statistics._normal_dist_inv_cdf -> double + p: double + mu: double + sigma: double + / +[clinic start generated code]*/ + +static double +_statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, + double sigma) +/*[clinic end generated code: output=02fd19ddaab36602 input=24715a74be15296a]*/ +{ + double q, num, den, r, x; + q = p - 0.5; + // Algorithm AS 241: The Percentage Points of the Normal Distribution + if(fabs(q) <= 0.425) { + r = 0.180625 - q * q; + // Hash sum AB: 55.88319 28806 14901 4439 + num = (((((((2.5090809287301226727e+3 * r + + 3.3430575583588128105e+4) * r + + 6.7265770927008700853e+4) * r + + 4.5921953931549871457e+4) * r + + 1.3731693765509461125e+4) * r + + 1.9715909503065514427e+3) * r + + 1.3314166789178437745e+2) * r + + 3.3871328727963666080e+0) * q; + den = (((((((5.2264952788528545610e+3 * r + + 2.8729085735721942674e+4) * r + + 3.9307895800092710610e+4) * r + + 2.1213794301586595867e+4) * r + + 5.3941960214247511077e+3) * r + + 6.8718700749205790830e+2) * r + + 4.2313330701600911252e+1) * r + + 1.0); + x = num / den; + return mu + (x * sigma); + } + r = q <= 0.0? p : 1.0-p; + r = sqrt(-log(r)); + if (r <= 5.0) { + r = r - 1.6; + // Hash sum CD: 49.33206 50330 16102 89036 + num = (((((((7.74545014278341407640e-4 * r + + 2.27238449892691845833e-2) * r + + 2.41780725177450611770e-1) * r + + 1.27045825245236838258e+0) * r + + 3.64784832476320460504e+0) * r + + 5.76949722146069140550e+0) * r + + 4.63033784615654529590e+0) * r + + 1.42343711074968357734e+0); + den = (((((((1.05075007164441684324e-9 * r + + 5.47593808499534494600e-4) * r + + 1.51986665636164571966e-2) * r + + 1.48103976427480074590e-1) * r + + 6.89767334985100004550e-1) * r + + 1.67638483018380384940e+0) * r + + 2.05319162663775882187e+0) * r + + 1.0); + } else { + r -= 5.0; + // Hash sum EF: 47.52583 31754 92896 71629 + num = (((((((2.01033439929228813265e-7 * r + + 2.71155556874348757815e-5) * r + + 1.24266094738807843860e-3) * r + + 2.65321895265761230930e-2) * r + + 2.96560571828504891230e-1) * r + + 1.78482653991729133580e+0) * r + + 5.46378491116411436990e+0) * r + + 6.65790464350110377720e+0); + den = (((((((2.04426310338993978564e-15 * r + + 1.42151175831644588870e-7) * r + + 1.84631831751005468180e-5) * r + + 7.86869131145613259100e-4) * r + + 1.48753612908506148525e-2) * r + + 1.36929880922735805310e-1) * r + + 5.99832206555887937690e-1) * r + + 1.0); + } + x = num / den; + if (q < 0.0) x = -x; + return mu + (x * sigma); +} + +static struct PyModuleDef statisticsmodule = { + PyModuleDef_HEAD_INIT, + "_statistics", + _statistics__normal_dist_inv_cdf__doc__, + -1, + speedups_methods, + NULL, + NULL, + NULL, + NULL +}; + + +PyMODINIT_FUNC +PyInit__statistics(void) +{ + PyObject *m = PyModule_Create(&statisticsmodule); + if (!m) return NULL; + return m; +} diff --git a/Modules/clinic/_statisticsmodule.c.h b/Modules/clinic/_statisticsmodule.c.h new file mode 100644 index 000000000000..f5a2e4678f30 --- /dev/null +++ b/Modules/clinic/_statisticsmodule.c.h @@ -0,0 +1,50 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_statistics__normal_dist_inv_cdf__doc__, +"_normal_dist_inv_cdf($module, p, mu, sigma, /)\n" +"--\n" +"\n"); + +#define _STATISTICS__NORMAL_DIST_INV_CDF_METHODDEF \ + {"_normal_dist_inv_cdf", (PyCFunction)(void(*)(void))_statistics__normal_dist_inv_cdf, METH_FASTCALL, _statistics__normal_dist_inv_cdf__doc__}, + +static double +_statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, + double sigma); + +static PyObject * +_statistics__normal_dist_inv_cdf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + double p; + double mu; + double sigma; + double _return_value; + + if (!_PyArg_CheckPositional("_normal_dist_inv_cdf", nargs, 3, 3)) { + goto exit; + } + p = PyFloat_AsDouble(args[0]); + if (PyErr_Occurred()) { + goto exit; + } + mu = PyFloat_AsDouble(args[1]); + if (PyErr_Occurred()) { + goto exit; + } + sigma = PyFloat_AsDouble(args[2]); + if (PyErr_Occurred()) { + goto exit; + } + _return_value = _statistics__normal_dist_inv_cdf_impl(module, p, mu, sigma); + if ((_return_value == -1.0) && PyErr_Occurred()) { + goto exit; + } + return_value = PyFloat_FromDouble(_return_value); + +exit: + return return_value; +} +/*[clinic end generated code: output=ba6af124acd34732 input=a9049054013a1b77]*/ diff --git a/PC/config.c b/PC/config.c index 6f34962bd72d..8eaeb31c9b93 100644 --- a/PC/config.c +++ b/PC/config.c @@ -23,6 +23,7 @@ extern PyObject* PyInit__sha1(void); extern PyObject* PyInit__sha256(void); extern PyObject* PyInit__sha512(void); extern PyObject* PyInit__sha3(void); +extern PyObject* PyInit__statistics(void); extern PyObject* PyInit__blake2(void); extern PyObject* PyInit_time(void); extern PyObject* PyInit__thread(void); @@ -103,6 +104,7 @@ struct _inittab _PyImport_Inittab[] = { {"_blake2", PyInit__blake2}, {"time", PyInit_time}, {"_thread", PyInit__thread}, + {"_statistics", PyInit__statistics}, #ifdef WIN32 {"msvcrt", PyInit_msvcrt}, {"_locale", PyInit__locale}, diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 09a63c04eab8..13c3b594e443 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -331,6 +331,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 63ab88b4a01d..ebab11930183 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -605,6 +605,9 @@ Modules + + Modules + Modules diff --git a/setup.py b/setup.py index 6cbbec9e1212..be2ac0b01d00 100644 --- a/setup.py +++ b/setup.py @@ -784,6 +784,8 @@ def detect_simple_extensions(self): self.add(Extension("_abc", ["_abc.c"])) # _queue module self.add(Extension("_queue", ["_queuemodule.c"])) + # _statistics module + self.add(Extension("_statistics", ["_statisticsmodule.c"])) # Modules with some UNIX dependencies -- on by default: # (If you have a really backward UNIX, select and socket may not be From webhook-mailer at python.org Sat Aug 24 00:09:50 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Aug 2019 04:09:50 -0000 Subject: [Python-checkins] Fix funny typo in Doc/bugs. (GH-15412) Message-ID: https://github.com/python/cpython/commit/e17f201cd9293f16593cc507d86f2c0e17b8f2c9 commit: e17f201cd9293f16593cc507d86f2c0e17b8f2c9 branch: master author: Antoine <43954001+awecx at users.noreply.github.com> committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-23T21:09:43-07:00 summary: Fix funny typo in Doc/bugs. (GH-15412) Fix typo in description of link to mozilla bug report writing guidelines. Though the URL is misleading, we're indeed trying to write bug _reports_, not to add bugs. Automerge-Triggered-By: @ned-deily files: M Doc/bugs.rst diff --git a/Doc/bugs.rst b/Doc/bugs.rst index 1e044ad2033d..a17f04d26fa4 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -80,7 +80,7 @@ taken on the bug. Article which goes into some detail about how to create a useful bug report. This describes what kind of information is useful and why it is useful. - `Bug Writing Guidelines `_ + `Bug Report Writing Guidelines `_ Information about writing a good bug report. Some of this is specific to the Mozilla project, but describes general good practices. From webhook-mailer at python.org Sat Aug 24 00:16:01 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Aug 2019 04:16:01 -0000 Subject: [Python-checkins] Fix funny typo in Doc/bugs. (GH-15412) Message-ID: https://github.com/python/cpython/commit/8f2606ba7573937dff3fb199819b665db2158c59 commit: 8f2606ba7573937dff3fb199819b665db2158c59 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-23T21:15:56-07:00 summary: Fix funny typo in Doc/bugs. (GH-15412) Fix typo in description of link to mozilla bug report writing guidelines. Though the URL is misleading, we're indeed trying to write bug _reports_, not to add bugs. Automerge-Triggered-By: @ned-deily (cherry picked from commit e17f201cd9293f16593cc507d86f2c0e17b8f2c9) Co-authored-by: Antoine <43954001+awecx at users.noreply.github.com> files: M Doc/bugs.rst diff --git a/Doc/bugs.rst b/Doc/bugs.rst index c449ba2e7192..1dbfadbf6e0b 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -72,7 +72,7 @@ taken on the bug. Article which goes into some detail about how to create a useful bug report. This describes what kind of information is useful and why it is useful. - `Bug Writing Guidelines `_ + `Bug Report Writing Guidelines `_ Information about writing a good bug report. Some of this is specific to the Mozilla project, but describes general good practices. From webhook-mailer at python.org Sat Aug 24 00:16:32 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Aug 2019 04:16:32 -0000 Subject: [Python-checkins] Fix funny typo in Doc/bugs. (GH-15412) Message-ID: https://github.com/python/cpython/commit/7784d4bb155f0f527301b29f29b5469ba8a7b5d4 commit: 7784d4bb155f0f527301b29f29b5469ba8a7b5d4 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-23T21:16:28-07:00 summary: Fix funny typo in Doc/bugs. (GH-15412) Fix typo in description of link to mozilla bug report writing guidelines. Though the URL is misleading, we're indeed trying to write bug _reports_, not to add bugs. Automerge-Triggered-By: @ned-deily (cherry picked from commit e17f201cd9293f16593cc507d86f2c0e17b8f2c9) Co-authored-by: Antoine <43954001+awecx at users.noreply.github.com> files: M Doc/bugs.rst diff --git a/Doc/bugs.rst b/Doc/bugs.rst index 1e044ad2033d..a17f04d26fa4 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -80,7 +80,7 @@ taken on the bug. Article which goes into some detail about how to create a useful bug report. This describes what kind of information is useful and why it is useful. - `Bug Writing Guidelines `_ + `Bug Report Writing Guidelines `_ Information about writing a good bug report. Some of this is specific to the Mozilla project, but describes general good practices. From webhook-mailer at python.org Sat Aug 24 00:30:29 2019 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 24 Aug 2019 04:30:29 -0000 Subject: [Python-checkins] [3.7] bpo-37461: Fix typo (inifite -> infinite) (GH-15430) Message-ID: https://github.com/python/cpython/commit/799e4e527019d9429fdef12d08a0c03b08a1fb59 commit: 799e4e527019d9429fdef12d08a0c03b08a1fb59 branch: 3.7 author: GeeTransit committer: Ned Deily date: 2019-08-24T00:30:25-04:00 summary: [3.7] bpo-37461: Fix typo (inifite -> infinite) (GH-15430) files: M Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst diff --git a/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst b/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst index 4bfd350c0b40..9d47578c6277 100644 --- a/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst +++ b/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst @@ -1,2 +1,2 @@ -Fix an inifite loop when parsing specially crafted email headers. Patch by +Fix an infinite loop when parsing specially crafted email headers. Patch by Abhilash Raj. From webhook-mailer at python.org Sat Aug 24 00:33:40 2019 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 24 Aug 2019 04:33:40 -0000 Subject: [Python-checkins] [3.6] bpo-37461: Fix typo (inifite -> infinite) (#15432) Message-ID: https://github.com/python/cpython/commit/f1f9c0c532089824791cfc18e6d6f29e1cd62596 commit: f1f9c0c532089824791cfc18e6d6f29e1cd62596 branch: 3.6 author: GeeTransit committer: Ned Deily date: 2019-08-24T00:33:36-04:00 summary: [3.6] bpo-37461: Fix typo (inifite -> infinite) (#15432) files: M Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst diff --git a/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst b/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst index 4bfd350c0b40..9d47578c6277 100644 --- a/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst +++ b/Misc/NEWS.d/next/Security/2019-07-16-08-11-00.bpo-37461.1Ahz7O.rst @@ -1,2 +1,2 @@ -Fix an inifite loop when parsing specially crafted email headers. Patch by +Fix an infinite loop when parsing specially crafted email headers. Patch by Abhilash Raj. From webhook-mailer at python.org Sat Aug 24 01:12:11 2019 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 24 Aug 2019 05:12:11 -0000 Subject: [Python-checkins] Fix link to changelog in 3.9 What's New page (GH-15445) Message-ID: https://github.com/python/cpython/commit/7913cbc09d1920343a9c5aeec24cb72e9c9402e5 commit: 7913cbc09d1920343a9c5aeec24cb72e9c9402e5 branch: master author: Ned Deily committer: GitHub date: 2019-08-24T01:12:05-04:00 summary: Fix link to changelog in 3.9 What's New page (GH-15445) files: M Doc/whatsnew/3.9.rst diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 05a17a5c7390..10217f194eb0 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -47,7 +47,7 @@ This article explains the new features in Python 3.9, compared to 3.8. -For full details, see the :source:`Misc/NEWS` file. +For full details, see the :ref:`changelog `. .. note:: From webhook-mailer at python.org Sat Aug 24 01:31:26 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 24 Aug 2019 05:31:26 -0000 Subject: [Python-checkins] bpo-19119: Remove invalid test and rename a misnamed test (GH-15442) Message-ID: https://github.com/python/cpython/commit/4101181fd87c2fab6456663d3c8cc99377cf0463 commit: 4101181fd87c2fab6456663d3c8cc99377cf0463 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-23T22:31:22-07:00 summary: bpo-19119: Remove invalid test and rename a misnamed test (GH-15442) files: M Lib/test/test_heapq.py diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py index 6c20b6297dfc..861ba7540df2 100644 --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -280,11 +280,6 @@ class LenOnly: def __len__(self): return 10 -class GetOnly: - "Dummy sequence class defining __getitem__ but not __len__." - def __getitem__(self, ndx): - return 10 - class CmpErr: "Dummy element that always raises an error during comparison" def __eq__(self, other): @@ -396,15 +391,7 @@ def test_len_only(self): for f in (self.module.nlargest, self.module.nsmallest): self.assertRaises(TypeError, f, 2, LenOnly()) - def test_get_only(self): - for f in (self.module.heapify, self.module.heappop): - self.assertRaises(TypeError, f, GetOnly()) - for f in (self.module.heappush, self.module.heapreplace): - self.assertRaises(TypeError, f, GetOnly(), 10) - for f in (self.module.nlargest, self.module.nsmallest): - self.assertRaises(TypeError, f, 2, GetOnly()) - - def test_get_only(self): + def test_cmp_err(self): seq = [CmpErr(), CmpErr(), CmpErr()] for f in (self.module.heapify, self.module.heappop): self.assertRaises(ZeroDivisionError, f, seq) From webhook-mailer at python.org Sat Aug 24 01:54:11 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 24 Aug 2019 05:54:11 -0000 Subject: [Python-checkins] bpo-19119: Remove invalid test and rename a misnamed test (GH-15442) (GH-15447) Message-ID: https://github.com/python/cpython/commit/ef3ccd737020a0bb49ea0bfe48069f89bb5370a1 commit: ef3ccd737020a0bb49ea0bfe48069f89bb5370a1 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-23T22:54:07-07:00 summary: bpo-19119: Remove invalid test and rename a misnamed test (GH-15442) (GH-15447) (cherry picked from commit 4101181fd87c2fab6456663d3c8cc99377cf0463) Co-authored-by: Raymond Hettinger files: M Lib/test/test_heapq.py diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py index 6c20b6297dfc..861ba7540df2 100644 --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -280,11 +280,6 @@ class LenOnly: def __len__(self): return 10 -class GetOnly: - "Dummy sequence class defining __getitem__ but not __len__." - def __getitem__(self, ndx): - return 10 - class CmpErr: "Dummy element that always raises an error during comparison" def __eq__(self, other): @@ -396,15 +391,7 @@ def test_len_only(self): for f in (self.module.nlargest, self.module.nsmallest): self.assertRaises(TypeError, f, 2, LenOnly()) - def test_get_only(self): - for f in (self.module.heapify, self.module.heappop): - self.assertRaises(TypeError, f, GetOnly()) - for f in (self.module.heappush, self.module.heapreplace): - self.assertRaises(TypeError, f, GetOnly(), 10) - for f in (self.module.nlargest, self.module.nsmallest): - self.assertRaises(TypeError, f, 2, GetOnly()) - - def test_get_only(self): + def test_cmp_err(self): seq = [CmpErr(), CmpErr(), CmpErr()] for f in (self.module.heapify, self.module.heappop): self.assertRaises(ZeroDivisionError, f, seq) From webhook-mailer at python.org Sat Aug 24 05:49:31 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 24 Aug 2019 09:49:31 -0000 Subject: [Python-checkins] bpo-29535: Remove promize about hash randomization of datetime objects. (GH-15269) Message-ID: https://github.com/python/cpython/commit/e9c90aa43144b0be1e4e393e8cb549573437a5da commit: e9c90aa43144b0be1e4e393e8cb549573437a5da branch: master author: Serhiy Storchaka committer: GitHub date: 2019-08-24T12:49:27+03:00 summary: bpo-29535: Remove promize about hash randomization of datetime objects. (GH-15269) files: M Doc/reference/datamodel.rst M Doc/using/cmdline.rst M Misc/python.man M Python/initconfig.c diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index fa47bf1c1619..1dd8e42ef87e 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1445,8 +1445,8 @@ Basic customization .. note:: - By default, the :meth:`__hash__` values of str, bytes and datetime - objects are "salted" with an unpredictable random value. Although they + By default, the :meth:`__hash__` values of str and bytes objects are + "salted" with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python. diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 22f42d966a55..d04c3b61dd5b 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -302,7 +302,7 @@ Miscellaneous options randomization is enabled by default. On previous versions of Python, this option turns on hash randomization, - so that the :meth:`__hash__` values of str, bytes and datetime + so that the :meth:`__hash__` values of str and bytes objects are "salted" with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python. @@ -625,7 +625,7 @@ conflict. .. envvar:: PYTHONHASHSEED If this variable is not set or set to ``random``, a random value is used - to seed the hashes of str, bytes and datetime objects. + to seed the hashes of str and bytes objects. If :envvar:`PYTHONHASHSEED` is set to an integer value, it is used as a fixed seed for generating the hash() of the types covered by the hash diff --git a/Misc/python.man b/Misc/python.man index 8d5ad8cd6ca8..3aa9f1f9c7ea 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -431,7 +431,7 @@ If this is set to a comma-separated string it is equivalent to specifying the \fB\-W\fP option for each separate value. .IP PYTHONHASHSEED If this variable is set to "random", a random value is used to seed the hashes -of str, bytes and datetime objects. +of str and bytes objects. If PYTHONHASHSEED is set to an integer value, it is used as a fixed seed for generating the hash() of the types covered by the hash randomization. Its diff --git a/Python/initconfig.c b/Python/initconfig.c index 87dea5ee050e..e67fea7b109c 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -83,8 +83,8 @@ static const char usage_5[] = "PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.\n"; static const char usage_6[] = "PYTHONHASHSEED: if this variable is set to 'random', a random value is used\n" -" to seed the hashes of str, bytes and datetime objects. It can also be\n" -" set to an integer in the range [0,4294967295] to get hash values with a\n" +" to seed the hashes of str and bytes objects. It can also be set to an\n" +" integer in the range [0,4294967295] to get hash values with a\n" " predictable seed.\n" "PYTHONMALLOC: set the Python memory allocators and/or install debug hooks\n" " on Python memory allocators. Use PYTHONMALLOC=debug to install debug\n" From webhook-mailer at python.org Sat Aug 24 06:11:56 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 24 Aug 2019 10:11:56 -0000 Subject: [Python-checkins] bpo-37830: Fix compilation of break and continue in finally. (GH-15320) Message-ID: https://github.com/python/cpython/commit/ef61c524ddeeb56da3858b86e349e7288d68178e commit: ef61c524ddeeb56da3858b86e349e7288d68178e branch: master author: Serhiy Storchaka committer: GitHub date: 2019-08-24T13:11:52+03:00 summary: bpo-37830: Fix compilation of break and continue in finally. (GH-15320) Fix compilation of "break" and "continue" in the "finally" block when the corresponding "try" block contains "return" with a non-constant value. files: A Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830.fNfMbz.rst M Lib/importlib/_bootstrap_external.py M Lib/test/test_dis.py M Lib/test/test_grammar.py M Lib/test/test_importlib/test_util.py M Objects/frameobject.c M PC/launcher.c M Python/compile.c M Python/importlib.h M Python/importlib_external.h M Python/importlib_zipimport.h diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index badd7a74cb90..67bd1d3cf99e 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -270,6 +270,7 @@ def _write_atomic(path, data, mode=0o666): # comprehensions #35224) # Python 3.8b2 3412 (Swap the position of positional args and positional # only args in ast.arguments #37593) +# Python 3.8b4 3413 (Fix "break" and "continue" in "finally" #37830) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually @@ -278,7 +279,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 = (3412).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3413).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/test/test_dis.py b/Lib/test/test_dis.py index 652af45d55ad..03b286016632 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -980,7 +980,7 @@ def jumpy(): Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=174, argrepr='to 174', offset=102, starts_line=20, is_jump_target=True), Instruction(opname='SETUP_FINALLY', opcode=122, arg=12, argval=118, argrepr='to 118', offset=104, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False), Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False), Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False), @@ -993,7 +993,7 @@ def jumpy(): Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=132, starts_line=23, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=134, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=134, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=136, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False), Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False), @@ -1003,7 +1003,7 @@ def jumpy(): Instruction(opname='SETUP_WITH', opcode=143, arg=14, argval=164, argrepr='to 164', offset=148, starts_line=None, is_jump_target=False), Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=150, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=152, starts_line=26, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=154, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval='Never reach this', argrepr="'Never reach this'", offset=154, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=156, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False), Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False), @@ -1014,7 +1014,7 @@ def jumpy(): Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=True), Instruction(opname='BEGIN_FINALLY', opcode=53, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=174, starts_line=28, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=176, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=176, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=178, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False), Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False), diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 78d94593c7f3..2ed73e3ae814 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -991,6 +991,60 @@ def g3(): return 4 self.assertEqual(g3(), 4) + def test_break_in_finally_after_return(self): + # See issue #37830 + def g1(x): + for count in [0, 1]: + count2 = 0 + while count2 < 20: + count2 += 10 + try: + return count + count2 + finally: + if x: + break + return 'end', count, count2 + self.assertEqual(g1(False), 10) + self.assertEqual(g1(True), ('end', 1, 10)) + + def g2(x): + for count in [0, 1]: + for count2 in [10, 20]: + try: + return count + count2 + finally: + if x: + break + return 'end', count, count2 + self.assertEqual(g2(False), 10) + self.assertEqual(g2(True), ('end', 1, 10)) + + def test_continue_in_finally_after_return(self): + # See issue #37830 + def g1(x): + count = 0 + while count < 100: + count += 1 + try: + return count + finally: + if x: + continue + return 'end', count + self.assertEqual(g1(False), 1) + self.assertEqual(g1(True), ('end', 100)) + + def g2(x): + for count in [0, 1]: + try: + return count + finally: + if x: + continue + return 'end', count + self.assertEqual(g2(False), 0) + self.assertEqual(g2(True), ('end', 1)) + def test_yield(self): # Allowed as standalone statement def g(): yield 1 diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py index 8489c198728a..17de46666acb 100644 --- a/Lib/test/test_importlib/test_util.py +++ b/Lib/test/test_importlib/test_util.py @@ -861,7 +861,7 @@ def test_magic_number(self): in advance. Such exceptional releases will then require an adjustment to this test case. """ - EXPECTED_MAGIC_NUMBER = 3410 + EXPECTED_MAGIC_NUMBER = 3413 actual = int.from_bytes(importlib.util.MAGIC_NUMBER[:2], 'little') msg = ( diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830.fNfMbz.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830.fNfMbz.rst new file mode 100644 index 000000000000..76f4bf671d1c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830.fNfMbz.rst @@ -0,0 +1,3 @@ +Fixed compilation of :keyword:`break` and :keyword:`continue` in the +:keyword:`finally` block when the corresponding :keyword:`try` block +contains :keyword:`return` with a non-constant value. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 5deb9858ce86..a796a59eee9e 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -233,6 +233,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore * the 'finally' blocks. */ memset(blockstack, '\0', sizeof(blockstack)); blockstack_top = 0; + unsigned char prevop = NOP; for (addr = 0; addr < code_len; addr += sizeof(_Py_CODEUNIT)) { unsigned char op = code[addr]; switch (op) { @@ -259,17 +260,24 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore "can't jump into the middle of a block"); return -1; } + int in_for_loop = op == FOR_ITER || code[target_addr] == END_ASYNC_FOR; if (first_in && !second_in) { - if (op != FOR_ITER && code[target_addr] != END_ASYNC_FOR) { - delta_iblock++; + if (!delta_iblock) { + if (in_for_loop) { + /* Pop the iterators of any 'for' and 'async for' loop + * we're jumping out of. */ + delta++; + } + else if (prevop == LOAD_CONST) { + /* Pops None pushed before SETUP_FINALLY. */ + delta++; + } } - else if (!delta_iblock) { - /* Pop the iterators of any 'for' and 'async for' loop - * we're jumping out of. */ - delta++; + if (!in_for_loop) { + delta_iblock++; } } - if (op != FOR_ITER && code[target_addr] != END_ASYNC_FOR) { + if (!in_for_loop) { blockstack[blockstack_top++] = target_addr; } break; @@ -293,6 +301,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore break; } } + prevop = op; } /* Verify that the blockstack tracking code didn't get lost. */ diff --git a/PC/launcher.c b/PC/launcher.c index ed5ead329e46..d23637c54ca1 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, 3410, L"3.8" }, + { 3400, 3419, L"3.8" }, { 0 } }; diff --git a/Python/compile.c b/Python/compile.c index d2de7a72a811..1bf05e291307 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -81,7 +81,7 @@ It's called a frame block to distinguish it from a basic block in the compiler IR. */ -enum fblocktype { WHILE_LOOP, FOR_LOOP, EXCEPT, FINALLY_TRY, FINALLY_END, +enum fblocktype { WHILE_LOOP, FOR_LOOP, EXCEPT, FINALLY_TRY, FINALLY_TRY2, FINALLY_END, WITH, ASYNC_WITH, HANDLER_CLEANUP }; struct fblockinfo { @@ -1664,7 +1664,12 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, return 1; case FINALLY_END: + info->fb_exit = NULL; ADDOP_I(c, POP_FINALLY, preserve_tos); + if (preserve_tos) { + ADDOP(c, ROT_TWO); + } + ADDOP(c, POP_TOP); return 1; case FOR_LOOP: @@ -1684,6 +1689,19 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, ADDOP_JREL(c, CALL_FINALLY, info->fb_exit); return 1; + case FINALLY_TRY2: + ADDOP(c, POP_BLOCK); + if (preserve_tos) { + ADDOP(c, ROT_TWO); + ADDOP(c, POP_TOP); + ADDOP_JREL(c, CALL_FINALLY, info->fb_exit); + } + else { + ADDOP_JREL(c, CALL_FINALLY, info->fb_exit); + ADDOP(c, POP_TOP); + } + return 1; + case WITH: case ASYNC_WITH: ADDOP(c, POP_BLOCK); @@ -2869,17 +2887,47 @@ compiler_continue(struct compiler *c) static int compiler_try_finally(struct compiler *c, stmt_ty s) { - basicblock *body, *end; + basicblock *start, *newcurblock, *body, *end; + int break_finally = 1; body = compiler_new_block(c); end = compiler_new_block(c); if (body == NULL || end == NULL) return 0; + start = c->u->u_curblock; + + /* `finally` block. Compile it first to determine if any of "break", + "continue" or "return" are used in it. */ + compiler_use_next_block(c, end); + if (!compiler_push_fblock(c, FINALLY_END, end, end)) + return 0; + VISIT_SEQ(c, stmt, s->v.Try.finalbody); + ADDOP(c, END_FINALLY); + break_finally = (c->u->u_fblock[c->u->u_nfblocks - 1].fb_exit == NULL); + if (break_finally) { + /* Pops a placeholder. See below */ + ADDOP(c, POP_TOP); + } + compiler_pop_fblock(c, FINALLY_END, end); + + newcurblock = c->u->u_curblock; + c->u->u_curblock = start; + start->b_next = NULL; + /* `try` block */ + c->u->u_lineno_set = 0; + c->u->u_lineno = s->lineno; + c->u->u_col_offset = s->col_offset; + if (break_finally) { + /* Pushes a placeholder for the value of "return" in the "try" block + to balance the stack for "break", "continue" and "return" in + the "finally" block. */ + ADDOP_LOAD_CONST(c, Py_None); + } ADDOP_JREL(c, SETUP_FINALLY, end); compiler_use_next_block(c, body); - if (!compiler_push_fblock(c, FINALLY_TRY, body, end)) + if (!compiler_push_fblock(c, break_finally ? FINALLY_TRY2 : FINALLY_TRY, body, end)) return 0; if (s->v.Try.handlers && asdl_seq_LEN(s->v.Try.handlers)) { if (!compiler_try_except(c, s)) @@ -2890,15 +2938,11 @@ compiler_try_finally(struct compiler *c, stmt_ty s) } ADDOP(c, POP_BLOCK); ADDOP(c, BEGIN_FINALLY); - compiler_pop_fblock(c, FINALLY_TRY, body); + compiler_pop_fblock(c, break_finally ? FINALLY_TRY2 : FINALLY_TRY, body); + + c->u->u_curblock->b_next = end; + c->u->u_curblock = newcurblock; - /* `finally` block */ - compiler_use_next_block(c, end); - if (!compiler_push_fblock(c, FINALLY_END, end, NULL)) - return 0; - VISIT_SEQ(c, stmt, s->v.Try.finalbody); - ADDOP(c, END_FINALLY); - compiler_pop_fblock(c, FINALLY_END, end); return 1; } diff --git a/Python/importlib.h b/Python/importlib.h index 5738af03b054..be3035d3e49a 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -301,14 +301,14 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 116,0,160,1,161,0,1,0,122,106,122,14,116,3,124,0, + 25,0,131,0,125,1,87,0,110,24,4,0,116,4,107,10, 114,48,1,0,1,0,1,0,100,1,125,1,89,0,110,2, - 88,0,124,1,100,1,107,8,114,112,116,4,100,1,107,8, - 114,76,116,5,124,0,131,1,125,1,110,8,116,6,124,0, + 88,0,124,1,100,1,107,8,114,112,116,5,100,1,107,8, + 114,76,116,6,124,0,131,1,125,1,110,8,116,7,124,0, 131,1,125,1,124,0,102,1,100,2,100,3,132,1,125,2, - 116,7,160,8,124,1,124,2,161,2,116,2,124,0,60,0, - 87,0,53,0,116,0,160,9,161,0,1,0,88,0,124,1, + 116,8,160,9,124,1,124,2,161,2,116,3,124,0,60,0, + 87,0,53,0,116,0,160,2,161,0,1,0,88,0,124,1, 83,0,41,4,122,139,71,101,116,32,111,114,32,99,114,101, 97,116,101,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, @@ -320,22 +320,22 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,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, + 116,0,160,1,161,0,1,0,122,24,116,3,160,4,124,1, + 161,1,124,0,107,8,114,30,116,3,124,1,61,0,87,0, + 53,0,116,0,160,2,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, + 99,113,117,105,114,101,95,108,111,99,107,218,12,114,101,108, + 101,97,115,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,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, + 57,0,0,0,114,58,0,0,0,114,59,0,0,0,114,60, + 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,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, @@ -911,14 +911,14 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 2,100,2,141,2,130,1,122,106,124,0,106,8,100,3,107, + 8,114,106,124,0,106,9,100,3,107,8,114,90,116,6,100, + 4,124,0,106,0,100,2,141,2,130,1,116,10,124,0,124, + 1,100,5,100,6,141,3,1,0,110,52,116,10,124,0,124, + 1,100,5,100,6,141,3,1,0,116,11,124,0,106,8,100, + 7,131,2,115,146,124,0,106,8,160,12,124,2,161,1,1, + 0,110,12,124,0,106,8,160,13,124,1,161,1,1,0,87, + 0,53,0,116,2,106,3,160,7,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, @@ -931,10 +931,10 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,116,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, + 0,0,0,114,45,0,0,0,114,79,0,0,0,218,3,112, + 111,112,114,109,0,0,0,114,116,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,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, @@ -962,8 +962,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 0,0,114,156,0,0,0,114,17,0,0,0,114,15,0,0, + 0,114,92,0,0,0,114,155,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, @@ -980,23 +980,23 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 107,8,114,108,116,9,100,4,124,0,106,7,100,5,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, + 116,13,100,6,124,0,106,7,124,0,106,0,131,3,1,0, + 87,0,53,0,100,3,124,0,95,4,88,0,124,1,83,0, + 41,7,78,114,150,0,0,0,84,70,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,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,116,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, + 114,155,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, @@ -1160,7 +1160,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 114,156,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, @@ -1256,7 +1256,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,41,1,114,97,0,0,0,114,168,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,155,0, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,156,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, @@ -1295,7 +1295,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 150,0,0,0,114,156,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, @@ -1326,7 +1326,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,218, + 0,0,0,114,59,0,0,0,41,4,114,30,0,0,0,218, 8,101,120,99,95,116,121,112,101,218,9,101,120,99,95,118, 97,108,117,101,218,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, @@ -1763,7 +1763,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 114,230,0,0,0,41,2,78,78,41,1,78,41,2,78,114, 22,0,0,0,41,4,78,78,114,10,0,0,0,114,22,0, 0,0,41,50,114,3,0,0,0,114,126,0,0,0,114,12, - 0,0,0,114,18,0,0,0,114,59,0,0,0,114,33,0, + 0,0,0,114,18,0,0,0,114,60,0,0,0,114,33,0, 0,0,114,42,0,0,0,114,19,0,0,0,114,20,0,0, 0,114,49,0,0,0,114,50,0,0,0,114,53,0,0,0, 114,65,0,0,0,114,67,0,0,0,114,76,0,0,0,114, diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 987ba5f33866..9bcf05057d1f 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -278,7 +278,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,84,13,0,0,114,28,0,0,0,114,16,0, + 0,0,0,105,85,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, @@ -392,7 +392,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,37,1,0,0,115,72,0,0, + 109,95,115,111,117,114,99,101,38,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, @@ -473,7 +473,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,108,1,0,0,115,52,0, + 114,111,109,95,99,97,99,104,101,109,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, @@ -508,7 +508,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,148,1,0,0,115,20, + 115,111,117,114,99,101,102,105,108,101,149,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, @@ -522,7 +522,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,167,1,0,0,115,16,0,0,0,0,1,14,1,2,1, + 100,168,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,0,0,0,0,2,0,0,0, 8,0,0,0,67,0,0,0,115,52,0,0,0,122,14,116, @@ -536,7 +536,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,179,1,0,0,115,12, + 95,99,97,108,99,95,109,111,100,101,180,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, @@ -574,7 +574,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,199,1,0,0,115,18, + 109,101,95,119,114,97,112,112,101,114,200,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, @@ -592,7 +592,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,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,210,1,0, + 0,114,6,0,0,0,218,5,95,119,114,97,112,211,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, @@ -600,7 +600,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,191,1,0,0,115,14,0,0, + 101,99,107,95,110,97,109,101,192,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,0,0,0, 0,5,0,0,0,6,0,0,0,67,0,0,0,115,60,0, @@ -628,7 +628,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,219,1,0, + 100,95,109,111,100,117,108,101,95,115,104,105,109,220,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,158, @@ -695,7 +695,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,236,1,0,0,115,28,0,0,0, + 105,102,121,95,112,121,99,237,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, @@ -749,7 +749,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,13,2, + 95,116,105,109,101,115,116,97,109,112,95,112,121,99,14,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, @@ -795,7 +795,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,218,11,115,111,117,114,99,101,95,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,41,2,0, + 100,97,116,101,95,104,97,115,104,95,112,121,99,42,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, @@ -819,7 +819,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,65,2,0, + 112,105,108,101,95,98,121,116,101,99,111,100,101,66,2,0, 0,115,20,0,0,0,0,2,10,1,10,1,12,1,8,1, 12,1,4,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, @@ -838,7 +838,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,78,2,0,0,115,12,0,0,0,0, + 109,112,95,112,121,99,79,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,80,0,0,0,116, @@ -856,7 +856,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,88,2, + 100,101,95,116,111,95,104,97,115,104,95,112,121,99,89,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, @@ -884,7 +884,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,99,2,0,0,115,10,0,0,0, + 95,115,111,117,114,99,101,100,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, @@ -946,7 +946,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,116,2,0,0,115,62,0,0,0,0,12,8,4,4, + 111,110,117,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, @@ -983,7 +983,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,196,2,0,0, + 112,101,110,95,114,101,103,105,115,116,114,121,197,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, @@ -1009,7 +1009,7 @@ 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,203, + 115,101,97,114,99,104,95,114,101,103,105,115,116,114,121,204, 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,8,1, 122,38,87,105,110,100,111,119,115,82,101,103,105,115,116,114, @@ -1032,7 +1032,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,218,2,0,0,115,28,0,0,0, + 110,100,95,115,112,101,99,219,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, @@ -1051,7 +1051,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,234,2,0,0, + 11,102,105,110,100,95,109,111,100,117,108,101,235,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, @@ -1061,7 +1061,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,184,2,0,0,115,28,0,0,0,8, + 0,114,191,0,0,0,185,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,12,15,2,1,114,191,0,0,0, 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -1097,7 +1097,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,253,2,0,0,115,8,0,0,0,0, + 0,114,182,0,0,0,254,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,0,0,0,0,2,0, @@ -1108,7 +1108,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,5,3,0,0,115,2,0,0,0,0,1,122,27,95,76, + 101,6,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, @@ -1128,7 +1128,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,8,3,0,0,115,12,0,0,0,0,2,12,1, + 117,108,101,9,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, @@ -1139,14 +1139,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,16,3,0, + 218,11,108,111,97,100,95,109,111,100,117,108,101,17,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,248,2,0,0,115,10,0,0,0, + 0,0,114,208,0,0,0,249,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, @@ -1171,7 +1171,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,23,3,0,0,115,2,0,0,0,0,6, + 109,116,105,109,101,24,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, @@ -1205,7 +1205,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,31,3,0,0,115,2,0,0,0,0, + 95,115,116,97,116,115,32,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, @@ -1229,7 +1229,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,45,3,0,0,115,2,0,0,0,0,8, + 101,99,111,100,101,46,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, @@ -1246,7 +1246,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,55,3,0,0,115,2,0,0,0,0,1, + 114,225,0,0,0,56,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, 0,0,0,0,5,0,0,0,10,0,0,0,67,0,0,0, @@ -1267,7 +1267,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,62,3,0,0,115,20,0,0,0,0,2,10, + 117,114,99,101,63,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, @@ -1289,7 +1289,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,72,3,0,0,115, + 114,99,101,95,116,111,95,99,111,100,101,73,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, @@ -1367,7 +1367,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,80,3,0,0,115,152,0,0,0,0,7, + 114,213,0,0,0,81,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, @@ -1383,7 +1383,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,21,3,0,0,115, + 0,114,6,0,0,0,114,221,0,0,0,22,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, @@ -1413,7 +1413,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 170,3,0,0,115,4,0,0,0,0,3,6,1,122,19,70, + 171,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, @@ -1422,7 +1422,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,176,3,0,0,115,6,0,0,0,0,1,12, + 101,113,95,95,177,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, @@ -1430,7 +1430,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,180, + 114,6,0,0,0,218,8,95,95,104,97,115,104,95,95,181, 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, @@ -1445,7 +1445,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,183,3,0,0,115,2,0,0,0,0,10,122,22, + 0,0,0,184,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,0, 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, @@ -1455,7 +1455,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,195,3,0,0,115,2,0,0,0,0, + 0,114,179,0,0,0,196,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, @@ -1475,7 +1475,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,90,4,114,101,97,100,114,65,0,0,0,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,200,3,0,0,115,10,0,0,0,0,2,14,1, + 0,0,0,201,3,0,0,115,10,0,0,0,0,2,14,1, 16,1,28,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, @@ -1484,7 +1484,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,211,3,0,0,115,6,0,0,0, + 95,114,101,97,100,101,114,212,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, @@ -1497,7 +1497,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 217,3,0,0,115,4,0,0,0,0,1,20,1,122,24,70, + 218,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, 0,0,0,0,3,0,0,0,3,0,0,0,67,0,0,0, @@ -1509,7 +1509,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 69,114,114,111,114,114,38,0,0,0,114,47,0,0,0,114, 44,0,0,0,114,255,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,221,3,0,0,115,8,0,0,0, + 99,101,95,112,97,116,104,222,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, @@ -1521,7 +1521,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,2,1,0, - 0,227,3,0,0,115,8,0,0,0,0,1,8,1,4,1, + 0,228,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, @@ -1531,7 +1531,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,233,3,0,0,115,2,0,0,0,0,1,122,19, + 110,116,115,234,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, @@ -1540,7 +1540,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,114,0,1,0,0,114,4,1,0,0,114,2,1,0,0, 114,8,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,165,3,0, + 0,0,0,114,6,0,0,0,114,239,0,0,0,166,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,11,2,1,10,5,8,4, 8,6,8,6,114,239,0,0,0,99,0,0,0,0,0,0, @@ -1563,7 +1563,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,241,3,0, + 0,0,0,114,6,0,0,0,114,224,0,0,0,242,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, @@ -1574,7 +1574,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,246,3,0,0,115,4,0,0,0,0,2,8, + 226,0,0,0,247,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,11,1,0,0,99,3,0, @@ -1609,7 +1609,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 12,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,251,3,0,0,115,48,0,0,0,0,2,12, + 225,0,0,0,252,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,28, 1,2,1,12,1,16,1,16,2,8,1,2,255,122,25,83, @@ -1618,7 +1618,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,9,1,0,0,237,3,0,0,115,8,0,0,0, + 0,0,114,9,1,0,0,238,3,0,0,115,8,0,0,0, 8,2,4,2,8,5,8,5,114,9,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, @@ -1640,7 +1640,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,30,4,0,0,115,22,0,0,0, + 0,0,114,213,0,0,0,31,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, @@ -1651,13 +1651,13 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,46,4,0,0,115,2,0,0,0,0,2,122,31,83,111, + 0,47,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,15,1,0,0,26,4,0,0,115,6,0,0,0, + 0,0,114,15,1,0,0,27,4,0,0,115,6,0,0,0, 8,2,4,2,8,16,114,15,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, @@ -1677,7 +1677,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,5,1,0,0,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,114,209,0,0,0,63,4,0,0, + 0,0,114,6,0,0,0,114,209,0,0,0,64,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, @@ -1686,7 +1686,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 67,4,0,0,115,6,0,0,0,0,1,12,1,10,255,122, + 68,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, @@ -1694,7 +1694,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 71,4,0,0,115,2,0,0,0,0,1,122,28,69,120,116, + 72,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,0,0,0,0,3,0,0,0,5,0,0,0,67,0, @@ -1711,7 +1711,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,74,4,0,0,115,18,0,0,0,0,2,4,1,4, + 0,0,75,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, @@ -1728,7 +1728,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 90,12,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,253,0, 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,114,217,0,0,0,82,4,0,0,115,10,0,0,0,0, + 0,114,217,0,0,0,83,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, @@ -1746,7 +1746,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,91,4,0,0, + 0,218,9,60,103,101,110,101,120,112,114,62,92,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, @@ -1754,7 +1754,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,88,4,0,0,115,8, + 114,6,0,0,0,114,182,0,0,0,89,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, @@ -1765,7 +1765,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,94, + 114,3,0,0,0,114,6,0,0,0,114,213,0,0,0,95, 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, @@ -1776,14 +1776,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 97,118,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,98,4,0,0,115,2,0,0,0,0,2,122,30,69, + 0,0,99,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,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,102,4,0,0,115,2,0,0,0,0,3,122, + 179,0,0,0,103,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, @@ -1792,7 +1792,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,252, - 0,0,0,55,4,0,0,115,22,0,0,0,8,2,4,6, + 0,0,0,56,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,252,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, @@ -1834,7 +1834,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,115,4,0,0,115, + 0,114,6,0,0,0,114,209,0,0,0,116,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, @@ -1852,7 +1852,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 1,0,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,121,4,0,0,115,8,0,0,0,0,2,18, + 97,109,101,115,122,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, @@ -1865,7 +1865,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,131,4,0,0,115,4,0,0,0,0,1, + 114,25,1,0,0,132,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, @@ -1881,7 +1881,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,135,4,0,0,115,16,0,0,0,0, + 99,117,108,97,116,101,136,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, @@ -1890,7 +1890,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 161,0,131,1,83,0,114,110,0,0,0,41,2,114,6,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,148,4,0,0,115,2,0,0,0,0,1, + 116,101,114,95,95,149,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, @@ -1898,7 +1898,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,151,4,0,0,115,2,0, + 103,101,116,105,116,101,109,95,95,152,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,0,0,0,0,3,0,0, @@ -1907,7 +1907,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,154,4,0,0,115,2,0,0,0,0,1, + 116,101,109,95,95,155,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, @@ -1915,7 +1915,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,157,4,0,0,115,2,0,0,0,0,1,122, + 101,110,95,95,158,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, @@ -1924,7 +1924,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,160,4,0,0,115,2,0,0,0,0,1,122, + 112,114,95,95,161,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, @@ -1932,7 +1932,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,163,4,0,0,115,2,0,0,0,0, + 97,105,110,115,95,95,164,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,0,0,0,0,2,0,0,0,3, @@ -1940,7 +1940,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,166,4,0,0,115,2,0,0,0,0, + 0,114,186,0,0,0,167,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, @@ -1948,7 +1948,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,108, + 114,3,0,0,0,114,6,0,0,0,114,22,1,0,0,109, 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, @@ -1965,7 +1965,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,172,4,0,0,115,2,0,0,0,0,1,122,25,95,78, + 0,173,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, @@ -1982,21 +1982,21 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 101,41,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,175,4,0,0,115,2,0,0,0, + 108,101,95,114,101,112,114,176,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,184,4,0,0,115,2,0,0,0,0,1,122, + 182,0,0,0,185,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,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,187,4,0,0,115,2,0,0,0,0,1,122, + 229,0,0,0,188,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, @@ -2005,21 +2005,21 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,190,4,0,0,115,2,0, + 6,0,0,0,114,213,0,0,0,191,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,193,4,0,0,115,2,0,0,0,0,1,122, + 212,0,0,0,194,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,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,253,0,0,0, 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, - 217,0,0,0,196,4,0,0,115,2,0,0,0,0,1,122, + 217,0,0,0,197,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, @@ -2037,7 +2037,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,199,4,0,0,115,8,0,0,0,0,7,6,1,4, + 0,0,200,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, @@ -2045,7 +2045,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,171,4,0,0,115,18,0, + 6,0,0,0,114,43,1,0,0,172,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, @@ -2086,7 +2086,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,217,4,0,0,115,10,0,0,0, + 0,0,114,46,1,0,0,218,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, @@ -2106,7 +2106,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,227,4,0,0,115, + 95,112,97,116,104,95,104,111,111,107,115,228,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, @@ -2137,7 +2137,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,240,4, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,241,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, @@ -2155,7 +2155,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,6,5,0,0, + 97,99,121,95,103,101,116,95,115,112,101,99,7,5,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, @@ -2187,7 +2187,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,21,5,0,0,115,40,0,0,0,0,5,4,1,8, + 101,99,22,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, @@ -2214,7 +2214,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,53,5,0,0,115,26,0,0,0,0, + 0,114,203,0,0,0,54,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, @@ -2234,7 +2234,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,77,5,0,0,115,8,0,0, + 0,0,0,114,206,0,0,0,78,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,99,3,0,0,0,0,0,0,0,0,0,0,0,7,0, @@ -2273,7 +2273,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,114,59,1,0,0,218,7,112,97,116,116,101,114,110, 90,5,102,111,117,110,100,114,3,0,0,0,114,3,0,0, 0,114,6,0,0,0,218,18,102,105,110,100,95,100,105,115, - 116,114,105,98,117,116,105,111,110,115,90,5,0,0,115,14, + 116,114,105,98,117,116,105,111,110,115,91,5,0,0,115,14, 0,0,0,0,10,8,1,12,1,8,1,6,1,22,1,12, 1,122,29,80,97,116,104,70,105,110,100,101,114,46,102,105, 110,100,95,100,105,115,116,114,105,98,117,116,105,111,110,115, @@ -2292,7 +2292,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,41,1,218,12,95,115,101,97,114,99,104,95,112,97, 116,104,41,2,114,32,0,0,0,114,44,0,0,0,169,2, 114,193,0,0,0,114,63,1,0,0,114,3,0,0,0,114, - 6,0,0,0,114,19,1,0,0,112,5,0,0,115,4,0, + 6,0,0,0,114,19,1,0,0,113,5,0,0,115,4,0, 0,0,4,2,2,255,122,43,80,97,116,104,70,105,110,100, 101,114,46,95,115,101,97,114,99,104,95,112,97,116,104,115, 46,60,108,111,99,97,108,115,62,46,60,103,101,110,101,120, @@ -2302,7 +2302,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 105,116,99,104,95,112,97,116,104,41,4,114,193,0,0,0, 114,63,1,0,0,90,5,112,97,116,104,115,114,67,1,0, 0,114,3,0,0,0,114,66,1,0,0,114,6,0,0,0, - 114,61,1,0,0,108,5,0,0,115,8,0,0,0,0,3, + 114,61,1,0,0,109,5,0,0,115,8,0,0,0,0,3, 8,1,18,2,10,254,122,24,80,97,116,104,70,105,110,100, 101,114,46,95,115,101,97,114,99,104,95,112,97,116,104,115, 99,1,0,0,0,0,0,0,0,0,0,0,0,5,0,0, @@ -2322,7 +2322,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,114,69,1,0,0,114,70,1,0,0,114,71,1,0,0, 90,13,80,89,80,89,95,79,80,69,78,95,66,85,71,114, 3,0,0,0,114,3,0,0,0,114,6,0,0,0,114,68, - 1,0,0,117,5,0,0,115,16,0,0,0,0,2,12,1, + 1,0,0,118,5,0,0,115,16,0,0,0,0,2,12,1, 8,1,8,1,4,1,16,1,10,1,28,1,122,23,80,97, 116,104,70,105,110,100,101,114,46,95,115,119,105,116,99,104, 95,112,97,116,104,99,3,0,0,0,0,0,0,0,0,0, @@ -2340,7 +2340,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 1,0,0,114,60,1,0,0,90,8,116,101,109,112,108,97, 116,101,90,8,109,97,110,105,102,101,115,116,114,3,0,0, 0,114,3,0,0,0,114,6,0,0,0,218,13,95,109,97, - 116,99,104,101,115,95,105,110,102,111,128,5,0,0,115,8, + 116,99,104,101,115,95,105,110,102,111,129,5,0,0,115,8, 0,0,0,0,2,8,1,4,1,12,1,122,24,80,97,116, 104,70,105,110,100,101,114,46,95,109,97,116,99,104,101,115, 95,105,110,102,111,99,3,0,0,0,0,0,0,0,0,0, @@ -2355,7 +2355,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 6,115,101,97,114,99,104,114,85,0,0,0,114,75,1,0, 0,114,76,1,0,0,114,3,0,0,0,114,3,0,0,0, 114,6,0,0,0,218,15,95,109,97,116,99,104,101,115,95, - 108,101,103,97,99,121,135,5,0,0,115,8,0,0,0,0, + 108,101,103,97,99,121,136,5,0,0,115,8,0,0,0,0, 2,8,1,4,1,12,1,122,26,80,97,116,104,70,105,110, 100,101,114,46,95,109,97,116,99,104,101,115,95,108,101,103, 97,99,121,99,3,0,0,0,0,0,0,0,0,0,0,0, @@ -2372,14 +2372,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,78,1,0,0,114,79,1,0,0,41,2,114,32,0,0, 0,114,41,1,0,0,169,2,114,193,0,0,0,114,77,1, 0,0,114,3,0,0,0,114,6,0,0,0,114,19,1,0, - 0,147,5,0,0,115,8,0,0,0,4,0,2,1,12,1, + 0,148,5,0,0,115,8,0,0,0,4,0,2,1,12,1, 12,254,122,42,80,97,116,104,70,105,110,100,101,114,46,95, 115,101,97,114,99,104,95,112,97,116,104,46,60,108,111,99, 97,108,115,62,46,60,103,101,110,101,120,112,114,62,41,3, 90,6,105,115,95,100,105,114,114,67,0,0,0,90,7,105, 116,101,114,100,105,114,41,3,114,193,0,0,0,90,4,114, 111,111,116,114,63,1,0,0,114,3,0,0,0,114,81,1, - 0,0,114,6,0,0,0,114,65,1,0,0,142,5,0,0, + 0,0,114,6,0,0,0,114,65,1,0,0,143,5,0,0, 115,8,0,0,0,0,2,8,1,4,1,12,1,122,23,80, 97,116,104,70,105,110,100,101,114,46,95,115,101,97,114,99, 104,95,112,97,116,104,41,1,78,41,2,78,78,41,1,78, @@ -2391,7 +2391,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 97,116,105,99,109,101,116,104,111,100,114,68,1,0,0,114, 78,1,0,0,114,79,1,0,0,114,65,1,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,213,4,0,0,115,54,0,0,0, + 0,0,114,45,1,0,0,214,4,0,0,115,54,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,12,12, 2,1,12,17,2,1,10,8,2,1,10,10,2,1,10,6, @@ -2437,7 +2437,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,167,5,0,0,115,4,0,0, + 0,0,0,114,19,1,0,0,168,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, @@ -2450,7 +2450,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,84,1,0,0,114,6,0,0,0,114,209,0,0,0, - 161,5,0,0,115,16,0,0,0,0,4,4,1,12,1,26, + 162,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, @@ -2459,7 +2459,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,86,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,175, + 114,3,0,0,0,114,6,0,0,0,114,46,1,0,0,176, 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, @@ -2483,7 +2483,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 181,5,0,0,115,8,0,0,0,0,7,10,1,8,1,8, + 182,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, @@ -2493,7 +2493,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 41,7,114,119,0,0,0,114,188,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,193,5,0,0,115,8, + 114,6,0,0,0,114,58,1,0,0,194,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,0,0,0,0,14, @@ -2548,7 +2548,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,198,5,0,0,115,74,0,0,0,0,5,4, + 203,0,0,0,199,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, @@ -2580,7 +2580,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,19,6,0,0,115,4,0,0,0,6,0,2,0, + 109,112,62,20,6,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, @@ -2596,7 +2596,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,91,1,0,0,246,5,0, + 0,0,0,114,6,0,0,0,114,91,1,0,0,247,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, @@ -2635,14 +2635,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,169,2,114,193,0,0,0,114,90,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,31,6,0,0,115,6,0,0,0,0,2,8,1,12, + 101,114,32,6,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,90,1,0,0,114,97,1,0,0,114, 3,0,0,0,114,96,1,0,0,114,6,0,0,0,218,9, - 112,97,116,104,95,104,111,111,107,21,6,0,0,115,4,0, + 112,97,116,104,95,104,111,111,107,22,6,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, @@ -2651,7 +2651,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 39,6,0,0,115,2,0,0,0,0,1,122,19,70,105,108, + 40,6,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, @@ -2659,7 +2659,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,114,58,1,0,0,114,203,0,0,0,114,91,1,0, 0,114,207,0,0,0,114,98,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,83,1,0,0,152,5,0,0,115,22,0, + 6,0,0,0,114,83,1,0,0,153,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,83,1,0,0,99,4,0, 0,0,0,0,0,0,0,0,0,0,6,0,0,0,8,0, @@ -2682,7 +2682,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,45,6,0,0,115,34, + 95,117,112,95,109,111,100,117,108,101,46,6,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,102,1,0,0,99,0,0,0,0,0, @@ -2702,7 +2702,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,68,6,0,0,115,8,0, + 6,0,0,0,114,184,0,0,0,69,6,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,0,0,0,0,12,0,0,0, 9,0,0,0,67,0,0,0,115,178,1,0,0,124,0,97, @@ -2755,7 +2755,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,104,6,0,0,115,4,0,0,0,4,0,2,0, + 1,0,0,105,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, @@ -2767,7 +2767,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,92,1,0,0,120,6,0,0,115,4,0,0,0, + 0,0,114,92,1,0,0,121,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, @@ -2791,7 +2791,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,79,6,0,0,115,78,0,0,0,0, + 95,115,101,116,117,112,80,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, @@ -2811,7 +2811,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,186,0,0,0,114,45,1,0,0,41,2,114,109,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,144,6,0, + 0,0,0,218,8,95,105,110,115,116,97,108,108,145,6,0, 0,115,8,0,0,0,0,2,8,1,6,1,20,1,114,112, 1,0,0,41,1,114,60,0,0,0,41,1,78,41,3,78, 78,78,41,2,114,73,0,0,0,114,73,0,0,0,41,1, @@ -2845,7 +2845,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 8,60,109,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,10,22,10,127,0,12,16,1,12,2,4,1, + 8,7,8,9,10,22,10,127,0,13,16,1,12,2,4,1, 4,2,6,2,6,2,8,2,16,71,8,40,8,19,8,12, 8,12,8,28,8,17,8,33,8,28,8,24,10,13,10,10, 10,11,8,14,6,3,4,1,2,255,12,68,14,64,14,29, diff --git a/Python/importlib_zipimport.h b/Python/importlib_zipimport.h index 056e85d343d8..6c9c4e846552 100644 --- a/Python/importlib_zipimport.h +++ b/Python/importlib_zipimport.h @@ -703,18 +703,18 @@ const unsigned char _Py_M__zipimport[] = { 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, + 2,131,1,130,1,100,3,97,0,122,60,122,16,100,5,100, + 6,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,88,0,87,0,53,0,100,4,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,108,97,98,108,101,84,70,114,0,0,0,0,169,1,218, + 10,100,101,99,111,109,112,114,101,115,115,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, From webhook-mailer at python.org Sat Aug 24 06:19:54 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Aug 2019 10:19:54 -0000 Subject: [Python-checkins] bpo-29535: Remove promize about hash randomization of datetime objects. (GH-15269) Message-ID: https://github.com/python/cpython/commit/076d0b9f5def35aeb0f8e8aadf658dc35aace81d commit: 076d0b9f5def35aeb0f8e8aadf658dc35aace81d branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-24T03:19:51-07:00 summary: bpo-29535: Remove promize about hash randomization of datetime objects. (GH-15269) (cherry picked from commit e9c90aa43144b0be1e4e393e8cb549573437a5da) Co-authored-by: Serhiy Storchaka files: M Doc/reference/datamodel.rst M Doc/using/cmdline.rst M Misc/python.man M Python/initconfig.c diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index fa47bf1c1619..1dd8e42ef87e 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1445,8 +1445,8 @@ Basic customization .. note:: - By default, the :meth:`__hash__` values of str, bytes and datetime - objects are "salted" with an unpredictable random value. Although they + By default, the :meth:`__hash__` values of str and bytes objects are + "salted" with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python. diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 6bc440f2fa8c..50143f2bd020 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -302,7 +302,7 @@ Miscellaneous options randomization is enabled by default. On previous versions of Python, this option turns on hash randomization, - so that the :meth:`__hash__` values of str, bytes and datetime + so that the :meth:`__hash__` values of str and bytes objects are "salted" with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python. @@ -618,7 +618,7 @@ conflict. .. envvar:: PYTHONHASHSEED If this variable is not set or set to ``random``, a random value is used - to seed the hashes of str, bytes and datetime objects. + to seed the hashes of str and bytes objects. If :envvar:`PYTHONHASHSEED` is set to an integer value, it is used as a fixed seed for generating the hash() of the types covered by the hash diff --git a/Misc/python.man b/Misc/python.man index 8d5ad8cd6ca8..3aa9f1f9c7ea 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -431,7 +431,7 @@ If this is set to a comma-separated string it is equivalent to specifying the \fB\-W\fP option for each separate value. .IP PYTHONHASHSEED If this variable is set to "random", a random value is used to seed the hashes -of str, bytes and datetime objects. +of str and bytes objects. If PYTHONHASHSEED is set to an integer value, it is used as a fixed seed for generating the hash() of the types covered by the hash randomization. Its diff --git a/Python/initconfig.c b/Python/initconfig.c index a87d8ae74860..49659045f7ab 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -83,8 +83,8 @@ static const char usage_5[] = "PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.\n"; static const char usage_6[] = "PYTHONHASHSEED: if this variable is set to 'random', a random value is used\n" -" to seed the hashes of str, bytes and datetime objects. It can also be\n" -" set to an integer in the range [0,4294967295] to get hash values with a\n" +" to seed the hashes of str and bytes objects. It can also be set to an\n" +" integer in the range [0,4294967295] to get hash values with a\n" " predictable seed.\n" "PYTHONMALLOC: set the Python memory allocators and/or install debug hooks\n" " on Python memory allocators. Use PYTHONMALLOC=debug to install debug\n" From webhook-mailer at python.org Sat Aug 24 06:22:18 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Aug 2019 10:22:18 -0000 Subject: [Python-checkins] bpo-28269: Replace strcasecmp with system function _stricmp. (GH-13095) Message-ID: https://github.com/python/cpython/commit/920ec4b7763d64b3742d7ddd339ad11cdbec62e9 commit: 920ec4b7763d64b3742d7ddd339ad11cdbec62e9 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-24T03:22:14-07:00 summary: bpo-28269: Replace strcasecmp with system function _stricmp. (GH-13095) (cherry picked from commit 05f2d84cae4ba1ff15b7a1d0347305393f4bdcc5) Co-authored-by: Minmin Gong files: A Misc/NEWS.d/next/Windows/2019-05-05-05-23-34.bpo-28269.-MOHI7.rst M Python/dynload_win.c diff --git a/Misc/NEWS.d/next/Windows/2019-05-05-05-23-34.bpo-28269.-MOHI7.rst b/Misc/NEWS.d/next/Windows/2019-05-05-05-23-34.bpo-28269.-MOHI7.rst new file mode 100644 index 000000000000..a531b98118a2 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2019-05-05-05-23-34.bpo-28269.-MOHI7.rst @@ -0,0 +1 @@ +Replace use of :c:func:`strcasecmp` for the system function :c:func:`_stricmp`. Patch by Minmin Gong. diff --git a/Python/dynload_win.c b/Python/dynload_win.c index 2f28c3cf9249..6deba1134e2a 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -38,24 +38,6 @@ const char *_PyImport_DynLoadFiletab[] = { NULL }; -/* Case insensitive string compare, to avoid any dependencies on particular - C RTL implementations */ - -static int strcasecmp (const char *string1, const char *string2) -{ - int first, second; - - do { - first = tolower(*string1); - second = tolower(*string2); - string1++; - string2++; - } while (first && first == second); - - return (first - second); -} - - /* Function to return the name of the "python" DLL that the supplied module directly imports. Looks through the list of imported modules and returns the first entry that starts with "python" (case sensitive) and @@ -297,7 +279,7 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, import_python = GetPythonImport(hDLL); if (import_python && - strcasecmp(buffer,import_python)) { + _stricmp(buffer,import_python)) { PyErr_Format(PyExc_ImportError, "Module use of %.150s conflicts " "with this version of Python.", From webhook-mailer at python.org Sat Aug 24 06:41:57 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 24 Aug 2019 10:41:57 -0000 Subject: [Python-checkins] [3.8] bpo-37830: Fix compilation of break and continue in finally. (GH-15320) (GH-15456) Message-ID: https://github.com/python/cpython/commit/ed146b52a3b6537689324e3bd9952055f9c6b43d commit: ed146b52a3b6537689324e3bd9952055f9c6b43d branch: 3.8 author: Serhiy Storchaka committer: GitHub date: 2019-08-24T13:41:53+03:00 summary: [3.8] bpo-37830: Fix compilation of break and continue in finally. (GH-15320) (GH-15456) Fix compilation of "break" and "continue" in the "finally" block when the corresponding "try" block contains "return" with a non-constant value. (cherry picked from commit ef61c524ddeeb56da3858b86e349e7288d68178e) files: A Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830.fNfMbz.rst M Lib/importlib/_bootstrap_external.py M Lib/test/test_dis.py M Lib/test/test_grammar.py M Lib/test/test_importlib/test_util.py M Objects/frameobject.c M PC/launcher.c M Python/compile.c M Python/importlib.h M Python/importlib_external.h M Python/importlib_zipimport.h diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index badd7a74cb90..67bd1d3cf99e 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -270,6 +270,7 @@ def _write_atomic(path, data, mode=0o666): # comprehensions #35224) # Python 3.8b2 3412 (Swap the position of positional args and positional # only args in ast.arguments #37593) +# Python 3.8b4 3413 (Fix "break" and "continue" in "finally" #37830) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually @@ -278,7 +279,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 = (3412).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3413).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/test/test_dis.py b/Lib/test/test_dis.py index 652af45d55ad..03b286016632 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -980,7 +980,7 @@ def jumpy(): Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=174, argrepr='to 174', offset=102, starts_line=20, is_jump_target=True), Instruction(opname='SETUP_FINALLY', opcode=122, arg=12, argval=118, argrepr='to 118', offset=104, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False), Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False), Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False), @@ -993,7 +993,7 @@ def jumpy(): Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=132, starts_line=23, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=134, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=134, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=136, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False), Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False), @@ -1003,7 +1003,7 @@ def jumpy(): Instruction(opname='SETUP_WITH', opcode=143, arg=14, argval=164, argrepr='to 164', offset=148, starts_line=None, is_jump_target=False), Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=150, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=152, starts_line=26, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=154, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval='Never reach this', argrepr="'Never reach this'", offset=154, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=156, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False), Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False), @@ -1014,7 +1014,7 @@ def jumpy(): Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=True), Instruction(opname='BEGIN_FINALLY', opcode=53, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=174, starts_line=28, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=176, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=176, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=178, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False), Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False), diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 78d94593c7f3..2ed73e3ae814 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -991,6 +991,60 @@ def g3(): return 4 self.assertEqual(g3(), 4) + def test_break_in_finally_after_return(self): + # See issue #37830 + def g1(x): + for count in [0, 1]: + count2 = 0 + while count2 < 20: + count2 += 10 + try: + return count + count2 + finally: + if x: + break + return 'end', count, count2 + self.assertEqual(g1(False), 10) + self.assertEqual(g1(True), ('end', 1, 10)) + + def g2(x): + for count in [0, 1]: + for count2 in [10, 20]: + try: + return count + count2 + finally: + if x: + break + return 'end', count, count2 + self.assertEqual(g2(False), 10) + self.assertEqual(g2(True), ('end', 1, 10)) + + def test_continue_in_finally_after_return(self): + # See issue #37830 + def g1(x): + count = 0 + while count < 100: + count += 1 + try: + return count + finally: + if x: + continue + return 'end', count + self.assertEqual(g1(False), 1) + self.assertEqual(g1(True), ('end', 100)) + + def g2(x): + for count in [0, 1]: + try: + return count + finally: + if x: + continue + return 'end', count + self.assertEqual(g2(False), 0) + self.assertEqual(g2(True), ('end', 1)) + def test_yield(self): # Allowed as standalone statement def g(): yield 1 diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py index 0350a5a5cc05..58faab46f62c 100644 --- a/Lib/test/test_importlib/test_util.py +++ b/Lib/test/test_importlib/test_util.py @@ -861,7 +861,7 @@ def test_magic_number(self): in advance. Such exceptional releases will then require an adjustment to this test case. """ - EXPECTED_MAGIC_NUMBER = 3410 + EXPECTED_MAGIC_NUMBER = 3413 actual = int.from_bytes(importlib.util.MAGIC_NUMBER[:2], 'little') msg = ( diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830.fNfMbz.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830.fNfMbz.rst new file mode 100644 index 000000000000..76f4bf671d1c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830.fNfMbz.rst @@ -0,0 +1,3 @@ +Fixed compilation of :keyword:`break` and :keyword:`continue` in the +:keyword:`finally` block when the corresponding :keyword:`try` block +contains :keyword:`return` with a non-constant value. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 5deb9858ce86..a796a59eee9e 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -233,6 +233,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore * the 'finally' blocks. */ memset(blockstack, '\0', sizeof(blockstack)); blockstack_top = 0; + unsigned char prevop = NOP; for (addr = 0; addr < code_len; addr += sizeof(_Py_CODEUNIT)) { unsigned char op = code[addr]; switch (op) { @@ -259,17 +260,24 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore "can't jump into the middle of a block"); return -1; } + int in_for_loop = op == FOR_ITER || code[target_addr] == END_ASYNC_FOR; if (first_in && !second_in) { - if (op != FOR_ITER && code[target_addr] != END_ASYNC_FOR) { - delta_iblock++; + if (!delta_iblock) { + if (in_for_loop) { + /* Pop the iterators of any 'for' and 'async for' loop + * we're jumping out of. */ + delta++; + } + else if (prevop == LOAD_CONST) { + /* Pops None pushed before SETUP_FINALLY. */ + delta++; + } } - else if (!delta_iblock) { - /* Pop the iterators of any 'for' and 'async for' loop - * we're jumping out of. */ - delta++; + if (!in_for_loop) { + delta_iblock++; } } - if (op != FOR_ITER && code[target_addr] != END_ASYNC_FOR) { + if (!in_for_loop) { blockstack[blockstack_top++] = target_addr; } break; @@ -293,6 +301,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore break; } } + prevop = op; } /* Verify that the blockstack tracking code didn't get lost. */ diff --git a/PC/launcher.c b/PC/launcher.c index ed5ead329e46..d23637c54ca1 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, 3410, L"3.8" }, + { 3400, 3419, L"3.8" }, { 0 } }; diff --git a/Python/compile.c b/Python/compile.c index 0336959d3da2..a6c5ab6324f0 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -81,7 +81,7 @@ It's called a frame block to distinguish it from a basic block in the compiler IR. */ -enum fblocktype { WHILE_LOOP, FOR_LOOP, EXCEPT, FINALLY_TRY, FINALLY_END, +enum fblocktype { WHILE_LOOP, FOR_LOOP, EXCEPT, FINALLY_TRY, FINALLY_TRY2, FINALLY_END, WITH, ASYNC_WITH, HANDLER_CLEANUP }; struct fblockinfo { @@ -1664,7 +1664,12 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, return 1; case FINALLY_END: + info->fb_exit = NULL; ADDOP_I(c, POP_FINALLY, preserve_tos); + if (preserve_tos) { + ADDOP(c, ROT_TWO); + } + ADDOP(c, POP_TOP); return 1; case FOR_LOOP: @@ -1684,6 +1689,19 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, ADDOP_JREL(c, CALL_FINALLY, info->fb_exit); return 1; + case FINALLY_TRY2: + ADDOP(c, POP_BLOCK); + if (preserve_tos) { + ADDOP(c, ROT_TWO); + ADDOP(c, POP_TOP); + ADDOP_JREL(c, CALL_FINALLY, info->fb_exit); + } + else { + ADDOP_JREL(c, CALL_FINALLY, info->fb_exit); + ADDOP(c, POP_TOP); + } + return 1; + case WITH: case ASYNC_WITH: ADDOP(c, POP_BLOCK); @@ -2869,17 +2887,47 @@ compiler_continue(struct compiler *c) static int compiler_try_finally(struct compiler *c, stmt_ty s) { - basicblock *body, *end; + basicblock *start, *newcurblock, *body, *end; + int break_finally = 1; body = compiler_new_block(c); end = compiler_new_block(c); if (body == NULL || end == NULL) return 0; + start = c->u->u_curblock; + + /* `finally` block. Compile it first to determine if any of "break", + "continue" or "return" are used in it. */ + compiler_use_next_block(c, end); + if (!compiler_push_fblock(c, FINALLY_END, end, end)) + return 0; + VISIT_SEQ(c, stmt, s->v.Try.finalbody); + ADDOP(c, END_FINALLY); + break_finally = (c->u->u_fblock[c->u->u_nfblocks - 1].fb_exit == NULL); + if (break_finally) { + /* Pops a placeholder. See below */ + ADDOP(c, POP_TOP); + } + compiler_pop_fblock(c, FINALLY_END, end); + + newcurblock = c->u->u_curblock; + c->u->u_curblock = start; + start->b_next = NULL; + /* `try` block */ + c->u->u_lineno_set = 0; + c->u->u_lineno = s->lineno; + c->u->u_col_offset = s->col_offset; + if (break_finally) { + /* Pushes a placeholder for the value of "return" in the "try" block + to balance the stack for "break", "continue" and "return" in + the "finally" block. */ + ADDOP_LOAD_CONST(c, Py_None); + } ADDOP_JREL(c, SETUP_FINALLY, end); compiler_use_next_block(c, body); - if (!compiler_push_fblock(c, FINALLY_TRY, body, end)) + if (!compiler_push_fblock(c, break_finally ? FINALLY_TRY2 : FINALLY_TRY, body, end)) return 0; if (s->v.Try.handlers && asdl_seq_LEN(s->v.Try.handlers)) { if (!compiler_try_except(c, s)) @@ -2890,15 +2938,11 @@ compiler_try_finally(struct compiler *c, stmt_ty s) } ADDOP(c, POP_BLOCK); ADDOP(c, BEGIN_FINALLY); - compiler_pop_fblock(c, FINALLY_TRY, body); + compiler_pop_fblock(c, break_finally ? FINALLY_TRY2 : FINALLY_TRY, body); + + c->u->u_curblock->b_next = end; + c->u->u_curblock = newcurblock; - /* `finally` block */ - compiler_use_next_block(c, end); - if (!compiler_push_fblock(c, FINALLY_END, end, NULL)) - return 0; - VISIT_SEQ(c, stmt, s->v.Try.finalbody); - ADDOP(c, END_FINALLY); - compiler_pop_fblock(c, FINALLY_END, end); return 1; } diff --git a/Python/importlib.h b/Python/importlib.h index a285a31e2065..67195747d8d9 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -301,14 +301,14 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 116,0,160,1,161,0,1,0,122,106,122,14,116,3,124,0, + 25,0,131,0,125,1,87,0,110,24,4,0,116,4,107,10, 114,48,1,0,1,0,1,0,100,1,125,1,89,0,110,2, - 88,0,124,1,100,1,107,8,114,112,116,4,100,1,107,8, - 114,76,116,5,124,0,131,1,125,1,110,8,116,6,124,0, + 88,0,124,1,100,1,107,8,114,112,116,5,100,1,107,8, + 114,76,116,6,124,0,131,1,125,1,110,8,116,7,124,0, 131,1,125,1,124,0,102,1,100,2,100,3,132,1,125,2, - 116,7,160,8,124,1,124,2,161,2,116,2,124,0,60,0, - 87,0,53,0,116,0,160,9,161,0,1,0,88,0,124,1, + 116,8,160,9,124,1,124,2,161,2,116,3,124,0,60,0, + 87,0,53,0,116,0,160,2,161,0,1,0,88,0,124,1, 83,0,41,4,122,139,71,101,116,32,111,114,32,99,114,101, 97,116,101,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, @@ -320,22 +320,22 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,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, + 116,0,160,1,161,0,1,0,122,24,116,3,160,4,124,1, + 161,1,124,0,107,8,114,30,116,3,124,1,61,0,87,0, + 53,0,116,0,160,2,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, + 99,113,117,105,114,101,95,108,111,99,107,218,12,114,101,108, + 101,97,115,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,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, + 57,0,0,0,114,58,0,0,0,114,59,0,0,0,114,60, + 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,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, @@ -910,14 +910,14 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 2,141,2,130,1,122,106,124,0,106,8,100,3,107,8,114, + 106,124,0,106,9,100,3,107,8,114,90,116,6,100,4,124, + 0,106,0,100,2,141,2,130,1,116,10,124,0,124,1,100, + 5,100,6,141,3,1,0,110,52,116,10,124,0,124,1,100, + 5,100,6,141,3,1,0,116,11,124,0,106,8,100,7,131, + 2,115,146,124,0,106,8,160,12,124,2,161,1,1,0,110, + 12,124,0,106,8,160,13,124,1,161,1,1,0,87,0,53, + 0,116,2,106,3,160,7,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, @@ -930,10 +930,10 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,114,45,0,0,0,114,79,0,0,0,218,3,112,111,112, + 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,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, @@ -961,8 +961,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 114,156,0,0,0,114,17,0,0,0,114,15,0,0,0,114, + 92,0,0,0,114,155,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, @@ -979,22 +979,22 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 114,108,116,9,100,4,124,0,106,7,100,5,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, + 100,6,124,0,106,7,124,0,106,0,131,3,1,0,87,0, + 53,0,100,3,124,0,95,4,88,0,124,1,83,0,41,7, + 78,114,150,0,0,0,84,70,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,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, + 79,0,0,0,114,150,0,0,0,114,63,0,0,0,114,155, 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, @@ -1158,7 +1158,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 170,0,0,0,114,115,0,0,0,114,97,0,0,0,114,156, 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, @@ -1255,7 +1255,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, 41,1,114,97,0,0,0,114,168,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,155,0,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,156,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, @@ -1294,7 +1294,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,0,114,156,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, @@ -1325,7 +1325,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,218,8,101, + 0,114,59,0,0,0,41,4,114,30,0,0,0,218,8,101, 120,99,95,116,121,112,101,218,9,101,120,99,95,118,97,108, 117,101,218,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, @@ -1762,7 +1762,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,0,41,2,78,78,41,1,78,41,2,78,114,22,0, 0,0,41,4,78,78,114,10,0,0,0,114,22,0,0,0, 41,50,114,3,0,0,0,114,126,0,0,0,114,12,0,0, - 0,114,18,0,0,0,114,59,0,0,0,114,33,0,0,0, + 0,114,18,0,0,0,114,60,0,0,0,114,33,0,0,0, 114,42,0,0,0,114,19,0,0,0,114,20,0,0,0,114, 49,0,0,0,114,50,0,0,0,114,53,0,0,0,114,65, 0,0,0,114,67,0,0,0,114,76,0,0,0,114,86,0, diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 987ba5f33866..9bcf05057d1f 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -278,7 +278,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,84,13,0,0,114,28,0,0,0,114,16,0, + 0,0,0,105,85,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, @@ -392,7 +392,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,37,1,0,0,115,72,0,0, + 109,95,115,111,117,114,99,101,38,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, @@ -473,7 +473,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,108,1,0,0,115,52,0, + 114,111,109,95,99,97,99,104,101,109,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, @@ -508,7 +508,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,148,1,0,0,115,20, + 115,111,117,114,99,101,102,105,108,101,149,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, @@ -522,7 +522,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,167,1,0,0,115,16,0,0,0,0,1,14,1,2,1, + 100,168,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,0,0,0,0,2,0,0,0, 8,0,0,0,67,0,0,0,115,52,0,0,0,122,14,116, @@ -536,7 +536,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,179,1,0,0,115,12, + 95,99,97,108,99,95,109,111,100,101,180,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, @@ -574,7 +574,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,199,1,0,0,115,18, + 109,101,95,119,114,97,112,112,101,114,200,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, @@ -592,7 +592,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,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,210,1,0, + 0,114,6,0,0,0,218,5,95,119,114,97,112,211,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, @@ -600,7 +600,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,191,1,0,0,115,14,0,0, + 101,99,107,95,110,97,109,101,192,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,0,0,0, 0,5,0,0,0,6,0,0,0,67,0,0,0,115,60,0, @@ -628,7 +628,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,219,1,0, + 100,95,109,111,100,117,108,101,95,115,104,105,109,220,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,158, @@ -695,7 +695,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,236,1,0,0,115,28,0,0,0, + 105,102,121,95,112,121,99,237,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, @@ -749,7 +749,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,13,2, + 95,116,105,109,101,115,116,97,109,112,95,112,121,99,14,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, @@ -795,7 +795,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,218,11,115,111,117,114,99,101,95,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,41,2,0, + 100,97,116,101,95,104,97,115,104,95,112,121,99,42,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, @@ -819,7 +819,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,65,2,0, + 112,105,108,101,95,98,121,116,101,99,111,100,101,66,2,0, 0,115,20,0,0,0,0,2,10,1,10,1,12,1,8,1, 12,1,4,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, @@ -838,7 +838,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,78,2,0,0,115,12,0,0,0,0, + 109,112,95,112,121,99,79,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,80,0,0,0,116, @@ -856,7 +856,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,88,2, + 100,101,95,116,111,95,104,97,115,104,95,112,121,99,89,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, @@ -884,7 +884,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,99,2,0,0,115,10,0,0,0, + 95,115,111,117,114,99,101,100,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, @@ -946,7 +946,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,116,2,0,0,115,62,0,0,0,0,12,8,4,4, + 111,110,117,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, @@ -983,7 +983,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,196,2,0,0, + 112,101,110,95,114,101,103,105,115,116,114,121,197,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, @@ -1009,7 +1009,7 @@ 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,203, + 115,101,97,114,99,104,95,114,101,103,105,115,116,114,121,204, 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,8,1, 122,38,87,105,110,100,111,119,115,82,101,103,105,115,116,114, @@ -1032,7 +1032,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,218,2,0,0,115,28,0,0,0, + 110,100,95,115,112,101,99,219,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, @@ -1051,7 +1051,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,234,2,0,0, + 11,102,105,110,100,95,109,111,100,117,108,101,235,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, @@ -1061,7 +1061,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,184,2,0,0,115,28,0,0,0,8, + 0,114,191,0,0,0,185,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,12,15,2,1,114,191,0,0,0, 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -1097,7 +1097,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,253,2,0,0,115,8,0,0,0,0, + 0,114,182,0,0,0,254,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,0,0,0,0,2,0, @@ -1108,7 +1108,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,5,3,0,0,115,2,0,0,0,0,1,122,27,95,76, + 101,6,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, @@ -1128,7 +1128,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,8,3,0,0,115,12,0,0,0,0,2,12,1, + 117,108,101,9,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, @@ -1139,14 +1139,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,16,3,0, + 218,11,108,111,97,100,95,109,111,100,117,108,101,17,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,248,2,0,0,115,10,0,0,0, + 0,0,114,208,0,0,0,249,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, @@ -1171,7 +1171,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,23,3,0,0,115,2,0,0,0,0,6, + 109,116,105,109,101,24,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, @@ -1205,7 +1205,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,31,3,0,0,115,2,0,0,0,0, + 95,115,116,97,116,115,32,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, @@ -1229,7 +1229,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,45,3,0,0,115,2,0,0,0,0,8, + 101,99,111,100,101,46,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, @@ -1246,7 +1246,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,55,3,0,0,115,2,0,0,0,0,1, + 114,225,0,0,0,56,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, 0,0,0,0,5,0,0,0,10,0,0,0,67,0,0,0, @@ -1267,7 +1267,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,62,3,0,0,115,20,0,0,0,0,2,10, + 117,114,99,101,63,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, @@ -1289,7 +1289,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,72,3,0,0,115, + 114,99,101,95,116,111,95,99,111,100,101,73,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, @@ -1367,7 +1367,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,80,3,0,0,115,152,0,0,0,0,7, + 114,213,0,0,0,81,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, @@ -1383,7 +1383,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,21,3,0,0,115, + 0,114,6,0,0,0,114,221,0,0,0,22,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, @@ -1413,7 +1413,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 170,3,0,0,115,4,0,0,0,0,3,6,1,122,19,70, + 171,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, @@ -1422,7 +1422,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,176,3,0,0,115,6,0,0,0,0,1,12, + 101,113,95,95,177,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, @@ -1430,7 +1430,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,180, + 114,6,0,0,0,218,8,95,95,104,97,115,104,95,95,181, 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, @@ -1445,7 +1445,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,183,3,0,0,115,2,0,0,0,0,10,122,22, + 0,0,0,184,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,0, 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, @@ -1455,7 +1455,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,195,3,0,0,115,2,0,0,0,0, + 0,114,179,0,0,0,196,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, @@ -1475,7 +1475,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,90,4,114,101,97,100,114,65,0,0,0,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,200,3,0,0,115,10,0,0,0,0,2,14,1, + 0,0,0,201,3,0,0,115,10,0,0,0,0,2,14,1, 16,1,28,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, @@ -1484,7 +1484,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,211,3,0,0,115,6,0,0,0, + 95,114,101,97,100,101,114,212,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, @@ -1497,7 +1497,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 217,3,0,0,115,4,0,0,0,0,1,20,1,122,24,70, + 218,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, 0,0,0,0,3,0,0,0,3,0,0,0,67,0,0,0, @@ -1509,7 +1509,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 69,114,114,111,114,114,38,0,0,0,114,47,0,0,0,114, 44,0,0,0,114,255,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,221,3,0,0,115,8,0,0,0, + 99,101,95,112,97,116,104,222,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, @@ -1521,7 +1521,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,2,1,0, - 0,227,3,0,0,115,8,0,0,0,0,1,8,1,4,1, + 0,228,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, @@ -1531,7 +1531,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,233,3,0,0,115,2,0,0,0,0,1,122,19, + 110,116,115,234,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, @@ -1540,7 +1540,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,114,0,1,0,0,114,4,1,0,0,114,2,1,0,0, 114,8,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,165,3,0, + 0,0,0,114,6,0,0,0,114,239,0,0,0,166,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,11,2,1,10,5,8,4, 8,6,8,6,114,239,0,0,0,99,0,0,0,0,0,0, @@ -1563,7 +1563,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,241,3,0, + 0,0,0,114,6,0,0,0,114,224,0,0,0,242,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, @@ -1574,7 +1574,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,246,3,0,0,115,4,0,0,0,0,2,8, + 226,0,0,0,247,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,11,1,0,0,99,3,0, @@ -1609,7 +1609,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 12,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,251,3,0,0,115,48,0,0,0,0,2,12, + 225,0,0,0,252,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,28, 1,2,1,12,1,16,1,16,2,8,1,2,255,122,25,83, @@ -1618,7 +1618,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,9,1,0,0,237,3,0,0,115,8,0,0,0, + 0,0,114,9,1,0,0,238,3,0,0,115,8,0,0,0, 8,2,4,2,8,5,8,5,114,9,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, @@ -1640,7 +1640,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,30,4,0,0,115,22,0,0,0, + 0,0,114,213,0,0,0,31,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, @@ -1651,13 +1651,13 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,46,4,0,0,115,2,0,0,0,0,2,122,31,83,111, + 0,47,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,15,1,0,0,26,4,0,0,115,6,0,0,0, + 0,0,114,15,1,0,0,27,4,0,0,115,6,0,0,0, 8,2,4,2,8,16,114,15,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, @@ -1677,7 +1677,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,5,1,0,0,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,114,209,0,0,0,63,4,0,0, + 0,0,114,6,0,0,0,114,209,0,0,0,64,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, @@ -1686,7 +1686,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 67,4,0,0,115,6,0,0,0,0,1,12,1,10,255,122, + 68,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, @@ -1694,7 +1694,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 71,4,0,0,115,2,0,0,0,0,1,122,28,69,120,116, + 72,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,0,0,0,0,3,0,0,0,5,0,0,0,67,0, @@ -1711,7 +1711,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,74,4,0,0,115,18,0,0,0,0,2,4,1,4, + 0,0,75,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, @@ -1728,7 +1728,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 90,12,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,253,0, 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,114,217,0,0,0,82,4,0,0,115,10,0,0,0,0, + 0,114,217,0,0,0,83,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, @@ -1746,7 +1746,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,91,4,0,0, + 0,218,9,60,103,101,110,101,120,112,114,62,92,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, @@ -1754,7 +1754,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,88,4,0,0,115,8, + 114,6,0,0,0,114,182,0,0,0,89,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, @@ -1765,7 +1765,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,94, + 114,3,0,0,0,114,6,0,0,0,114,213,0,0,0,95, 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, @@ -1776,14 +1776,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 97,118,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,98,4,0,0,115,2,0,0,0,0,2,122,30,69, + 0,0,99,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,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,102,4,0,0,115,2,0,0,0,0,3,122, + 179,0,0,0,103,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, @@ -1792,7 +1792,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,252, - 0,0,0,55,4,0,0,115,22,0,0,0,8,2,4,6, + 0,0,0,56,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,252,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, @@ -1834,7 +1834,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,115,4,0,0,115, + 0,114,6,0,0,0,114,209,0,0,0,116,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, @@ -1852,7 +1852,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 1,0,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,121,4,0,0,115,8,0,0,0,0,2,18, + 97,109,101,115,122,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, @@ -1865,7 +1865,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,131,4,0,0,115,4,0,0,0,0,1, + 114,25,1,0,0,132,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, @@ -1881,7 +1881,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,135,4,0,0,115,16,0,0,0,0, + 99,117,108,97,116,101,136,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, @@ -1890,7 +1890,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 161,0,131,1,83,0,114,110,0,0,0,41,2,114,6,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,148,4,0,0,115,2,0,0,0,0,1, + 116,101,114,95,95,149,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, @@ -1898,7 +1898,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,151,4,0,0,115,2,0, + 103,101,116,105,116,101,109,95,95,152,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,0,0,0,0,3,0,0, @@ -1907,7 +1907,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,154,4,0,0,115,2,0,0,0,0,1, + 116,101,109,95,95,155,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, @@ -1915,7 +1915,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,157,4,0,0,115,2,0,0,0,0,1,122, + 101,110,95,95,158,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, @@ -1924,7 +1924,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,160,4,0,0,115,2,0,0,0,0,1,122, + 112,114,95,95,161,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, @@ -1932,7 +1932,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,163,4,0,0,115,2,0,0,0,0, + 97,105,110,115,95,95,164,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,0,0,0,0,2,0,0,0,3, @@ -1940,7 +1940,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,166,4,0,0,115,2,0,0,0,0, + 0,114,186,0,0,0,167,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, @@ -1948,7 +1948,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,108, + 114,3,0,0,0,114,6,0,0,0,114,22,1,0,0,109, 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, @@ -1965,7 +1965,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,172,4,0,0,115,2,0,0,0,0,1,122,25,95,78, + 0,173,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, @@ -1982,21 +1982,21 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 101,41,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,175,4,0,0,115,2,0,0,0, + 108,101,95,114,101,112,114,176,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,184,4,0,0,115,2,0,0,0,0,1,122, + 182,0,0,0,185,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,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,187,4,0,0,115,2,0,0,0,0,1,122, + 229,0,0,0,188,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, @@ -2005,21 +2005,21 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,190,4,0,0,115,2,0, + 6,0,0,0,114,213,0,0,0,191,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,193,4,0,0,115,2,0,0,0,0,1,122, + 212,0,0,0,194,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,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,253,0,0,0, 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, - 217,0,0,0,196,4,0,0,115,2,0,0,0,0,1,122, + 217,0,0,0,197,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, @@ -2037,7 +2037,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,199,4,0,0,115,8,0,0,0,0,7,6,1,4, + 0,0,200,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, @@ -2045,7 +2045,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,171,4,0,0,115,18,0, + 6,0,0,0,114,43,1,0,0,172,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, @@ -2086,7 +2086,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,217,4,0,0,115,10,0,0,0, + 0,0,114,46,1,0,0,218,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, @@ -2106,7 +2106,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,227,4,0,0,115, + 95,112,97,116,104,95,104,111,111,107,115,228,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, @@ -2137,7 +2137,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,240,4, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,241,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, @@ -2155,7 +2155,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,6,5,0,0, + 97,99,121,95,103,101,116,95,115,112,101,99,7,5,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, @@ -2187,7 +2187,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,21,5,0,0,115,40,0,0,0,0,5,4,1,8, + 101,99,22,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, @@ -2214,7 +2214,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,53,5,0,0,115,26,0,0,0,0, + 0,114,203,0,0,0,54,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, @@ -2234,7 +2234,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,77,5,0,0,115,8,0,0, + 0,0,0,114,206,0,0,0,78,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,99,3,0,0,0,0,0,0,0,0,0,0,0,7,0, @@ -2273,7 +2273,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,114,59,1,0,0,218,7,112,97,116,116,101,114,110, 90,5,102,111,117,110,100,114,3,0,0,0,114,3,0,0, 0,114,6,0,0,0,218,18,102,105,110,100,95,100,105,115, - 116,114,105,98,117,116,105,111,110,115,90,5,0,0,115,14, + 116,114,105,98,117,116,105,111,110,115,91,5,0,0,115,14, 0,0,0,0,10,8,1,12,1,8,1,6,1,22,1,12, 1,122,29,80,97,116,104,70,105,110,100,101,114,46,102,105, 110,100,95,100,105,115,116,114,105,98,117,116,105,111,110,115, @@ -2292,7 +2292,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,41,1,218,12,95,115,101,97,114,99,104,95,112,97, 116,104,41,2,114,32,0,0,0,114,44,0,0,0,169,2, 114,193,0,0,0,114,63,1,0,0,114,3,0,0,0,114, - 6,0,0,0,114,19,1,0,0,112,5,0,0,115,4,0, + 6,0,0,0,114,19,1,0,0,113,5,0,0,115,4,0, 0,0,4,2,2,255,122,43,80,97,116,104,70,105,110,100, 101,114,46,95,115,101,97,114,99,104,95,112,97,116,104,115, 46,60,108,111,99,97,108,115,62,46,60,103,101,110,101,120, @@ -2302,7 +2302,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 105,116,99,104,95,112,97,116,104,41,4,114,193,0,0,0, 114,63,1,0,0,90,5,112,97,116,104,115,114,67,1,0, 0,114,3,0,0,0,114,66,1,0,0,114,6,0,0,0, - 114,61,1,0,0,108,5,0,0,115,8,0,0,0,0,3, + 114,61,1,0,0,109,5,0,0,115,8,0,0,0,0,3, 8,1,18,2,10,254,122,24,80,97,116,104,70,105,110,100, 101,114,46,95,115,101,97,114,99,104,95,112,97,116,104,115, 99,1,0,0,0,0,0,0,0,0,0,0,0,5,0,0, @@ -2322,7 +2322,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,114,69,1,0,0,114,70,1,0,0,114,71,1,0,0, 90,13,80,89,80,89,95,79,80,69,78,95,66,85,71,114, 3,0,0,0,114,3,0,0,0,114,6,0,0,0,114,68, - 1,0,0,117,5,0,0,115,16,0,0,0,0,2,12,1, + 1,0,0,118,5,0,0,115,16,0,0,0,0,2,12,1, 8,1,8,1,4,1,16,1,10,1,28,1,122,23,80,97, 116,104,70,105,110,100,101,114,46,95,115,119,105,116,99,104, 95,112,97,116,104,99,3,0,0,0,0,0,0,0,0,0, @@ -2340,7 +2340,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 1,0,0,114,60,1,0,0,90,8,116,101,109,112,108,97, 116,101,90,8,109,97,110,105,102,101,115,116,114,3,0,0, 0,114,3,0,0,0,114,6,0,0,0,218,13,95,109,97, - 116,99,104,101,115,95,105,110,102,111,128,5,0,0,115,8, + 116,99,104,101,115,95,105,110,102,111,129,5,0,0,115,8, 0,0,0,0,2,8,1,4,1,12,1,122,24,80,97,116, 104,70,105,110,100,101,114,46,95,109,97,116,99,104,101,115, 95,105,110,102,111,99,3,0,0,0,0,0,0,0,0,0, @@ -2355,7 +2355,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 6,115,101,97,114,99,104,114,85,0,0,0,114,75,1,0, 0,114,76,1,0,0,114,3,0,0,0,114,3,0,0,0, 114,6,0,0,0,218,15,95,109,97,116,99,104,101,115,95, - 108,101,103,97,99,121,135,5,0,0,115,8,0,0,0,0, + 108,101,103,97,99,121,136,5,0,0,115,8,0,0,0,0, 2,8,1,4,1,12,1,122,26,80,97,116,104,70,105,110, 100,101,114,46,95,109,97,116,99,104,101,115,95,108,101,103, 97,99,121,99,3,0,0,0,0,0,0,0,0,0,0,0, @@ -2372,14 +2372,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,78,1,0,0,114,79,1,0,0,41,2,114,32,0,0, 0,114,41,1,0,0,169,2,114,193,0,0,0,114,77,1, 0,0,114,3,0,0,0,114,6,0,0,0,114,19,1,0, - 0,147,5,0,0,115,8,0,0,0,4,0,2,1,12,1, + 0,148,5,0,0,115,8,0,0,0,4,0,2,1,12,1, 12,254,122,42,80,97,116,104,70,105,110,100,101,114,46,95, 115,101,97,114,99,104,95,112,97,116,104,46,60,108,111,99, 97,108,115,62,46,60,103,101,110,101,120,112,114,62,41,3, 90,6,105,115,95,100,105,114,114,67,0,0,0,90,7,105, 116,101,114,100,105,114,41,3,114,193,0,0,0,90,4,114, 111,111,116,114,63,1,0,0,114,3,0,0,0,114,81,1, - 0,0,114,6,0,0,0,114,65,1,0,0,142,5,0,0, + 0,0,114,6,0,0,0,114,65,1,0,0,143,5,0,0, 115,8,0,0,0,0,2,8,1,4,1,12,1,122,23,80, 97,116,104,70,105,110,100,101,114,46,95,115,101,97,114,99, 104,95,112,97,116,104,41,1,78,41,2,78,78,41,1,78, @@ -2391,7 +2391,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 97,116,105,99,109,101,116,104,111,100,114,68,1,0,0,114, 78,1,0,0,114,79,1,0,0,114,65,1,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,213,4,0,0,115,54,0,0,0, + 0,0,114,45,1,0,0,214,4,0,0,115,54,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,12,12, 2,1,12,17,2,1,10,8,2,1,10,10,2,1,10,6, @@ -2437,7 +2437,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,167,5,0,0,115,4,0,0, + 0,0,0,114,19,1,0,0,168,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, @@ -2450,7 +2450,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,84,1,0,0,114,6,0,0,0,114,209,0,0,0, - 161,5,0,0,115,16,0,0,0,0,4,4,1,12,1,26, + 162,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, @@ -2459,7 +2459,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,86,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,175, + 114,3,0,0,0,114,6,0,0,0,114,46,1,0,0,176, 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, @@ -2483,7 +2483,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 181,5,0,0,115,8,0,0,0,0,7,10,1,8,1,8, + 182,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, @@ -2493,7 +2493,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 41,7,114,119,0,0,0,114,188,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,193,5,0,0,115,8, + 114,6,0,0,0,114,58,1,0,0,194,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,0,0,0,0,14, @@ -2548,7 +2548,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,198,5,0,0,115,74,0,0,0,0,5,4, + 203,0,0,0,199,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, @@ -2580,7 +2580,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,19,6,0,0,115,4,0,0,0,6,0,2,0, + 109,112,62,20,6,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, @@ -2596,7 +2596,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,91,1,0,0,246,5,0, + 0,0,0,114,6,0,0,0,114,91,1,0,0,247,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, @@ -2635,14 +2635,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,169,2,114,193,0,0,0,114,90,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,31,6,0,0,115,6,0,0,0,0,2,8,1,12, + 101,114,32,6,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,90,1,0,0,114,97,1,0,0,114, 3,0,0,0,114,96,1,0,0,114,6,0,0,0,218,9, - 112,97,116,104,95,104,111,111,107,21,6,0,0,115,4,0, + 112,97,116,104,95,104,111,111,107,22,6,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, @@ -2651,7 +2651,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, - 39,6,0,0,115,2,0,0,0,0,1,122,19,70,105,108, + 40,6,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, @@ -2659,7 +2659,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,114,58,1,0,0,114,203,0,0,0,114,91,1,0, 0,114,207,0,0,0,114,98,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,83,1,0,0,152,5,0,0,115,22,0, + 6,0,0,0,114,83,1,0,0,153,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,83,1,0,0,99,4,0, 0,0,0,0,0,0,0,0,0,0,6,0,0,0,8,0, @@ -2682,7 +2682,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,45,6,0,0,115,34, + 95,117,112,95,109,111,100,117,108,101,46,6,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,102,1,0,0,99,0,0,0,0,0, @@ -2702,7 +2702,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,68,6,0,0,115,8,0, + 6,0,0,0,114,184,0,0,0,69,6,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,0,0,0,0,12,0,0,0, 9,0,0,0,67,0,0,0,115,178,1,0,0,124,0,97, @@ -2755,7 +2755,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,104,6,0,0,115,4,0,0,0,4,0,2,0, + 1,0,0,105,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, @@ -2767,7 +2767,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,92,1,0,0,120,6,0,0,115,4,0,0,0, + 0,0,114,92,1,0,0,121,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, @@ -2791,7 +2791,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,79,6,0,0,115,78,0,0,0,0, + 95,115,101,116,117,112,80,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, @@ -2811,7 +2811,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,186,0,0,0,114,45,1,0,0,41,2,114,109,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,144,6,0, + 0,0,0,218,8,95,105,110,115,116,97,108,108,145,6,0, 0,115,8,0,0,0,0,2,8,1,6,1,20,1,114,112, 1,0,0,41,1,114,60,0,0,0,41,1,78,41,3,78, 78,78,41,2,114,73,0,0,0,114,73,0,0,0,41,1, @@ -2845,7 +2845,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 8,60,109,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,10,22,10,127,0,12,16,1,12,2,4,1, + 8,7,8,9,10,22,10,127,0,13,16,1,12,2,4,1, 4,2,6,2,6,2,8,2,16,71,8,40,8,19,8,12, 8,12,8,28,8,17,8,33,8,28,8,24,10,13,10,10, 10,11,8,14,6,3,4,1,2,255,12,68,14,64,14,29, diff --git a/Python/importlib_zipimport.h b/Python/importlib_zipimport.h index 056e85d343d8..6c9c4e846552 100644 --- a/Python/importlib_zipimport.h +++ b/Python/importlib_zipimport.h @@ -703,18 +703,18 @@ const unsigned char _Py_M__zipimport[] = { 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, + 2,131,1,130,1,100,3,97,0,122,60,122,16,100,5,100, + 6,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,88,0,87,0,53,0,100,4,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,108,97,98,108,101,84,70,114,0,0,0,0,169,1,218, + 10,100,101,99,111,109,112,114,101,115,115,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, From webhook-mailer at python.org Sat Aug 24 11:26:45 2019 From: webhook-mailer at python.org (Jason R. Coombs) Date: Sat, 24 Aug 2019 15:26:45 -0000 Subject: [Python-checkins] bpo-37772: fix zipfile.Path.iterdir() outputs (GH-15170) Message-ID: https://github.com/python/cpython/commit/a4e2991bdc993b60b6457c8a38d6e4a1fc845781 commit: a4e2991bdc993b60b6457c8a38d6e4a1fc845781 branch: master author: shireenrao committer: Jason R. Coombs date: 2019-08-24T11:26:41-04:00 summary: bpo-37772: fix zipfile.Path.iterdir() outputs (GH-15170) * fix Path._add_implied_dirs to include all implied directories * fix Path._add_implied_dirs to include all implied directories * Optimize code by using sets instead of lists * ?? Added by blurb_it. * fix Path._add_implied_dirs to include all implied directories * Optimize code by using sets instead of lists * ?? Added by blurb_it. * Add tests to zipfile.Path.iterdir() fix * Update test for zipfile.Path.iterdir() * remove whitespace from test file * Rewrite NEWS blurb to describe the user-facing impact and avoid implementation details. * remove redundant [] within set comprehension * Update to use unique_everseen to maintain order and other suggestions in review * remove whitespace and add back add_dirs in tests * Add new standalone function parents using posixpath to get parents of a directory * removing whitespace (sorry) * Remove import pathlib from zipfile.py * Rewrite _parents as a slice on a generator of the ancestry of a path. * Remove check for '.' and '/', now that parents no longer returns those. * Separate calculation of implied dirs from adding those * Re-use _implied_dirs in tests for generating zipfile with dir entries. * Replace three fixtures (abcde, abcdef, abde) with one representative example alpharep. * Simplify implementation of _implied_dirs by collapsing the generation of parent directories for each name. files: A Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst M Lib/test/test_zipfile.py M Lib/zipfile.py diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py index 0c8ffcdbf14a..8e437e5cb2b9 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -2397,37 +2397,49 @@ def test_extract_command(self): consume = tuple -def add_dirs(zipfile): +def add_dirs(zf): """ - Given a writable zipfile, inject directory entries for + Given a writable zip file zf, 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 + for name in zipfile.Path._implied_dirs(zf.namelist()): + zf.writestr(name, b"") + return zf -def build_abcde_files(): +def build_alpharep_fixture(): """ Create a zip file with this structure: . ??? a.txt - ??? b - ??? c.txt - ??? d - ??? e.txt + ??? b + ? ??? c.txt + ? ??? d + ? ? ??? e.txt + ? ??? f.txt + ??? g + ??? h + ??? i.txt + + This fixture has the following key characteristics: + + - a file at the root (a) + - a file two levels deep (b/d/e) + - multiple files in a directory (b/c, b/f) + - a directory containing only a directory (g/h) + + "alpha" because it uses alphabet + "rep" because it's a representative example """ 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" + zf.writestr("b/f.txt", b"content of f") + zf.writestr("g/h/i.txt", b"content of i") + zf.filename = "alpharep.zip" return zf @@ -2436,60 +2448,64 @@ def setUp(self): self.fixtures = contextlib.ExitStack() self.addCleanup(self.fixtures.close) - def zipfile_abcde(self): + def zipfile_alpharep(self): with self.subTest(): - yield build_abcde_files() + yield build_alpharep_fixture() with self.subTest(): - yield add_dirs(build_abcde_files()) + yield add_dirs(build_alpharep_fixture()) 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 + for alpharep in self.zipfile_alpharep(): + buffer = alpharep.fp + alpharep.close() + path = tmpdir / alpharep.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) + def test_iterdir_and_types(self): + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) assert root.is_dir() - a, b = root.iterdir() + a, b, g = root.iterdir() assert a.is_file() assert b.is_dir() - c, d = b.iterdir() - assert c.is_file() + assert g.is_dir() + c, f, d = b.iterdir() + assert c.is_file() and f.is_file() e, = d.iterdir() assert e.is_file() + h, = g.iterdir() + i, = h.iterdir() + assert i.is_file() def test_open(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) - a, b = root.iterdir() + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) + a, b, g = 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() + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) + a, b, g = root.iterdir() assert a.read_text() == "content of a" assert a.read_bytes() == b"content of a" def test_joinpath(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) a = root.joinpath("a") assert a.is_file() e = root.joinpath("b").joinpath("d").joinpath("e.txt") assert e.read_text() == "content of e" def test_traverse_truediv(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) a = root / "a" assert a.is_file() e = root / "b" / "d" / "e.txt" @@ -2504,26 +2520,27 @@ def test_pathlike_construction(self): zipfile.Path(pathlike) def test_traverse_pathlike(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) root / pathlib.Path("a") def test_parent(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) assert (root / 'a').parent.at == '' assert (root / 'a' / 'b').parent.at == 'a/' def test_dir_parent(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) assert (root / 'b').parent.at == '' assert (root / 'b/').parent.at == '' def test_missing_dir_parent(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) assert (root / 'missing dir/').parent.at == '' + if __name__ == "__main__": unittest.main() diff --git a/Lib/zipfile.py b/Lib/zipfile.py index 3c1f1235034a..dfd090795019 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -7,6 +7,7 @@ import functools import importlib.util import io +import itertools import os import posixpath import shutil @@ -2104,6 +2105,65 @@ def _compile(file, optimize=-1): return (fname, archivename) +def _unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in itertools.filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element + + +def _parents(path): + """ + Given a path with elements separated by + posixpath.sep, generate all parents of that path. + + >>> list(_parents('b/d')) + ['b'] + >>> list(_parents('/b/d/')) + ['/b'] + >>> list(_parents('b/d/f/')) + ['b/d', 'b'] + >>> list(_parents('b')) + [] + >>> list(_parents('')) + [] + """ + return itertools.islice(_ancestry(path), 1, None) + + +def _ancestry(path): + """ + Given a path with elements separated by + posixpath.sep, generate all elements of that path + + >>> list(_ancestry('b/d')) + ['b/d', 'b'] + >>> list(_ancestry('/b/d/')) + ['/b/d', '/b'] + >>> list(_ancestry('b/d/f/')) + ['b/d/f', 'b/d', 'b'] + >>> list(_ancestry('b')) + ['b'] + >>> list(_ancestry('')) + [] + """ + path = path.rstrip(posixpath.sep) + while path and path != posixpath.sep: + yield path + path, tail = posixpath.split(path) + + class Path: """ A pathlib-compatible interface for zip files. @@ -2227,12 +2287,17 @@ def joinpath(self, add): __truediv__ = joinpath @staticmethod - def _add_implied_dirs(names): - return names + [ - name + "/" - for name in map(posixpath.dirname, names) - if name and name + "/" not in names - ] + def _implied_dirs(names): + return _unique_everseen( + parent + "/" + for name in names + for parent in _parents(name) + if parent + "/" not in names + ) + + @classmethod + def _add_implied_dirs(cls, names): + return names + list(cls._implied_dirs(names)) @property def parent(self): diff --git a/Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst b/Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst new file mode 100644 index 000000000000..f9ec6a33b07b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst @@ -0,0 +1 @@ +In ``zipfile.Path``, when adding implicit dirs, ensure that ancestral directories are added and that duplicates are excluded. From webhook-mailer at python.org Sat Aug 24 12:03:56 2019 From: webhook-mailer at python.org (Jason R. Coombs) Date: Sat, 24 Aug 2019 16:03:56 -0000 Subject: [Python-checkins] bpo-37772: fix zipfile.Path.iterdir() outputs (GH-15170) (#15461) Message-ID: https://github.com/python/cpython/commit/c410f381bf66c48d84812e19e3ba7c2878511a3e commit: c410f381bf66c48d84812e19e3ba7c2878511a3e branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Jason R. Coombs date: 2019-08-24T12:03:52-04:00 summary: bpo-37772: fix zipfile.Path.iterdir() outputs (GH-15170) (#15461) * fix Path._add_implied_dirs to include all implied directories * fix Path._add_implied_dirs to include all implied directories * Optimize code by using sets instead of lists * ?? Added by blurb_it. * fix Path._add_implied_dirs to include all implied directories * Optimize code by using sets instead of lists * ?? Added by blurb_it. * Add tests to zipfile.Path.iterdir() fix * Update test for zipfile.Path.iterdir() * remove whitespace from test file * Rewrite NEWS blurb to describe the user-facing impact and avoid implementation details. * remove redundant [] within set comprehension * Update to use unique_everseen to maintain order and other suggestions in review * remove whitespace and add back add_dirs in tests * Add new standalone function parents using posixpath to get parents of a directory * removing whitespace (sorry) * Remove import pathlib from zipfile.py * Rewrite _parents as a slice on a generator of the ancestry of a path. * Remove check for '.' and '/', now that parents no longer returns those. * Separate calculation of implied dirs from adding those * Re-use _implied_dirs in tests for generating zipfile with dir entries. * Replace three fixtures (abcde, abcdef, abde) with one representative example alpharep. * Simplify implementation of _implied_dirs by collapsing the generation of parent directories for each name. (cherry picked from commit a4e2991bdc993b60b6457c8a38d6e4a1fc845781) Co-authored-by: shireenrao files: A Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst M Lib/test/test_zipfile.py M Lib/zipfile.py diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py index 0c8ffcdbf14a..8e437e5cb2b9 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -2397,37 +2397,49 @@ def test_extract_command(self): consume = tuple -def add_dirs(zipfile): +def add_dirs(zf): """ - Given a writable zipfile, inject directory entries for + Given a writable zip file zf, 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 + for name in zipfile.Path._implied_dirs(zf.namelist()): + zf.writestr(name, b"") + return zf -def build_abcde_files(): +def build_alpharep_fixture(): """ Create a zip file with this structure: . ??? a.txt - ??? b - ??? c.txt - ??? d - ??? e.txt + ??? b + ? ??? c.txt + ? ??? d + ? ? ??? e.txt + ? ??? f.txt + ??? g + ??? h + ??? i.txt + + This fixture has the following key characteristics: + + - a file at the root (a) + - a file two levels deep (b/d/e) + - multiple files in a directory (b/c, b/f) + - a directory containing only a directory (g/h) + + "alpha" because it uses alphabet + "rep" because it's a representative example """ 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" + zf.writestr("b/f.txt", b"content of f") + zf.writestr("g/h/i.txt", b"content of i") + zf.filename = "alpharep.zip" return zf @@ -2436,60 +2448,64 @@ def setUp(self): self.fixtures = contextlib.ExitStack() self.addCleanup(self.fixtures.close) - def zipfile_abcde(self): + def zipfile_alpharep(self): with self.subTest(): - yield build_abcde_files() + yield build_alpharep_fixture() with self.subTest(): - yield add_dirs(build_abcde_files()) + yield add_dirs(build_alpharep_fixture()) 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 + for alpharep in self.zipfile_alpharep(): + buffer = alpharep.fp + alpharep.close() + path = tmpdir / alpharep.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) + def test_iterdir_and_types(self): + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) assert root.is_dir() - a, b = root.iterdir() + a, b, g = root.iterdir() assert a.is_file() assert b.is_dir() - c, d = b.iterdir() - assert c.is_file() + assert g.is_dir() + c, f, d = b.iterdir() + assert c.is_file() and f.is_file() e, = d.iterdir() assert e.is_file() + h, = g.iterdir() + i, = h.iterdir() + assert i.is_file() def test_open(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) - a, b = root.iterdir() + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) + a, b, g = 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() + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) + a, b, g = root.iterdir() assert a.read_text() == "content of a" assert a.read_bytes() == b"content of a" def test_joinpath(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) a = root.joinpath("a") assert a.is_file() e = root.joinpath("b").joinpath("d").joinpath("e.txt") assert e.read_text() == "content of e" def test_traverse_truediv(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) a = root / "a" assert a.is_file() e = root / "b" / "d" / "e.txt" @@ -2504,26 +2520,27 @@ def test_pathlike_construction(self): zipfile.Path(pathlike) def test_traverse_pathlike(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) root / pathlib.Path("a") def test_parent(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) assert (root / 'a').parent.at == '' assert (root / 'a' / 'b').parent.at == 'a/' def test_dir_parent(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) assert (root / 'b').parent.at == '' assert (root / 'b/').parent.at == '' def test_missing_dir_parent(self): - for zipfile_abcde in self.zipfile_abcde(): - root = zipfile.Path(zipfile_abcde) + for alpharep in self.zipfile_alpharep(): + root = zipfile.Path(alpharep) assert (root / 'missing dir/').parent.at == '' + if __name__ == "__main__": unittest.main() diff --git a/Lib/zipfile.py b/Lib/zipfile.py index 3c1f1235034a..dfd090795019 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -7,6 +7,7 @@ import functools import importlib.util import io +import itertools import os import posixpath import shutil @@ -2104,6 +2105,65 @@ def _compile(file, optimize=-1): return (fname, archivename) +def _unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in itertools.filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element + + +def _parents(path): + """ + Given a path with elements separated by + posixpath.sep, generate all parents of that path. + + >>> list(_parents('b/d')) + ['b'] + >>> list(_parents('/b/d/')) + ['/b'] + >>> list(_parents('b/d/f/')) + ['b/d', 'b'] + >>> list(_parents('b')) + [] + >>> list(_parents('')) + [] + """ + return itertools.islice(_ancestry(path), 1, None) + + +def _ancestry(path): + """ + Given a path with elements separated by + posixpath.sep, generate all elements of that path + + >>> list(_ancestry('b/d')) + ['b/d', 'b'] + >>> list(_ancestry('/b/d/')) + ['/b/d', '/b'] + >>> list(_ancestry('b/d/f/')) + ['b/d/f', 'b/d', 'b'] + >>> list(_ancestry('b')) + ['b'] + >>> list(_ancestry('')) + [] + """ + path = path.rstrip(posixpath.sep) + while path and path != posixpath.sep: + yield path + path, tail = posixpath.split(path) + + class Path: """ A pathlib-compatible interface for zip files. @@ -2227,12 +2287,17 @@ def joinpath(self, add): __truediv__ = joinpath @staticmethod - def _add_implied_dirs(names): - return names + [ - name + "/" - for name in map(posixpath.dirname, names) - if name and name + "/" not in names - ] + def _implied_dirs(names): + return _unique_everseen( + parent + "/" + for name in names + for parent in _parents(name) + if parent + "/" not in names + ) + + @classmethod + def _add_implied_dirs(cls, names): + return names + list(cls._implied_dirs(names)) @property def parent(self): diff --git a/Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst b/Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst new file mode 100644 index 000000000000..f9ec6a33b07b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst @@ -0,0 +1 @@ +In ``zipfile.Path``, when adding implicit dirs, ensure that ancestral directories are added and that duplicates are excluded. From webhook-mailer at python.org Sat Aug 24 13:01:40 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sat, 24 Aug 2019 17:01:40 -0000 Subject: [Python-checkins] (TH-15402) Message-ID: https://github.com/python/cpython/commit/a50f0a4c2bd997e4534162ecc1853cb54c7ae902 commit: a50f0a4c2bd997e4534162ecc1853cb54c7ae902 branch: master author: GeeTransit committer: Terry Jan Reedy date: 2019-08-24T13:01:36-04:00 summary: (TH-15402) files: M Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst index a44fd3b59b4f..2a5b0bd0e90c 100644 --- a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst @@ -1 +1 @@ -IDLE - Refactor autocompete and improve testing. +Refactor IDLE autocomplete and improve testing. From webhook-mailer at python.org Sat Aug 24 13:19:41 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 24 Aug 2019 17:19:41 -0000 Subject: [Python-checkins] bpo-37812: Convert CHECK_SMALL_INT macro to a function so the return is explicit. (GH-15216) Message-ID: https://github.com/python/cpython/commit/5e63ab05f114987478a21612d918a1c0276fe9d2 commit: 5e63ab05f114987478a21612d918a1c0276fe9d2 branch: master author: Greg Price committer: Raymond Hettinger date: 2019-08-24T10:19:37-07:00 summary: bpo-37812: Convert CHECK_SMALL_INT macro to a function so the return is explicit. (GH-15216) files: A Misc/NEWS.d/next/Core and Builtins/2019-08-23-22-46-25.bpo-37812.vsWZwS.rst M Objects/longobject.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-23-22-46-25.bpo-37812.vsWZwS.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-23-22-46-25.bpo-37812.vsWZwS.rst new file mode 100644 index 000000000000..90c3ff3f7ef9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-23-22-46-25.bpo-37812.vsWZwS.rst @@ -0,0 +1,3 @@ +The ``CHECK_SMALL_INT`` macro used inside :file:`Object/longobject.c` has +been replaced with an explicit ``return`` at each call site, conditioned on +a ``static inline`` function ``is_small_int``. diff --git a/Objects/longobject.c b/Objects/longobject.c index 3978f5c4a167..74037be7a1ea 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -41,6 +41,13 @@ PyObject *_PyLong_One = NULL; -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive). */ static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS]; + +static inline int +is_small_int(long long ival) +{ + return -NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS; +} + #ifdef COUNT_ALLOCS Py_ssize_t _Py_quick_int_allocs, _Py_quick_neg_int_allocs; #endif @@ -49,7 +56,7 @@ static PyObject * get_small_int(sdigit ival) { PyObject *v; - assert(-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS); + assert(is_small_int(ival)); v = (PyObject *)&small_ints[ival + NSMALLNEGINTS]; Py_INCREF(v); #ifdef COUNT_ALLOCS @@ -60,17 +67,13 @@ get_small_int(sdigit ival) #endif return v; } -#define CHECK_SMALL_INT(ival) \ - do if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { \ - return get_small_int((sdigit)ival); \ - } while(0) static PyLongObject * maybe_small_long(PyLongObject *v) { if (v && Py_ABS(Py_SIZE(v)) <= 1) { sdigit ival = MEDIUM_VALUE(v); - if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { + if (is_small_int(ival)) { Py_DECREF(v); return (PyLongObject *)get_small_int(ival); } @@ -78,7 +81,8 @@ maybe_small_long(PyLongObject *v) return v; } #else -#define CHECK_SMALL_INT(ival) +#define is_small_int(ival) 0 +#define get_small_int(ival) (assert(0), NULL) #define maybe_small_long(val) (val) #endif @@ -293,7 +297,9 @@ _PyLong_Copy(PyLongObject *src) i = -(i); if (i < 2) { sdigit ival = MEDIUM_VALUE(src); - CHECK_SMALL_INT(ival); + if (is_small_int(ival)) { + return get_small_int(ival); + } } result = _PyLong_New(i); if (result != NULL) { @@ -315,7 +321,9 @@ PyLong_FromLong(long ival) int ndigits = 0; int sign; - CHECK_SMALL_INT(ival); + if (is_small_int(ival)) { + return get_small_int((sdigit)ival); + } if (ival < 0) { /* negate: can't write this as abs_ival = -ival since that @@ -1146,7 +1154,10 @@ PyLong_FromLongLong(long long ival) int ndigits = 0; int negative = 0; - CHECK_SMALL_INT(ival); + if (is_small_int(ival)) { + return get_small_int((sdigit)ival); + } + if (ival < 0) { /* avoid signed overflow on negation; see comments in PyLong_FromLong above. */ @@ -1218,7 +1229,10 @@ PyLong_FromSsize_t(Py_ssize_t ival) int ndigits = 0; int negative = 0; - CHECK_SMALL_INT(ival); + if (is_small_int(ival)) { + return get_small_int((sdigit)ival); + } + if (ival < 0) { /* avoid signed overflow when ival = SIZE_T_MIN */ abs_ival = (size_t)(-1-ival)+1; From webhook-mailer at python.org Sat Aug 24 13:43:58 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 24 Aug 2019 17:43:58 -0000 Subject: [Python-checkins] bpo-32118: Simplify docs for sequence comparison (GH-15450) Message-ID: https://github.com/python/cpython/commit/edd21129dd304e178ca8be82ba689488dfb58276 commit: edd21129dd304e178ca8be82ba689488dfb58276 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-24T10:43:55-07:00 summary: bpo-32118: Simplify docs for sequence comparison (GH-15450) files: M Doc/reference/expressions.rst diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 432327a87c37..ee13c5f4c6fc 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1425,6 +1425,10 @@ built-in types. themselves. For example, if ``x = float('NaN')``, ``3 < x``, ``x < 3``, ``x == x``, ``x != x`` are all false. This behavior is compliant with IEEE 754. +* ``None`` and ``NotImplemented`` are singletons. :PEP:`8` advises that + comparisons for singletons should always be done with ``is`` or ``is not``, + never the equality operators. + * Binary sequences (instances of :class:`bytes` or :class:`bytearray`) can be compared within and across their types. They compare lexicographically using the numeric values of their elements. @@ -1442,25 +1446,9 @@ built-in types. :exc:`TypeError`. Sequences compare lexicographically using comparison of corresponding - elements, whereby reflexivity of the elements is enforced. - - In enforcing reflexivity of elements, the comparison of collections assumes - that for a collection element ``x``, ``x == x`` is always true. Based on - that assumption, element identity is compared first, and element comparison - is performed only for distinct elements. This approach yields the same - result as a strict element comparison would, if the compared elements are - reflexive. For non-reflexive elements, the result is different than for - strict element comparison, and may be surprising: The non-reflexive - not-a-number values for example result in the following comparison behavior - when used in a list:: - - >>> nan = float('NaN') - >>> nan is nan - True - >>> nan == nan - False <-- the defined non-reflexive behavior of NaN - >>> [nan] == [nan] - True <-- list enforces reflexivity and tests identity first + elements. The built-in containers typically assume identical objects are + equal to themselves. That lets them bypass equality tests for identical + objects to improve performance and to maintain their internal invariants. Lexicographical comparison between built-in collections works as follows: From webhook-mailer at python.org Sat Aug 24 13:51:26 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 24 Aug 2019 17:51:26 -0000 Subject: [Python-checkins] bpo-37798: Test both Python and C versions in test_statistics.py (GH-15453) Message-ID: https://github.com/python/cpython/commit/8ad22a42267d4ecb1c080d420933680cc126363e commit: 8ad22a42267d4ecb1c080d420933680cc126363e branch: master author: Dong-hee Na committer: Raymond Hettinger date: 2019-08-24T10:51:20-07:00 summary: bpo-37798: Test both Python and C versions in test_statistics.py (GH-15453) files: A Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst M Lib/test/test_statistics.py diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 104718ed7db6..23dd96e365a8 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -18,6 +18,7 @@ from decimal import Decimal from fractions import Fraction +from test import support # Module to be tested. @@ -178,6 +179,23 @@ class _DoNothing: # We prefer this for testing numeric values that may not be exactly equal, # and avoid using TestCase.assertAlmostEqual, because it sucks :-) +py_statistics = support.import_fresh_module('statistics', blocked=['_statistics']) +c_statistics = support.import_fresh_module('statistics', fresh=['_statistics']) + + +class TestModules(unittest.TestCase): + func_names = ['_normal_dist_inv_cdf'] + + def test_py_functions(self): + for fname in self.func_names: + self.assertEqual(getattr(py_statistics, fname).__module__, 'statistics') + + @unittest.skipUnless(c_statistics, 'requires _statistics') + def test_c_functions(self): + for fname in self.func_names: + self.assertEqual(getattr(c_statistics, fname).__module__, '_statistics') + + class NumericTestCase(unittest.TestCase): """Unit test class for numeric work. @@ -2314,7 +2332,7 @@ def test_error_cases(self): quantiles([10, None, 30], n=4) # data is non-numeric -class TestNormalDist(unittest.TestCase): +class TestNormalDist: # General note on precision: The pdf(), cdf(), and overlap() methods # depend on functions in the math libraries that do not make @@ -2324,35 +2342,35 @@ class TestNormalDist(unittest.TestCase): # implementing our own implementations from scratch. def test_slots(self): - nd = statistics.NormalDist(300, 23) + nd = self.module.NormalDist(300, 23) with self.assertRaises(TypeError): vars(nd) self.assertEqual(tuple(nd.__slots__), ('_mu', '_sigma')) def test_instantiation_and_attributes(self): - nd = statistics.NormalDist(500, 17) + nd = self.module.NormalDist(500, 17) self.assertEqual(nd.mean, 500) self.assertEqual(nd.stdev, 17) self.assertEqual(nd.variance, 17**2) # default arguments - nd = statistics.NormalDist() + nd = self.module.NormalDist() self.assertEqual(nd.mean, 0) self.assertEqual(nd.stdev, 1) self.assertEqual(nd.variance, 1**2) # error case: negative sigma - with self.assertRaises(statistics.StatisticsError): - statistics.NormalDist(500, -10) + with self.assertRaises(self.module.StatisticsError): + self.module.NormalDist(500, -10) # verify that subclass type is honored - class NewNormalDist(statistics.NormalDist): + class NewNormalDist(self.module.NormalDist): pass nnd = NewNormalDist(200, 5) self.assertEqual(type(nnd), NewNormalDist) def test_alternative_constructor(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist data = [96, 107, 90, 92, 110] # list input self.assertEqual(NormalDist.from_samples(data), NormalDist(99, 9)) @@ -2361,9 +2379,9 @@ def test_alternative_constructor(self): # iterator input self.assertEqual(NormalDist.from_samples(iter(data)), NormalDist(99, 9)) # error cases - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): NormalDist.from_samples([]) # empty input - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): NormalDist.from_samples([10]) # only one input # verify that subclass type is honored @@ -2373,7 +2391,7 @@ class NewNormalDist(NormalDist): self.assertEqual(type(nnd), NewNormalDist) def test_sample_generation(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist mu, sigma = 10_000, 3.0 X = NormalDist(mu, sigma) n = 1_000 @@ -2381,7 +2399,7 @@ def test_sample_generation(self): self.assertEqual(len(data), n) self.assertEqual(set(map(type, data)), {float}) # mean(data) expected to fall within 8 standard deviations - xbar = statistics.mean(data) + xbar = self.module.mean(data) self.assertTrue(mu - sigma*8 <= xbar <= mu + sigma*8) # verify that seeding makes reproducible sequences @@ -2395,7 +2413,7 @@ def test_sample_generation(self): self.assertNotEqual(data1, data2) def test_pdf(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist X = NormalDist(100, 15) # Verify peak around center self.assertLess(X.pdf(99), X.pdf(100)) @@ -2426,7 +2444,7 @@ def test_pdf(self): self.assertAlmostEqual(Z.pdf(-x / 100.0), px, places=4) # Error case: variance is zero Y = NormalDist(100, 0) - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): Y.pdf(90) # Special values self.assertEqual(X.pdf(float('-Inf')), 0.0) @@ -2434,7 +2452,7 @@ def test_pdf(self): self.assertTrue(math.isnan(X.pdf(float('NaN')))) def test_cdf(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist X = NormalDist(100, 15) cdfs = [X.cdf(x) for x in range(1, 200)] self.assertEqual(set(map(type, cdfs)), {float}) @@ -2456,7 +2474,7 @@ def test_cdf(self): self.assertAlmostEqual(Z.cdf(-z), 1.0 - cum_prob, places=5) # Error case: variance is zero Y = NormalDist(100, 0) - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): Y.cdf(90) # Special values self.assertEqual(X.cdf(float('-Inf')), 0.0) @@ -2465,7 +2483,7 @@ def test_cdf(self): @support.skip_if_pgo_task def test_inv_cdf(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist # Center case should be exact. iq = NormalDist(100, 15) @@ -2513,15 +2531,15 @@ def test_inv_cdf(self): self.assertAlmostEqual(iq.inv_cdf(iq.cdf(x)), x, places=5) # Error cases: - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): iq.inv_cdf(0.0) # p is zero - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): iq.inv_cdf(-0.1) # p under zero - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): iq.inv_cdf(1.0) # p is one - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): iq.inv_cdf(1.1) # p over one - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): iq = NormalDist(100, 0) # sigma is zero iq.inv_cdf(0.5) @@ -2529,7 +2547,7 @@ def test_inv_cdf(self): self.assertTrue(math.isnan(Z.inv_cdf(float('NaN')))) def test_overlap(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist # Match examples from Imman and Bradley for X1, X2, published_result in [ @@ -2586,26 +2604,26 @@ def overlap_numeric(X, Y, *, steps=8_192, z=5): X.overlap(X, X) # too may arguments with self.assertRaises(TypeError): X.overlap(None) # right operand not a NormalDist - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): X.overlap(NormalDist(1, 0)) # right operand sigma is zero - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): NormalDist(1, 0).overlap(X) # left operand sigma is zero def test_properties(self): - X = statistics.NormalDist(100, 15) + X = self.module.NormalDist(100, 15) self.assertEqual(X.mean, 100) self.assertEqual(X.stdev, 15) self.assertEqual(X.variance, 225) def test_same_type_addition_and_subtraction(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist X = NormalDist(100, 12) Y = NormalDist(40, 5) self.assertEqual(X + Y, NormalDist(140, 13)) # __add__ self.assertEqual(X - Y, NormalDist(60, 13)) # __sub__ def test_translation_and_scaling(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist X = NormalDist(100, 15) y = 10 self.assertEqual(+X, NormalDist(100, 15)) # __pos__ @@ -2621,7 +2639,7 @@ def test_translation_and_scaling(self): y / X def test_unary_operations(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist X = NormalDist(100, 12) Y = +X self.assertIsNot(X, Y) @@ -2633,7 +2651,7 @@ def test_unary_operations(self): self.assertEqual(X.stdev, Y.stdev) def test_equality(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist nd1 = NormalDist() nd2 = NormalDist(2, 4) nd3 = NormalDist() @@ -2673,7 +2691,7 @@ def __init__(self, mu, sigma): self.assertNotEqual(nd, lnd) def test_pickle_and_copy(self): - nd = statistics.NormalDist(37.5, 5.625) + nd = self.module.NormalDist(37.5, 5.625) nd1 = copy.copy(nd) self.assertEqual(nd, nd1) nd2 = copy.deepcopy(nd) @@ -2682,14 +2700,36 @@ def test_pickle_and_copy(self): self.assertEqual(nd, nd3) def test_hashability(self): - ND = statistics.NormalDist + ND = self.module.NormalDist s = {ND(100, 15), ND(100.0, 15.0), ND(100, 10), ND(95, 15), ND(100, 15)} self.assertEqual(len(s), 3) def test_repr(self): - nd = statistics.NormalDist(37.5, 5.625) + nd = self.module.NormalDist(37.5, 5.625) self.assertEqual(repr(nd), 'NormalDist(mu=37.5, sigma=5.625)') +# Swapping the sys.modules['statistics'] is to solving the +# _pickle.PicklingError: +# Can't pickle : +# it's not the same object as statistics.NormalDist +class TestNormalDistPython(unittest.TestCase, TestNormalDist): + module = py_statistics + def setUp(self): + sys.modules['statistics'] = self.module + + def tearDown(self): + sys.modules['statistics'] = statistics + + + at unittest.skipUnless(c_statistics, 'requires _statistics') +class TestNormalDistC(unittest.TestCase, TestNormalDist): + module = c_statistics + def setUp(self): + sys.modules['statistics'] = self.module + + def tearDown(self): + sys.modules['statistics'] = statistics + # === Run tests === diff --git a/Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst b/Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst new file mode 100644 index 000000000000..25cfa0047886 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst @@ -0,0 +1,2 @@ +Update test_statistics.py to verify that the statistics module works well +for both C and Python implementations. Patch by Dong-hee Na From webhook-mailer at python.org Sat Aug 24 13:53:12 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 24 Aug 2019 17:53:12 -0000 Subject: [Python-checkins] bpo-32118: Simplify docs for sequence comparison (GH-15450) (#15466) Message-ID: https://github.com/python/cpython/commit/0ad85681de639792751ea53ec964d87d4ad45d71 commit: 0ad85681de639792751ea53ec964d87d4ad45d71 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-24T10:53:09-07:00 summary: bpo-32118: Simplify docs for sequence comparison (GH-15450) (#15466) (cherry picked from commit edd21129dd304e178ca8be82ba689488dfb58276) Co-authored-by: Raymond Hettinger files: M Doc/reference/expressions.rst diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 432327a87c37..ee13c5f4c6fc 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1425,6 +1425,10 @@ built-in types. themselves. For example, if ``x = float('NaN')``, ``3 < x``, ``x < 3``, ``x == x``, ``x != x`` are all false. This behavior is compliant with IEEE 754. +* ``None`` and ``NotImplemented`` are singletons. :PEP:`8` advises that + comparisons for singletons should always be done with ``is`` or ``is not``, + never the equality operators. + * Binary sequences (instances of :class:`bytes` or :class:`bytearray`) can be compared within and across their types. They compare lexicographically using the numeric values of their elements. @@ -1442,25 +1446,9 @@ built-in types. :exc:`TypeError`. Sequences compare lexicographically using comparison of corresponding - elements, whereby reflexivity of the elements is enforced. - - In enforcing reflexivity of elements, the comparison of collections assumes - that for a collection element ``x``, ``x == x`` is always true. Based on - that assumption, element identity is compared first, and element comparison - is performed only for distinct elements. This approach yields the same - result as a strict element comparison would, if the compared elements are - reflexive. For non-reflexive elements, the result is different than for - strict element comparison, and may be surprising: The non-reflexive - not-a-number values for example result in the following comparison behavior - when used in a list:: - - >>> nan = float('NaN') - >>> nan is nan - True - >>> nan == nan - False <-- the defined non-reflexive behavior of NaN - >>> [nan] == [nan] - True <-- list enforces reflexivity and tests identity first + elements. The built-in containers typically assume identical objects are + equal to themselves. That lets them bypass equality tests for identical + objects to improve performance and to maintain their internal invariants. Lexicographical comparison between built-in collections works as follows: From webhook-mailer at python.org Sat Aug 24 14:07:28 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Sat, 24 Aug 2019 18:07:28 -0000 Subject: [Python-checkins] Fix typos in the documentation of Parser/pgen (GH-15416) Message-ID: https://github.com/python/cpython/commit/43710b67b3d40325ba2c31b793895aed48fd8aa7 commit: 43710b67b3d40325ba2c31b793895aed48fd8aa7 branch: master author: Shashi Ranjan committer: Pablo Galindo date: 2019-08-24T19:07:24+01:00 summary: Fix typos in the documentation of Parser/pgen (GH-15416) Co-Authored-By: Antoine <43954001+awecx at users.noreply.github.com> files: M Parser/pgen/pgen.py diff --git a/Parser/pgen/pgen.py b/Parser/pgen/pgen.py index d7dcb769334c..2f444eb8c86f 100644 --- a/Parser/pgen/pgen.py +++ b/Parser/pgen/pgen.py @@ -10,11 +10,11 @@ * An LL(1) parser (Left-to-right, Leftmost derivation, 1 token-lookahead) is a top-down parser for a subset of context-free languages. It parses the input from Left to right, performing Leftmost derivation of the sentence, and can - only use 1 tokens of lookahead when parsing a sentence. + only use 1 token of lookahead when parsing a sentence. * A parsing table is a collection of data that a generic implementation of the LL(1) parser consumes to know how to parse a given context-free grammar. In - this case the collection of thata involves Deterministic Finite Automatons, + this case the collection of data involves Deterministic Finite Automatons, calculated first sets, keywords and transition labels. * A grammar is defined by production rules (or just 'productions') that specify @@ -26,9 +26,9 @@ rule_name: rule_description; - meaning the rule 'a: b' specifies that a can be replaced by b. A Context-free - grammars is a grammars in which the left-hand side of each production rule - consists of only a single nonterminal symbol. Context free grammars can + meaning the rule 'a: b' specifies that a can be replaced by b. A context-free + grammar is a grammar in which the left-hand side of each production rule + consists of only a single nonterminal symbol. Context-free grammars can always be recognized by a Non-Deterministic Automatons. * Terminal symbols are literal symbols which may appear in the outputs of the @@ -47,8 +47,8 @@ * The first sets of a rule (FIRST(rule)) are defined to be the set of terminals that can appear in the first position of any string derived from the rule. - This is useful for LL(1) parsers as the parser is only allow to look at the - next token in the input to know which rule needs to parse. For example given + This is useful for LL(1) parsers as the parser is only allowed to look at the + next token in the input to know which rule needs to parse. For example, given this grammar: start: '(' A | B ')' From tjreedy at udel.edu Sat Aug 24 14:07:34 2019 From: tjreedy at udel.edu (Terry Reedy) Date: Sat, 24 Aug 2019 14:07:34 -0400 Subject: [Python-checkins] (TH-15402) In-Reply-To: <46G4LM6nJrzpBlx@mail.python.org> References: <46G4LM6nJrzpBlx@mail.python.org> Message-ID: <2aecff02-30c5-b7e4-a96e-7bb908fc14cb@udel.edu> On 8/24/2019 1:01 PM, Terry Jan Reedy wrote: > https://github.com/python/cpython/commit/a50f0a4c2bd997e4534162ecc1853cb54c7ae902 > commit: a50f0a4c2bd997e4534162ecc1853cb54c7ae902 > branch: master > author: GeeTransit > committer: Terry Jan Reedy > date: 2019-08-24T13:01:36-04:00 > summary: > > (TH-15402) I hit [Merge] by accident. Miss I. cannot backport. Will revert and resubmit. From webhook-mailer at python.org Sat Aug 24 14:10:08 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sat, 24 Aug 2019 18:10:08 -0000 Subject: [Python-checkins] Revert "(TH-15402)" (#15468) Message-ID: https://github.com/python/cpython/commit/fa7a6f5e355f69452682f1beba66bd1ac7fef79a commit: fa7a6f5e355f69452682f1beba66bd1ac7fef79a branch: master author: Terry Jan Reedy committer: GitHub date: 2019-08-24T14:10:04-04:00 summary: Revert "(TH-15402)" (#15468) This reverts commit a50f0a4c2bd997e4534162ecc1853cb54c7ae902. files: M Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst index 2a5b0bd0e90c..a44fd3b59b4f 100644 --- a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst @@ -1 +1 @@ -Refactor IDLE autocomplete and improve testing. +IDLE - Refactor autocompete and improve testing. From webhook-mailer at python.org Sat Aug 24 14:14:25 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 24 Aug 2019 18:14:25 -0000 Subject: [Python-checkins] bpo-37798: Test both Python and C versions in test_statistics.py (GH-15453) (GH-15467) Message-ID: https://github.com/python/cpython/commit/d5a66bc56f68d0f7cc3470722a31d7f731754af6 commit: d5a66bc56f68d0f7cc3470722a31d7f731754af6 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-24T11:14:20-07:00 summary: bpo-37798: Test both Python and C versions in test_statistics.py (GH-15453) (GH-15467) (cherry picked from commit 8ad22a42267d4ecb1c080d420933680cc126363e) Co-authored-by: Dong-hee Na files: A Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst M Lib/test/test_statistics.py diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 104718ed7db6..23dd96e365a8 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -18,6 +18,7 @@ from decimal import Decimal from fractions import Fraction +from test import support # Module to be tested. @@ -178,6 +179,23 @@ class _DoNothing: # We prefer this for testing numeric values that may not be exactly equal, # and avoid using TestCase.assertAlmostEqual, because it sucks :-) +py_statistics = support.import_fresh_module('statistics', blocked=['_statistics']) +c_statistics = support.import_fresh_module('statistics', fresh=['_statistics']) + + +class TestModules(unittest.TestCase): + func_names = ['_normal_dist_inv_cdf'] + + def test_py_functions(self): + for fname in self.func_names: + self.assertEqual(getattr(py_statistics, fname).__module__, 'statistics') + + @unittest.skipUnless(c_statistics, 'requires _statistics') + def test_c_functions(self): + for fname in self.func_names: + self.assertEqual(getattr(c_statistics, fname).__module__, '_statistics') + + class NumericTestCase(unittest.TestCase): """Unit test class for numeric work. @@ -2314,7 +2332,7 @@ def test_error_cases(self): quantiles([10, None, 30], n=4) # data is non-numeric -class TestNormalDist(unittest.TestCase): +class TestNormalDist: # General note on precision: The pdf(), cdf(), and overlap() methods # depend on functions in the math libraries that do not make @@ -2324,35 +2342,35 @@ class TestNormalDist(unittest.TestCase): # implementing our own implementations from scratch. def test_slots(self): - nd = statistics.NormalDist(300, 23) + nd = self.module.NormalDist(300, 23) with self.assertRaises(TypeError): vars(nd) self.assertEqual(tuple(nd.__slots__), ('_mu', '_sigma')) def test_instantiation_and_attributes(self): - nd = statistics.NormalDist(500, 17) + nd = self.module.NormalDist(500, 17) self.assertEqual(nd.mean, 500) self.assertEqual(nd.stdev, 17) self.assertEqual(nd.variance, 17**2) # default arguments - nd = statistics.NormalDist() + nd = self.module.NormalDist() self.assertEqual(nd.mean, 0) self.assertEqual(nd.stdev, 1) self.assertEqual(nd.variance, 1**2) # error case: negative sigma - with self.assertRaises(statistics.StatisticsError): - statistics.NormalDist(500, -10) + with self.assertRaises(self.module.StatisticsError): + self.module.NormalDist(500, -10) # verify that subclass type is honored - class NewNormalDist(statistics.NormalDist): + class NewNormalDist(self.module.NormalDist): pass nnd = NewNormalDist(200, 5) self.assertEqual(type(nnd), NewNormalDist) def test_alternative_constructor(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist data = [96, 107, 90, 92, 110] # list input self.assertEqual(NormalDist.from_samples(data), NormalDist(99, 9)) @@ -2361,9 +2379,9 @@ def test_alternative_constructor(self): # iterator input self.assertEqual(NormalDist.from_samples(iter(data)), NormalDist(99, 9)) # error cases - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): NormalDist.from_samples([]) # empty input - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): NormalDist.from_samples([10]) # only one input # verify that subclass type is honored @@ -2373,7 +2391,7 @@ class NewNormalDist(NormalDist): self.assertEqual(type(nnd), NewNormalDist) def test_sample_generation(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist mu, sigma = 10_000, 3.0 X = NormalDist(mu, sigma) n = 1_000 @@ -2381,7 +2399,7 @@ def test_sample_generation(self): self.assertEqual(len(data), n) self.assertEqual(set(map(type, data)), {float}) # mean(data) expected to fall within 8 standard deviations - xbar = statistics.mean(data) + xbar = self.module.mean(data) self.assertTrue(mu - sigma*8 <= xbar <= mu + sigma*8) # verify that seeding makes reproducible sequences @@ -2395,7 +2413,7 @@ def test_sample_generation(self): self.assertNotEqual(data1, data2) def test_pdf(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist X = NormalDist(100, 15) # Verify peak around center self.assertLess(X.pdf(99), X.pdf(100)) @@ -2426,7 +2444,7 @@ def test_pdf(self): self.assertAlmostEqual(Z.pdf(-x / 100.0), px, places=4) # Error case: variance is zero Y = NormalDist(100, 0) - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): Y.pdf(90) # Special values self.assertEqual(X.pdf(float('-Inf')), 0.0) @@ -2434,7 +2452,7 @@ def test_pdf(self): self.assertTrue(math.isnan(X.pdf(float('NaN')))) def test_cdf(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist X = NormalDist(100, 15) cdfs = [X.cdf(x) for x in range(1, 200)] self.assertEqual(set(map(type, cdfs)), {float}) @@ -2456,7 +2474,7 @@ def test_cdf(self): self.assertAlmostEqual(Z.cdf(-z), 1.0 - cum_prob, places=5) # Error case: variance is zero Y = NormalDist(100, 0) - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): Y.cdf(90) # Special values self.assertEqual(X.cdf(float('-Inf')), 0.0) @@ -2465,7 +2483,7 @@ def test_cdf(self): @support.skip_if_pgo_task def test_inv_cdf(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist # Center case should be exact. iq = NormalDist(100, 15) @@ -2513,15 +2531,15 @@ def test_inv_cdf(self): self.assertAlmostEqual(iq.inv_cdf(iq.cdf(x)), x, places=5) # Error cases: - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): iq.inv_cdf(0.0) # p is zero - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): iq.inv_cdf(-0.1) # p under zero - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): iq.inv_cdf(1.0) # p is one - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): iq.inv_cdf(1.1) # p over one - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): iq = NormalDist(100, 0) # sigma is zero iq.inv_cdf(0.5) @@ -2529,7 +2547,7 @@ def test_inv_cdf(self): self.assertTrue(math.isnan(Z.inv_cdf(float('NaN')))) def test_overlap(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist # Match examples from Imman and Bradley for X1, X2, published_result in [ @@ -2586,26 +2604,26 @@ def overlap_numeric(X, Y, *, steps=8_192, z=5): X.overlap(X, X) # too may arguments with self.assertRaises(TypeError): X.overlap(None) # right operand not a NormalDist - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): X.overlap(NormalDist(1, 0)) # right operand sigma is zero - with self.assertRaises(statistics.StatisticsError): + with self.assertRaises(self.module.StatisticsError): NormalDist(1, 0).overlap(X) # left operand sigma is zero def test_properties(self): - X = statistics.NormalDist(100, 15) + X = self.module.NormalDist(100, 15) self.assertEqual(X.mean, 100) self.assertEqual(X.stdev, 15) self.assertEqual(X.variance, 225) def test_same_type_addition_and_subtraction(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist X = NormalDist(100, 12) Y = NormalDist(40, 5) self.assertEqual(X + Y, NormalDist(140, 13)) # __add__ self.assertEqual(X - Y, NormalDist(60, 13)) # __sub__ def test_translation_and_scaling(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist X = NormalDist(100, 15) y = 10 self.assertEqual(+X, NormalDist(100, 15)) # __pos__ @@ -2621,7 +2639,7 @@ def test_translation_and_scaling(self): y / X def test_unary_operations(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist X = NormalDist(100, 12) Y = +X self.assertIsNot(X, Y) @@ -2633,7 +2651,7 @@ def test_unary_operations(self): self.assertEqual(X.stdev, Y.stdev) def test_equality(self): - NormalDist = statistics.NormalDist + NormalDist = self.module.NormalDist nd1 = NormalDist() nd2 = NormalDist(2, 4) nd3 = NormalDist() @@ -2673,7 +2691,7 @@ def __init__(self, mu, sigma): self.assertNotEqual(nd, lnd) def test_pickle_and_copy(self): - nd = statistics.NormalDist(37.5, 5.625) + nd = self.module.NormalDist(37.5, 5.625) nd1 = copy.copy(nd) self.assertEqual(nd, nd1) nd2 = copy.deepcopy(nd) @@ -2682,14 +2700,36 @@ def test_pickle_and_copy(self): self.assertEqual(nd, nd3) def test_hashability(self): - ND = statistics.NormalDist + ND = self.module.NormalDist s = {ND(100, 15), ND(100.0, 15.0), ND(100, 10), ND(95, 15), ND(100, 15)} self.assertEqual(len(s), 3) def test_repr(self): - nd = statistics.NormalDist(37.5, 5.625) + nd = self.module.NormalDist(37.5, 5.625) self.assertEqual(repr(nd), 'NormalDist(mu=37.5, sigma=5.625)') +# Swapping the sys.modules['statistics'] is to solving the +# _pickle.PicklingError: +# Can't pickle : +# it's not the same object as statistics.NormalDist +class TestNormalDistPython(unittest.TestCase, TestNormalDist): + module = py_statistics + def setUp(self): + sys.modules['statistics'] = self.module + + def tearDown(self): + sys.modules['statistics'] = statistics + + + at unittest.skipUnless(c_statistics, 'requires _statistics') +class TestNormalDistC(unittest.TestCase, TestNormalDist): + module = c_statistics + def setUp(self): + sys.modules['statistics'] = self.module + + def tearDown(self): + sys.modules['statistics'] = statistics + # === Run tests === diff --git a/Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst b/Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst new file mode 100644 index 000000000000..25cfa0047886 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst @@ -0,0 +1,2 @@ +Update test_statistics.py to verify that the statistics module works well +for both C and Python implementations. Patch by Dong-hee Na From webhook-mailer at python.org Sat Aug 24 14:15:48 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 24 Aug 2019 18:15:48 -0000 Subject: [Python-checkins] bpo-14112: Allow beginners to explore shallowness in greater depth ; -) (GH-15465) Message-ID: https://github.com/python/cpython/commit/69ee87e99cfe0b79389cffa92d126af868baf353 commit: 69ee87e99cfe0b79389cffa92d126af868baf353 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-24T11:15:44-07:00 summary: bpo-14112: Allow beginners to explore shallowness in greater depth ;-) (GH-15465) files: M Doc/library/copy.rst M Doc/tutorial/introduction.rst diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index c7bd89f96372..a8e8bfb1e832 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -31,6 +31,7 @@ Interface summary: Raised for module specific errors. +.. _shallow_vs_deep_copy: The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances): diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst index a4dbd6351b77..2a1666128a20 100644 --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -394,7 +394,8 @@ indexed and sliced:: [9, 16, 25] All slice operations return a new list containing the requested elements. This -means that the following slice returns a new (shallow) copy of the list:: +means that the following slice returns a +:ref:`shallow copy ` of the list:: >>> squares[:] [1, 4, 9, 16, 25] From webhook-mailer at python.org Sat Aug 24 14:33:22 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 24 Aug 2019 18:33:22 -0000 Subject: [Python-checkins] bpo-14112: Allow beginners to explore shallowness in greater depth ; -) (GH-15465) (GH-15469) Message-ID: https://github.com/python/cpython/commit/a8424940b4873791fc178a9f19a7bf1779a6cf42 commit: a8424940b4873791fc178a9f19a7bf1779a6cf42 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-24T11:33:18-07:00 summary: bpo-14112: Allow beginners to explore shallowness in greater depth ;-) (GH-15465) (GH-15469) (cherry picked from commit 69ee87e99cfe0b79389cffa92d126af868baf353) Co-authored-by: Raymond Hettinger files: M Doc/library/copy.rst M Doc/tutorial/introduction.rst diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index c7bd89f96372..a8e8bfb1e832 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -31,6 +31,7 @@ Interface summary: Raised for module specific errors. +.. _shallow_vs_deep_copy: The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances): diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst index a4dbd6351b77..2a1666128a20 100644 --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -394,7 +394,8 @@ indexed and sliced:: [9, 16, 25] All slice operations return a new list containing the requested elements. This -means that the following slice returns a new (shallow) copy of the list:: +means that the following slice returns a +:ref:`shallow copy ` of the list:: >>> squares[:] [1, 4, 9, 16, 25] From webhook-mailer at python.org Sat Aug 24 15:49:00 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Aug 2019 19:49:00 -0000 Subject: [Python-checkins] Clarify argument types in datetime docs. (GH-15459) Message-ID: https://github.com/python/cpython/commit/c5218fce02d6bd7bb343db20c8f14e8d9640783a commit: c5218fce02d6bd7bb343db20c8f14e8d9640783a branch: master author: J?rgen Gmach committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-24T12:48:55-07:00 summary: Clarify argument types in datetime docs. (GH-15459) "Arguments may be integers... " could be misunderstand as they also could be strings. New wording makes it clear that arguments have to be integers. modified: Doc/library/datetime.rst Automerge-Triggered-By: @pganssle files: M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index c935e3526512..0135fa4b0218 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -401,7 +401,7 @@ systems. .. class:: date(year, month, day) - All arguments are required. Arguments may be integers, in the following + All arguments are required. Arguments must be integers in the following ranges: * ``MINYEAR <= year <= MAXYEAR`` @@ -714,7 +714,7 @@ Constructor: .. class:: datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0) The year, month and day arguments are required. *tzinfo* may be ``None``, or an - instance of a :class:`tzinfo` subclass. The remaining arguments may be integers, + instance of a :class:`tzinfo` subclass. The remaining arguments must be integers in the following ranges: * ``MINYEAR <= year <= MAXYEAR``, @@ -1439,7 +1439,7 @@ day, and subject to adjustment via a :class:`tzinfo` object. .. class:: time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0) All arguments are optional. *tzinfo* may be ``None``, or an instance of a - :class:`tzinfo` subclass. The remaining arguments may be integers, in the + :class:`tzinfo` subclass. The remaining arguments must be integers in the following ranges: * ``0 <= hour < 24``, From webhook-mailer at python.org Sat Aug 24 15:57:54 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Aug 2019 19:57:54 -0000 Subject: [Python-checkins] [3.8] Clarify argument types in datetime docs. (GH-15459) (GH-15472) Message-ID: https://github.com/python/cpython/commit/ffe43b20956cbabc9dfa3758101069dbaa12918d commit: ffe43b20956cbabc9dfa3758101069dbaa12918d branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-24T12:57:50-07:00 summary: [3.8] Clarify argument types in datetime docs. (GH-15459) (GH-15472) "Arguments may be integers... " could be misunderstand as they also could be strings. New wording makes it clear that arguments have to be integers. modified: Doc/library/datetime.rst Automerge-Triggered-By: @pganssle (cherry picked from commit c5218fce02d6bd7bb343db20c8f14e8d9640783a) Co-authored-by: J?rgen Gmach Automerge-Triggered-By: @pganssle files: M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index c935e3526512..0135fa4b0218 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -401,7 +401,7 @@ systems. .. class:: date(year, month, day) - All arguments are required. Arguments may be integers, in the following + All arguments are required. Arguments must be integers in the following ranges: * ``MINYEAR <= year <= MAXYEAR`` @@ -714,7 +714,7 @@ Constructor: .. class:: datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0) The year, month and day arguments are required. *tzinfo* may be ``None``, or an - instance of a :class:`tzinfo` subclass. The remaining arguments may be integers, + instance of a :class:`tzinfo` subclass. The remaining arguments must be integers in the following ranges: * ``MINYEAR <= year <= MAXYEAR``, @@ -1439,7 +1439,7 @@ day, and subject to adjustment via a :class:`tzinfo` object. .. class:: time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0) All arguments are optional. *tzinfo* may be ``None``, or an instance of a - :class:`tzinfo` subclass. The remaining arguments may be integers, in the + :class:`tzinfo` subclass. The remaining arguments must be integers in the following ranges: * ``0 <= hour < 24``, From webhook-mailer at python.org Sat Aug 24 15:58:18 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Aug 2019 19:58:18 -0000 Subject: [Python-checkins] Clarify argument types in datetime docs. (GH-15459) Message-ID: https://github.com/python/cpython/commit/d9140a26c44577d624522daef5c313b046fd0014 commit: d9140a26c44577d624522daef5c313b046fd0014 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-24T12:58:14-07:00 summary: Clarify argument types in datetime docs. (GH-15459) "Arguments may be integers... " could be misunderstand as they also could be strings. New wording makes it clear that arguments have to be integers. modified: Doc/library/datetime.rst Automerge-Triggered-By: @pganssle (cherry picked from commit c5218fce02d6bd7bb343db20c8f14e8d9640783a) Co-authored-by: J?rgen Gmach files: M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 270b2386d716..c725b75b98c1 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -401,7 +401,7 @@ systems. .. class:: date(year, month, day) - All arguments are required. Arguments may be integers, in the following + All arguments are required. Arguments must be integers in the following ranges: * ``MINYEAR <= year <= MAXYEAR`` @@ -707,7 +707,7 @@ Constructor: .. class:: datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0) The year, month and day arguments are required. *tzinfo* may be ``None``, or an - instance of a :class:`tzinfo` subclass. The remaining arguments may be integers, + instance of a :class:`tzinfo` subclass. The remaining arguments must be integers in the following ranges: * ``MINYEAR <= year <= MAXYEAR``, @@ -1422,7 +1422,7 @@ day, and subject to adjustment via a :class:`tzinfo` object. .. class:: time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0) All arguments are optional. *tzinfo* may be ``None``, or an instance of a - :class:`tzinfo` subclass. The remaining arguments may be integers, in the + :class:`tzinfo` subclass. The remaining arguments must be integers in the following ranges: * ``0 <= hour < 24``, From webhook-mailer at python.org Sat Aug 24 17:32:37 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sat, 24 Aug 2019 21:32:37 -0000 Subject: [Python-checkins] Fix typo and rearrange words in IDLE news item (GH-15471) Message-ID: https://github.com/python/cpython/commit/0dfc025cccc5adf4f209e2421c7686b1e637eeae commit: 0dfc025cccc5adf4f209e2421c7686b1e637eeae branch: master author: Terry Jan Reedy committer: GitHub date: 2019-08-24T17:32:33-04:00 summary: Fix typo and rearrange words in IDLE news item (GH-15471) Redo of #15402 by GeeTransit and Kyle Stanley. files: M Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst index a44fd3b59b4f..2a5b0bd0e90c 100644 --- a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst @@ -1 +1 @@ -IDLE - Refactor autocompete and improve testing. +Refactor IDLE autocomplete and improve testing. From webhook-mailer at python.org Sat Aug 24 17:42:20 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Aug 2019 21:42:20 -0000 Subject: [Python-checkins] Fix typo and rearrange words in IDLE news item (GH-15471) Message-ID: https://github.com/python/cpython/commit/bf99801cf74347f0feaac2bf05842dcfa825963d commit: bf99801cf74347f0feaac2bf05842dcfa825963d branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-24T14:42:16-07:00 summary: Fix typo and rearrange words in IDLE news item (GH-15471) Redo of GH-15402 by GeeTransit and Kyle Stanley. (cherry picked from commit 0dfc025cccc5adf4f209e2421c7686b1e637eeae) Co-authored-by: Terry Jan Reedy files: M Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst index a44fd3b59b4f..2a5b0bd0e90c 100644 --- a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst @@ -1 +1 @@ -IDLE - Refactor autocompete and improve testing. +Refactor IDLE autocomplete and improve testing. From webhook-mailer at python.org Sat Aug 24 17:44:26 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Aug 2019 21:44:26 -0000 Subject: [Python-checkins] Fix typo and rearrange words in IDLE news item (GH-15471) Message-ID: https://github.com/python/cpython/commit/e6802d8a2ea50fae3ee0079622d1402ea83e441e commit: e6802d8a2ea50fae3ee0079622d1402ea83e441e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-24T14:44:22-07:00 summary: Fix typo and rearrange words in IDLE news item (GH-15471) Redo of GH-15402 by GeeTransit and Kyle Stanley. (cherry picked from commit 0dfc025cccc5adf4f209e2421c7686b1e637eeae) Co-authored-by: Terry Jan Reedy files: M Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst index a44fd3b59b4f..2a5b0bd0e90c 100644 --- a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst +++ b/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst @@ -1 +1 @@ -IDLE - Refactor autocompete and improve testing. +Refactor IDLE autocomplete and improve testing. From webhook-mailer at python.org Sat Aug 24 18:37:28 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 24 Aug 2019 22:37:28 -0000 Subject: [Python-checkins] bpo-19072: Make @classmethod support chained decorators (GH-8405) Message-ID: https://github.com/python/cpython/commit/805f8f9afea116c5d4d000570e3d02ae84502f43 commit: 805f8f9afea116c5d4d000570e3d02ae84502f43 branch: master author: Berker Peksag committer: Raymond Hettinger date: 2019-08-24T15:37:25-07:00 summary: bpo-19072: Make @classmethod support chained decorators (GH-8405) files: A Misc/NEWS.d/next/Core and Builtins/2018-07-23-13-09-54.bpo-19072.Gc59GS.rst M Doc/library/functions.rst M Lib/test/test_decorators.py M Lib/test/test_property.py M Objects/funcobject.c diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index c225f3dee921..a7b6610ebdf1 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -222,10 +222,12 @@ are always available. They are listed here in alphabetical order. implied first argument. Class methods are different than C++ or Java static methods. If you want those, - see :func:`staticmethod`. - + see :func:`staticmethod` in this section. For more information on class methods, see :ref:`types`. + .. versionchanged:: 3.9 + Class methods can now wrap other :term:`descriptors ` such as + :func:`property`. .. function:: compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) diff --git a/Lib/test/test_decorators.py b/Lib/test/test_decorators.py index d0a2ec9fddb8..8953f6480612 100644 --- a/Lib/test/test_decorators.py +++ b/Lib/test/test_decorators.py @@ -265,6 +265,45 @@ def bar(): return 42 self.assertEqual(bar(), 42) self.assertEqual(actions, expected_actions) + def test_wrapped_descriptor_inside_classmethod(self): + class BoundWrapper: + def __init__(self, wrapped): + self.__wrapped__ = wrapped + + def __call__(self, *args, **kwargs): + return self.__wrapped__(*args, **kwargs) + + class Wrapper: + def __init__(self, wrapped): + self.__wrapped__ = wrapped + + def __get__(self, instance, owner): + bound_function = self.__wrapped__.__get__(instance, owner) + return BoundWrapper(bound_function) + + def decorator(wrapped): + return Wrapper(wrapped) + + class Class: + @decorator + @classmethod + def inner(cls): + # This should already work. + return 'spam' + + @classmethod + @decorator + def outer(cls): + # Raised TypeError with a message saying that the 'Wrapper' + # object is not callable. + return 'eggs' + + self.assertEqual(Class.inner(), 'spam') + self.assertEqual(Class.outer(), 'eggs') + self.assertEqual(Class().inner(), 'spam') + self.assertEqual(Class().outer(), 'eggs') + + class TestClassDecorators(unittest.TestCase): def test_simple(self): diff --git a/Lib/test/test_property.py b/Lib/test/test_property.py index f6f8f5ed0e45..172737ade143 100644 --- a/Lib/test/test_property.py +++ b/Lib/test/test_property.py @@ -183,6 +183,27 @@ def test_refleaks_in___init__(self): fake_prop.__init__('fget', 'fset', 'fdel', 'doc') self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") + def test_class_property(self): + class A: + @classmethod + @property + def __doc__(cls): + return 'A doc for %r' % cls.__name__ + self.assertEqual(A.__doc__, "A doc for 'A'") + + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") + def test_class_property_override(self): + class A: + """First""" + @classmethod + @property + def __doc__(cls): + return 'Second' + self.assertEqual(A.__doc__, 'Second') + # Issue 5890: subclasses of property do not preserve method __doc__ strings class PropertySub(property): diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-07-23-13-09-54.bpo-19072.Gc59GS.rst b/Misc/NEWS.d/next/Core and Builtins/2018-07-23-13-09-54.bpo-19072.Gc59GS.rst new file mode 100644 index 000000000000..1d27789420e0 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-07-23-13-09-54.bpo-19072.Gc59GS.rst @@ -0,0 +1,3 @@ +The :class:`classmethod` decorator can now wrap other descriptors +such as property objects. Adapted from a patch written by Graham +Dumpleton. diff --git a/Objects/funcobject.c b/Objects/funcobject.c index a65c1f4a55bb..b6ffc2a184c9 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -741,6 +741,10 @@ cm_descr_get(PyObject *self, PyObject *obj, PyObject *type) } if (type == NULL) type = (PyObject *)(Py_TYPE(obj)); + if (Py_TYPE(cm->cm_callable)->tp_descr_get != NULL) { + return Py_TYPE(cm->cm_callable)->tp_descr_get(cm->cm_callable, type, + NULL); + } return PyMethod_New(cm->cm_callable, type); } From webhook-mailer at python.org Sat Aug 24 22:10:43 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 25 Aug 2019 02:10:43 -0000 Subject: [Python-checkins] bpo-37942: Improve argument clinic float converter (GH-15470) Message-ID: https://github.com/python/cpython/commit/aef9ad82f7f667cd001a7112d3bc636e918626f7 commit: aef9ad82f7f667cd001a7112d3bc636e918626f7 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-24T19:10:39-07:00 summary: bpo-37942: Improve argument clinic float converter (GH-15470) files: A Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst M Lib/test/clinic.test M Modules/clinic/_ssl.c.h M Modules/clinic/_statisticsmodule.c.h M Modules/clinic/audioop.c.h M Modules/clinic/cmathmodule.c.h M Modules/clinic/mathmodule.c.h M Python/clinic/sysmodule.c.h M Python/getargs.c M Tools/clinic/clinic.py diff --git a/Lib/test/clinic.test b/Lib/test/clinic.test index 62c2f00c6b2b..ac6f419c0d3a 100644 --- a/Lib/test/clinic.test +++ b/Lib/test/clinic.test @@ -1587,9 +1587,15 @@ test_float_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - a = (float) PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + a = (float) (PyFloat_AS_DOUBLE(args[0])); + } + else + { + a = (float) PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional: return_value = test_float_converter_impl(module, a); @@ -1600,7 +1606,7 @@ exit: static PyObject * test_float_converter_impl(PyObject *module, float a) -/*[clinic end generated code: output=8293566b2ec1fc52 input=259c0d98eca35034]*/ +/*[clinic end generated code: output=6b9c7443d2601cea input=259c0d98eca35034]*/ /*[clinic input] @@ -1634,9 +1640,15 @@ test_double_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - a = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + a = PyFloat_AS_DOUBLE(args[0]); + } + else + { + a = PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional: return_value = test_double_converter_impl(module, a); @@ -1647,7 +1659,7 @@ exit: static PyObject * test_double_converter_impl(PyObject *module, double a) -/*[clinic end generated code: output=487081a9b8da67ab input=c6a9945706a41c27]*/ +/*[clinic end generated code: output=5b7b9a0f0791b2cc input=c6a9945706a41c27]*/ /*[clinic input] diff --git a/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst b/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst new file mode 100644 index 000000000000..6f6431409554 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst @@ -0,0 +1 @@ +Improve ArgumentClinic converter for floats. diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index b1012f7aee2e..adef7dbf90ce 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -1093,9 +1093,15 @@ _ssl_RAND_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } } - entropy = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[1])) { + entropy = PyFloat_AS_DOUBLE(args[1]); + } + else + { + entropy = PyFloat_AsDouble(args[1]); + if (entropy == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = _ssl_RAND_add_impl(module, &view, entropy); @@ -1476,4 +1482,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=a399d0eb393b6fab input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5003112e167cd948 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_statisticsmodule.c.h b/Modules/clinic/_statisticsmodule.c.h index f5a2e4678f30..5ff01efddcde 100644 --- a/Modules/clinic/_statisticsmodule.c.h +++ b/Modules/clinic/_statisticsmodule.c.h @@ -26,17 +26,35 @@ _statistics__normal_dist_inv_cdf(PyObject *module, PyObject *const *args, Py_ssi if (!_PyArg_CheckPositional("_normal_dist_inv_cdf", nargs, 3, 3)) { goto exit; } - p = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + p = PyFloat_AS_DOUBLE(args[0]); } - mu = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + p = PyFloat_AsDouble(args[0]); + if (p == -1.0 && PyErr_Occurred()) { + goto exit; + } } - sigma = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[1])) { + mu = PyFloat_AS_DOUBLE(args[1]); + } + else + { + mu = PyFloat_AsDouble(args[1]); + if (mu == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[2])) { + sigma = PyFloat_AS_DOUBLE(args[2]); + } + else + { + sigma = PyFloat_AsDouble(args[2]); + if (sigma == -1.0 && PyErr_Occurred()) { + goto exit; + } } _return_value = _statistics__normal_dist_inv_cdf_impl(module, p, mu, sigma); if ((_return_value == -1.0) && PyErr_Occurred()) { @@ -47,4 +65,4 @@ _statistics__normal_dist_inv_cdf(PyObject *module, PyObject *const *args, Py_ssi exit: return return_value; } -/*[clinic end generated code: output=ba6af124acd34732 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c5826928a238326c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/audioop.c.h b/Modules/clinic/audioop.c.h index 4ea7155373be..aa176964b0f3 100644 --- a/Modules/clinic/audioop.c.h +++ b/Modules/clinic/audioop.c.h @@ -615,9 +615,15 @@ audioop_mul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (width == -1 && PyErr_Occurred()) { goto exit; } - factor = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + factor = PyFloat_AS_DOUBLE(args[2]); + } + else + { + factor = PyFloat_AsDouble(args[2]); + if (factor == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = audioop_mul_impl(module, &fragment, width, factor); @@ -671,13 +677,25 @@ audioop_tomono(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (width == -1 && PyErr_Occurred()) { goto exit; } - lfactor = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + lfactor = PyFloat_AS_DOUBLE(args[2]); } - rfactor = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + else + { + lfactor = PyFloat_AsDouble(args[2]); + if (lfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[3])) { + rfactor = PyFloat_AS_DOUBLE(args[3]); + } + else + { + rfactor = PyFloat_AsDouble(args[3]); + if (rfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = audioop_tomono_impl(module, &fragment, width, lfactor, rfactor); @@ -731,13 +749,25 @@ audioop_tostereo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (width == -1 && PyErr_Occurred()) { goto exit; } - lfactor = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + lfactor = PyFloat_AS_DOUBLE(args[2]); } - rfactor = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + else + { + lfactor = PyFloat_AsDouble(args[2]); + if (lfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[3])) { + rfactor = PyFloat_AS_DOUBLE(args[3]); + } + else + { + rfactor = PyFloat_AsDouble(args[3]); + if (rfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = audioop_tostereo_impl(module, &fragment, width, lfactor, rfactor); @@ -1439,4 +1469,4 @@ audioop_adpcm2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=2b173a25726252e9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=af32f4bce9c934fa input=a9049054013a1b77]*/ diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h index 83c498c22406..33509872069f 100644 --- a/Modules/clinic/cmathmodule.c.h +++ b/Modules/clinic/cmathmodule.c.h @@ -766,13 +766,25 @@ cmath_rect(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("rect", nargs, 2, 2)) { goto exit; } - r = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + r = PyFloat_AS_DOUBLE(args[0]); } - phi = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + r = PyFloat_AsDouble(args[0]); + if (r == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + phi = PyFloat_AS_DOUBLE(args[1]); + } + else + { + phi = PyFloat_AsDouble(args[1]); + if (phi == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = cmath_rect_impl(module, r, phi); @@ -922,17 +934,29 @@ cmath_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec goto skip_optional_kwonly; } if (args[2]) { - rel_tol = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + rel_tol = PyFloat_AS_DOUBLE(args[2]); + } + else + { + rel_tol = PyFloat_AsDouble(args[2]); + if (rel_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } if (!--noptargs) { goto skip_optional_kwonly; } } - abs_tol = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[3])) { + abs_tol = PyFloat_AS_DOUBLE(args[3]); + } + else + { + abs_tol = PyFloat_AsDouble(args[3]); + if (abs_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional_kwonly: _return_value = cmath_isclose_impl(module, a, b, rel_tol, abs_tol); @@ -944,4 +968,4 @@ cmath_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=c7afb866e593fa45 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3ab228947d1709cc input=a9049054013a1b77]*/ diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h index 84561b955787..95d68ee55ae5 100644 --- a/Modules/clinic/mathmodule.c.h +++ b/Modules/clinic/mathmodule.c.h @@ -117,9 +117,15 @@ math_frexp(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_frexp_impl(module, x); @@ -151,9 +157,15 @@ math_ldexp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("ldexp", nargs, 2, 2)) { goto exit; } - x = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + x = PyFloat_AS_DOUBLE(args[0]); + } + else + { + x = PyFloat_AsDouble(args[0]); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } i = args[1]; return_value = math_ldexp_impl(module, x, i); @@ -182,9 +194,15 @@ math_modf(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_modf_impl(module, x); @@ -277,13 +295,25 @@ math_fmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("fmod", nargs, 2, 2)) { goto exit; } - x = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + x = PyFloat_AS_DOUBLE(args[0]); } - y = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + x = PyFloat_AsDouble(args[0]); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + y = PyFloat_AS_DOUBLE(args[1]); + } + else + { + y = PyFloat_AsDouble(args[1]); + if (y == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_fmod_impl(module, x, y); @@ -349,13 +379,25 @@ math_pow(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("pow", nargs, 2, 2)) { goto exit; } - x = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + x = PyFloat_AS_DOUBLE(args[0]); } - y = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + x = PyFloat_AsDouble(args[0]); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + y = PyFloat_AS_DOUBLE(args[1]); + } + else + { + y = PyFloat_AsDouble(args[1]); + if (y == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_pow_impl(module, x, y); @@ -381,9 +423,15 @@ math_degrees(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_degrees_impl(module, x); @@ -409,9 +457,15 @@ math_radians(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_radians_impl(module, x); @@ -437,9 +491,15 @@ math_isfinite(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_isfinite_impl(module, x); @@ -465,9 +525,15 @@ math_isnan(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_isnan_impl(module, x); @@ -493,9 +559,15 @@ math_isinf(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_isinf_impl(module, x); @@ -550,29 +622,53 @@ math_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - a = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + a = PyFloat_AS_DOUBLE(args[0]); } - b = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + a = PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + b = PyFloat_AS_DOUBLE(args[1]); + } + else + { + b = PyFloat_AsDouble(args[1]); + if (b == -1.0 && PyErr_Occurred()) { + goto exit; + } } if (!noptargs) { goto skip_optional_kwonly; } if (args[2]) { - rel_tol = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + rel_tol = PyFloat_AS_DOUBLE(args[2]); + } + else + { + rel_tol = PyFloat_AsDouble(args[2]); + if (rel_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } if (!--noptargs) { goto skip_optional_kwonly; } } - abs_tol = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[3])) { + abs_tol = PyFloat_AS_DOUBLE(args[3]); + } + else + { + abs_tol = PyFloat_AsDouble(args[3]); + if (abs_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional_kwonly: _return_value = math_isclose_impl(module, a, b, rel_tol, abs_tol); @@ -712,4 +808,4 @@ math_comb(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=f93cfe13ab2fdb4e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9a2b3dc91eb9aadd input=a9049054013a1b77]*/ diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 1f09e0215a5b..2f3bd146e288 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -306,9 +306,15 @@ sys_setswitchinterval(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double interval; - interval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + interval = PyFloat_AS_DOUBLE(arg); + } + else + { + interval = PyFloat_AsDouble(arg); + if (interval == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = sys_setswitchinterval_impl(module, interval); @@ -989,4 +995,4 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=acef77d2bb8f6da9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b26faa0abdd700da input=a9049054013a1b77]*/ diff --git a/Python/getargs.c b/Python/getargs.c index cdc16d4730b5..fe6474c18112 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -887,7 +887,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'f': {/* float */ float *p = va_arg(*p_va, float *); double dval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) + if (dval == -1.0 && PyErr_Occurred()) RETURN_ERR_OCCURRED; else *p = (float) dval; @@ -897,7 +897,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'd': {/* double */ double *p = va_arg(*p_va, double *); double dval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) + if (dval == -1.0 && PyErr_Occurred()) RETURN_ERR_OCCURRED; else *p = dval; diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 9880b3951339..d5863a3effe9 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -3106,9 +3106,15 @@ class float_converter(CConverter): def parse_arg(self, argname, argnum): if self.format_unit == 'f': return """ - {paramname} = (float) PyFloat_AsDouble({argname}); - if (PyErr_Occurred()) {{{{ - goto exit; + if (PyFloat_CheckExact({argname})) {{{{ + {paramname} = (float) (PyFloat_AS_DOUBLE({argname})); + }}}} + else + {{{{ + {paramname} = (float) PyFloat_AsDouble({argname}); + if ({paramname} == -1.0 && PyErr_Occurred()) {{{{ + goto exit; + }}}} }}}} """.format(argname=argname, paramname=self.name) return super().parse_arg(argname, argnum) @@ -3122,9 +3128,15 @@ class double_converter(CConverter): def parse_arg(self, argname, argnum): if self.format_unit == 'd': return """ - {paramname} = PyFloat_AsDouble({argname}); - if (PyErr_Occurred()) {{{{ - goto exit; + if (PyFloat_CheckExact({argname})) {{{{ + {paramname} = PyFloat_AS_DOUBLE({argname}); + }}}} + else + {{{{ + {paramname} = PyFloat_AsDouble({argname}); + if ({paramname} == -1.0 && PyErr_Occurred()) {{{{ + goto exit; + }}}} }}}} """.format(argname=argname, paramname=self.name) return super().parse_arg(argname, argnum) From webhook-mailer at python.org Sat Aug 24 22:45:16 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 25 Aug 2019 02:45:16 -0000 Subject: [Python-checkins] [3.8] bpo-37942: Improve argument clinic float converter (GH-15470) (GH-15480) Message-ID: https://github.com/python/cpython/commit/21161d73d979012ec3b7247261178b3aa1555486 commit: 21161d73d979012ec3b7247261178b3aa1555486 branch: 3.8 author: Raymond Hettinger committer: GitHub date: 2019-08-24T19:45:12-07:00 summary: [3.8] bpo-37942: Improve argument clinic float converter (GH-15470) (GH-15480) (cherry picked from commit aef9ad82f7f667cd001a7112d3bc636e918626f7) files: A Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst M Lib/test/clinic.test M Modules/clinic/_ssl.c.h M Modules/clinic/_statisticsmodule.c.h M Modules/clinic/audioop.c.h M Modules/clinic/cmathmodule.c.h M Modules/clinic/mathmodule.c.h M Python/clinic/sysmodule.c.h M Python/getargs.c M Tools/clinic/clinic.py diff --git a/Lib/test/clinic.test b/Lib/test/clinic.test index 62c2f00c6b2b..ac6f419c0d3a 100644 --- a/Lib/test/clinic.test +++ b/Lib/test/clinic.test @@ -1587,9 +1587,15 @@ test_float_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - a = (float) PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + a = (float) (PyFloat_AS_DOUBLE(args[0])); + } + else + { + a = (float) PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional: return_value = test_float_converter_impl(module, a); @@ -1600,7 +1606,7 @@ exit: static PyObject * test_float_converter_impl(PyObject *module, float a) -/*[clinic end generated code: output=8293566b2ec1fc52 input=259c0d98eca35034]*/ +/*[clinic end generated code: output=6b9c7443d2601cea input=259c0d98eca35034]*/ /*[clinic input] @@ -1634,9 +1640,15 @@ test_double_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - a = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + a = PyFloat_AS_DOUBLE(args[0]); + } + else + { + a = PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional: return_value = test_double_converter_impl(module, a); @@ -1647,7 +1659,7 @@ exit: static PyObject * test_double_converter_impl(PyObject *module, double a) -/*[clinic end generated code: output=487081a9b8da67ab input=c6a9945706a41c27]*/ +/*[clinic end generated code: output=5b7b9a0f0791b2cc input=c6a9945706a41c27]*/ /*[clinic input] diff --git a/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst b/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst new file mode 100644 index 000000000000..6f6431409554 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst @@ -0,0 +1 @@ +Improve ArgumentClinic converter for floats. diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index b1012f7aee2e..adef7dbf90ce 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -1093,9 +1093,15 @@ _ssl_RAND_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } } - entropy = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[1])) { + entropy = PyFloat_AS_DOUBLE(args[1]); + } + else + { + entropy = PyFloat_AsDouble(args[1]); + if (entropy == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = _ssl_RAND_add_impl(module, &view, entropy); @@ -1476,4 +1482,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=a399d0eb393b6fab input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5003112e167cd948 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_statisticsmodule.c.h b/Modules/clinic/_statisticsmodule.c.h index f5a2e4678f30..5ff01efddcde 100644 --- a/Modules/clinic/_statisticsmodule.c.h +++ b/Modules/clinic/_statisticsmodule.c.h @@ -26,17 +26,35 @@ _statistics__normal_dist_inv_cdf(PyObject *module, PyObject *const *args, Py_ssi if (!_PyArg_CheckPositional("_normal_dist_inv_cdf", nargs, 3, 3)) { goto exit; } - p = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + p = PyFloat_AS_DOUBLE(args[0]); } - mu = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + p = PyFloat_AsDouble(args[0]); + if (p == -1.0 && PyErr_Occurred()) { + goto exit; + } } - sigma = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[1])) { + mu = PyFloat_AS_DOUBLE(args[1]); + } + else + { + mu = PyFloat_AsDouble(args[1]); + if (mu == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[2])) { + sigma = PyFloat_AS_DOUBLE(args[2]); + } + else + { + sigma = PyFloat_AsDouble(args[2]); + if (sigma == -1.0 && PyErr_Occurred()) { + goto exit; + } } _return_value = _statistics__normal_dist_inv_cdf_impl(module, p, mu, sigma); if ((_return_value == -1.0) && PyErr_Occurred()) { @@ -47,4 +65,4 @@ _statistics__normal_dist_inv_cdf(PyObject *module, PyObject *const *args, Py_ssi exit: return return_value; } -/*[clinic end generated code: output=ba6af124acd34732 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c5826928a238326c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/audioop.c.h b/Modules/clinic/audioop.c.h index 4ea7155373be..aa176964b0f3 100644 --- a/Modules/clinic/audioop.c.h +++ b/Modules/clinic/audioop.c.h @@ -615,9 +615,15 @@ audioop_mul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (width == -1 && PyErr_Occurred()) { goto exit; } - factor = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + factor = PyFloat_AS_DOUBLE(args[2]); + } + else + { + factor = PyFloat_AsDouble(args[2]); + if (factor == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = audioop_mul_impl(module, &fragment, width, factor); @@ -671,13 +677,25 @@ audioop_tomono(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (width == -1 && PyErr_Occurred()) { goto exit; } - lfactor = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + lfactor = PyFloat_AS_DOUBLE(args[2]); } - rfactor = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + else + { + lfactor = PyFloat_AsDouble(args[2]); + if (lfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[3])) { + rfactor = PyFloat_AS_DOUBLE(args[3]); + } + else + { + rfactor = PyFloat_AsDouble(args[3]); + if (rfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = audioop_tomono_impl(module, &fragment, width, lfactor, rfactor); @@ -731,13 +749,25 @@ audioop_tostereo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (width == -1 && PyErr_Occurred()) { goto exit; } - lfactor = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + lfactor = PyFloat_AS_DOUBLE(args[2]); } - rfactor = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + else + { + lfactor = PyFloat_AsDouble(args[2]); + if (lfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[3])) { + rfactor = PyFloat_AS_DOUBLE(args[3]); + } + else + { + rfactor = PyFloat_AsDouble(args[3]); + if (rfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = audioop_tostereo_impl(module, &fragment, width, lfactor, rfactor); @@ -1439,4 +1469,4 @@ audioop_adpcm2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=2b173a25726252e9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=af32f4bce9c934fa input=a9049054013a1b77]*/ diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h index 83c498c22406..33509872069f 100644 --- a/Modules/clinic/cmathmodule.c.h +++ b/Modules/clinic/cmathmodule.c.h @@ -766,13 +766,25 @@ cmath_rect(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("rect", nargs, 2, 2)) { goto exit; } - r = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + r = PyFloat_AS_DOUBLE(args[0]); } - phi = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + r = PyFloat_AsDouble(args[0]); + if (r == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + phi = PyFloat_AS_DOUBLE(args[1]); + } + else + { + phi = PyFloat_AsDouble(args[1]); + if (phi == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = cmath_rect_impl(module, r, phi); @@ -922,17 +934,29 @@ cmath_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec goto skip_optional_kwonly; } if (args[2]) { - rel_tol = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + rel_tol = PyFloat_AS_DOUBLE(args[2]); + } + else + { + rel_tol = PyFloat_AsDouble(args[2]); + if (rel_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } if (!--noptargs) { goto skip_optional_kwonly; } } - abs_tol = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[3])) { + abs_tol = PyFloat_AS_DOUBLE(args[3]); + } + else + { + abs_tol = PyFloat_AsDouble(args[3]); + if (abs_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional_kwonly: _return_value = cmath_isclose_impl(module, a, b, rel_tol, abs_tol); @@ -944,4 +968,4 @@ cmath_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=c7afb866e593fa45 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3ab228947d1709cc input=a9049054013a1b77]*/ diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h index 84561b955787..95d68ee55ae5 100644 --- a/Modules/clinic/mathmodule.c.h +++ b/Modules/clinic/mathmodule.c.h @@ -117,9 +117,15 @@ math_frexp(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_frexp_impl(module, x); @@ -151,9 +157,15 @@ math_ldexp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("ldexp", nargs, 2, 2)) { goto exit; } - x = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + x = PyFloat_AS_DOUBLE(args[0]); + } + else + { + x = PyFloat_AsDouble(args[0]); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } i = args[1]; return_value = math_ldexp_impl(module, x, i); @@ -182,9 +194,15 @@ math_modf(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_modf_impl(module, x); @@ -277,13 +295,25 @@ math_fmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("fmod", nargs, 2, 2)) { goto exit; } - x = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + x = PyFloat_AS_DOUBLE(args[0]); } - y = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + x = PyFloat_AsDouble(args[0]); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + y = PyFloat_AS_DOUBLE(args[1]); + } + else + { + y = PyFloat_AsDouble(args[1]); + if (y == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_fmod_impl(module, x, y); @@ -349,13 +379,25 @@ math_pow(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("pow", nargs, 2, 2)) { goto exit; } - x = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + x = PyFloat_AS_DOUBLE(args[0]); } - y = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + x = PyFloat_AsDouble(args[0]); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + y = PyFloat_AS_DOUBLE(args[1]); + } + else + { + y = PyFloat_AsDouble(args[1]); + if (y == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_pow_impl(module, x, y); @@ -381,9 +423,15 @@ math_degrees(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_degrees_impl(module, x); @@ -409,9 +457,15 @@ math_radians(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_radians_impl(module, x); @@ -437,9 +491,15 @@ math_isfinite(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_isfinite_impl(module, x); @@ -465,9 +525,15 @@ math_isnan(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_isnan_impl(module, x); @@ -493,9 +559,15 @@ math_isinf(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_isinf_impl(module, x); @@ -550,29 +622,53 @@ math_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - a = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + a = PyFloat_AS_DOUBLE(args[0]); } - b = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + a = PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + b = PyFloat_AS_DOUBLE(args[1]); + } + else + { + b = PyFloat_AsDouble(args[1]); + if (b == -1.0 && PyErr_Occurred()) { + goto exit; + } } if (!noptargs) { goto skip_optional_kwonly; } if (args[2]) { - rel_tol = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + rel_tol = PyFloat_AS_DOUBLE(args[2]); + } + else + { + rel_tol = PyFloat_AsDouble(args[2]); + if (rel_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } if (!--noptargs) { goto skip_optional_kwonly; } } - abs_tol = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[3])) { + abs_tol = PyFloat_AS_DOUBLE(args[3]); + } + else + { + abs_tol = PyFloat_AsDouble(args[3]); + if (abs_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional_kwonly: _return_value = math_isclose_impl(module, a, b, rel_tol, abs_tol); @@ -712,4 +808,4 @@ math_comb(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=f93cfe13ab2fdb4e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9a2b3dc91eb9aadd input=a9049054013a1b77]*/ diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 6f248ff18d9d..563332eeb5c6 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -362,9 +362,15 @@ sys_setswitchinterval(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double interval; - interval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + interval = PyFloat_AS_DOUBLE(arg); + } + else + { + interval = PyFloat_AsDouble(arg); + if (interval == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = sys_setswitchinterval_impl(module, interval); @@ -1082,4 +1088,4 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=43c4fde7b5783d8d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1a67b37c4486d65f input=a9049054013a1b77]*/ diff --git a/Python/getargs.c b/Python/getargs.c index 59f0fdabb74a..051ebc78a0f8 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -887,7 +887,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'f': {/* float */ float *p = va_arg(*p_va, float *); double dval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) + if (dval == -1.0 && PyErr_Occurred()) RETURN_ERR_OCCURRED; else *p = (float) dval; @@ -897,7 +897,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'd': {/* double */ double *p = va_arg(*p_va, double *); double dval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) + if (dval == -1.0 && PyErr_Occurred()) RETURN_ERR_OCCURRED; else *p = dval; diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 9880b3951339..d5863a3effe9 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -3106,9 +3106,15 @@ class float_converter(CConverter): def parse_arg(self, argname, argnum): if self.format_unit == 'f': return """ - {paramname} = (float) PyFloat_AsDouble({argname}); - if (PyErr_Occurred()) {{{{ - goto exit; + if (PyFloat_CheckExact({argname})) {{{{ + {paramname} = (float) (PyFloat_AS_DOUBLE({argname})); + }}}} + else + {{{{ + {paramname} = (float) PyFloat_AsDouble({argname}); + if ({paramname} == -1.0 && PyErr_Occurred()) {{{{ + goto exit; + }}}} }}}} """.format(argname=argname, paramname=self.name) return super().parse_arg(argname, argnum) @@ -3122,9 +3128,15 @@ class double_converter(CConverter): def parse_arg(self, argname, argnum): if self.format_unit == 'd': return """ - {paramname} = PyFloat_AsDouble({argname}); - if (PyErr_Occurred()) {{{{ - goto exit; + if (PyFloat_CheckExact({argname})) {{{{ + {paramname} = PyFloat_AS_DOUBLE({argname}); + }}}} + else + {{{{ + {paramname} = PyFloat_AsDouble({argname}); + if ({paramname} == -1.0 && PyErr_Occurred()) {{{{ + goto exit; + }}}} }}}} """.format(argname=argname, paramname=self.name) return super().parse_arg(argname, argnum) From webhook-mailer at python.org Sun Aug 25 01:53:02 2019 From: webhook-mailer at python.org (Tal Einat) Date: Sun, 25 Aug 2019 05:53:02 -0000 Subject: [Python-checkins] bpo-37929: IDLE: avoid Squeezer-related config dialog crashes (GH-15452) Message-ID: https://github.com/python/cpython/commit/d4b4c00b57d24f6ee2cf3a96213406bb09953df3 commit: d4b4c00b57d24f6ee2cf3a96213406bb09953df3 branch: master author: Tal Einat committer: GitHub date: 2019-08-25T08:52:58+03:00 summary: bpo-37929: IDLE: avoid Squeezer-related config dialog crashes (GH-15452) These were caused by keeping around a reference to the Squeezer instance and calling it's load_font() upon config changes, which sometimes happened even if the shell window no longer existed. This change completely removes that mechanism, instead having the editor window properly update its width attribute, which can then be used by Squeezer. files: A Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst M Lib/idlelib/editor.py M Lib/idlelib/idle_test/test_squeezer.py M Lib/idlelib/squeezer.py diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 35027da76bce..793ed3afaed0 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -10,6 +10,7 @@ import webbrowser from tkinter import * +from tkinter.font import Font from tkinter.ttk import Scrollbar import tkinter.simpledialog as tkSimpleDialog import tkinter.messagebox as tkMessageBox @@ -120,14 +121,13 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.prompt_last_line = '' # Override in PyShell self.text_frame = text_frame = Frame(top) self.vbar = vbar = Scrollbar(text_frame, name='vbar') - self.width = idleConf.GetOption('main', 'EditorWindow', - 'width', type='int') + width = idleConf.GetOption('main', 'EditorWindow', 'width', type='int') text_options = { 'name': 'text', 'padx': 5, 'wrap': 'none', 'highlightthickness': 0, - 'width': self.width, + 'width': width, 'tabstyle': 'wordprocessor', # new in 8.5 'height': idleConf.GetOption( 'main', 'EditorWindow', 'height', type='int'), @@ -154,6 +154,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text.bind('', self.mousescroll) text.bind('', self.mousescroll) text.bind('', self.mousescroll) + text.bind('', self.handle_winconfig) text.bind("<>", self.cut) text.bind("<>", self.copy) text.bind("<>", self.paste) @@ -211,6 +212,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text['font'] = idleConf.GetFont(self.root, 'main', 'EditorWindow') text.grid(row=1, column=1, sticky=NSEW) text.focus_set() + self.set_width() # usetabs true -> literal tab characters are used by indent and # dedent cmds, possibly mixed with spaces if @@ -338,6 +340,22 @@ def __init__(self, flist=None, filename=None, key=None, root=None): else: self.update_menu_state('options', '*Line Numbers', 'disabled') + def handle_winconfig(self, event=None): + self.set_width() + + def set_width(self): + text = self.text + inner_padding = sum(map(text.tk.getint, [text.cget('border'), + text.cget('padx')])) + pixel_width = text.winfo_width() - 2 * inner_padding + + # Divide the width of the Text widget by the font width, + # which is taken to be the width of '0' (zero). + # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21 + zero_char_width = \ + Font(text, font=text.cget('font')).measure('0') + self.width = pixel_width // zero_char_width + def _filename_to_unicode(self, filename): """Return filename as BMP unicode so displayable in Tk.""" # Decode bytes to unicode. @@ -830,6 +848,7 @@ def ResetFont(self): # Finally, update the main text widget. new_font = idleConf.GetFont(self.root, 'main', 'EditorWindow') self.text['font'] = new_font + self.set_width() def RemoveKeybindings(self): "Remove the keybindings before they are changed." diff --git a/Lib/idlelib/idle_test/test_squeezer.py b/Lib/idlelib/idle_test/test_squeezer.py index 4e3da030a3ad..1af2ce832845 100644 --- a/Lib/idlelib/idle_test/test_squeezer.py +++ b/Lib/idlelib/idle_test/test_squeezer.py @@ -82,18 +82,10 @@ def test_several_lines_different_lengths(self): class SqueezerTest(unittest.TestCase): """Tests for the Squeezer class.""" - def tearDown(self): - # Clean up the Squeezer class's reference to its instance, - # to avoid side-effects from one test case upon another. - if Squeezer._instance_weakref is not None: - Squeezer._instance_weakref = None - def make_mock_editor_window(self, with_text_widget=False): """Create a mock EditorWindow instance.""" editwin = NonCallableMagicMock() - # isinstance(editwin, PyShell) must be true for Squeezer to enable - # auto-squeezing; in practice this will always be true. - editwin.__class__ = PyShell + editwin.width = 80 if with_text_widget: editwin.root = get_test_tk_root(self) @@ -107,7 +99,6 @@ def make_squeezer_instance(self, editor_window=None): if editor_window is None: editor_window = self.make_mock_editor_window() squeezer = Squeezer(editor_window) - squeezer.get_line_width = Mock(return_value=80) return squeezer def make_text_widget(self, root=None): @@ -143,8 +134,8 @@ def test_count_lines(self): line_width=line_width, expected=expected): text = eval(text_code) - squeezer.get_line_width.return_value = line_width - self.assertEqual(squeezer.count_lines(text), expected) + with patch.object(editwin, 'width', line_width): + self.assertEqual(squeezer.count_lines(text), expected) def test_init(self): """Test the creation of Squeezer instances.""" @@ -294,7 +285,6 @@ def test_reload(self): """Test the reload() class-method.""" editwin = self.make_mock_editor_window(with_text_widget=True) squeezer = self.make_squeezer_instance(editwin) - squeezer.load_font = Mock() orig_auto_squeeze_min_lines = squeezer.auto_squeeze_min_lines @@ -307,7 +297,6 @@ def test_reload(self): Squeezer.reload() self.assertEqual(squeezer.auto_squeeze_min_lines, new_auto_squeeze_min_lines) - squeezer.load_font.assert_called() def test_reload_no_squeezer_instances(self): """Test that Squeezer.reload() runs without any instances existing.""" diff --git a/Lib/idlelib/squeezer.py b/Lib/idlelib/squeezer.py index 032401f2abc7..be1538a25fde 100644 --- a/Lib/idlelib/squeezer.py +++ b/Lib/idlelib/squeezer.py @@ -15,10 +15,8 @@ messages and their tracebacks. """ import re -import weakref import tkinter as tk -from tkinter.font import Font import tkinter.messagebox as tkMessageBox from idlelib.config import idleConf @@ -203,8 +201,6 @@ class Squeezer: This avoids IDLE's shell slowing down considerably, and even becoming completely unresponsive, when very long outputs are written. """ - _instance_weakref = None - @classmethod def reload(cls): """Load class variables from config.""" @@ -213,14 +209,6 @@ def reload(cls): type="int", default=50, ) - # Loading the font info requires a Tk root. IDLE doesn't rely - # on Tkinter's "default root", so the instance will reload - # font info using its editor windows's Tk root. - if cls._instance_weakref is not None: - instance = cls._instance_weakref() - if instance is not None: - instance.load_font() - def __init__(self, editwin): """Initialize settings for Squeezer. @@ -241,9 +229,6 @@ def __init__(self, editwin): # however, needs to make such changes. self.base_text = editwin.per.bottom - Squeezer._instance_weakref = weakref.ref(self) - self.load_font() - # Twice the text widget's border width and internal padding; # pre-calculated here for the get_line_width() method. self.window_width_delta = 2 * ( @@ -298,24 +283,7 @@ def count_lines(self, s): Tabs are considered tabwidth characters long. """ - linewidth = self.get_line_width() - return count_lines_with_wrapping(s, linewidth) - - def get_line_width(self): - # The maximum line length in pixels: The width of the text - # widget, minus twice the border width and internal padding. - linewidth_pixels = \ - self.base_text.winfo_width() - self.window_width_delta - - # Divide the width of the Text widget by the font width, - # which is taken to be the width of '0' (zero). - # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21 - return linewidth_pixels // self.zero_char_width - - def load_font(self): - text = self.base_text - self.zero_char_width = \ - Font(text, font=text.cget('font')).measure('0') + return count_lines_with_wrapping(s, self.editwin.width) def squeeze_current_text_event(self, event): """squeeze-current-text event handler diff --git a/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst b/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst new file mode 100644 index 000000000000..d627b2de2a7c --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst @@ -0,0 +1 @@ +IDLE Settings dialog now closes properly when there is no shell window. From webhook-mailer at python.org Sun Aug 25 02:17:24 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Aug 2019 06:17:24 -0000 Subject: [Python-checkins] bpo-37929: IDLE: avoid Squeezer-related config dialog crashes (GH-15452) Message-ID: https://github.com/python/cpython/commit/f2b468dd6d0bdbe2e87c0ca7515800a115e95e54 commit: f2b468dd6d0bdbe2e87c0ca7515800a115e95e54 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-24T23:17:19-07:00 summary: bpo-37929: IDLE: avoid Squeezer-related config dialog crashes (GH-15452) These were caused by keeping around a reference to the Squeezer instance and calling it's load_font() upon config changes, which sometimes happened even if the shell window no longer existed. This change completely removes that mechanism, instead having the editor window properly update its width attribute, which can then be used by Squeezer. (cherry picked from commit d4b4c00b57d24f6ee2cf3a96213406bb09953df3) Co-authored-by: Tal Einat files: A Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst M Lib/idlelib/editor.py M Lib/idlelib/idle_test/test_squeezer.py M Lib/idlelib/squeezer.py diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 35027da76bce..793ed3afaed0 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -10,6 +10,7 @@ import webbrowser from tkinter import * +from tkinter.font import Font from tkinter.ttk import Scrollbar import tkinter.simpledialog as tkSimpleDialog import tkinter.messagebox as tkMessageBox @@ -120,14 +121,13 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.prompt_last_line = '' # Override in PyShell self.text_frame = text_frame = Frame(top) self.vbar = vbar = Scrollbar(text_frame, name='vbar') - self.width = idleConf.GetOption('main', 'EditorWindow', - 'width', type='int') + width = idleConf.GetOption('main', 'EditorWindow', 'width', type='int') text_options = { 'name': 'text', 'padx': 5, 'wrap': 'none', 'highlightthickness': 0, - 'width': self.width, + 'width': width, 'tabstyle': 'wordprocessor', # new in 8.5 'height': idleConf.GetOption( 'main', 'EditorWindow', 'height', type='int'), @@ -154,6 +154,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text.bind('', self.mousescroll) text.bind('', self.mousescroll) text.bind('', self.mousescroll) + text.bind('', self.handle_winconfig) text.bind("<>", self.cut) text.bind("<>", self.copy) text.bind("<>", self.paste) @@ -211,6 +212,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text['font'] = idleConf.GetFont(self.root, 'main', 'EditorWindow') text.grid(row=1, column=1, sticky=NSEW) text.focus_set() + self.set_width() # usetabs true -> literal tab characters are used by indent and # dedent cmds, possibly mixed with spaces if @@ -338,6 +340,22 @@ def __init__(self, flist=None, filename=None, key=None, root=None): else: self.update_menu_state('options', '*Line Numbers', 'disabled') + def handle_winconfig(self, event=None): + self.set_width() + + def set_width(self): + text = self.text + inner_padding = sum(map(text.tk.getint, [text.cget('border'), + text.cget('padx')])) + pixel_width = text.winfo_width() - 2 * inner_padding + + # Divide the width of the Text widget by the font width, + # which is taken to be the width of '0' (zero). + # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21 + zero_char_width = \ + Font(text, font=text.cget('font')).measure('0') + self.width = pixel_width // zero_char_width + def _filename_to_unicode(self, filename): """Return filename as BMP unicode so displayable in Tk.""" # Decode bytes to unicode. @@ -830,6 +848,7 @@ def ResetFont(self): # Finally, update the main text widget. new_font = idleConf.GetFont(self.root, 'main', 'EditorWindow') self.text['font'] = new_font + self.set_width() def RemoveKeybindings(self): "Remove the keybindings before they are changed." diff --git a/Lib/idlelib/idle_test/test_squeezer.py b/Lib/idlelib/idle_test/test_squeezer.py index 4e3da030a3ad..1af2ce832845 100644 --- a/Lib/idlelib/idle_test/test_squeezer.py +++ b/Lib/idlelib/idle_test/test_squeezer.py @@ -82,18 +82,10 @@ def test_several_lines_different_lengths(self): class SqueezerTest(unittest.TestCase): """Tests for the Squeezer class.""" - def tearDown(self): - # Clean up the Squeezer class's reference to its instance, - # to avoid side-effects from one test case upon another. - if Squeezer._instance_weakref is not None: - Squeezer._instance_weakref = None - def make_mock_editor_window(self, with_text_widget=False): """Create a mock EditorWindow instance.""" editwin = NonCallableMagicMock() - # isinstance(editwin, PyShell) must be true for Squeezer to enable - # auto-squeezing; in practice this will always be true. - editwin.__class__ = PyShell + editwin.width = 80 if with_text_widget: editwin.root = get_test_tk_root(self) @@ -107,7 +99,6 @@ def make_squeezer_instance(self, editor_window=None): if editor_window is None: editor_window = self.make_mock_editor_window() squeezer = Squeezer(editor_window) - squeezer.get_line_width = Mock(return_value=80) return squeezer def make_text_widget(self, root=None): @@ -143,8 +134,8 @@ def test_count_lines(self): line_width=line_width, expected=expected): text = eval(text_code) - squeezer.get_line_width.return_value = line_width - self.assertEqual(squeezer.count_lines(text), expected) + with patch.object(editwin, 'width', line_width): + self.assertEqual(squeezer.count_lines(text), expected) def test_init(self): """Test the creation of Squeezer instances.""" @@ -294,7 +285,6 @@ def test_reload(self): """Test the reload() class-method.""" editwin = self.make_mock_editor_window(with_text_widget=True) squeezer = self.make_squeezer_instance(editwin) - squeezer.load_font = Mock() orig_auto_squeeze_min_lines = squeezer.auto_squeeze_min_lines @@ -307,7 +297,6 @@ def test_reload(self): Squeezer.reload() self.assertEqual(squeezer.auto_squeeze_min_lines, new_auto_squeeze_min_lines) - squeezer.load_font.assert_called() def test_reload_no_squeezer_instances(self): """Test that Squeezer.reload() runs without any instances existing.""" diff --git a/Lib/idlelib/squeezer.py b/Lib/idlelib/squeezer.py index 032401f2abc7..be1538a25fde 100644 --- a/Lib/idlelib/squeezer.py +++ b/Lib/idlelib/squeezer.py @@ -15,10 +15,8 @@ messages and their tracebacks. """ import re -import weakref import tkinter as tk -from tkinter.font import Font import tkinter.messagebox as tkMessageBox from idlelib.config import idleConf @@ -203,8 +201,6 @@ class Squeezer: This avoids IDLE's shell slowing down considerably, and even becoming completely unresponsive, when very long outputs are written. """ - _instance_weakref = None - @classmethod def reload(cls): """Load class variables from config.""" @@ -213,14 +209,6 @@ def reload(cls): type="int", default=50, ) - # Loading the font info requires a Tk root. IDLE doesn't rely - # on Tkinter's "default root", so the instance will reload - # font info using its editor windows's Tk root. - if cls._instance_weakref is not None: - instance = cls._instance_weakref() - if instance is not None: - instance.load_font() - def __init__(self, editwin): """Initialize settings for Squeezer. @@ -241,9 +229,6 @@ def __init__(self, editwin): # however, needs to make such changes. self.base_text = editwin.per.bottom - Squeezer._instance_weakref = weakref.ref(self) - self.load_font() - # Twice the text widget's border width and internal padding; # pre-calculated here for the get_line_width() method. self.window_width_delta = 2 * ( @@ -298,24 +283,7 @@ def count_lines(self, s): Tabs are considered tabwidth characters long. """ - linewidth = self.get_line_width() - return count_lines_with_wrapping(s, linewidth) - - def get_line_width(self): - # The maximum line length in pixels: The width of the text - # widget, minus twice the border width and internal padding. - linewidth_pixels = \ - self.base_text.winfo_width() - self.window_width_delta - - # Divide the width of the Text widget by the font width, - # which is taken to be the width of '0' (zero). - # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21 - return linewidth_pixels // self.zero_char_width - - def load_font(self): - text = self.base_text - self.zero_char_width = \ - Font(text, font=text.cget('font')).measure('0') + return count_lines_with_wrapping(s, self.editwin.width) def squeeze_current_text_event(self, event): """squeeze-current-text event handler diff --git a/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst b/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst new file mode 100644 index 000000000000..d627b2de2a7c --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst @@ -0,0 +1 @@ +IDLE Settings dialog now closes properly when there is no shell window. From webhook-mailer at python.org Sun Aug 25 02:18:05 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Aug 2019 06:18:05 -0000 Subject: [Python-checkins] bpo-37929: IDLE: avoid Squeezer-related config dialog crashes (GH-15452) Message-ID: https://github.com/python/cpython/commit/e266d062e017b122b9741db2bd5fb99742378623 commit: e266d062e017b122b9741db2bd5fb99742378623 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-24T23:18:01-07:00 summary: bpo-37929: IDLE: avoid Squeezer-related config dialog crashes (GH-15452) These were caused by keeping around a reference to the Squeezer instance and calling it's load_font() upon config changes, which sometimes happened even if the shell window no longer existed. This change completely removes that mechanism, instead having the editor window properly update its width attribute, which can then be used by Squeezer. (cherry picked from commit d4b4c00b57d24f6ee2cf3a96213406bb09953df3) Co-authored-by: Tal Einat files: A Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst M Lib/idlelib/editor.py M Lib/idlelib/idle_test/test_squeezer.py M Lib/idlelib/squeezer.py diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 35027da76bce..793ed3afaed0 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -10,6 +10,7 @@ import webbrowser from tkinter import * +from tkinter.font import Font from tkinter.ttk import Scrollbar import tkinter.simpledialog as tkSimpleDialog import tkinter.messagebox as tkMessageBox @@ -120,14 +121,13 @@ def __init__(self, flist=None, filename=None, key=None, root=None): self.prompt_last_line = '' # Override in PyShell self.text_frame = text_frame = Frame(top) self.vbar = vbar = Scrollbar(text_frame, name='vbar') - self.width = idleConf.GetOption('main', 'EditorWindow', - 'width', type='int') + width = idleConf.GetOption('main', 'EditorWindow', 'width', type='int') text_options = { 'name': 'text', 'padx': 5, 'wrap': 'none', 'highlightthickness': 0, - 'width': self.width, + 'width': width, 'tabstyle': 'wordprocessor', # new in 8.5 'height': idleConf.GetOption( 'main', 'EditorWindow', 'height', type='int'), @@ -154,6 +154,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text.bind('', self.mousescroll) text.bind('', self.mousescroll) text.bind('', self.mousescroll) + text.bind('', self.handle_winconfig) text.bind("<>", self.cut) text.bind("<>", self.copy) text.bind("<>", self.paste) @@ -211,6 +212,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None): text['font'] = idleConf.GetFont(self.root, 'main', 'EditorWindow') text.grid(row=1, column=1, sticky=NSEW) text.focus_set() + self.set_width() # usetabs true -> literal tab characters are used by indent and # dedent cmds, possibly mixed with spaces if @@ -338,6 +340,22 @@ def __init__(self, flist=None, filename=None, key=None, root=None): else: self.update_menu_state('options', '*Line Numbers', 'disabled') + def handle_winconfig(self, event=None): + self.set_width() + + def set_width(self): + text = self.text + inner_padding = sum(map(text.tk.getint, [text.cget('border'), + text.cget('padx')])) + pixel_width = text.winfo_width() - 2 * inner_padding + + # Divide the width of the Text widget by the font width, + # which is taken to be the width of '0' (zero). + # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21 + zero_char_width = \ + Font(text, font=text.cget('font')).measure('0') + self.width = pixel_width // zero_char_width + def _filename_to_unicode(self, filename): """Return filename as BMP unicode so displayable in Tk.""" # Decode bytes to unicode. @@ -830,6 +848,7 @@ def ResetFont(self): # Finally, update the main text widget. new_font = idleConf.GetFont(self.root, 'main', 'EditorWindow') self.text['font'] = new_font + self.set_width() def RemoveKeybindings(self): "Remove the keybindings before they are changed." diff --git a/Lib/idlelib/idle_test/test_squeezer.py b/Lib/idlelib/idle_test/test_squeezer.py index 4e3da030a3ad..1af2ce832845 100644 --- a/Lib/idlelib/idle_test/test_squeezer.py +++ b/Lib/idlelib/idle_test/test_squeezer.py @@ -82,18 +82,10 @@ def test_several_lines_different_lengths(self): class SqueezerTest(unittest.TestCase): """Tests for the Squeezer class.""" - def tearDown(self): - # Clean up the Squeezer class's reference to its instance, - # to avoid side-effects from one test case upon another. - if Squeezer._instance_weakref is not None: - Squeezer._instance_weakref = None - def make_mock_editor_window(self, with_text_widget=False): """Create a mock EditorWindow instance.""" editwin = NonCallableMagicMock() - # isinstance(editwin, PyShell) must be true for Squeezer to enable - # auto-squeezing; in practice this will always be true. - editwin.__class__ = PyShell + editwin.width = 80 if with_text_widget: editwin.root = get_test_tk_root(self) @@ -107,7 +99,6 @@ def make_squeezer_instance(self, editor_window=None): if editor_window is None: editor_window = self.make_mock_editor_window() squeezer = Squeezer(editor_window) - squeezer.get_line_width = Mock(return_value=80) return squeezer def make_text_widget(self, root=None): @@ -143,8 +134,8 @@ def test_count_lines(self): line_width=line_width, expected=expected): text = eval(text_code) - squeezer.get_line_width.return_value = line_width - self.assertEqual(squeezer.count_lines(text), expected) + with patch.object(editwin, 'width', line_width): + self.assertEqual(squeezer.count_lines(text), expected) def test_init(self): """Test the creation of Squeezer instances.""" @@ -294,7 +285,6 @@ def test_reload(self): """Test the reload() class-method.""" editwin = self.make_mock_editor_window(with_text_widget=True) squeezer = self.make_squeezer_instance(editwin) - squeezer.load_font = Mock() orig_auto_squeeze_min_lines = squeezer.auto_squeeze_min_lines @@ -307,7 +297,6 @@ def test_reload(self): Squeezer.reload() self.assertEqual(squeezer.auto_squeeze_min_lines, new_auto_squeeze_min_lines) - squeezer.load_font.assert_called() def test_reload_no_squeezer_instances(self): """Test that Squeezer.reload() runs without any instances existing.""" diff --git a/Lib/idlelib/squeezer.py b/Lib/idlelib/squeezer.py index 032401f2abc7..be1538a25fde 100644 --- a/Lib/idlelib/squeezer.py +++ b/Lib/idlelib/squeezer.py @@ -15,10 +15,8 @@ messages and their tracebacks. """ import re -import weakref import tkinter as tk -from tkinter.font import Font import tkinter.messagebox as tkMessageBox from idlelib.config import idleConf @@ -203,8 +201,6 @@ class Squeezer: This avoids IDLE's shell slowing down considerably, and even becoming completely unresponsive, when very long outputs are written. """ - _instance_weakref = None - @classmethod def reload(cls): """Load class variables from config.""" @@ -213,14 +209,6 @@ def reload(cls): type="int", default=50, ) - # Loading the font info requires a Tk root. IDLE doesn't rely - # on Tkinter's "default root", so the instance will reload - # font info using its editor windows's Tk root. - if cls._instance_weakref is not None: - instance = cls._instance_weakref() - if instance is not None: - instance.load_font() - def __init__(self, editwin): """Initialize settings for Squeezer. @@ -241,9 +229,6 @@ def __init__(self, editwin): # however, needs to make such changes. self.base_text = editwin.per.bottom - Squeezer._instance_weakref = weakref.ref(self) - self.load_font() - # Twice the text widget's border width and internal padding; # pre-calculated here for the get_line_width() method. self.window_width_delta = 2 * ( @@ -298,24 +283,7 @@ def count_lines(self, s): Tabs are considered tabwidth characters long. """ - linewidth = self.get_line_width() - return count_lines_with_wrapping(s, linewidth) - - def get_line_width(self): - # The maximum line length in pixels: The width of the text - # widget, minus twice the border width and internal padding. - linewidth_pixels = \ - self.base_text.winfo_width() - self.window_width_delta - - # Divide the width of the Text widget by the font width, - # which is taken to be the width of '0' (zero). - # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21 - return linewidth_pixels // self.zero_char_width - - def load_font(self): - text = self.base_text - self.zero_char_width = \ - Font(text, font=text.cget('font')).measure('0') + return count_lines_with_wrapping(s, self.editwin.width) def squeeze_current_text_event(self, event): """squeeze-current-text event handler diff --git a/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst b/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst new file mode 100644 index 000000000000..d627b2de2a7c --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst @@ -0,0 +1 @@ +IDLE Settings dialog now closes properly when there is no shell window. From webhook-mailer at python.org Sun Aug 25 03:57:31 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 25 Aug 2019 07:57:31 -0000 Subject: [Python-checkins] bpo-37905: Improve docs for NormalDist (GH-15486) Message-ID: https://github.com/python/cpython/commit/8371799e300475c8f9f967e900816218d3500e5d commit: 8371799e300475c8f9f967e900816218d3500e5d branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-25T00:57:26-07:00 summary: bpo-37905: Improve docs for NormalDist (GH-15486) files: M Doc/library/statistics.rst diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index bb77228ceac1..04b731dcc444 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -667,12 +667,8 @@ of applications in statistics. .. method:: NormalDist.overlap(other) - Compute the `overlapping coefficient (OVL) - `_ - between two normal distributions, giving a measure of agreement. - Returns a value between 0.0 and 1.0 giving `the overlapping area for - the two probability density functions - `_. + Returns a value between 0.0 and 1.0 giving the overlapping area for + the two probability density functions. Instances of :class:`NormalDist` support addition, subtraction, multiplication and division by a constant. These operations @@ -734,16 +730,6 @@ Find the `quartiles `_ and `deciles >>> [round(sat.inv_cdf(p / 10)) for p in range(1, 10)] [810, 896, 958, 1011, 1060, 1109, 1162, 1224, 1310] -What percentage of men and women will have the same height in `two normally -distributed populations with known means and standard deviations -`_? - - >>> men = NormalDist(70, 4) - >>> women = NormalDist(65, 3.5) - >>> ovl = men.overlap(women) - >>> round(ovl * 100.0, 1) - 50.3 - To estimate the distribution for a model than isn't easy to solve analytically, :class:`NormalDist` can generate input samples for a `Monte Carlo simulation `_: @@ -754,11 +740,12 @@ Carlo simulation `_: ... return (3*x + 7*x*y - 5*y) / (11 * z) ... >>> n = 100_000 - >>> X = NormalDist(10, 2.5).samples(n) - >>> Y = NormalDist(15, 1.75).samples(n) - >>> Z = NormalDist(5, 1.25).samples(n) + >>> seed = 86753099035768 + >>> X = NormalDist(10, 2.5).samples(n, seed=seed) + >>> Y = NormalDist(15, 1.75).samples(n, seed=seed) + >>> Z = NormalDist(50, 1.25).samples(n, seed=seed) >>> NormalDist.from_samples(map(model, X, Y, Z)) # doctest: +SKIP - NormalDist(mu=19.640137307085507, sigma=47.03273142191088) + NormalDist(mu=1.8661894803304777, sigma=0.65238717376862) Normal distributions commonly arise in machine learning problems. From webhook-mailer at python.org Sun Aug 25 04:04:29 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 25 Aug 2019 08:04:29 -0000 Subject: [Python-checkins] bpo-37905: Improve docs for NormalDist (GH-15486) (GH-15487) Message-ID: https://github.com/python/cpython/commit/970548c00b366dcb8eb0c2bec0ffcab30ba03aee commit: 970548c00b366dcb8eb0c2bec0ffcab30ba03aee branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-25T01:04:24-07:00 summary: bpo-37905: Improve docs for NormalDist (GH-15486) (GH-15487) (cherry picked from commit 8371799e300475c8f9f967e900816218d3500e5d) Co-authored-by: Raymond Hettinger files: M Doc/library/statistics.rst diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 1a19e3741921..cbe2b8223faf 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -667,12 +667,8 @@ of applications in statistics. .. method:: NormalDist.overlap(other) - Compute the `overlapping coefficient (OVL) - `_ - between two normal distributions, giving a measure of agreement. - Returns a value between 0.0 and 1.0 giving `the overlapping area for - the two probability density functions - `_. + Returns a value between 0.0 and 1.0 giving the overlapping area for + the two probability density functions. Instances of :class:`NormalDist` support addition, subtraction, multiplication and division by a constant. These operations @@ -734,16 +730,6 @@ Find the `quartiles `_ and `deciles >>> [round(sat.inv_cdf(p / 10)) for p in range(1, 10)] [810, 896, 958, 1011, 1060, 1109, 1162, 1224, 1310] -What percentage of men and women will have the same height in `two normally -distributed populations with known means and standard deviations -`_? - - >>> men = NormalDist(70, 4) - >>> women = NormalDist(65, 3.5) - >>> ovl = men.overlap(women) - >>> round(ovl * 100.0, 1) - 50.3 - To estimate the distribution for a model than isn't easy to solve analytically, :class:`NormalDist` can generate input samples for a `Monte Carlo simulation `_: @@ -754,11 +740,12 @@ Carlo simulation `_: ... return (3*x + 7*x*y - 5*y) / (11 * z) ... >>> n = 100_000 - >>> X = NormalDist(10, 2.5).samples(n) - >>> Y = NormalDist(15, 1.75).samples(n) - >>> Z = NormalDist(5, 1.25).samples(n) + >>> seed = 86753099035768 + >>> X = NormalDist(10, 2.5).samples(n, seed=seed) + >>> Y = NormalDist(15, 1.75).samples(n, seed=seed) + >>> Z = NormalDist(50, 1.25).samples(n, seed=seed) >>> NormalDist.from_samples(map(model, X, Y, Z)) # doctest: +SKIP - NormalDist(mu=19.640137307085507, sigma=47.03273142191088) + NormalDist(mu=1.8661894803304777, sigma=0.65238717376862) Normal distributions commonly arise in machine learning problems. From webhook-mailer at python.org Sun Aug 25 05:44:14 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 25 Aug 2019 09:44:14 -0000 Subject: [Python-checkins] bpo-34880: Add the LOAD_ASSERTION_ERROR opcode. (GH-15073) Message-ID: https://github.com/python/cpython/commit/ce6a070414ed1e1374d1e6212bfbff61b6d5d755 commit: ce6a070414ed1e1374d1e6212bfbff61b6d5d755 branch: master author: Zackery Spytz committer: Serhiy Storchaka date: 2019-08-25T12:44:09+03:00 summary: bpo-34880: Add the LOAD_ASSERTION_ERROR opcode. (GH-15073) Fix assert statement misbehavior if AssertionError is shadowed. files: A Misc/NEWS.d/next/Core and Builtins/2019-08-01-10-45-51.bpo-34880.u_x_CG.rst M Doc/library/dis.rst M Doc/whatsnew/3.9.rst M Include/opcode.h M Lib/importlib/_bootstrap_external.py M Lib/opcode.py M Lib/test/test_dis.py M Lib/test/test_exceptions.py M Python/ceval.c M Python/compile.c M Python/importlib.h M Python/importlib_external.h M Python/importlib_zipimport.h M Python/opcode_targets.h diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 4a20245e3032..b5243d0f364d 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -752,6 +752,14 @@ iterations of the loop. from the block stack. +.. opcode:: LOAD_ASSERTION_ERROR + + Pushes :exc:`AssertionError` onto the stack. Used by the :keyword:`assert` + statement. + + .. versionadded:: 3.9 + + .. opcode:: LOAD_BUILD_CLASS Pushes :func:`builtins.__build_class__` onto the stack. It is later called diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 10217f194eb0..e20ae47462eb 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -226,3 +226,12 @@ Changes in the Python API * The :mod:`venv` activation scripts no longer special-case when ``__VENV_PROMPT__`` is set to ``""``. + + +CPython bytecode changes +------------------------ + +* The :opcode:`LOAD_ASSERTION_ERROR` opcode was added for handling the + :keyword:`assert` statement. Previously, the assert statement would not work + correctly if the :exc:`AssertionError` exception was being shadowed. + (Contributed by Zackery Spytz in :issue:`34880`.) diff --git a/Include/opcode.h b/Include/opcode.h index 2a29e9788570..95d56014860b 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -53,6 +53,7 @@ extern "C" { #define LOAD_BUILD_CLASS 71 #define YIELD_FROM 72 #define GET_AWAITABLE 73 +#define LOAD_ASSERTION_ERROR 74 #define INPLACE_LSHIFT 75 #define INPLACE_RSHIFT 76 #define INPLACE_AND 77 diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 67bd1d3cf99e..671b043c73d5 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -271,6 +271,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.8b2 3412 (Swap the position of positional args and positional # only args in ast.arguments #37593) # Python 3.8b4 3413 (Fix "break" and "continue" in "finally" #37830) +# Python 3.9a0 3420 (add LOAD_ASSERTION_ERROR #34880) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually @@ -279,7 +280,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 = (3413).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3420).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/opcode.py b/Lib/opcode.py index 3fb716b5d96a..0ae0068f2f22 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -109,7 +109,7 @@ def jabs_op(name, op): def_op('LOAD_BUILD_CLASS', 71) def_op('YIELD_FROM', 72) def_op('GET_AWAITABLE', 73) - +def_op('LOAD_ASSERTION_ERROR', 74) def_op('INPLACE_LSHIFT', 75) def_op('INPLACE_RSHIFT', 76) def_op('INPLACE_AND', 77) diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 03b286016632..11f97e6c0838 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -147,7 +147,7 @@ def bug1333982(x=[]): dis_bug1333982 = """\ %3d 0 LOAD_CONST 1 (0) 2 POP_JUMP_IF_TRUE 26 - 4 LOAD_GLOBAL 0 (AssertionError) + 4 LOAD_ASSERTION_ERROR 6 LOAD_CONST 2 ( at 0x..., file "%s", line %d>) 8 LOAD_CONST 3 ('bug1333982..') 10 MAKE_FUNCTION 0 diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 10c1e076464e..4d1aa4bca623 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1285,6 +1285,22 @@ def g(): next(i) next(i) + @unittest.skipUnless(__debug__, "Won't work if __debug__ is False") + def test_assert_shadowing(self): + # Shadowing AssertionError would cause the assert statement to + # misbehave. + global AssertionError + AssertionError = TypeError + try: + assert False, 'hello' + except BaseException as e: + del AssertionError + self.assertIsInstance(e, AssertionError) + self.assertEqual(str(e), 'hello') + else: + del AssertionError + self.fail('Expected exception') + class ImportErrorTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-01-10-45-51.bpo-34880.u_x_CG.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-01-10-45-51.bpo-34880.u_x_CG.rst new file mode 100644 index 000000000000..31c42cb2e4cc --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-01-10-45-51.bpo-34880.u_x_CG.rst @@ -0,0 +1,3 @@ +The :keyword:`assert` statement now works properly if the +:exc:`AssertionError` exception is being shadowed. +Patch by Zackery Spytz. diff --git a/Python/ceval.c b/Python/ceval.c index ee03350031d9..7a3f42c3437f 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2242,6 +2242,13 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) } } + case TARGET(LOAD_ASSERTION_ERROR): { + PyObject *value = PyExc_AssertionError; + Py_INCREF(value); + PUSH(value); + FAST_DISPATCH(); + } + case TARGET(LOAD_BUILD_CLASS): { _Py_IDENTIFIER(__build_class__); diff --git a/Python/compile.c b/Python/compile.c index 1bf05e291307..edd8625cba91 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1129,6 +1129,8 @@ stack_effect(int opcode, int oparg, int jump) return (oparg & FVS_MASK) == FVS_HAVE_SPEC ? -1 : 0; case LOAD_METHOD: return 1; + case LOAD_ASSERTION_ERROR: + return 1; default: return PY_INVALID_STACK_EFFECT; } @@ -3253,16 +3255,10 @@ compiler_from_import(struct compiler *c, stmt_ty s) static int compiler_assert(struct compiler *c, stmt_ty s) { - static PyObject *assertion_error = NULL; basicblock *end; if (c->c_optimize) return 1; - if (assertion_error == NULL) { - assertion_error = PyUnicode_InternFromString("AssertionError"); - if (assertion_error == NULL) - return 0; - } if (s->v.Assert.test->kind == Tuple_kind && asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) { @@ -3277,7 +3273,7 @@ compiler_assert(struct compiler *c, stmt_ty s) return 0; if (!compiler_jump_if(c, s->v.Assert.test, end, 1)) return 0; - ADDOP_O(c, LOAD_GLOBAL, assertion_error, names); + ADDOP(c, LOAD_ASSERTION_ERROR); if (s->v.Assert.msg) { VISIT(c, expr, s->v.Assert.msg); ADDOP_I(c, CALL_FUNCTION, 1); diff --git a/Python/importlib.h b/Python/importlib.h index be3035d3e49a..8f25dcef31a6 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -174,18 +174,17 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,2,107,4,115,48,74,0,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, + 107,2,114,108,100,0,124,0,95,3,124,0,106,6,114,108, + 124,0,4,0,106,6,100,3,56,0,2,0,95,6,124,0, + 106,7,160,8,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, + 37,0,0,0,41,9,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, + 105,109,101,69,114,114,111,114,114,27,0,0,0,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, @@ -204,7 +203,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 39,0,0,0,114,47,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, @@ -231,7 +230,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 1,114,27,0,0,0,114,46,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, @@ -241,7 +240,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 0,114,42,0,0,0,114,46,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, @@ -250,17 +249,17 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 114,125,41,32,97,116,32,123,125,114,43,0,0,0,114,46, 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,0,114,47,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,0,0,114,47,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,114,48,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, + 8,4,8,5,114,48,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, @@ -279,8 +278,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 117,108,101,95,108,111,99,107,114,50,0,0,0,114,51,0, + 0,0,114,38,0,0,0,114,46,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, @@ -288,17 +287,17 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 0,0,41,2,114,51,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,114,2,0,0,0,114,31,0,0,0,114,53,0,0,0, + 114,55,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,141,0, + 0,0,115,6,0,0,0,8,2,8,4,8,4,114,49,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,3,124,0, @@ -332,15 +331,15 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,114,60, + 56,0,0,0,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,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, + 0,0,114,48,0,0,0,114,20,0,0,0,218,8,95,119, + 101,97,107,114,101,102,114,60,0,0,0,41,3,114,17,0, + 0,0,114,24,0,0,0,114,61,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,52,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, + 11,20,2,10,2,114,52,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, @@ -358,12 +357,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 41,4,114,52,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, + 6,8,1,2,1,12,1,14,3,6,2,114,64,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, @@ -386,11 +385,11 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 0,0,41,3,218,1,102,114,54,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, + 115,2,0,0,0,0,8,114,66,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, @@ -405,12 +404,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 32,122,2,35,32,41,1,90,4,102,105,108,101,78,41,7, 114,15,0,0,0,218,5,102,108,97,103,115,218,7,118,101, 114,98,111,115,101,218,10,115,116,97,114,116,115,119,105,116, - 104,218,5,112,114,105,110,116,114,45,0,0,0,218,6,115, + 104,218,5,112,114,105,110,116,114,44,0,0,0,218,6,115, 116,100,101,114,114,41,3,218,7,109,101,115,115,97,103,101, - 114,68,0,0,0,114,55,0,0,0,114,10,0,0,0,114, + 114,67,0,0,0,114,54,0,0,0,114,10,0,0,0,114, 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, + 8,0,0,0,0,2,12,1,10,1,8,1,114,75,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, @@ -427,7 +426,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 114,111,114,114,44,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, @@ -436,11 +435,11 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 114,12,0,0,0,41,2,114,82,0,0,0,114,83,0,0, + 0,114,10,0,0,0,114,81,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, + 10,1,114,85,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, @@ -453,20 +452,20 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 124,1,161,1,124,1,100,2,141,2,130,1,136,0,124,0, 124,1,131,2,83,0,169,3,78,122,27,123,33,114,125,32, 105,115,32,110,111,116,32,97,32,102,114,111,122,101,110,32, - 109,111,100,117,108,101,114,16,0,0,0,41,4,114,57,0, - 0,0,218,9,105,115,95,102,114,111,122,101,110,114,79,0, - 0,0,114,45,0,0,0,114,80,0,0,0,114,82,0,0, + 109,111,100,117,108,101,114,16,0,0,0,41,4,114,56,0, + 0,0,218,9,105,115,95,102,114,111,122,101,110,114,78,0, + 0,0,114,44,0,0,0,114,79,0,0,0,114,81,0,0, 0,114,10,0,0,0,114,11,0,0,0,218,24,95,114,101, 113,117,105,114,101,115,95,102,114,111,122,101,110,95,119,114, 97,112,112,101,114,243,0,0,0,115,10,0,0,0,0,1, 10,1,10,1,2,255,6,2,122,50,95,114,101,113,117,105, 114,101,115,95,102,114,111,122,101,110,46,60,108,111,99,97, 108,115,62,46,95,114,101,113,117,105,114,101,115,95,102,114, - 111,122,101,110,95,119,114,97,112,112,101,114,114,85,0,0, - 0,41,2,114,83,0,0,0,114,89,0,0,0,114,10,0, - 0,0,114,82,0,0,0,114,11,0,0,0,218,16,95,114, + 111,122,101,110,95,119,114,97,112,112,101,114,114,84,0,0, + 0,41,2,114,82,0,0,0,114,88,0,0,0,114,10,0, + 0,0,114,81,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,115,6,0,0,0,0,2,12,5,10,1,114,89,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, @@ -484,12 +483,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 111,97,100,41,4,114,30,0,0,0,114,80,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, + 10,1,10,2,114,96,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, @@ -512,20 +511,20 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 0,0,114,98,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, + 101,95,95,114,44,0,0,0,41,5,114,95,0,0,0,218, + 6,108,111,97,100,101,114,114,94,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, + 110,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, @@ -636,13 +635,13 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, 100,1,124,0,95,5,100,0,124,0,95,6,100,0,83,0, - 41,2,78,70,41,7,114,17,0,0,0,114,109,0,0,0, - 114,113,0,0,0,114,114,0,0,0,218,26,115,117,98,109, + 41,2,78,70,41,7,114,17,0,0,0,114,108,0,0,0, + 114,112,0,0,0,114,113,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,218,13,95,115,101,116,95,102,105,108, 101,97,116,116,114,218,7,95,99,97,99,104,101,100,41,6, - 114,30,0,0,0,114,17,0,0,0,114,109,0,0,0,114, - 113,0,0,0,114,114,0,0,0,114,115,0,0,0,114,10, + 114,30,0,0,0,114,17,0,0,0,114,108,0,0,0,114, + 112,0,0,0,114,113,0,0,0,114,114,0,0,0,114,10, 0,0,0,114,10,0,0,0,114,11,0,0,0,114,31,0, 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, @@ -660,12 +659,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,116,0,0,0,218,9,95,95,99,108,97,115, + 41,122,2,44,32,41,9,114,44,0,0,0,114,17,0,0, + 0,114,108,0,0,0,114,112,0,0,0,218,6,97,112,112, + 101,110,100,114,115,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, + 114,30,0,0,0,114,54,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,47,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, @@ -678,9 +677,9 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 124,0,106,5,124,1,106,5,107,2,87,0,83,0,4,0, 116,6,107,10,114,102,1,0,1,0,1,0,116,7,6,0, 89,0,83,0,88,0,100,0,83,0,114,13,0,0,0,41, - 8,114,116,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, + 8,114,115,0,0,0,114,17,0,0,0,114,108,0,0,0, + 114,112,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,105,0,0,0, 218,14,78,111,116,73,109,112,108,101,109,101,110,116,101,100, 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, @@ -694,20 +693,20 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,118,0,0,0,114,113,0,0,0,114,117, + 0,0,41,6,114,117,0,0,0,114,112,0,0,0,114,116, 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,122, + 103,101,116,95,99,97,99,104,101,100,114,46,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,121, 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,118,0,0,0,41, - 2,114,30,0,0,0,114,122,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,122,0,0,0,129, + 0,83,0,114,13,0,0,0,41,1,114,117,0,0,0,41, + 2,114,30,0,0,0,114,121,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,121,0,0,0,129, 1,0,0,115,2,0,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, @@ -715,35 +714,35 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,116,0,0,0, + 78,218,1,46,114,22,0,0,0,41,3,114,115,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, + 110,114,46,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,117,0,0,0,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,141,1,0,0,115,2,0,0, + 0,83,0,114,13,0,0,0,41,1,114,116,0,0,0,114, + 46,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,122,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,117,0,0,0,41,2,114,30,0,0, + 4,98,111,111,108,114,116,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,123,0,0,0,145,1,0,0, + 0,0,114,11,0,0,0,114,122,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,122,0,0,0,218,6,115,101,116, - 116,101,114,114,130,0,0,0,114,123,0,0,0,114,10,0, + 0,0,114,47,0,0,0,114,124,0,0,0,218,8,112,114, + 111,112,101,114,116,121,114,121,0,0,0,218,6,115,101,116, + 116,101,114,114,129,0,0,0,114,122,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, + 0,114,111,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, + 111,0,0,0,169,2,114,112,0,0,0,114,114,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, @@ -760,18 +759,18 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 32,98,97,115,101,100,32,111,110,32,118,97,114,105,111,117, 115,32,108,111,97,100,101,114,32,109,101,116,104,111,100,115, 46,90,12,103,101,116,95,102,105,108,101,110,97,109,101,78, - 41,1,114,109,0,0,0,41,2,114,109,0,0,0,114,116, - 0,0,0,114,115,0,0,0,70,114,135,0,0,0,41,7, - 114,4,0,0,0,114,126,0,0,0,114,127,0,0,0,218, + 41,1,114,108,0,0,0,41,2,114,108,0,0,0,114,115, + 0,0,0,114,114,0,0,0,70,114,134,0,0,0,41,7, + 114,4,0,0,0,114,125,0,0,0,114,126,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,114,115,0,0,0,114,79,0, - 0,0,114,112,0,0,0,41,6,114,17,0,0,0,114,109, - 0,0,0,114,113,0,0,0,114,115,0,0,0,114,136,0, + 108,111,99,97,116,105,111,110,114,114,0,0,0,114,78,0, + 0,0,114,111,0,0,0,41,6,114,17,0,0,0,114,108, + 0,0,0,114,112,0,0,0,114,114,0,0,0,114,135,0, 0,0,90,6,115,101,97,114,99,104,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,91,0,0,0,150,1, + 10,0,0,0,114,11,0,0,0,114,90,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, + 1,2,1,14,1,14,1,12,3,4,2,114,90,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, @@ -793,23 +792,23 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 95,12,124,3,83,0,41,4,78,169,1,114,112,0,0,0, + 70,84,41,13,114,104,0,0,0,114,105,0,0,0,114,1, + 0,0,0,114,97,0,0,0,114,107,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,117,0,0,0,114,122,0,0, - 0,114,116,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,122,0,0,0, - 114,116,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 95,95,114,111,0,0,0,114,116,0,0,0,114,121,0,0, + 0,114,115,0,0,0,41,8,114,95,0,0,0,114,108,0, + 0,0,114,112,0,0,0,114,94,0,0,0,114,17,0,0, + 0,90,8,108,111,99,97,116,105,111,110,114,121,0,0,0, + 114,115,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, + 14,1,20,1,6,1,6,1,114,141,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, @@ -843,18 +842,18 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,114,97,0,0,0,218,11,95,95,112,97,99,107,97, + 103,101,95,95,114,140,0,0,0,114,107,0,0,0,114,138, 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,116, - 0,0,0,114,126,0,0,0,114,127,0,0,0,218,16,95, + 1,0,0,0,114,105,0,0,0,114,108,0,0,0,114,115, + 0,0,0,114,125,0,0,0,114,126,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,123,0, - 0,0,114,113,0,0,0,114,122,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, + 107,0,0,0,114,97,0,0,0,114,129,0,0,0,114,144, + 0,0,0,114,104,0,0,0,114,140,0,0,0,114,122,0, + 0,0,114,112,0,0,0,114,121,0,0,0,114,138,0,0, + 0,41,5,114,94,0,0,0,114,95,0,0,0,114,143,0, + 0,0,114,108,0,0,0,114,145,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, @@ -863,7 +862,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 2,1,12,1,16,1,6,1,114,147,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, @@ -880,13 +879,13 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 4,0,0,0,114,108,0,0,0,114,148,0,0,0,114,78, + 0,0,0,114,18,0,0,0,114,17,0,0,0,114,147,0, + 0,0,169,2,114,94,0,0,0,114,95,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, + 12,1,8,2,8,1,10,1,10,1,114,151,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, @@ -898,14 +897,14 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 2,83,0,100,1,83,0,41,7,122,38,82,101,116,117,114, 110,32,116,104,101,32,114,101,112,114,32,116,111,32,117,115, 101,32,102,111,114,32,116,104,101,32,109,111,100,117,108,101, - 46,78,114,100,0,0,0,114,101,0,0,0,114,102,0,0, - 0,114,103,0,0,0,250,18,60,109,111,100,117,108,101,32, + 46,78,114,99,0,0,0,114,100,0,0,0,114,101,0,0, + 0,114,102,0,0,0,250,18,60,109,111,100,117,108,101,32, 123,33,114,125,32,40,123,125,41,62,41,5,114,17,0,0, - 0,114,113,0,0,0,114,109,0,0,0,114,45,0,0,0, - 114,123,0,0,0,41,2,114,95,0,0,0,114,17,0,0, + 0,114,112,0,0,0,114,108,0,0,0,114,44,0,0,0, + 114,122,0,0,0,41,2,114,94,0,0,0,114,17,0,0, 0,114,10,0,0,0,114,10,0,0,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, + 114,106,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,106, 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,204,0,0, 0,124,0,106,0,125,2,116,1,124,2,131,1,143,180,1, @@ -928,18 +927,18 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,218,3,112, - 111,112,114,109,0,0,0,114,116,0,0,0,114,148,0,0, + 105,115,115,105,110,103,32,108,111,97,100,101,114,84,114,142, + 0,0,0,114,149,0,0,0,41,14,114,17,0,0,0,114, + 49,0,0,0,114,15,0,0,0,114,91,0,0,0,114,34, + 0,0,0,114,44,0,0,0,114,78,0,0,0,218,3,112, + 111,112,114,108,0,0,0,114,115,0,0,0,114,147,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,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, + 117,108,101,114,149,0,0,0,41,4,114,94,0,0,0,114, + 95,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,92,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, + 2,14,1,12,4,14,2,16,4,14,1,24,1,114,92,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, @@ -959,21 +958,21 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,156,0,0,0,114,17,0,0,0,114,15,0,0, - 0,114,92,0,0,0,114,155,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, + 89,0,110,2,88,0,124,1,83,0,41,7,78,114,97,0, + 0,0,114,144,0,0,0,114,140,0,0,0,114,127,0,0, + 0,114,22,0,0,0,114,104,0,0,0,41,14,114,108,0, + 0,0,114,155,0,0,0,114,17,0,0,0,114,15,0,0, + 0,114,91,0,0,0,114,154,0,0,0,114,6,0,0,0, + 114,97,0,0,0,114,105,0,0,0,114,1,0,0,0,114, + 144,0,0,0,114,4,0,0,0,114,128,0,0,0,114,104, + 0,0,0,114,150,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, + 1,114,157,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, @@ -989,20 +988,20 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 161,1,125,1,124,1,116,5,106,6,124,0,106,7,60,0, 116,13,100,6,124,0,106,7,124,0,106,0,131,3,1,0, 87,0,53,0,100,3,124,0,95,4,88,0,124,1,83,0, - 41,7,78,114,150,0,0,0,84,70,114,154,0,0,0,114, + 41,7,78,114,149,0,0,0,84,70,114,153,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,41,14,114,109,0,0,0,114, - 4,0,0,0,114,158,0,0,0,114,152,0,0,0,90,13, + 125,32,35,32,123,33,114,125,41,14,114,108,0,0,0,114, + 4,0,0,0,114,157,0,0,0,114,151,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,116,0,0, - 0,114,79,0,0,0,114,150,0,0,0,114,63,0,0,0, - 114,155,0,0,0,114,76,0,0,0,114,151,0,0,0,114, + 0,0,114,91,0,0,0,114,17,0,0,0,114,115,0,0, + 0,114,78,0,0,0,114,149,0,0,0,114,62,0,0,0, + 114,154,0,0,0,114,75,0,0,0,114,150,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, + 1,20,2,8,2,114,158,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, @@ -1019,11 +1018,11 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 100,117,108,101,115,44,32,116,104,97,116,32,101,120,105,115, 116,105,110,103,32,109,111,100,117,108,101,32,103,101,116,115, 10,32,32,32,32,99,108,111,98,98,101,114,101,100,46,10, - 10,32,32,32,32,78,41,3,114,50,0,0,0,114,17,0, - 0,0,114,159,0,0,0,41,1,114,95,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,94,0, + 10,32,32,32,32,78,41,3,114,49,0,0,0,114,17,0, + 0,0,114,158,0,0,0,41,1,114,94,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,93,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, + 93,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,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, @@ -1055,9 +1054,9 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 98,117,105,108,116,45,105,110,41,62,41,2,114,44,0,0, + 0,114,1,0,0,0,41,1,114,95,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,114,98,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, @@ -1066,9 +1065,9 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 110,114,136,0,0,0,41,3,114,56,0,0,0,90,10,105, + 115,95,98,117,105,108,116,105,110,114,90,0,0,0,169,4, + 218,3,99,108,115,114,80,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, @@ -1089,8 +1088,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,166,0,0,0,114,109,0,0,0,41,4,114,163, - 0,0,0,114,81,0,0,0,114,164,0,0,0,114,95,0, + 41,2,114,165,0,0,0,114,108,0,0,0,41,4,114,162, + 0,0,0,114,80,0,0,0,114,163,0,0,0,114,94,0, 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, 0,218,11,102,105,110,100,95,109,111,100,117,108,101,222,2, 0,0,115,4,0,0,0,0,9,12,1,122,27,66,117,105, @@ -1102,12 +1101,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 114,76,0,0,0,114,16,0,0,0,41,8,114,17,0,0, + 0,114,15,0,0,0,114,77,0,0,0,114,78,0,0,0, + 114,44,0,0,0,114,66,0,0,0,114,56,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,114,30,0,0,0,114,94,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,148,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, @@ -1115,11 +1114,11 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 105,110,32,109,111,100,117,108,101,78,41,3,114,66,0,0, + 0,114,56,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,95,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, + 149,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, @@ -1128,7 +1127,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,169,2,114,162,0,0,0,114,80,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, @@ -1139,7 +1138,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,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, + 167,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, 0,0,0,218,10,103,101,116,95,115,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, @@ -1149,23 +1148,23 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 70,114,10,0,0,0,114,167,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,114,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,156,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, + 100,114,98,0,0,0,218,11,99,108,97,115,115,109,101,116, + 104,111,100,114,165,0,0,0,114,166,0,0,0,114,148,0, + 0,0,114,149,0,0,0,114,85,0,0,0,114,168,0,0, + 0,114,169,0,0,0,114,114,0,0,0,114,96,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,159,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, + 4,114,159,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, @@ -1189,21 +1188,21 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 124,0,106,1,116,2,106,3,161,2,83,0,41,2,114,160, + 0,0,0,114,152,0,0,0,41,4,114,44,0,0,0,114, + 1,0,0,0,114,172,0,0,0,114,137,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,0,114,98,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,0,100,0,83,0,41, - 2,78,114,137,0,0,0,41,4,114,57,0,0,0,114,88, - 0,0,0,114,91,0,0,0,114,138,0,0,0,114,162,0, + 2,78,114,136,0,0,0,41,4,114,56,0,0,0,114,87, + 0,0,0,114,90,0,0,0,114,137,0,0,0,114,161,0, 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,166,0,0,0,32,3,0,0,115,6,0,0,0,0, + 0,114,165,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,0,0,0,0,3,0,0,0, @@ -1215,9 +1214,9 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 78,41,2,114,56,0,0,0,114,87,0,0,0,41,3,114, + 162,0,0,0,114,80,0,0,0,114,163,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,166,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, @@ -1226,8 +1225,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 2,114,162,0,0,0,114,94,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,148,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, @@ -1236,14 +1235,14 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 1,0,100,0,83,0,114,86,0,0,0,41,10,114,104,0, + 0,0,114,17,0,0,0,114,56,0,0,0,114,87,0,0, + 0,114,78,0,0,0,114,44,0,0,0,114,66,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,95,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, + 149,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, @@ -1255,8 +1254,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,41,1,114,97,0,0,0,114,168,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,156,0, + 32,32,41,1,114,96,0,0,0,114,167,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,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, @@ -1265,9 +1264,9 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 101,46,41,2,114,56,0,0,0,114,174,0,0,0,114,167, 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,0,114,168,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, @@ -1275,9 +1274,9 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 101,32,99,111,100,101,46,78,114,10,0,0,0,114,167,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, + 0,114,169,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, @@ -1285,23 +1284,23 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 99,107,97,103,101,46,41,2,114,56,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, + 114,167,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,114,114,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,156,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,2,0,0,0,114,3,0,0,0,114,137,0,0, + 0,114,170,0,0,0,114,98,0,0,0,114,171,0,0,0, + 114,165,0,0,0,114,166,0,0,0,114,148,0,0,0,114, + 149,0,0,0,114,155,0,0,0,114,89,0,0,0,114,168, + 0,0,0,114,169,0,0,0,114,114,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, + 0,114,172,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, + 1,12,4,2,1,2,1,12,4,2,1,2,1,114,172,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, @@ -1314,9 +1313,9 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 107,46,78,41,2,114,56,0,0,0,114,57,0,0,0,114, + 46,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,53,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, @@ -1325,19 +1324,19 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,59,0,0,0,41,4,114,30,0,0,0,218, + 101,120,99,101,112,116,105,111,110,115,46,78,41,2,114,56, + 0,0,0,114,58,0,0,0,41,4,114,30,0,0,0,218, 8,101,120,99,95,116,121,112,101,218,9,101,120,99,95,118, 97,108,117,101,218,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,0,114,55,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, + 0,114,3,0,0,0,114,53,0,0,0,114,55,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, + 11,0,0,0,114,177,0,0,0,91,3,0,0,115,6,0, + 0,0,8,2,4,2,8,4,114,177,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, @@ -1347,28 +1346,28 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 46,114,127,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,114,79,0,0,0,114, - 45,0,0,0,41,5,114,17,0,0,0,218,7,112,97,99, + 115,112,108,105,116,218,3,108,101,110,114,78,0,0,0,114, + 44,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,187,0,0,0,99,3,0, + 16,1,12,1,8,1,8,1,114,186,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,116,1,124,1,124,3,131,2,83,0,114,13,0, - 0,0,41,2,114,167,0,0,0,114,91,0,0,0,41,4, - 218,6,102,105,110,100,101,114,114,17,0,0,0,114,164,0, - 0,0,114,109,0,0,0,114,10,0,0,0,114,10,0,0, + 0,0,41,2,114,166,0,0,0,114,90,0,0,0,41,4, + 218,6,102,105,110,100,101,114,114,17,0,0,0,114,163,0, + 0,0,114,108,0,0,0,114,10,0,0,0,114,10,0,0, 0,114,11,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,189,0,0,0,99, + 0,0,0,3,12,1,8,1,4,1,114,188,0,0,0,99, 3,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, @@ -1395,20 +1394,20 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 112,97,116,104,114,78,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,189,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,190,0,0,0,90,9,105, - 115,95,114,101,108,111,97,100,114,188,0,0,0,114,166,0, - 0,0,114,95,0,0,0,114,96,0,0,0,114,105,0,0, + 114,116,87,97,114,110,105,110,103,114,91,0,0,0,114,177, + 0,0,0,114,165,0,0,0,114,105,0,0,0,114,188,0, + 0,0,114,104,0,0,0,41,10,114,17,0,0,0,114,163, + 0,0,0,114,164,0,0,0,114,189,0,0,0,90,9,105, + 115,95,114,101,108,111,97,100,114,187,0,0,0,114,165,0, + 0,0,114,94,0,0,0,114,95,0,0,0,114,104,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,194,0,0,0, + 4,14,2,8,1,8,2,10,2,10,2,114,193,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, @@ -1432,13 +1431,13 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,218,10,86,97,108,117,101, - 69,114,114,111,114,114,79,0,0,0,169,3,114,17,0,0, - 0,114,185,0,0,0,114,186,0,0,0,114,10,0,0,0, + 44,0,0,0,114,14,0,0,0,218,10,86,97,108,117,101, + 69,114,114,111,114,114,78,0,0,0,169,3,114,17,0,0, + 0,114,184,0,0,0,114,185,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,200,0,0,0,122,16,78, + 10,1,4,1,8,2,12,1,114,199,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, @@ -1456,24 +1455,24 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 6,78,114,127,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, + 12,114,128,0,0,0,114,15,0,0,0,114,91,0,0,0, + 114,66,0,0,0,114,140,0,0,0,114,105,0,0,0,218, + 8,95,69,82,82,95,77,83,71,114,44,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,194,0,0,0,114,159,0,0,0,114,5,0, + 114,111,114,114,193,0,0,0,114,158,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, + 116,95,114,163,0,0,0,114,129,0,0,0,90,13,112,97, + 114,101,110,116,95,109,111,100,117,108,101,114,156,0,0,0, + 114,94,0,0,0,114,95,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,205,0,0,0,99,2,0,0,0,0, + 2,10,1,22,1,114,204,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, @@ -1487,15 +1486,15 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 122,40,105,109,112,111,114,116,32,111,102,32,123,125,32,104, 97,108,116,101,100,59,32,78,111,110,101,32,105,110,32,115, 121,115,46,109,111,100,117,108,101,115,114,16,0,0,0,41, - 9,114,50,0,0,0,114,15,0,0,0,114,92,0,0,0, + 9,114,49,0,0,0,114,15,0,0,0,114,91,0,0,0, 114,34,0,0,0,218,14,95,78,69,69,68,83,95,76,79, - 65,68,73,78,71,114,205,0,0,0,114,45,0,0,0,114, - 203,0,0,0,114,65,0,0,0,41,4,114,17,0,0,0, - 114,204,0,0,0,114,96,0,0,0,114,75,0,0,0,114, + 65,68,73,78,71,114,204,0,0,0,114,44,0,0,0,114, + 202,0,0,0,114,64,0,0,0,41,4,114,17,0,0,0, + 114,203,0,0,0,114,95,0,0,0,114,74,0,0,0,114, 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,14, 95,102,105,110,100,95,97,110,100,95,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,207,0, + 2,8,1,4,1,2,255,4,2,12,2,8,1,114,206,0, 0,0,114,22,0,0,0,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,42,0,0,0,116,0,124,0,124,1,124,2,131,3,1, @@ -1521,11 +1520,11 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, - 200,0,0,0,114,187,0,0,0,114,207,0,0,0,218,11, - 95,103,99,100,95,105,109,112,111,114,116,114,199,0,0,0, + 199,0,0,0,114,186,0,0,0,114,206,0,0,0,218,11, + 95,103,99,100,95,105,109,112,111,114,116,114,198,0,0,0, 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 208,0,0,0,234,3,0,0,115,8,0,0,0,0,9,12, - 1,8,1,12,1,114,208,0,0,0,169,1,218,9,114,101, + 207,0,0,0,234,3,0,0,115,8,0,0,0,0,9,12, + 1,8,1,12,1,114,207,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, @@ -1561,22 +1560,22 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,209,0, - 0,0,114,182,0,0,0,78,41,16,114,195,0,0,0,114, - 196,0,0,0,114,1,0,0,0,114,197,0,0,0,114,14, + 250,1,42,218,7,95,95,97,108,108,95,95,84,114,208,0, + 0,0,114,181,0,0,0,78,41,16,114,194,0,0,0,114, + 195,0,0,0,114,1,0,0,0,114,196,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,212,0,0,0,114, - 45,0,0,0,114,67,0,0,0,114,203,0,0,0,114,17, - 0,0,0,114,15,0,0,0,114,92,0,0,0,114,34,0, - 0,0,114,206,0,0,0,41,8,114,96,0,0,0,218,8, - 102,114,111,109,108,105,115,116,114,204,0,0,0,114,210,0, + 101,95,102,114,111,109,108,105,115,116,114,211,0,0,0,114, + 44,0,0,0,114,66,0,0,0,114,202,0,0,0,114,17, + 0,0,0,114,15,0,0,0,114,91,0,0,0,114,34,0, + 0,0,114,205,0,0,0,41,8,114,95,0,0,0,218,8, + 102,114,111,109,108,105,115,116,114,203,0,0,0,114,209,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,213,0,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,212,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,213,0,0,0,99,1,0,0,0,0, + 2,8,1,22,1,114,212,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, @@ -1598,7 +1597,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, + 10,32,32,32,32,114,144,0,0,0,114,104,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, @@ -1608,17 +1607,17 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,191,0,0,0,114,192, - 0,0,0,114,193,0,0,0,114,129,0,0,0,41,3,218, - 7,103,108,111,98,97,108,115,114,185,0,0,0,114,95,0, + 32,95,95,112,97,116,104,95,95,114,1,0,0,0,114,140, + 0,0,0,114,127,0,0,0,114,22,0,0,0,41,6,114, + 34,0,0,0,114,129,0,0,0,114,190,0,0,0,114,191, + 0,0,0,114,192,0,0,0,114,128,0,0,0,41,3,218, + 7,103,108,111,98,97,108,115,114,184,0,0,0,114,94,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,219,0,0,0,114,10,0,0,0,99,5,0, + 1,14,1,114,218,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, @@ -1662,30 +1661,30 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 109,112,111,114,116,32,109,111,100,96,96,32,119,111,117,108, 100,32,104,97,118,101,32,97,32,39,108,101,118,101,108,39, 32,111,102,32,50,41,46,10,10,32,32,32,32,114,22,0, - 0,0,78,114,128,0,0,0,114,141,0,0,0,41,9,114, - 208,0,0,0,114,219,0,0,0,218,9,112,97,114,116,105, - 116,105,111,110,114,184,0,0,0,114,15,0,0,0,114,92, - 0,0,0,114,1,0,0,0,114,4,0,0,0,114,213,0, - 0,0,41,9,114,17,0,0,0,114,218,0,0,0,218,6, - 108,111,99,97,108,115,114,214,0,0,0,114,186,0,0,0, - 114,96,0,0,0,90,8,103,108,111,98,97,108,115,95,114, - 185,0,0,0,90,7,99,117,116,95,111,102,102,114,10,0, + 0,0,78,114,127,0,0,0,114,140,0,0,0,41,9,114, + 207,0,0,0,114,218,0,0,0,218,9,112,97,114,116,105, + 116,105,111,110,114,183,0,0,0,114,15,0,0,0,114,91, + 0,0,0,114,1,0,0,0,114,4,0,0,0,114,212,0, + 0,0,41,9,114,17,0,0,0,114,217,0,0,0,218,6, + 108,111,99,97,108,115,114,213,0,0,0,114,185,0,0,0, + 114,95,0,0,0,90,8,103,108,111,98,97,108,115,95,114, + 184,0,0,0,90,7,99,117,116,95,111,102,102,114,10,0, 0,0,114,10,0,0,0,114,11,0,0,0,218,10,95,95, 105,109,112,111,114,116,95,95,57,4,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, - 222,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, + 221,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,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, + 110,97,109,101,100,32,41,4,114,159,0,0,0,114,165,0, + 0,0,114,78,0,0,0,114,158,0,0,0,41,2,114,17, + 0,0,0,114,94,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,223,0,0, + 8,0,0,0,0,1,10,1,8,1,12,1,114,222,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, @@ -1714,16 +1713,16 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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,191,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,195,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,223,0,0,0,114, + 32,32,32,41,3,114,23,0,0,0,114,190,0,0,0,114, + 63,0,0,0,78,41,15,114,56,0,0,0,114,15,0,0, + 0,114,14,0,0,0,114,91,0,0,0,218,5,105,116,101, + 109,115,114,194,0,0,0,114,77,0,0,0,114,159,0,0, + 0,114,87,0,0,0,114,172,0,0,0,114,141,0,0,0, + 114,147,0,0,0,114,1,0,0,0,114,222,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, + 0,114,95,0,0,0,114,108,0,0,0,114,94,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, @@ -1731,7 +1730,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, - 227,0,0,0,99,2,0,0,0,0,0,0,0,0,0,0, + 226,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, @@ -1739,12 +1738,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 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, - 227,0,0,0,114,15,0,0,0,114,190,0,0,0,114,119, - 0,0,0,114,160,0,0,0,114,173,0,0,0,41,2,114, - 225,0,0,0,114,226,0,0,0,114,10,0,0,0,114,10, + 226,0,0,0,114,15,0,0,0,114,189,0,0,0,114,118, + 0,0,0,114,159,0,0,0,114,172,0,0,0,41,2,114, + 224,0,0,0,114,225,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,228,0,0,0,99,0,0,0,0,0,0,0,0,0, + 1,114,227,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, @@ -1754,31 +1753,31 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 102,105,108,101,115,121,115,116,101,109,32,97,99,99,101,115, 115,114,22,0,0,0,78,41,6,218,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,126,0,0,0,114,228,0,0,0,114, - 15,0,0,0,114,92,0,0,0,114,1,0,0,0,41,1, - 114,229,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 101,114,110,97,108,114,125,0,0,0,114,227,0,0,0,114, + 15,0,0,0,114,91,0,0,0,114,1,0,0,0,41,1, + 114,228,0,0,0,114,10,0,0,0,114,10,0,0,0,114, 11,0,0,0,218,27,95,105,110,115,116,97,108,108,95,101, 120,116,101,114,110,97,108,95,105,109,112,111,114,116,101,114, 115,144,4,0,0,115,6,0,0,0,0,3,8,1,4,1, - 114,230,0,0,0,41,2,78,78,41,1,78,41,2,78,114, + 114,229,0,0,0,41,2,78,78,41,1,78,41,2,78,114, 22,0,0,0,41,4,78,78,114,10,0,0,0,114,22,0, - 0,0,41,50,114,3,0,0,0,114,126,0,0,0,114,12, - 0,0,0,114,18,0,0,0,114,60,0,0,0,114,33,0, + 0,0,41,50,114,3,0,0,0,114,125,0,0,0,114,12, + 0,0,0,114,18,0,0,0,114,59,0,0,0,114,33,0, 0,0,114,42,0,0,0,114,19,0,0,0,114,20,0,0, - 0,114,49,0,0,0,114,50,0,0,0,114,53,0,0,0, - 114,65,0,0,0,114,67,0,0,0,114,76,0,0,0,114, - 86,0,0,0,114,90,0,0,0,114,97,0,0,0,114,111, - 0,0,0,114,112,0,0,0,114,91,0,0,0,114,142,0, - 0,0,114,148,0,0,0,114,152,0,0,0,114,107,0,0, - 0,114,93,0,0,0,114,158,0,0,0,114,159,0,0,0, - 114,94,0,0,0,114,160,0,0,0,114,173,0,0,0,114, - 178,0,0,0,114,187,0,0,0,114,189,0,0,0,114,194, - 0,0,0,114,200,0,0,0,90,15,95,69,82,82,95,77, - 83,71,95,80,82,69,70,73,88,114,202,0,0,0,114,205, - 0,0,0,218,6,111,98,106,101,99,116,114,206,0,0,0, - 114,207,0,0,0,114,208,0,0,0,114,213,0,0,0,114, - 219,0,0,0,114,222,0,0,0,114,223,0,0,0,114,227, - 0,0,0,114,228,0,0,0,114,230,0,0,0,114,10,0, + 0,114,48,0,0,0,114,49,0,0,0,114,52,0,0,0, + 114,64,0,0,0,114,66,0,0,0,114,75,0,0,0,114, + 85,0,0,0,114,89,0,0,0,114,96,0,0,0,114,110, + 0,0,0,114,111,0,0,0,114,90,0,0,0,114,141,0, + 0,0,114,147,0,0,0,114,151,0,0,0,114,106,0,0, + 0,114,92,0,0,0,114,157,0,0,0,114,158,0,0,0, + 114,93,0,0,0,114,159,0,0,0,114,172,0,0,0,114, + 177,0,0,0,114,186,0,0,0,114,188,0,0,0,114,193, + 0,0,0,114,199,0,0,0,90,15,95,69,82,82,95,77, + 83,71,95,80,82,69,70,73,88,114,201,0,0,0,114,204, + 0,0,0,218,6,111,98,106,101,99,116,114,205,0,0,0, + 114,206,0,0,0,114,207,0,0,0,114,212,0,0,0,114, + 218,0,0,0,114,221,0,0,0,114,222,0,0,0,114,226, + 0,0,0,114,227,0,0,0,114,229,0,0,0,114,10,0, 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, 0,218,8,60,109,111,100,117,108,101,62,1,0,0,0,115, 94,0,0,0,4,24,4,2,8,8,8,8,4,2,4,3, diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 9bcf05057d1f..c69819676af8 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -111,29 +111,28 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 0,131,1,100,1,107,2,115,16,74,0,130,1,116,1,160, + 2,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,114,16,0,0,0,169,3,218,3,108,101,110,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, + 16,1,114,26,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, + 16,74,0,130,1,116,1,160,2,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,0,114,24,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,2,16,1,114,28,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, @@ -154,7 +153,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,2,10,1,2,255,114,37,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, @@ -166,15 +165,15 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 41,6,114,22,0,0,0,114,30,0,0,0,218,10,114,112, + 97,114,116,105,116,105,111,110,114,34,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, + 1,114,46,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, @@ -186,9 +185,9 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 43,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, + 0,0,0,115,2,0,0,0,0,7,114,48,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, @@ -197,32 +196,32 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 3,122,49,84,101,115,116,32,119,104,101,116,104,101,114,32, 116,104,101,32,112,97,116,104,32,105,115,32,116,104,101,32, 115,112,101,99,105,102,105,101,100,32,109,111,100,101,32,116, - 121,112,101,46,70,105,0,240,0,0,41,3,114,49,0,0, + 121,112,101,46,70,105,0,240,0,0,41,3,114,48,0,0, 0,218,7,79,83,69,114,114,111,114,218,7,115,116,95,109, - 111,100,101,41,3,114,44,0,0,0,218,4,109,111,100,101, + 111,100,101,41,3,114,43,0,0,0,218,4,109,111,100,101, 90,9,115,116,97,116,95,105,110,102,111,114,3,0,0,0, 114,3,0,0,0,114,6,0,0,0,218,18,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,0, + 1,114,52,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,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, + 46,105,0,128,0,0,41,1,114,52,0,0,0,114,47,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, + 0,0,0,115,2,0,0,0,0,2,114,53,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,218,6,103,101,116,99,119,100,114,52,0,0,0,114,47, 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,115,6,0,0,0,0,2,4,1,8,1,114,55, 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, @@ -235,13 +234,13 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 115,111,108,117,116,101,34,46,10,32,32,32,32,114,38,0, + 0,0,233,3,0,0,0,41,3,114,10,0,0,0,114,30, 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, + 105,116,104,95,99,111,108,111,110,114,47,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, + 0,0,0,0,6,114,58,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, @@ -264,21 +263,21 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,114,101,110,116,32,119,114,105,116,105,110,103,32,111,102, 32,116,104,101,10,32,32,32,32,116,101,109,112,111,114,97, 114,121,32,102,105,108,101,32,105,115,32,97,116,116,101,109, - 112,116,101,100,46,250,5,123,125,46,123,125,114,60,0,0, + 112,116,101,100,46,250,5,123,125,46,123,125,114,59,0,0, 0,90,2,119,98,78,41,13,218,6,102,111,114,109,97,116, 218,2,105,100,114,2,0,0,0,90,4,111,112,101,110,90, 6,79,95,69,88,67,76,90,7,79,95,67,82,69,65,84, 90,8,79,95,87,82,79,78,76,89,218,3,95,105,111,218, 6,70,105,108,101,73,79,218,5,119,114,105,116,101,218,7, - 114,101,112,108,97,99,101,114,50,0,0,0,90,6,117,110, - 108,105,110,107,41,6,114,44,0,0,0,114,26,0,0,0, - 114,52,0,0,0,90,8,112,97,116,104,95,116,109,112,90, + 114,101,112,108,97,99,101,114,49,0,0,0,90,6,117,110, + 108,105,110,107,41,6,114,43,0,0,0,114,25,0,0,0, + 114,51,0,0,0,90,8,112,97,116,104,95,116,109,112,90, 2,102,100,218,4,102,105,108,101,114,3,0,0,0,114,3, 0,0,0,114,6,0,0,0,218,13,95,119,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,85,13,0,0,114,28,0,0,0,114,16,0, + 20,1,16,1,14,1,2,1,14,1,14,1,6,1,114,68, + 0,0,0,105,92,13,0,0,114,27,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, @@ -362,42 +361,42 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 114,39,0,0,0,114,38,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, + 105,99,122,7,123,125,46,123,125,123,125,250,1,58,114,27, 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, + 116,104,114,46,0,0,0,114,40,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, + 114,114,35,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, + 114,114,61,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, + 58,0,0,0,114,37,0,0,0,114,54,0,0,0,114,30, 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, + 67,65,67,72,69,41,12,114,43,0,0,0,90,14,100,101, + 98,117,103,95,111,118,101,114,114,105,100,101,114,69,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, + 114,45,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,38,1,0,0,115,72,0,0, + 109,95,115,111,117,114,99,101,39,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, + 1,4,1,8,1,2,253,4,5,114,97,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, @@ -442,42 +441,42 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 114,71,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, + 116,111,114,121,32,105,110,32,114,70,0,0,0,62,2,0, + 0,0,114,27,0,0,0,114,56,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, + 32,51,32,100,111,116,115,32,105,110,32,114,56,0,0,0, + 114,27,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, + 118,97,108,117,101,114,72,0,0,0,41,22,114,8,0,0, + 0,114,79,0,0,0,114,80,0,0,0,114,81,0,0,0, + 114,2,0,0,0,114,78,0,0,0,114,46,0,0,0,114, + 89,0,0,0,114,29,0,0,0,114,30,0,0,0,114,10, + 0,0,0,114,34,0,0,0,114,22,0,0,0,114,91,0, + 0,0,114,86,0,0,0,218,5,99,111,117,110,116,114,42, + 0,0,0,114,87,0,0,0,114,85,0,0,0,218,9,112, + 97,114,116,105,116,105,111,110,114,37,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, + 114,43,0,0,0,114,93,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, + 111,116,95,99,111,117,110,116,114,69,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,109,1,0,0,115,52,0, + 114,111,109,95,99,97,99,104,101,110,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, + 10,1,16,2,14,1,114,102,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, @@ -499,18 +498,18 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 46,10,10,32,32,32,32,114,72,0,0,0,78,114,70,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, + 41,7,114,22,0,0,0,114,40,0,0,0,218,5,108,111, + 119,101,114,114,102,0,0,0,114,81,0,0,0,114,86,0, + 0,0,114,53,0,0,0,41,5,218,13,98,121,116,101,99, + 111,100,101,95,112,97,116,104,114,95,0,0,0,114,44,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,149,1,0,0,115,20, + 115,111,117,114,99,101,102,105,108,101,150,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, + 1,12,1,18,1,18,1,114,108,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, @@ -518,12 +517,12 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 1,0,89,0,113,70,88,0,110,22,124,0,160,0,116,1, 116,5,131,1,161,1,114,66,124,0,83,0,100,0,83,0, 100,0,83,0,169,1,78,41,6,218,8,101,110,100,115,119, - 105,116,104,218,5,116,117,112,108,101,114,102,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, + 105,116,104,218,5,116,117,112,108,101,114,101,0,0,0,114, + 97,0,0,0,114,81,0,0,0,114,88,0,0,0,41,1, + 114,96,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,168,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, + 100,169,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,112,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, @@ -532,13 +531,13 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 100,101,32,102,105,108,101,46,114,59,0,0,0,233,128,0, + 0,0,41,3,114,48,0,0,0,114,50,0,0,0,114,49, + 0,0,0,41,2,114,43,0,0,0,114,51,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,180,1,0,0,115,12, + 95,99,97,108,99,95,109,111,100,101,181,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, + 114,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, @@ -569,12 +568,12 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 109,101,41,2,114,116,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,116, 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,200,1,0,0,115,18, + 109,101,95,119,114,97,112,112,101,114,201,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, @@ -591,18 +590,18 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,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,211,1,0, + 108,100,114,66,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,212,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,192,1,0,0,115,14,0,0, + 10,95,98,111,111,116,115,116,114,97,112,114,132,0,0,0, + 218,9,78,97,109,101,69,114,114,111,114,41,3,114,121,0, + 0,0,114,122,0,0,0,114,132,0,0,0,114,3,0,0, + 0,114,120,0,0,0,114,6,0,0,0,218,11,95,99,104, + 101,99,107,95,110,97,109,101,193,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,0,0,0, + 135,0,0,0,99,2,0,0,0,0,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, @@ -620,17 +619,17 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 105,110,103,32,95,95,105,110,105,116,95,95,114,72,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, + 114,22,0,0,0,114,74,0,0,0,114,75,0,0,0,114, + 61,0,0,0,218,13,73,109,112,111,114,116,87,97,114,110, + 105,110,103,41,5,114,118,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,220,1,0, + 100,95,109,111,100,117,108,101,95,115,104,105,109,221,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, + 114,142,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,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, @@ -688,16 +687,16 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 133,0,0,0,218,16,95,118,101,114,98,111,115,101,95,109, + 101,115,115,97,103,101,114,117,0,0,0,114,22,0,0,0, + 218,8,69,79,70,69,114,114,111,114,114,26,0,0,0,41, + 6,114,25,0,0,0,114,116,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, + 92,0,0,0,114,82,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,237,1,0,0,115,28,0,0,0, + 105,102,121,95,112,121,99,238,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, + 12,1,8,1,16,2,8,1,16,1,12,1,114,151,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, @@ -739,19 +738,19 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 32,115,116,97,108,101,46,10,10,32,32,32,32,114,145,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, + 102,111,114,32,114,143,0,0,0,78,114,144,0,0,0,41, + 4,114,26,0,0,0,114,133,0,0,0,114,148,0,0,0, + 114,117,0,0,0,41,6,114,25,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, + 99,101,95,115,105,122,101,114,116,0,0,0,114,150,0,0, + 0,114,92,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,14,2, + 95,116,105,109,101,115,116,97,109,112,95,112,121,99,15,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, + 1,8,1,22,255,2,2,114,155,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, @@ -787,17 +786,17 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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,114, - 145,0,0,0,122,46,104,97,115,104,32,105,110,32,98,121, + 97,108,101,46,10,10,32,32,32,32,114,145,0,0,0,114, + 144,0,0,0,122,46,104,97,115,104,32,105,110,32,98,121, 116,101,99,111,100,101,32,100,111,101,115,110,39,116,32,109, 97,116,99,104,32,104,97,115,104,32,111,102,32,115,111,117, - 114,99,101,32,78,41,1,114,118,0,0,0,41,4,114,26, + 114,99,101,32,78,41,1,114,117,0,0,0,41,4,114,25, 0,0,0,218,11,115,111,117,114,99,101,95,104,97,115,104, - 114,117,0,0,0,114,151,0,0,0,114,3,0,0,0,114, + 114,116,0,0,0,114,150,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,42,2,0, + 100,97,116,101,95,104,97,115,104,95,112,121,99,43,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, + 2,254,114,157,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,80,0,0,0,116,0,160,1,124,0,161,1,125,4,116, 2,124,4,116,3,131,2,114,56,116,4,160,5,100,1,124, @@ -810,19 +809,19 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 116,0,0,0,114,43,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, + 121,112,101,114,133,0,0,0,114,148,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, + 101,110,97,109,101,114,117,0,0,0,114,61,0,0,0,41, + 5,114,25,0,0,0,114,116,0,0,0,114,106,0,0,0, + 114,107,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,66,2,0, + 112,105,108,101,95,98,121,116,101,99,111,100,101,67,2,0, 0,115,20,0,0,0,0,2,10,1,10,1,12,1,8,1, - 12,1,4,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, + 12,1,4,2,10,1,2,0,2,255,114,164,0,0,0,114, + 72,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, @@ -831,2024 +830,2024 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 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, + 101,100,32,112,121,99,46,114,72,0,0,0,41,6,218,9, + 98,121,116,101,97,114,114,97,121,114,147,0,0,0,218,6, + 101,120,116,101,110,100,114,20,0,0,0,114,159,0,0,0, + 218,5,100,117,109,112,115,41,4,114,163,0,0,0,218,5, + 109,116,105,109,101,114,154,0,0,0,114,25,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,79,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, + 109,112,95,112,121,99,80,2,0,0,115,12,0,0,0,0, + 2,8,1,14,1,14,1,14,1,16,1,114,169,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,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, + 0,116,4,124,1,131,1,100,2,107,2,115,50,74,0,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, + 5,160,6,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,89,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,100,2,100,3,161,2, - 125,4,124,4,160,6,124,0,160,6,124,3,100,1,25,0, - 161,1,161,1,83,0,41,4,122,121,68,101,99,111,100,101, - 32,98,121,116,101,115,32,114,101,112,114,101,115,101,110,116, - 105,110,103,32,115,111,117,114,99,101,32,99,111,100,101,32, - 97,110,100,32,114,101,116,117,114,110,32,116,104,101,32,115, - 116,114,105,110,103,46,10,10,32,32,32,32,85,110,105,118, - 101,114,115,97,108,32,110,101,119,108,105,110,101,32,115,117, - 112,112,111,114,116,32,105,115,32,117,115,101,100,32,105,110, - 32,116,104,101,32,100,101,99,111,100,105,110,103,46,10,32, - 32,32,32,114,73,0,0,0,78,84,41,7,218,8,116,111, - 107,101,110,105,122,101,114,64,0,0,0,90,7,66,121,116, - 101,115,73,79,90,8,114,101,97,100,108,105,110,101,90,15, - 100,101,116,101,99,116,95,101,110,99,111,100,105,110,103,90, - 25,73,110,99,114,101,109,101,110,116,97,108,78,101,119,108, - 105,110,101,68,101,99,111,100,101,114,218,6,100,101,99,111, - 100,101,41,5,218,12,115,111,117,114,99,101,95,98,121,116, - 101,115,114,172,0,0,0,90,21,115,111,117,114,99,101,95, - 98,121,116,101,115,95,114,101,97,100,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,100,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, + 97,115,101,100,32,112,121,99,46,114,38,0,0,0,114,145, + 0,0,0,41,7,114,165,0,0,0,114,147,0,0,0,114, + 166,0,0,0,114,20,0,0,0,114,22,0,0,0,114,159, + 0,0,0,114,167,0,0,0,41,5,114,163,0,0,0,114, + 156,0,0,0,90,7,99,104,101,99,107,101,100,114,25,0, + 0,0,114,82,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,90,2,0,0,115,14,0, + 0,0,0,2,8,1,12,1,14,1,16,1,10,1,16,1, + 114,170,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,100,2,100,3,161,2,125,4,124,4,160, + 6,124,0,160,6,124,3,100,1,25,0,161,1,161,1,83, + 0,41,4,122,121,68,101,99,111,100,101,32,98,121,116,101, + 115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,115, + 111,117,114,99,101,32,99,111,100,101,32,97,110,100,32,114, + 101,116,117,114,110,32,116,104,101,32,115,116,114,105,110,103, + 46,10,10,32,32,32,32,85,110,105,118,101,114,115,97,108, + 32,110,101,119,108,105,110,101,32,115,117,112,112,111,114,116, + 32,105,115,32,117,115,101,100,32,105,110,32,116,104,101,32, + 100,101,99,111,100,105,110,103,46,10,32,32,32,32,114,72, + 0,0,0,78,84,41,7,218,8,116,111,107,101,110,105,122, + 101,114,63,0,0,0,90,7,66,121,116,101,115,73,79,90, + 8,114,101,97,100,108,105,110,101,90,15,100,101,116,101,99, + 116,95,101,110,99,111,100,105,110,103,90,25,73,110,99,114, + 101,109,101,110,116,97,108,78,101,119,108,105,110,101,68,101, + 99,111,100,101,114,218,6,100,101,99,111,100,101,41,5,218, + 12,115,111,117,114,99,101,95,98,121,116,101,115,114,171,0, + 0,0,90,21,115,111,117,114,99,101,95,98,121,116,101,115, + 95,114,101,97,100,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,101,2,0,0,115,10,0,0,0,0,5,8,1,12, + 1,10,1,12,1,114,175,0,0,0,169,2,114,139,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,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,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,117,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,80,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,14, - 100,10,100,11,132,1,131,1,90,10,101,7,100,15,100,12, - 100,13,132,1,131,1,90,11,100,9,83,0,41,16,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,197,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,114,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,2,133,2,25,0,22,0,100,3,141,2,125, - 3,122,38,124,0,160,6,124,3,161,1,143,18,125,4,116, - 7,160,8,124,4,100,4,161,2,125,5,87,0,53,0,81, - 0,82,0,88,0,87,0,110,22,4,0,116,9,107,10,114, - 108,1,0,1,0,1,0,89,0,100,0,83,0,88,0,124, - 5,83,0,41,5,78,122,5,37,100,46,37,100,114,28,0, - 0,0,41,2,114,139,0,0,0,90,11,115,121,115,95,118, - 101,114,115,105,111,110,114,40,0,0,0,41,10,218,11,68, - 69,66,85,71,95,66,85,73,76,68,218,18,82,69,71,73, - 83,84,82,89,95,75,69,89,95,68,69,66,85,71,218,12, - 82,69,71,73,83,84,82,89,95,75,69,89,114,62,0,0, - 0,114,8,0,0,0,218,12,118,101,114,115,105,111,110,95, - 105,110,102,111,114,194,0,0,0,114,192,0,0,0,90,10, - 81,117,101,114,121,86,97,108,117,101,114,50,0,0,0,41, - 6,114,193,0,0,0,114,139,0,0,0,90,12,114,101,103, - 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,204, - 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,8,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,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,219,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,235,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,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,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, + 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,72,0,0,0,41,17,114,127,0,0,0,114,178,0,0, + 0,114,117,0,0,0,114,2,0,0,0,114,78,0,0,0, + 114,133,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,110,0, + 0,0,114,111,0,0,0,114,139,0,0,0,218,9,95,80, + 79,80,85,76,65,84,69,114,181,0,0,0,114,177,0,0, + 0,114,46,0,0,0,218,6,97,112,112,101,110,100,41,9, + 114,116,0,0,0,90,8,108,111,99,97,116,105,111,110,114, + 139,0,0,0,114,177,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,181,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,118,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,189,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,80,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,14,100,10,100,11,132, + 1,131,1,90,10,101,7,100,15,100,12,100,13,132,1,131, + 1,90,11,100,9,83,0,41,16,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,109,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,49,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,198,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,114,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,2, + 133,2,25,0,22,0,100,3,141,2,125,3,122,38,124,0, + 160,6,124,3,161,1,143,18,125,4,116,7,160,8,124,4, + 100,4,161,2,125,5,87,0,53,0,81,0,82,0,88,0, + 87,0,110,22,4,0,116,9,107,10,114,108,1,0,1,0, + 1,0,89,0,100,0,83,0,88,0,124,5,83,0,41,5, + 78,122,5,37,100,46,37,100,114,27,0,0,0,41,2,114, + 138,0,0,0,90,11,115,121,115,95,118,101,114,115,105,111, + 110,114,39,0,0,0,41,10,218,11,68,69,66,85,71,95, + 66,85,73,76,68,218,18,82,69,71,73,83,84,82,89,95, + 75,69,89,95,68,69,66,85,71,218,12,82,69,71,73,83, + 84,82,89,95,75,69,89,114,61,0,0,0,114,8,0,0, + 0,218,12,118,101,114,115,105,111,110,95,105,110,102,111,114, + 193,0,0,0,114,191,0,0,0,90,10,81,117,101,114,121, + 86,97,108,117,101,114,49,0,0,0,41,6,114,192,0,0, + 0,114,138,0,0,0,90,12,114,101,103,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,205,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,8,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,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, + 179,0,0,0,41,8,114,199,0,0,0,114,48,0,0,0, + 114,49,0,0,0,114,183,0,0,0,114,110,0,0,0,114, + 111,0,0,0,114,133,0,0,0,218,16,115,112,101,99,95, + 102,114,111,109,95,108,111,97,100,101,114,41,8,114,192,0, + 0,0,114,138,0,0,0,114,43,0,0,0,218,6,116,97, + 114,103,101,116,114,198,0,0,0,114,139,0,0,0,114,188, + 0,0,0,114,186,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,220,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,202,0,0,0, + 114,139,0,0,0,169,4,114,192,0,0,0,114,138,0,0, + 0,114,43,0,0,0,114,186,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,236,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,2,78,78,41, + 1,78,41,12,114,124,0,0,0,114,123,0,0,0,114,125, + 0,0,0,114,126,0,0,0,114,196,0,0,0,114,195,0, + 0,0,114,194,0,0,0,218,11,99,108,97,115,115,109,101, + 116,104,111,100,114,193,0,0,0,114,199,0,0,0,114,202, + 0,0,0,114,205,0,0,0,114,3,0,0,0,114,3,0, + 0,0,114,3,0,0,0,114,6,0,0,0,114,190,0,0, + 0,186,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,12,15,2,1,114,190,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,3,100,2,161,1,100,4,25,0,125,4,124,3,100, + 5,107,2,111,62,124,4,100,5,107,3,83,0,41,6,122, + 141,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,105,115,95,112,97,99, + 107,97,103,101,32,98,121,32,99,104,101,99,107,105,110,103, + 32,105,102,10,32,32,32,32,32,32,32,32,116,104,101,32, + 112,97,116,104,32,114,101,116,117,114,110,101,100,32,98,121, + 32,103,101,116,95,102,105,108,101,110,97,109,101,32,104,97, + 115,32,97,32,102,105,108,101,110,97,109,101,32,111,102,32, + 39,95,95,105,110,105,116,95,95,46,112,121,39,46,114,38, + 0,0,0,114,70,0,0,0,114,72,0,0,0,114,27,0, + 0,0,218,8,95,95,105,110,105,116,95,95,41,4,114,46, + 0,0,0,114,178,0,0,0,114,42,0,0,0,114,40,0, + 0,0,41,5,114,118,0,0,0,114,138,0,0,0,114,96, + 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,181,0,0, + 0,255,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,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,118,0,0,0,114,186,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,7,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,124,0,0,0,114,117,0,0,0,114,61, + 0,0,0,114,133,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,130,0,0,0,41,3, + 114,118,0,0,0,218,6,109,111,100,117,108,101,114,163,0, 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,114,191,0,0,0,185,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,12,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,3,100,2,161,1,100,4,25,0, - 125,4,124,3,100,5,107,2,111,62,124,4,100,5,107,3, - 83,0,41,6,122,141,67,111,110,99,114,101,116,101,32,105, + 0,218,11,101,120,101,99,95,109,111,100,117,108,101,10,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,133,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,118,0,0,0,114,138,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,18,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,124,0,0,0,114,123,0,0,0,114,125,0,0,0, + 114,126,0,0,0,114,181,0,0,0,114,211,0,0,0,114, + 216,0,0,0,114,219,0,0,0,114,3,0,0,0,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,114,207,0, + 0,0,250,2,0,0,115,10,0,0,0,8,2,4,3,8, + 8,8,3,8,8,114,207,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,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,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,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,49,0,0,0,169,2,114,118,0,0,0, + 114,43,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, + 25,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,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,168,0,0,0,41,1,114,222,0,0, + 0,114,221,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,33,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,118,0,0,0,114,107,0,0,0,90, + 10,99,97,99,104,101,95,112,97,116,104,114,25,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, + 47,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,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,32,32,32, + 32,32,32,32,32,78,114,3,0,0,0,41,3,114,118,0, + 0,0,114,43,0,0,0,114,25,0,0,0,114,3,0,0, + 0,114,3,0,0,0,114,6,0,0,0,114,224,0,0,0, + 57,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,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,105, - 115,95,112,97,99,107,97,103,101,32,98,121,32,99,104,101, - 99,107,105,110,103,32,105,102,10,32,32,32,32,32,32,32, - 32,116,104,101,32,112,97,116,104,32,114,101,116,117,114,110, - 101,100,32,98,121,32,103,101,116,95,102,105,108,101,110,97, - 109,101,32,104,97,115,32,97,32,102,105,108,101,110,97,109, - 101,32,111,102,32,39,95,95,105,110,105,116,95,95,46,112, - 121,39,46,114,39,0,0,0,114,71,0,0,0,114,73,0, - 0,0,114,28,0,0,0,218,8,95,95,105,110,105,116,95, - 95,41,4,114,47,0,0,0,114,179,0,0,0,114,43,0, - 0,0,114,41,0,0,0,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,254,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,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,6,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,9,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,17,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,249,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,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,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, - 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,24,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,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,32,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,46,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,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,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, + 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,115,0,0,0,78,41,5,114,178,0,0,0, + 218,8,103,101,116,95,100,97,116,97,114,49,0,0,0,114, + 117,0,0,0,114,175,0,0,0,41,5,114,118,0,0,0, + 114,138,0,0,0,114,43,0,0,0,114,173,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,64, + 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,104,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,214,0,0,0,84,41,2,218,12,100,111,110,116,95, + 105,110,104,101,114,105,116,114,83,0,0,0,41,3,114,133, + 0,0,0,114,213,0,0,0,218,7,99,111,109,112,105,108, + 101,41,4,114,118,0,0,0,114,25,0,0,0,114,43,0, + 0,0,114,229,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,74,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,56, + 124,7,115,254,116,9,106,10,100,11,107,2,144,1,114,56, + 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,168,0,0,0,114,158, + 0,0,0,114,144,0,0,0,114,38,0,0,0,114,72,0, + 0,0,114,27,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,116,0, + 0,0,114,106,0,0,0,114,107,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,178,0,0,0,114,97,0,0,0,114,81,0, + 0,0,114,223,0,0,0,114,49,0,0,0,114,17,0,0, + 0,114,226,0,0,0,114,151,0,0,0,218,10,109,101,109, + 111,114,121,118,105,101,119,114,162,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,156,0,0,0,218,17,95,82,65,87,95,77, + 65,71,73,67,95,78,85,77,66,69,82,114,157,0,0,0, + 114,155,0,0,0,114,117,0,0,0,114,149,0,0,0,114, + 133,0,0,0,114,148,0,0,0,114,164,0,0,0,114,232, + 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,170,0, + 0,0,114,169,0,0,0,114,22,0,0,0,114,225,0,0, + 0,41,15,114,118,0,0,0,114,138,0,0,0,114,107,0, + 0,0,114,153,0,0,0,114,173,0,0,0,114,156,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,106,0,0,0, + 218,2,115,116,114,25,0,0,0,114,150,0,0,0,114,82, + 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,212,0,0,0, + 82,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,124,0,0,0, + 114,123,0,0,0,114,125,0,0,0,114,222,0,0,0,114, + 223,0,0,0,114,225,0,0,0,114,224,0,0,0,114,228, + 0,0,0,114,232,0,0,0,114,212,0,0,0,114,3,0, + 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, + 0,114,220,0,0,0,23,3,0,0,115,14,0,0,0,8, + 2,8,8,8,14,8,10,8,7,8,10,14,8,114,220,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,90,6,101,7,135,0,102,1,100,8,100,9,132,8, + 131,1,90,8,101,7,100,10,100,11,132,0,131,1,90,9, + 100,12,100,13,132,0,90,10,101,7,100,14,100,15,132,0, + 131,1,90,11,100,16,100,17,132,0,90,12,100,18,100,19, + 132,0,90,13,100,20,100,21,132,0,90,14,100,22,100,23, + 132,0,90,15,135,0,4,0,90,16,83,0,41,24,218,10, + 70,105,108,101,76,111,97,100,101,114,122,103,66,97,115,101, + 32,102,105,108,101,32,108,111,97,100,101,114,32,99,108,97, + 115,115,32,119,104,105,99,104,32,105,109,112,108,101,109,101, + 110,116,115,32,116,104,101,32,108,111,97,100,101,114,32,112, + 114,111,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,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,158,0,0,0,41,3,114,118,0,0,0,114,138,0, + 0,0,114,43,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,114,208,0,0,0,172,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,109,0,0,0,169,2,218,9,95,95,99,108, + 97,115,115,95,95,114,130,0,0,0,169,2,114,118,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,178, + 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,109,0,0,0,169,3,218,4,104,97,115,104, + 114,116,0,0,0,114,43,0,0,0,169,1,114,118,0,0, 0,114,3,0,0,0,114,3,0,0,0,114,6,0,0,0, - 114,225,0,0,0,56,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, - 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,63,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,73,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,56,124,7,115,254,116,9,106,10,100,11,107, - 2,144,1,114,56,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,81,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,22,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,90,6,101,7,135,0,102,1,100, - 8,100,9,132,8,131,1,90,8,101,7,100,10,100,11,132, - 0,131,1,90,9,100,12,100,13,132,0,90,10,101,7,100, - 14,100,15,132,0,131,1,90,11,100,16,100,17,132,0,90, - 12,100,18,100,19,132,0,90,13,100,20,100,21,132,0,90, - 14,100,22,100,23,132,0,90,15,135,0,4,0,90,16,83, - 0,41,24,218,10,70,105,108,101,76,111,97,100,101,114,122, - 103,66,97,115,101,32,102,105,108,101,32,108,111,97,100,101, - 114,32,99,108,97,115,115,32,119,104,105,99,104,32,105,109, - 112,108,101,109,101,110,116,115,32,116,104,101,32,108,111,97, - 100,101,114,32,112,114,111,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,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, - 171,3,0,0,115,4,0,0,0,0,3,6,1,122,19,70, + 218,8,95,95,104,97,115,104,95,95,182,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,32,109,111,100,117,108,101,32,102,114,111,109,32,97, + 32,102,105,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, + 41,3,218,5,115,117,112,101,114,114,238,0,0,0,114,219, + 0,0,0,114,218,0,0,0,169,1,114,240,0,0,0,114, + 3,0,0,0,114,6,0,0,0,114,219,0,0,0,185,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,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,47,0,0,0,114,218,0,0,0,114,3,0, + 0,0,114,3,0,0,0,114,6,0,0,0,114,178,0,0, + 0,197,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,102, + 0,0,0,116,0,124,0,116,1,116,2,102,2,131,2,114, + 58,116,3,160,4,116,5,124,1,131,1,161,1,143,22,125, + 2,124,2,160,6,161,0,87,0,2,0,53,0,81,0,82, + 0,163,0,83,0,81,0,82,0,88,0,110,40,116,3,160, + 7,124,1,100,1,161,2,143,22,125,2,124,2,160,6,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,8,114,160,0,0,0,114, + 220,0,0,0,218,19,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,114,63,0,0,0,90,9, + 111,112,101,110,95,99,111,100,101,114,84,0,0,0,90,4, + 114,101,97,100,114,64,0,0,0,41,3,114,118,0,0,0, + 114,43,0,0,0,114,67,0,0,0,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,114,226,0,0,0,202,3, + 0,0,115,10,0,0,0,0,2,14,1,16,1,28,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,109,0,0,0,41,1,114,181,0, + 0,0,169,2,114,118,0,0,0,114,215,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,213,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,78,114,72,0,0,0,114,250,0,0,0,41,5,114,37, + 0,0,0,114,46,0,0,0,114,43,0,0,0,114,63,0, + 0,0,114,64,0,0,0,169,3,114,118,0,0,0,90,8, + 114,101,115,111,117,114,99,101,114,43,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,219,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,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,72,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,37,0,0,0,114,46,0,0,0,114,43,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,223,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,72,0,0,0,41,5,114,34, + 0,0,0,114,37,0,0,0,114,46,0,0,0,114,43,0, + 0,0,114,53,0,0,0,169,3,114,118,0,0,0,114,116, + 0,0,0,114,43,0,0,0,114,3,0,0,0,114,3,0, + 0,0,114,6,0,0,0,114,1,1,0,0,229,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,46,0,0,0,114,43,0,0,0, + 114,245,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,235,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,124,0,0,0,114,123,0,0,0,114,125,0,0,0,114, + 126,0,0,0,114,208,0,0,0,114,242,0,0,0,114,246, + 0,0,0,114,135,0,0,0,114,219,0,0,0,114,178,0, + 0,0,114,226,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,248,0,0,0,114,6, + 0,0,0,114,238,0,0,0,167,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,11,2,1,10,5,8,4,8,6,8,6,114, + 238,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,7,156,1,100,8,100,9,132,2,90,6,100,10,83,0, + 41,11,218,16,83,111,117,114,99,101,70,105,108,101,76,111, + 97,100,101,114,122,62,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,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,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, + 168,0,0,0,114,233,0,0,0,41,3,114,48,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,118,0,0,0,114,43,0,0,0,114, + 237,0,0,0,114,3,0,0,0,114,3,0,0,0,114,6, + 0,0,0,114,223,0,0,0,243,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,114,0,0,0,114,224,0,0,0, + 41,5,114,118,0,0,0,114,107,0,0,0,114,106,0,0, + 0,114,25,0,0,0,114,51,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,225,0,0,0,248, + 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,59, + 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,252,0,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,108,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,113,60, + 4,0,116,7,107,10,114,112,1,0,1,0,1,0,89,0, + 113,60,89,0,113,60,4,0,116,8,107,10,114,166,1,0, + 125,8,1,0,122,26,116,9,160,10,100,1,124,4,124,8, + 161,3,1,0,87,0,89,0,162,6,1,0,100,2,83,0, + 100,2,125,8,126,8,88,0,89,0,113,60,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,246,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, + 46,0,0,0,114,55,0,0,0,114,185,0,0,0,114,41, + 0,0,0,114,37,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,49,0,0,0,114,133,0,0,0,114, + 148,0,0,0,114,68,0,0,0,41,9,114,118,0,0,0, + 114,43,0,0,0,114,25,0,0,0,114,11,1,0,0,218, + 6,112,97,114,101,110,116,114,96,0,0,0,114,36,0,0, + 0,114,32,0,0,0,114,227,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,224,0,0,0,253, + 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,28,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,124,0,0,0,114,123,0,0,0, + 114,125,0,0,0,114,126,0,0,0,114,223,0,0,0,114, + 225,0,0,0,114,224,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,239,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,5,132,0, + 90,5,100,6,83,0,41,7,218,20,83,111,117,114,99,101, + 108,101,115,115,70,105,108,101,76,111,97,100,101,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,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,158,0,0,0,114,144,0,0,0,41,2,114,116, + 0,0,0,114,106,0,0,0,41,5,114,178,0,0,0,114, + 226,0,0,0,114,151,0,0,0,114,164,0,0,0,114,234, + 0,0,0,41,5,114,118,0,0,0,114,138,0,0,0,114, + 43,0,0,0,114,25,0,0,0,114,150,0,0,0,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,114,212,0, + 0,0,32,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,218,0,0,0,114,3,0,0,0,114,3,0, + 0,0,114,6,0,0,0,114,228,0,0,0,48,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,124,0,0,0, + 114,123,0,0,0,114,125,0,0,0,114,126,0,0,0,114, + 212,0,0,0,114,228,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,28,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,114,251,0,0,0,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,109,0,0,0,114,158,0,0,0,114,4, + 1,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, + 0,0,114,208,0,0,0,65,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,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,177,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, + 124,1,106,1,107,2,83,0,114,109,0,0,0,114,239,0, + 0,0,114,241,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,114,242,0,0,0,69,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,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,181, - 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,32,109,111,100,117,108,101,32,102, - 114,111,109,32,97,32,102,105,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,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,184,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,0, + 106,2,131,1,65,0,83,0,114,109,0,0,0,114,243,0, + 0,0,114,245,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,114,246,0,0,0,73,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,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,133,0,0,0,114, + 213,0,0,0,114,162,0,0,0,90,14,99,114,101,97,116, + 101,95,100,121,110,97,109,105,99,114,148,0,0,0,114,116, + 0,0,0,114,43,0,0,0,41,3,114,118,0,0,0,114, + 186,0,0,0,114,215,0,0,0,114,3,0,0,0,114,3, + 0,0,0,114,6,0,0,0,114,211,0,0,0,76,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,41,3,122, + 30,73,110,105,116,105,97,108,105,122,101,32,97,110,32,101, + 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,122, + 40,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, + 101,32,123,33,114,125,32,101,120,101,99,117,116,101,100,32, + 102,114,111,109,32,123,33,114,125,78,41,7,114,133,0,0, + 0,114,213,0,0,0,114,162,0,0,0,90,12,101,120,101, + 99,95,100,121,110,97,109,105,99,114,148,0,0,0,114,116, + 0,0,0,114,43,0,0,0,114,252,0,0,0,114,3,0, + 0,0,114,3,0,0,0,114,6,0,0,0,114,216,0,0, + 0,84,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,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,38,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,208,0,0,0, + 78,114,3,0,0,0,169,2,114,31,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,93,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,46,0,0,0,114,43, + 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,218,0,0, + 0,114,3,0,0,0,114,17,1,0,0,114,6,0,0,0, + 114,181,0,0,0,90,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, - 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,196,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,102,0,0,0,116,0,124,0,116,1,116,2, - 102,2,131,2,114,58,116,3,160,4,116,5,124,1,131,1, - 161,1,143,22,125,2,124,2,160,6,161,0,87,0,2,0, - 53,0,81,0,82,0,163,0,83,0,81,0,82,0,88,0, - 110,40,116,3,160,7,124,1,100,1,161,2,143,22,125,2, - 124,2,160,6,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,8,114, - 161,0,0,0,114,221,0,0,0,218,19,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,114,64, - 0,0,0,90,9,111,112,101,110,95,99,111,100,101,114,85, - 0,0,0,90,4,114,101,97,100,114,65,0,0,0,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,201,3,0,0,115,10,0,0,0,0,2,14,1, - 16,1,28,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,212,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,78,114,73,0,0,0,114,251,0,0, - 0,41,5,114,38,0,0,0,114,47,0,0,0,114,44,0, - 0,0,114,64,0,0,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, - 218,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, - 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,255,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,222,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,2,1,0, - 0,228,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,1,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,234,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,254,0,0, - 0,114,0,1,0,0,114,4,1,0,0,114,2,1,0,0, - 114,8,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,166,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,11,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,7,156,1,100,8,100,9,132,2,90, - 6,100,10,83,0,41,11,218,16,83,111,117,114,99,101,70, - 105,108,101,76,111,97,100,101,114,122,62,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,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,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,242,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, + 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,218,0,0,0,114,3,0,0,0,114,3,0,0,0, + 114,6,0,0,0,114,212,0,0,0,96,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,115,105,111, + 110,32,109,111,100,117,108,101,115,32,104,97,118,101,32,110, + 111,32,115,111,117,114,99,101,32,99,111,100,101,46,78,114, + 3,0,0,0,114,218,0,0,0,114,3,0,0,0,114,3, + 0,0,0,114,6,0,0,0,114,228,0,0,0,100,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,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,249,0,0, + 0,114,47,0,0,0,114,218,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,178,0,0,0,104, + 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, + 124,0,0,0,114,123,0,0,0,114,125,0,0,0,114,126, + 0,0,0,114,208,0,0,0,114,242,0,0,0,114,246,0, + 0,0,114,211,0,0,0,114,216,0,0,0,114,181,0,0, + 0,114,212,0,0,0,114,228,0,0,0,114,135,0,0,0, + 114,178,0,0,0,114,3,0,0,0,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,114,251,0,0,0,57,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,251,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,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,109,0,0,0,41,6,218,5, + 95,110,97,109,101,218,5,95,112,97,116,104,114,111,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,118,0,0,0,114,116,0,0,0, + 114,43,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,208,0,0,0,117,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,1,100,4, + 102,2,83,0,41,5,122,62,82,101,116,117,114,110,115,32, + 97,32,116,117,112,108,101,32,111,102,32,40,112,97,114,101, + 110,116,45,109,111,100,117,108,101,45,110,97,109,101,44,32, + 112,97,114,101,110,116,45,112,97,116,104,45,97,116,116,114, + 45,110,97,109,101,41,114,70,0,0,0,114,39,0,0,0, + 41,2,114,8,0,0,0,114,43,0,0,0,90,8,95,95, + 112,97,116,104,95,95,41,2,114,22,1,0,0,114,40,0, + 0,0,41,4,114,118,0,0,0,114,13,1,0,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,123, + 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,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,109,0,0,0,41,4,114,29,1,0,0,114,129, + 0,0,0,114,8,0,0,0,218,7,109,111,100,117,108,101, + 115,41,3,114,118,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,24,1,0,0, + 133,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,109,0,0, + 0,41,8,114,111,0,0,0,114,24,1,0,0,114,25,1, + 0,0,114,26,1,0,0,114,22,1,0,0,114,139,0,0, + 0,114,177,0,0,0,114,23,1,0,0,41,3,114,118,0, + 0,0,90,11,112,97,114,101,110,116,95,112,97,116,104,114, + 186,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,137,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,109,0,0,0,41,2,114,5,1,0,0,114,31,1, + 0,0,114,245,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, + 150,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,109, + 0,0,0,169,1,114,31,1,0,0,41,2,114,118,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,153,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,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,109,0,0,0,41,1,114,23, + 1,0,0,41,3,114,118,0,0,0,114,34,1,0,0,114, + 43,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, + 156,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,109,0,0,0,41,2,114,22,0,0,0,114,31,1, + 0,0,114,245,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,159, + 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,61,0,0,0,114,23,1,0, + 0,114,245,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,162, + 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,109,0, + 0,0,114,33,1,0,0,169,2,114,118,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,165,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,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,109,0,0,0,41,2,114,23, + 1,0,0,114,185,0,0,0,114,39,1,0,0,114,3,0, + 0,0,114,3,0,0,0,114,6,0,0,0,114,185,0,0, + 0,168,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,124,0,0,0,114,123,0,0,0, + 114,125,0,0,0,114,126,0,0,0,114,208,0,0,0,114, + 29,1,0,0,114,24,1,0,0,114,31,1,0,0,114,32, + 1,0,0,114,35,1,0,0,114,36,1,0,0,114,37,1, + 0,0,114,38,1,0,0,114,41,1,0,0,114,185,0,0, + 0,114,3,0,0,0,114,3,0,0,0,114,3,0,0,0, + 114,6,0,0,0,114,21,1,0,0,110,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,21,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,109,0,0,0,41,2,114,21,1,0,0,114,23, + 1,0,0,114,27,1,0,0,114,3,0,0,0,114,3,0, + 0,0,114,6,0,0,0,114,208,0,0,0,174,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,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,25,60,109,111,100,117,108,101,32,123,33,114, + 125,32,40,110,97,109,101,115,112,97,99,101,41,62,41,2, + 114,61,0,0,0,114,124,0,0,0,41,2,114,192,0,0, + 0,114,215,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,177,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,218,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,181,0,0,0,186, + 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,114,39,0,0, + 0,114,3,0,0,0,114,218,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,228,0,0,0,189, + 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,39,0,0,0,122,8,60, + 115,116,114,105,110,103,62,114,214,0,0,0,84,41,1,114, + 230,0,0,0,41,1,114,231,0,0,0,114,218,0,0,0, 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, - 226,0,0,0,247,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,11,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,252,0,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,108,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,113,60,4,0,116,7,107,10,114,112,1,0,1, - 0,1,0,89,0,113,60,89,0,113,60,4,0,116,8,107, - 10,114,166,1,0,125,8,1,0,122,26,116,9,160,10,100, - 1,124,4,124,8,161,3,1,0,87,0,89,0,162,6,1, - 0,100,2,83,0,100,2,125,8,126,8,88,0,89,0,113, - 60,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,246,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, - 12,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, + 212,0,0,0,192,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,209,0,0, + 0,114,3,0,0,0,114,210,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,211,0,0,0,195, + 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,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,109,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,216,0,0,0,198, + 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,133,0,0,0,114,148,0,0,0,114,23,1,0,0,114, + 217,0,0,0,114,218,0,0,0,114,3,0,0,0,114,3, + 0,0,0,114,6,0,0,0,114,219,0,0,0,201,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, + 124,0,0,0,114,123,0,0,0,114,125,0,0,0,114,208, + 0,0,0,114,206,0,0,0,114,43,1,0,0,114,181,0, + 0,0,114,228,0,0,0,114,212,0,0,0,114,211,0,0, + 0,114,216,0,0,0,114,219,0,0,0,114,3,0,0,0, 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, - 225,0,0,0,252,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,28, - 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,9,1,0,0,238,3,0,0,115,8,0,0,0, - 8,2,4,2,8,5,8,5,114,9,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,5,132,0,90,5,100,6,83,0,41,7,218,20,83, - 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, - 100,101,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,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,31,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,47,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, + 42,1,0,0,173,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, + 42,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,180,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,29,100,11,100,12,132,1,131,1,90,9,101,4,100,30, + 100,13,100,14,132,1,131,1,90,10,101,4,100,31,100,15, + 100,16,132,1,131,1,90,11,101,4,100,32,100,17,100,18, + 132,1,131,1,90,12,101,4,100,19,100,20,132,0,131,1, + 90,13,101,14,100,21,100,22,132,0,131,1,90,15,101,4, + 100,23,100,24,132,0,131,1,90,16,101,4,100,25,100,26, + 132,0,131,1,90,17,101,4,100,27,100,28,132,0,131,1, + 90,18,100,10,83,0,41,33,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,0,113,14,116,4,124,2,100,2, + 131,2,114,14,124,2,160,5,161,0,1,0,113,14,100,1, + 83,0,41,3,122,125,67,97,108,108,32,116,104,101,32,105, + 110,118,97,108,105,100,97,116,101,95,99,97,99,104,101,115, + 40,41,32,109,101,116,104,111,100,32,111,110,32,97,108,108, + 32,112,97,116,104,32,101,110,116,114,121,32,102,105,110,100, + 101,114,115,10,32,32,32,32,32,32,32,32,115,116,111,114, + 101,100,32,105,110,32,115,121,115,46,112,97,116,104,95,105, + 109,112,111,114,116,101,114,95,99,97,99,104,101,115,32,40, + 119,104,101,114,101,32,105,109,112,108,101,109,101,110,116,101, + 100,41,46,78,218,17,105,110,118,97,108,105,100,97,116,101, + 95,99,97,99,104,101,115,41,6,218,4,108,105,115,116,114, + 8,0,0,0,218,19,112,97,116,104,95,105,109,112,111,114, + 116,101,114,95,99,97,99,104,101,218,5,105,116,101,109,115, + 114,127,0,0,0,114,45,1,0,0,41,3,114,192,0,0, + 0,114,116,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,45,1, + 0,0,219,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,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,74,0,0,0,114,75,0,0,0,114,137, + 0,0,0,114,117,0,0,0,41,3,114,192,0,0,0,114, + 43,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,229,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,39,0,0,0,78,41,7,114,2,0,0,0, + 114,54,0,0,0,114,2,1,0,0,114,8,0,0,0,114, + 47,1,0,0,218,8,75,101,121,69,114,114,111,114,114,51, + 1,0,0,41,3,114,192,0,0,0,114,43,0,0,0,114, + 49,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,242,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,136,0,0, + 0,41,7,114,127,0,0,0,114,136,0,0,0,114,205,0, + 0,0,114,133,0,0,0,114,200,0,0,0,114,182,0,0, + 0,114,177,0,0,0,41,6,114,192,0,0,0,114,138,0, + 0,0,114,49,1,0,0,114,139,0,0,0,114,140,0,0, + 0,114,186,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,8,5,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,28,113,8,124,0,160,3,124,5, + 161,1,125,6,124,6,100,1,107,9,114,8,116,4,124,6, + 100,2,131,2,114,70,124,6,160,5,124,1,124,3,161,2, + 125,7,110,12,124,0,160,6,124,1,124,6,161,2,125,7, + 124,7,100,1,107,8,114,92,113,8,124,7,106,7,100,1, + 107,9,114,110,124,7,2,0,1,0,83,0,124,7,106,8, + 125,8,124,8,100,1,107,8,114,132,116,9,100,3,131,1, + 130,1,124,4,160,10,124,8,161,1,1,0,113,8,116,11, + 160,12,124,1,100,1,161,2,125,7,124,4,124,7,95,8, + 124,7,83,0,41,4,122,63,70,105,110,100,32,116,104,101, + 32,108,111,97,100,101,114,32,111,114,32,110,97,109,101,115, + 112,97,99,101,95,112,97,116,104,32,102,111,114,32,116,104, + 105,115,32,109,111,100,117,108,101,47,112,97,99,107,97,103, + 101,32,110,97,109,101,46,78,114,202,0,0,0,122,19,115, + 112,101,99,32,109,105,115,115,105,110,103,32,108,111,97,100, + 101,114,41,13,114,160,0,0,0,114,84,0,0,0,218,5, + 98,121,116,101,115,114,53,1,0,0,114,127,0,0,0,114, + 202,0,0,0,114,54,1,0,0,114,139,0,0,0,114,177, + 0,0,0,114,117,0,0,0,114,166,0,0,0,114,133,0, + 0,0,114,182,0,0,0,41,9,114,192,0,0,0,114,138, + 0,0,0,114,43,0,0,0,114,201,0,0,0,218,14,110, + 97,109,101,115,112,97,99,101,95,112,97,116,104,90,5,101, + 110,116,114,121,114,49,1,0,0,114,186,0,0,0,114,140, 0,0,0,114,3,0,0,0,114,3,0,0,0,114,6,0, - 0,0,114,15,1,0,0,27,4,0,0,115,6,0,0,0, - 8,2,4,2,8,16,114,15,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,114,252,0,0,0,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,5,1,0,0,114,3,0,0,0,114,3,0, - 0,0,114,6,0,0,0,114,209,0,0,0,64,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, - 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, - 68,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, - 72,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,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,75,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,41,3,122,30,73,110,105,116,105,97,108,105,122,101, - 32,97,110,32,101,120,116,101,110,115,105,111,110,32,109,111, - 100,117,108,101,122,40,101,120,116,101,110,115,105,111,110,32, - 109,111,100,117,108,101,32,123,33,114,125,32,101,120,101,99, - 117,116,101,100,32,102,114,111,109,32,123,33,114,125,78,41, - 7,114,134,0,0,0,114,214,0,0,0,114,163,0,0,0, - 90,12,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,253,0, - 0,0,114,3,0,0,0,114,3,0,0,0,114,6,0,0, - 0,114,217,0,0,0,83,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,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,92,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,89,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,95, - 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,115,105,111,110,32,109,111,100,117,108,101,115,32,104, - 97,118,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,99,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,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,103,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,252, - 0,0,0,56,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,252,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,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,116,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,1,100,4,102,2,83,0,41,5,122,62,82,101,116, - 117,114,110,115,32,97,32,116,117,112,108,101,32,111,102,32, - 40,112,97,114,101,110,116,45,109,111,100,117,108,101,45,110, - 97,109,101,44,32,112,97,114,101,110,116,45,112,97,116,104, - 45,97,116,116,114,45,110,97,109,101,41,114,71,0,0,0, - 114,40,0,0,0,41,2,114,8,0,0,0,114,44,0,0, - 0,90,8,95,95,112,97,116,104,95,95,41,2,114,23,1, - 0,0,114,41,0,0,0,41,4,114,119,0,0,0,114,14, - 1,0,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,122,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,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,132,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,136,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,6,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,149,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,152,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,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,155,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,158,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,218,9,95,103,101,116,95,115,112,101,99,23,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,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, + 43,0,0,0,114,57,1,0,0,114,139,0,0,0,114,177, + 0,0,0,114,180,0,0,0,114,21,1,0,0,41,6,114, + 192,0,0,0,114,138,0,0,0,114,43,0,0,0,114,201, + 0,0,0,114,186,0,0,0,114,56,1,0,0,114,3,0, + 0,0,114,3,0,0,0,114,6,0,0,0,114,202,0,0, + 0,55,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,203,0,0,0,114,204,0,0,0,114, + 3,0,0,0,114,3,0,0,0,114,6,0,0,0,114,205, + 0,0,0,79,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,99,3,0,0, + 0,0,0,0,0,0,0,0,0,7,0,0,0,4,0,0, + 0,67,0,0,0,115,78,0,0,0,100,1,100,2,108,0, + 125,3,100,1,100,3,108,1,109,2,125,4,1,0,124,2, + 100,2,107,8,114,34,116,3,106,4,125,2,124,1,100,2, + 107,8,114,46,100,4,110,8,124,3,160,5,124,1,161,1, + 125,5,124,0,160,6,124,5,124,2,161,2,125,6,116,7, + 124,4,124,6,131,2,83,0,41,5,97,37,1,0,0,10, + 32,32,32,32,32,32,32,32,70,105,110,100,32,100,105,115, + 116,114,105,98,117,116,105,111,110,115,46,10,10,32,32,32, + 32,32,32,32,32,82,101,116,117,114,110,32,97,110,32,105, + 116,101,114,97,98,108,101,32,111,102,32,97,108,108,32,68, + 105,115,116,114,105,98,117,116,105,111,110,32,105,110,115,116, + 97,110,99,101,115,32,99,97,112,97,98,108,101,32,111,102, + 10,32,32,32,32,32,32,32,32,108,111,97,100,105,110,103, + 32,116,104,101,32,109,101,116,97,100,97,116,97,32,102,111, + 114,32,112,97,99,107,97,103,101,115,32,109,97,116,99,104, + 105,110,103,32,116,104,101,32,96,96,110,97,109,101,96,96, + 10,32,32,32,32,32,32,32,32,40,111,114,32,97,108,108, + 32,110,97,109,101,115,32,105,102,32,110,111,116,32,115,117, + 112,112,108,105,101,100,41,32,97,108,111,110,103,32,116,104, + 101,32,112,97,116,104,115,32,105,110,32,116,104,101,32,108, + 105,115,116,10,32,32,32,32,32,32,32,32,111,102,32,100, + 105,114,101,99,116,111,114,105,101,115,32,96,96,112,97,116, + 104,96,96,32,40,100,101,102,97,117,108,116,115,32,116,111, + 32,115,121,115,46,112,97,116,104,41,46,10,32,32,32,32, + 32,32,32,32,114,72,0,0,0,78,41,1,218,16,80,97, + 116,104,68,105,115,116,114,105,98,117,116,105,111,110,122,2, + 46,42,41,8,218,2,114,101,90,18,105,109,112,111,114,116, + 108,105,98,46,109,101,116,97,100,97,116,97,114,58,1,0, + 0,114,8,0,0,0,114,43,0,0,0,90,6,101,115,99, + 97,112,101,218,13,95,115,101,97,114,99,104,95,112,97,116, + 104,115,218,3,109,97,112,41,7,114,192,0,0,0,114,116, + 0,0,0,114,43,0,0,0,114,59,1,0,0,114,58,1, + 0,0,218,7,112,97,116,116,101,114,110,90,5,102,111,117, + 110,100,114,3,0,0,0,114,3,0,0,0,114,6,0,0, + 0,218,18,102,105,110,100,95,100,105,115,116,114,105,98,117, + 116,105,111,110,115,92,5,0,0,115,14,0,0,0,0,10, + 8,1,12,1,8,1,6,1,22,1,12,1,122,29,80,97, + 116,104,70,105,110,100,101,114,46,102,105,110,100,95,100,105, + 115,116,114,105,98,117,116,105,111,110,115,99,3,0,0,0, + 0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0, + 3,0,0,0,115,44,0,0,0,100,1,100,2,108,0,125, + 3,124,3,106,1,160,2,135,0,135,1,102,2,100,3,100, + 4,132,8,116,3,136,0,106,4,124,2,131,2,68,0,131, + 1,161,1,83,0,41,5,122,49,70,105,110,100,32,109,101, + 116,97,100,97,116,97,32,100,105,114,101,99,116,111,114,105, + 101,115,32,105,110,32,112,97,116,104,115,32,104,101,117,114, + 105,115,116,105,99,97,108,108,121,46,114,72,0,0,0,78, + 99,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,5,0,0,0,51,0,0,0,115,26,0,0,0,124,0, + 93,18,125,1,136,0,160,0,124,1,136,1,161,2,86,0, + 1,0,113,2,100,0,83,0,114,109,0,0,0,41,1,218, + 12,95,115,101,97,114,99,104,95,112,97,116,104,41,2,114, + 31,0,0,0,114,43,0,0,0,169,2,114,192,0,0,0, + 114,62,1,0,0,114,3,0,0,0,114,6,0,0,0,114, + 18,1,0,0,114,5,0,0,115,4,0,0,0,4,2,2, + 255,122,43,80,97,116,104,70,105,110,100,101,114,46,95,115, + 101,97,114,99,104,95,112,97,116,104,115,46,60,108,111,99, + 97,108,115,62,46,60,103,101,110,101,120,112,114,62,41,5, + 218,9,105,116,101,114,116,111,111,108,115,90,5,99,104,97, + 105,110,90,13,102,114,111,109,95,105,116,101,114,97,98,108, + 101,114,61,1,0,0,218,12,95,115,119,105,116,99,104,95, + 112,97,116,104,41,4,114,192,0,0,0,114,62,1,0,0, + 90,5,112,97,116,104,115,114,66,1,0,0,114,3,0,0, + 0,114,65,1,0,0,114,6,0,0,0,114,60,1,0,0, + 110,5,0,0,115,8,0,0,0,0,3,8,1,18,2,10, + 254,122,24,80,97,116,104,70,105,110,100,101,114,46,95,115, + 101,97,114,99,104,95,112,97,116,104,115,99,1,0,0,0, + 0,0,0,0,0,0,0,0,5,0,0,0,10,0,0,0, + 67,0,0,0,115,96,0,0,0,100,1,100,2,108,0,109, + 1,125,1,1,0,100,1,100,0,108,2,125,2,100,1,100, + 0,108,3,125,3,100,3,125,4,124,4,114,48,116,4,106, + 5,160,6,124,0,161,1,114,86,124,1,116,7,131,1,143, + 24,1,0,124,2,160,8,124,0,161,1,87,0,2,0,53, + 0,81,0,82,0,163,0,83,0,81,0,82,0,88,0,124, + 3,160,8,124,0,161,1,83,0,41,4,78,114,72,0,0, + 0,41,1,218,8,115,117,112,112,114,101,115,115,70,41,9, + 90,10,99,111,110,116,101,120,116,108,105,98,114,68,1,0, + 0,218,7,122,105,112,102,105,108,101,218,7,112,97,116,104, + 108,105,98,90,2,111,115,114,43,0,0,0,90,6,105,115, + 102,105,108,101,218,9,69,120,99,101,112,116,105,111,110,90, + 4,80,97,116,104,41,5,114,43,0,0,0,114,68,1,0, + 0,114,69,1,0,0,114,70,1,0,0,90,13,80,89,80, + 89,95,79,80,69,78,95,66,85,71,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,114,67,1,0,0,119,5, + 0,0,115,16,0,0,0,0,2,12,1,8,1,8,1,4, + 1,16,1,10,1,28,1,122,23,80,97,116,104,70,105,110, + 100,101,114,46,95,115,119,105,116,99,104,95,112,97,116,104, + 99,3,0,0,0,0,0,0,0,0,0,0,0,6,0,0, + 0,5,0,0,0,67,0,0,0,115,44,0,0,0,100,1, + 100,0,108,0,125,3,100,2,125,4,124,4,106,1,124,1, + 100,3,141,1,125,5,124,3,106,2,124,5,124,2,106,3, + 124,3,106,4,100,4,141,3,83,0,41,5,78,114,72,0, + 0,0,122,32,123,112,97,116,116,101,114,110,125,40,45,46, + 42,41,63,92,46,40,100,105,115,116,124,101,103,103,41,45, + 105,110,102,111,169,1,114,62,1,0,0,169,1,114,82,0, + 0,0,41,5,114,59,1,0,0,114,61,0,0,0,90,5, + 109,97,116,99,104,114,116,0,0,0,218,10,73,71,78,79, + 82,69,67,65,83,69,169,6,114,192,0,0,0,218,10,110, + 111,114,109,97,108,105,122,101,100,114,40,1,0,0,114,59, + 1,0,0,90,8,116,101,109,112,108,97,116,101,90,8,109, + 97,110,105,102,101,115,116,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,218,13,95,109,97,116,99,104,101,115, + 95,105,110,102,111,130,5,0,0,115,8,0,0,0,0,2, + 8,1,4,1,12,1,122,24,80,97,116,104,70,105,110,100, + 101,114,46,95,109,97,116,99,104,101,115,95,105,110,102,111, + 99,3,0,0,0,0,0,0,0,0,0,0,0,6,0,0, + 0,5,0,0,0,67,0,0,0,115,46,0,0,0,100,1, + 100,0,108,0,125,3,100,2,125,4,124,4,106,1,124,1, + 100,3,141,1,125,5,124,3,106,2,124,5,116,3,124,2, + 131,1,124,3,106,4,100,4,141,3,83,0,41,5,78,114, + 72,0,0,0,122,30,123,112,97,116,116,101,114,110,125,45, + 46,42,92,46,101,103,103,91,92,92,47,93,69,71,71,45, + 73,78,70,79,114,72,1,0,0,114,73,1,0,0,41,5, + 114,59,1,0,0,114,61,0,0,0,90,6,115,101,97,114, + 99,104,114,84,0,0,0,114,74,1,0,0,114,75,1,0, + 0,114,3,0,0,0,114,3,0,0,0,114,6,0,0,0, + 218,15,95,109,97,116,99,104,101,115,95,108,101,103,97,99, + 121,137,5,0,0,115,8,0,0,0,0,2,8,1,4,1, + 12,1,122,26,80,97,116,104,70,105,110,100,101,114,46,95, + 109,97,116,99,104,101,115,95,108,101,103,97,99,121,99,3, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,4, + 0,0,0,3,0,0,0,115,48,0,0,0,124,1,160,0, + 161,0,115,12,100,1,83,0,124,2,160,1,100,2,100,3, + 161,2,137,1,135,0,135,1,102,2,100,4,100,5,132,8, + 124,1,160,2,161,0,68,0,131,1,83,0,41,6,78,114, + 3,0,0,0,250,1,45,114,44,0,0,0,99,1,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,5,0,0, + 0,51,0,0,0,115,42,0,0,0,124,0,93,34,125,1, + 136,0,160,0,136,1,124,1,161,2,115,30,136,0,160,1, + 136,1,124,1,161,2,114,2,124,1,86,0,1,0,113,2, + 100,0,83,0,114,109,0,0,0,41,2,114,77,1,0,0, + 114,78,1,0,0,41,2,114,31,0,0,0,114,40,1,0, + 0,169,2,114,192,0,0,0,114,76,1,0,0,114,3,0, + 0,0,114,6,0,0,0,114,18,1,0,0,149,5,0,0, + 115,8,0,0,0,4,0,2,1,12,1,12,254,122,42,80, + 97,116,104,70,105,110,100,101,114,46,95,115,101,97,114,99, + 104,95,112,97,116,104,46,60,108,111,99,97,108,115,62,46, + 60,103,101,110,101,120,112,114,62,41,3,90,6,105,115,95, + 100,105,114,114,66,0,0,0,90,7,105,116,101,114,100,105, + 114,41,3,114,192,0,0,0,90,4,114,111,111,116,114,62, + 1,0,0,114,3,0,0,0,114,80,1,0,0,114,6,0, + 0,0,114,64,1,0,0,144,5,0,0,115,8,0,0,0, + 0,2,8,1,4,1,12,1,122,23,80,97,116,104,70,105, + 110,100,101,114,46,95,115,101,97,114,99,104,95,112,97,116, + 104,41,1,78,41,2,78,78,41,1,78,41,2,78,78,41, + 19,114,124,0,0,0,114,123,0,0,0,114,125,0,0,0, + 114,126,0,0,0,114,206,0,0,0,114,45,1,0,0,114, + 51,1,0,0,114,53,1,0,0,114,54,1,0,0,114,57, + 1,0,0,114,202,0,0,0,114,205,0,0,0,114,63,1, + 0,0,114,60,1,0,0,218,12,115,116,97,116,105,99,109, + 101,116,104,111,100,114,67,1,0,0,114,77,1,0,0,114, + 78,1,0,0,114,64,1,0,0,114,3,0,0,0,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,114,44,1, + 0,0,215,4,0,0,115,54,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,12,12,2,1,12,17,2, + 1,10,8,2,1,10,10,2,1,10,6,2,1,10,6,2, + 1,114,44,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,132,8,124,4,68,0,131,1,161,1,1,0, + 113,8,124,3,124,0,95,1,124,1,112,54,100,3,124,0, + 95,2,100,4,124,0,95,3,116,4,131,0,124,0,95,5, + 116,4,131,0,124,0,95,6,100,5,83,0,41,6,122,154, + 73,110,105,116,105,97,108,105,122,101,32,119,105,116,104,32, + 116,104,101,32,112,97,116,104,32,116,111,32,115,101,97,114, + 99,104,32,111,110,32,97,110,100,32,97,32,118,97,114,105, + 97,98,108,101,32,110,117,109,98,101,114,32,111,102,10,32, + 32,32,32,32,32,32,32,50,45,116,117,112,108,101,115,32, + 99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,108, + 111,97,100,101,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,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,109, + 0,0,0,114,3,0,0,0,114,15,1,0,0,169,1,114, + 139,0,0,0,114,3,0,0,0,114,6,0,0,0,114,18, + 1,0,0,169,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,70,0,0,0,114,104,0, + 0,0,78,41,7,114,166,0,0,0,218,8,95,108,111,97, + 100,101,114,115,114,43,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, + 118,0,0,0,114,43,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,188,0,0,0,114,3,0,0,0,114,83,1,0, + 0,114,6,0,0,0,114,208,0,0,0,163,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,104,0,0,0,78,41,1,114,85,1,0, + 0,114,245,0,0,0,114,3,0,0,0,114,3,0,0,0, + 114,6,0,0,0,114,45,1,0,0,177,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,202,0,0,0,114,139,0,0, + 0,114,177,0,0,0,41,3,114,118,0,0,0,114,138,0, + 0,0,114,186,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,114,136,0,0,0,183,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, + 176,0,0,0,41,1,114,189,0,0,0,41,7,114,118,0, + 0,0,114,187,0,0,0,114,138,0,0,0,114,43,0,0, + 0,90,4,115,109,115,108,114,201,0,0,0,114,139,0,0, + 0,114,3,0,0,0,114,3,0,0,0,114,6,0,0,0, + 114,57,1,0,0,195,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,0,0,0,0,14,0,0,0,8,0, + 0,0,67,0,0,0,115,98,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,150,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,82,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,114,224,116, + 15,124,12,131,1,114,224,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,94,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,70,0,0,0,114,27,0,0,0,114,104,0,0,0, + 114,208,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,40,0,0,0, + 114,48,0,0,0,114,43,0,0,0,114,2,0,0,0,114, + 54,0,0,0,114,9,1,0,0,114,49,0,0,0,114,85, + 1,0,0,218,11,95,102,105,108,108,95,99,97,99,104,101, + 114,7,0,0,0,114,88,1,0,0,114,105,0,0,0,114, + 87,1,0,0,114,37,0,0,0,114,84,1,0,0,114,53, + 0,0,0,114,57,1,0,0,114,55,0,0,0,114,133,0, + 0,0,114,148,0,0,0,114,182,0,0,0,114,177,0,0, + 0,41,14,114,118,0,0,0,114,138,0,0,0,114,201,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,168,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,16,1,0,0,114,187,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,186,0,0,0,114,3,0,0,0, + 114,3,0,0,0,114,6,0,0,0,114,202,0,0,0,200, + 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,12,1,8,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,70,0,0,0,114,60,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,105,0,0,0,41,2,114,31,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,21,6, + 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,43,0,0,0,114,2, + 0,0,0,114,6,1,0,0,114,54,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,86,1,0,0,114,87,1,0,0, + 114,100,0,0,0,114,61,0,0,0,114,105,0,0,0,218, + 3,97,100,100,114,11,0,0,0,114,88,1,0,0,41,9, + 114,118,0,0,0,114,43,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,40,1,0,0,114,116,0,0,0, + 114,28,1,0,0,114,16,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,90,1,0,0,248,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, + 32,119,104,105,99,104,32,114,101,116,117,114,110,115,32,97, + 32,99,108,111,115,117,114,101,32,116,111,32,117,115,101,32, + 111,110,32,115,121,115,46,112,97,116,104,95,104,111,111,107, + 10,32,32,32,32,32,32,32,32,119,104,105,99,104,32,119, + 105,108,108,32,114,101,116,117,114,110,32,97,110,32,105,110, + 115,116,97,110,99,101,32,117,115,105,110,103,32,116,104,101, + 32,115,112,101,99,105,102,105,101,100,32,108,111,97,100,101, + 114,115,32,97,110,100,32,116,104,101,32,112,97,116,104,10, + 32,32,32,32,32,32,32,32,99,97,108,108,101,100,32,111, + 110,32,116,104,101,32,99,108,111,115,117,114,101,46,10,10, + 32,32,32,32,32,32,32,32,73,102,32,116,104,101,32,112, + 97,116,104,32,99,97,108,108,101,100,32,111,110,32,116,104, + 101,32,99,108,111,115,117,114,101,32,105,115,32,110,111,116, + 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,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,47,0,0,0,41,2,114,55, + 0,0,0,114,117,0,0,0,114,47,0,0,0,169,2,114, + 192,0,0,0,114,89,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,33,6,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,192,0,0,0, + 114,89,1,0,0,114,96,1,0,0,114,3,0,0,0,114, + 95,1,0,0,114,6,0,0,0,218,9,112,97,116,104,95, + 104,111,111,107,23,6,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,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,161,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,164,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,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,167,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,109, - 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,173,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,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,25,60,109,111,100,117,108, - 101,32,123,33,114,125,32,40,110,97,109,101,115,112,97,99, - 101,41,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,176,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,185,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,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,188,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,191,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, + 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,61,0,0,0,114,43,0, + 0,0,114,245,0,0,0,114,3,0,0,0,114,3,0,0, + 0,114,6,0,0,0,114,38,1,0,0,41,6,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,124,0,0,0,114,123,0,0,0,114,125,0,0,0,114, + 126,0,0,0,114,208,0,0,0,114,45,1,0,0,114,142, + 0,0,0,114,205,0,0,0,114,136,0,0,0,114,57,1, + 0,0,114,202,0,0,0,114,90,1,0,0,114,206,0,0, + 0,114,97,1,0,0,114,38,1,0,0,114,3,0,0,0, 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, - 212,0,0,0,194,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,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,253,0,0,0, - 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,114, - 217,0,0,0,197,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,200,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,172,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,180,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,29,100,11,100,12,132,1,131,1,90, - 9,101,4,100,30,100,13,100,14,132,1,131,1,90,10,101, - 4,100,31,100,15,100,16,132,1,131,1,90,11,101,4,100, - 32,100,17,100,18,132,1,131,1,90,12,101,4,100,19,100, - 20,132,0,131,1,90,13,101,14,100,21,100,22,132,0,131, - 1,90,15,101,4,100,23,100,24,132,0,131,1,90,16,101, - 4,100,25,100,26,132,0,131,1,90,17,101,4,100,27,100, - 28,132,0,131,1,90,18,100,10,83,0,41,33,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,0,113,14,116, - 4,124,2,100,2,131,2,114,14,124,2,160,5,161,0,1, - 0,113,14,100,1,83,0,41,3,122,125,67,97,108,108,32, - 116,104,101,32,105,110,118,97,108,105,100,97,116,101,95,99, - 97,99,104,101,115,40,41,32,109,101,116,104,111,100,32,111, - 110,32,97,108,108,32,112,97,116,104,32,101,110,116,114,121, - 32,102,105,110,100,101,114,115,10,32,32,32,32,32,32,32, - 32,115,116,111,114,101,100,32,105,110,32,115,121,115,46,112, - 97,116,104,95,105,109,112,111,114,116,101,114,95,99,97,99, - 104,101,115,32,40,119,104,101,114,101,32,105,109,112,108,101, - 109,101,110,116,101,100,41,46,78,218,17,105,110,118,97,108, - 105,100,97,116,101,95,99,97,99,104,101,115,41,6,218,4, - 108,105,115,116,114,8,0,0,0,218,19,112,97,116,104,95, - 105,109,112,111,114,116,101,114,95,99,97,99,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,218,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,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,228,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,3,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,241,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,7,5,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,28,113,8,124, - 0,160,3,124,5,161,1,125,6,124,6,100,1,107,9,114, - 8,116,4,124,6,100,2,131,2,114,70,124,6,160,5,124, - 1,124,3,161,2,125,7,110,12,124,0,160,6,124,1,124, - 6,161,2,125,7,124,7,100,1,107,8,114,92,113,8,124, - 7,106,7,100,1,107,9,114,110,124,7,2,0,1,0,83, - 0,124,7,106,8,125,8,124,8,100,1,107,8,114,132,116, - 9,100,3,131,1,130,1,124,4,160,10,124,8,161,1,1, - 0,113,8,116,11,160,12,124,1,100,1,161,2,125,7,124, - 4,124,7,95,8,124,7,83,0,41,4,122,63,70,105,110, - 100,32,116,104,101,32,108,111,97,100,101,114,32,111,114,32, - 110,97,109,101,115,112,97,99,101,95,112,97,116,104,32,102, - 111,114,32,116,104,105,115,32,109,111,100,117,108,101,47,112, - 97,99,107,97,103,101,32,110,97,109,101,46,78,114,203,0, - 0,0,122,19,115,112,101,99,32,109,105,115,115,105,110,103, - 32,108,111,97,100,101,114,41,13,114,161,0,0,0,114,85, - 0,0,0,218,5,98,121,116,101,115,114,54,1,0,0,114, - 128,0,0,0,114,203,0,0,0,114,55,1,0,0,114,140, - 0,0,0,114,178,0,0,0,114,118,0,0,0,114,167,0, - 0,0,114,134,0,0,0,114,183,0,0,0,41,9,114,193, - 0,0,0,114,139,0,0,0,114,44,0,0,0,114,202,0, - 0,0,218,14,110,97,109,101,115,112,97,99,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,22,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,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,54,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,78,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,99,3,0,0,0,0,0,0,0,0,0,0,0,7,0, - 0,0,4,0,0,0,67,0,0,0,115,78,0,0,0,100, - 1,100,2,108,0,125,3,100,1,100,3,108,1,109,2,125, - 4,1,0,124,2,100,2,107,8,114,34,116,3,106,4,125, - 2,124,1,100,2,107,8,114,46,100,4,110,8,124,3,160, - 5,124,1,161,1,125,5,124,0,160,6,124,5,124,2,161, - 2,125,6,116,7,124,4,124,6,131,2,83,0,41,5,97, - 37,1,0,0,10,32,32,32,32,32,32,32,32,70,105,110, - 100,32,100,105,115,116,114,105,98,117,116,105,111,110,115,46, - 10,10,32,32,32,32,32,32,32,32,82,101,116,117,114,110, - 32,97,110,32,105,116,101,114,97,98,108,101,32,111,102,32, - 97,108,108,32,68,105,115,116,114,105,98,117,116,105,111,110, - 32,105,110,115,116,97,110,99,101,115,32,99,97,112,97,98, - 108,101,32,111,102,10,32,32,32,32,32,32,32,32,108,111, - 97,100,105,110,103,32,116,104,101,32,109,101,116,97,100,97, - 116,97,32,102,111,114,32,112,97,99,107,97,103,101,115,32, - 109,97,116,99,104,105,110,103,32,116,104,101,32,96,96,110, - 97,109,101,96,96,10,32,32,32,32,32,32,32,32,40,111, - 114,32,97,108,108,32,110,97,109,101,115,32,105,102,32,110, - 111,116,32,115,117,112,112,108,105,101,100,41,32,97,108,111, - 110,103,32,116,104,101,32,112,97,116,104,115,32,105,110,32, - 116,104,101,32,108,105,115,116,10,32,32,32,32,32,32,32, - 32,111,102,32,100,105,114,101,99,116,111,114,105,101,115,32, - 96,96,112,97,116,104,96,96,32,40,100,101,102,97,117,108, - 116,115,32,116,111,32,115,121,115,46,112,97,116,104,41,46, - 10,32,32,32,32,32,32,32,32,114,73,0,0,0,78,41, - 1,218,16,80,97,116,104,68,105,115,116,114,105,98,117,116, - 105,111,110,122,2,46,42,41,8,218,2,114,101,90,18,105, - 109,112,111,114,116,108,105,98,46,109,101,116,97,100,97,116, - 97,114,59,1,0,0,114,8,0,0,0,114,44,0,0,0, - 90,6,101,115,99,97,112,101,218,13,95,115,101,97,114,99, - 104,95,112,97,116,104,115,218,3,109,97,112,41,7,114,193, - 0,0,0,114,117,0,0,0,114,44,0,0,0,114,60,1, - 0,0,114,59,1,0,0,218,7,112,97,116,116,101,114,110, - 90,5,102,111,117,110,100,114,3,0,0,0,114,3,0,0, - 0,114,6,0,0,0,218,18,102,105,110,100,95,100,105,115, - 116,114,105,98,117,116,105,111,110,115,91,5,0,0,115,14, - 0,0,0,0,10,8,1,12,1,8,1,6,1,22,1,12, - 1,122,29,80,97,116,104,70,105,110,100,101,114,46,102,105, - 110,100,95,100,105,115,116,114,105,98,117,116,105,111,110,115, - 99,3,0,0,0,0,0,0,0,0,0,0,0,4,0,0, - 0,6,0,0,0,3,0,0,0,115,44,0,0,0,100,1, - 100,2,108,0,125,3,124,3,106,1,160,2,135,0,135,1, - 102,2,100,3,100,4,132,8,116,3,136,0,106,4,124,2, - 131,2,68,0,131,1,161,1,83,0,41,5,122,49,70,105, - 110,100,32,109,101,116,97,100,97,116,97,32,100,105,114,101, - 99,116,111,114,105,101,115,32,105,110,32,112,97,116,104,115, - 32,104,101,117,114,105,115,116,105,99,97,108,108,121,46,114, - 73,0,0,0,78,99,1,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,5,0,0,0,51,0,0,0,115,26, - 0,0,0,124,0,93,18,125,1,136,0,160,0,124,1,136, - 1,161,2,86,0,1,0,113,2,100,0,83,0,114,110,0, - 0,0,41,1,218,12,95,115,101,97,114,99,104,95,112,97, - 116,104,41,2,114,32,0,0,0,114,44,0,0,0,169,2, - 114,193,0,0,0,114,63,1,0,0,114,3,0,0,0,114, - 6,0,0,0,114,19,1,0,0,113,5,0,0,115,4,0, - 0,0,4,2,2,255,122,43,80,97,116,104,70,105,110,100, - 101,114,46,95,115,101,97,114,99,104,95,112,97,116,104,115, - 46,60,108,111,99,97,108,115,62,46,60,103,101,110,101,120, - 112,114,62,41,5,218,9,105,116,101,114,116,111,111,108,115, - 90,5,99,104,97,105,110,90,13,102,114,111,109,95,105,116, - 101,114,97,98,108,101,114,62,1,0,0,218,12,95,115,119, - 105,116,99,104,95,112,97,116,104,41,4,114,193,0,0,0, - 114,63,1,0,0,90,5,112,97,116,104,115,114,67,1,0, - 0,114,3,0,0,0,114,66,1,0,0,114,6,0,0,0, - 114,61,1,0,0,109,5,0,0,115,8,0,0,0,0,3, - 8,1,18,2,10,254,122,24,80,97,116,104,70,105,110,100, - 101,114,46,95,115,101,97,114,99,104,95,112,97,116,104,115, - 99,1,0,0,0,0,0,0,0,0,0,0,0,5,0,0, - 0,10,0,0,0,67,0,0,0,115,96,0,0,0,100,1, - 100,2,108,0,109,1,125,1,1,0,100,1,100,0,108,2, - 125,2,100,1,100,0,108,3,125,3,100,3,125,4,124,4, - 114,48,116,4,106,5,160,6,124,0,161,1,114,86,124,1, - 116,7,131,1,143,24,1,0,124,2,160,8,124,0,161,1, - 87,0,2,0,53,0,81,0,82,0,163,0,83,0,81,0, - 82,0,88,0,124,3,160,8,124,0,161,1,83,0,41,4, - 78,114,73,0,0,0,41,1,218,8,115,117,112,112,114,101, - 115,115,70,41,9,90,10,99,111,110,116,101,120,116,108,105, - 98,114,69,1,0,0,218,7,122,105,112,102,105,108,101,218, - 7,112,97,116,104,108,105,98,90,2,111,115,114,44,0,0, - 0,90,6,105,115,102,105,108,101,218,9,69,120,99,101,112, - 116,105,111,110,90,4,80,97,116,104,41,5,114,44,0,0, - 0,114,69,1,0,0,114,70,1,0,0,114,71,1,0,0, - 90,13,80,89,80,89,95,79,80,69,78,95,66,85,71,114, - 3,0,0,0,114,3,0,0,0,114,6,0,0,0,114,68, - 1,0,0,118,5,0,0,115,16,0,0,0,0,2,12,1, - 8,1,8,1,4,1,16,1,10,1,28,1,122,23,80,97, - 116,104,70,105,110,100,101,114,46,95,115,119,105,116,99,104, - 95,112,97,116,104,99,3,0,0,0,0,0,0,0,0,0, - 0,0,6,0,0,0,5,0,0,0,67,0,0,0,115,44, - 0,0,0,100,1,100,0,108,0,125,3,100,2,125,4,124, - 4,106,1,124,1,100,3,141,1,125,5,124,3,106,2,124, - 5,124,2,106,3,124,3,106,4,100,4,141,3,83,0,41, - 5,78,114,73,0,0,0,122,32,123,112,97,116,116,101,114, - 110,125,40,45,46,42,41,63,92,46,40,100,105,115,116,124, - 101,103,103,41,45,105,110,102,111,169,1,114,63,1,0,0, - 169,1,114,83,0,0,0,41,5,114,60,1,0,0,114,62, - 0,0,0,90,5,109,97,116,99,104,114,117,0,0,0,218, - 10,73,71,78,79,82,69,67,65,83,69,169,6,114,193,0, - 0,0,218,10,110,111,114,109,97,108,105,122,101,100,114,41, - 1,0,0,114,60,1,0,0,90,8,116,101,109,112,108,97, - 116,101,90,8,109,97,110,105,102,101,115,116,114,3,0,0, - 0,114,3,0,0,0,114,6,0,0,0,218,13,95,109,97, - 116,99,104,101,115,95,105,110,102,111,129,5,0,0,115,8, - 0,0,0,0,2,8,1,4,1,12,1,122,24,80,97,116, - 104,70,105,110,100,101,114,46,95,109,97,116,99,104,101,115, - 95,105,110,102,111,99,3,0,0,0,0,0,0,0,0,0, - 0,0,6,0,0,0,5,0,0,0,67,0,0,0,115,46, - 0,0,0,100,1,100,0,108,0,125,3,100,2,125,4,124, - 4,106,1,124,1,100,3,141,1,125,5,124,3,106,2,124, - 5,116,3,124,2,131,1,124,3,106,4,100,4,141,3,83, - 0,41,5,78,114,73,0,0,0,122,30,123,112,97,116,116, - 101,114,110,125,45,46,42,92,46,101,103,103,91,92,92,47, - 93,69,71,71,45,73,78,70,79,114,73,1,0,0,114,74, - 1,0,0,41,5,114,60,1,0,0,114,62,0,0,0,90, - 6,115,101,97,114,99,104,114,85,0,0,0,114,75,1,0, - 0,114,76,1,0,0,114,3,0,0,0,114,3,0,0,0, - 114,6,0,0,0,218,15,95,109,97,116,99,104,101,115,95, - 108,101,103,97,99,121,136,5,0,0,115,8,0,0,0,0, - 2,8,1,4,1,12,1,122,26,80,97,116,104,70,105,110, - 100,101,114,46,95,109,97,116,99,104,101,115,95,108,101,103, - 97,99,121,99,3,0,0,0,0,0,0,0,0,0,0,0, - 3,0,0,0,4,0,0,0,3,0,0,0,115,48,0,0, - 0,124,1,160,0,161,0,115,12,100,1,83,0,124,2,160, - 1,100,2,100,3,161,2,137,1,135,0,135,1,102,2,100, - 4,100,5,132,8,124,1,160,2,161,0,68,0,131,1,83, - 0,41,6,78,114,3,0,0,0,250,1,45,114,45,0,0, - 0,99,1,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,5,0,0,0,51,0,0,0,115,42,0,0,0,124, - 0,93,34,125,1,136,0,160,0,136,1,124,1,161,2,115, - 30,136,0,160,1,136,1,124,1,161,2,114,2,124,1,86, - 0,1,0,113,2,100,0,83,0,114,110,0,0,0,41,2, - 114,78,1,0,0,114,79,1,0,0,41,2,114,32,0,0, - 0,114,41,1,0,0,169,2,114,193,0,0,0,114,77,1, - 0,0,114,3,0,0,0,114,6,0,0,0,114,19,1,0, - 0,148,5,0,0,115,8,0,0,0,4,0,2,1,12,1, - 12,254,122,42,80,97,116,104,70,105,110,100,101,114,46,95, - 115,101,97,114,99,104,95,112,97,116,104,46,60,108,111,99, - 97,108,115,62,46,60,103,101,110,101,120,112,114,62,41,3, - 90,6,105,115,95,100,105,114,114,67,0,0,0,90,7,105, - 116,101,114,100,105,114,41,3,114,193,0,0,0,90,4,114, - 111,111,116,114,63,1,0,0,114,3,0,0,0,114,81,1, - 0,0,114,6,0,0,0,114,65,1,0,0,143,5,0,0, - 115,8,0,0,0,0,2,8,1,4,1,12,1,122,23,80, - 97,116,104,70,105,110,100,101,114,46,95,115,101,97,114,99, - 104,95,112,97,116,104,41,1,78,41,2,78,78,41,1,78, - 41,2,78,78,41,19,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,64,1,0,0,114,61,1,0,0,218,12,115,116, - 97,116,105,99,109,101,116,104,111,100,114,68,1,0,0,114, - 78,1,0,0,114,79,1,0,0,114,65,1,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,214,4,0,0,115,54,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,12,12, - 2,1,12,17,2,1,10,8,2,1,10,10,2,1,10,6, - 2,1,10,6,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,132,8,124,4,68,0,131, - 1,161,1,1,0,113,8,124,3,124,0,95,1,124,1,112, - 54,100,3,124,0,95,2,100,4,124,0,95,3,116,4,131, - 0,124,0,95,5,116,4,131,0,124,0,95,6,100,5,83, - 0,41,6,122,154,73,110,105,116,105,97,108,105,122,101,32, - 119,105,116,104,32,116,104,101,32,112,97,116,104,32,116,111, - 32,115,101,97,114,99,104,32,111,110,32,97,110,100,32,97, - 32,118,97,114,105,97,98,108,101,32,110,117,109,98,101,114, - 32,111,102,10,32,32,32,32,32,32,32,32,50,45,116,117, - 112,108,101,115,32,99,111,110,116,97,105,110,105,110,103,32, - 116,104,101,32,108,111,97,100,101,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,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,168,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,84,1,0,0,114,6,0,0,0,114,209,0,0,0, - 162,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,86,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,176, - 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, - 182,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,41,1,114,190,0,0,0, - 41,7,114,119,0,0,0,114,188,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,194,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,0,0,0,0,14, - 0,0,0,8,0,0,0,67,0,0,0,115,98,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,150,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,82,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,114,224,116,15,124,12,131,1,114,224,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,94,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,10,1,0,0,114,50, - 0,0,0,114,86,1,0,0,218,11,95,102,105,108,108,95, - 99,97,99,104,101,114,7,0,0,0,114,89,1,0,0,114, - 106,0,0,0,114,88,1,0,0,114,38,0,0,0,114,85, - 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, + 82,1,0,0,154,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,82,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,83,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,139,0,0,0,114,14,1,0,0,114,8,1, + 0,0,114,189,0,0,0,114,71,1,0,0,41,6,90,2, + 110,115,114,116,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,139,0,0, + 0,114,186,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,47,6,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,101,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,6,102,2,125,2,124, + 0,124,1,124,2,103,3,83,0,41,1,122,95,82,101,116, + 117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,102, + 105,108,101,45,98,97,115,101,100,32,109,111,100,117,108,101, + 32,108,111,97,100,101,114,115,46,10,10,32,32,32,32,69, + 97,99,104,32,105,116,101,109,32,105,115,32,97,32,116,117, + 112,108,101,32,40,108,111,97,100,101,114,44,32,115,117,102, + 102,105,120,101,115,41,46,10,32,32,32,32,41,7,114,251, + 0,0,0,114,162,0,0,0,218,18,101,120,116,101,110,115, + 105,111,110,95,115,117,102,102,105,120,101,115,114,8,1,0, + 0,114,101,0,0,0,114,14,1,0,0,114,88,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, - 203,0,0,0,199,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,12,1,8,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,20,6,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,7,1,0,0,114,55,0, - 0,0,114,3,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,87,1,0,0, - 114,88,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,89, - 1,0,0,41,9,114,119,0,0,0,114,44,0,0,0,114, - 8,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,91,1,0,0,247,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,32,119,104,105,99,104,32,114,101,116,117, - 114,110,115,32,97,32,99,108,111,115,117,114,101,32,116,111, - 32,117,115,101,32,111,110,32,115,121,115,46,112,97,116,104, - 95,104,111,111,107,10,32,32,32,32,32,32,32,32,119,104, - 105,99,104,32,119,105,108,108,32,114,101,116,117,114,110,32, - 97,110,32,105,110,115,116,97,110,99,101,32,117,115,105,110, - 103,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, - 108,111,97,100,101,114,115,32,97,110,100,32,116,104,101,32, - 112,97,116,104,10,32,32,32,32,32,32,32,32,99,97,108, - 108,101,100,32,111,110,32,116,104,101,32,99,108,111,115,117, - 114,101,46,10,10,32,32,32,32,32,32,32,32,73,102,32, - 116,104,101,32,112,97,116,104,32,99,97,108,108,101,100,32, - 111,110,32,116,104,101,32,99,108,111,115,117,114,101,32,105, - 115,32,110,111,116,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,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,90,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,32,6,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,90,1,0,0,114,97,1,0,0,114, - 3,0,0,0,114,96,1,0,0,114,6,0,0,0,218,9, - 112,97,116,104,95,104,111,111,107,22,6,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, - 40,6,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,91,1,0, - 0,114,207,0,0,0,114,98,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,83,1,0,0,153,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,83,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,84,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,15,1, - 0,0,114,9,1,0,0,114,190,0,0,0,114,72,1,0, - 0,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,46,6,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,102,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,6, - 102,2,125,2,124,0,124,1,124,2,103,3,83,0,41,1, - 122,95,82,101,116,117,114,110,115,32,97,32,108,105,115,116, - 32,111,102,32,102,105,108,101,45,98,97,115,101,100,32,109, - 111,100,117,108,101,32,108,111,97,100,101,114,115,46,10,10, - 32,32,32,32,69,97,99,104,32,105,116,101,109,32,105,115, - 32,97,32,116,117,112,108,101,32,40,108,111,97,100,101,114, - 44,32,115,117,102,102,105,120,101,115,41,46,10,32,32,32, - 32,41,7,114,252,0,0,0,114,163,0,0,0,218,18,101, - 120,116,101,110,115,105,111,110,95,115,117,102,102,105,120,101, - 115,114,9,1,0,0,114,102,0,0,0,114,15,1,0,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,69,6,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,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,105,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,92,1,0,0,121,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,103,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,80,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,110,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,1, - 1,0,116,2,106,7,160,8,116,9,161,1,1,0,100,1, - 83,0,41,2,122,41,73,110,115,116,97,108,108,32,116,104, - 101,32,112,97,116,104,45,98,97,115,101,100,32,105,109,112, - 111,114,116,32,99,111,109,112,111,110,101,110,116,115,46,78, - 41,10,114,110,1,0,0,114,184,0,0,0,114,8,0,0, - 0,114,51,1,0,0,114,167,0,0,0,114,83,1,0,0, - 114,98,1,0,0,218,9,109,101,116,97,95,112,97,116,104, - 114,186,0,0,0,114,45,1,0,0,41,2,114,109,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,145,6,0, - 0,115,8,0,0,0,0,2,8,1,6,1,20,1,114,112, - 1,0,0,41,1,114,60,0,0,0,41,1,78,41,3,78, - 78,78,41,2,114,73,0,0,0,114,73,0,0,0,41,1, - 84,41,1,78,41,1,78,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,73,86,69,95,80,76,65,84,70,79,82,77,83, - 95,66,89,84,69,83,95,75,69,89,114,11,0,0,0,114, - 13,0,0,0,114,20,0,0,0,114,27,0,0,0,114,29, - 0,0,0,114,38,0,0,0,114,47,0,0,0,114,49,0, - 0,0,114,53,0,0,0,114,54,0,0,0,114,56,0,0, - 0,114,59,0,0,0,114,69,0,0,0,218,4,116,121,112, - 101,218,8,95,95,99,111,100,101,95,95,114,162,0,0,0, - 114,18,0,0,0,114,148,0,0,0,114,17,0,0,0,114, - 24,0,0,0,114,236,0,0,0,114,92,0,0,0,114,88, - 0,0,0,114,102,0,0,0,114,89,0,0,0,90,23,68, - 69,66,85,71,95,66,89,84,69,67,79,68,69,95,83,85, - 70,70,73,88,69,83,90,27,79,80,84,73,77,73,90,69, - 68,95,66,89,84,69,67,79,68,69,95,83,85,70,70,73, - 88,69,83,114,98,0,0,0,114,103,0,0,0,114,109,0, - 0,0,114,113,0,0,0,114,115,0,0,0,114,136,0,0, - 0,114,143,0,0,0,114,152,0,0,0,114,156,0,0,0, - 114,158,0,0,0,114,165,0,0,0,114,170,0,0,0,114, - 171,0,0,0,114,176,0,0,0,218,6,111,98,106,101,99, - 116,114,185,0,0,0,114,190,0,0,0,114,191,0,0,0, - 114,208,0,0,0,114,221,0,0,0,114,239,0,0,0,114, - 9,1,0,0,114,15,1,0,0,114,21,1,0,0,114,252, - 0,0,0,114,22,1,0,0,114,43,1,0,0,114,45,1, - 0,0,114,83,1,0,0,114,102,1,0,0,114,184,0,0, - 0,114,110,1,0,0,114,112,1,0,0,114,3,0,0,0, - 114,3,0,0,0,114,3,0,0,0,114,6,0,0,0,218, - 8,60,109,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,10,22,10,127,0,13,16,1,12,2,4,1, - 4,2,6,2,6,2,8,2,16,71,8,40,8,19,8,12, - 8,12,8,28,8,17,8,33,8,28,8,24,10,13,10,10, - 10,11,8,14,6,3,4,1,2,255,12,68,14,64,14,29, - 16,127,0,17,14,72,18,45,18,26,4,3,18,53,14,63, - 14,42,14,127,0,68,14,127,0,22,10,23,8,11,8,65, + 183,0,0,0,70,6,0,0,115,8,0,0,0,0,5,12, + 1,8,1,8,1,114,183,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,74,0,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,8,107,10,114,214, + 1,0,1,0,1,0,89,0,113,106,89,0,113,106,88,0, + 113,106,116,8,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,9,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,10,131,0, + 131,3,1,0,116,11,160,12,116,2,160,13,161,0,161,1, + 1,0,124,5,100,4,107,2,144,1,114,174,116,14,160,15, + 100,22,161,1,1,0,100,23,116,11,107,6,144,1,114,174, + 100,24,116,16,95,17,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,63,0, + 0,0,114,74,0,0,0,218,8,98,117,105,108,116,105,110, + 115,114,159,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,38,0,0,0,78,41,1,114,22,0,0,0,41,2, + 114,31,0,0,0,114,94,0,0,0,114,3,0,0,0,114, + 3,0,0,0,114,6,0,0,0,114,18,1,0,0,106,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,72,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,34,0,0,0,114,30,0,0,0,114,39,0,0,0,114, + 57,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,73,0,0,0,114, + 3,0,0,0,41,2,114,31,0,0,0,218,1,115,114,3, + 0,0,0,114,3,0,0,0,114,6,0,0,0,114,91,1, + 0,0,122,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,191,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, + 18,114,133,0,0,0,114,8,0,0,0,114,162,0,0,0, + 114,30,1,0,0,114,124,0,0,0,90,18,95,98,117,105, + 108,116,105,110,95,102,114,111,109,95,110,97,109,101,114,128, + 0,0,0,218,3,97,108,108,114,117,0,0,0,114,35,0, + 0,0,114,13,0,0,0,114,20,1,0,0,114,166,0,0, + 0,114,102,1,0,0,114,101,0,0,0,114,185,0,0,0, + 114,190,0,0,0,114,194,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,30,0,0,0,114,34,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,81,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,109,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,1,1,0,116,2,106,7,160,8,116,9, + 161,1,1,0,100,1,83,0,41,2,122,41,73,110,115,116, + 97,108,108,32,116,104,101,32,112,97,116,104,45,98,97,115, + 101,100,32,105,109,112,111,114,116,32,99,111,109,112,111,110, + 101,110,116,115,46,78,41,10,114,109,1,0,0,114,183,0, + 0,0,114,8,0,0,0,114,50,1,0,0,114,166,0,0, + 0,114,82,1,0,0,114,97,1,0,0,218,9,109,101,116, + 97,95,112,97,116,104,114,185,0,0,0,114,44,1,0,0, + 41,2,114,108,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,146,6,0,0,115,8,0,0,0,0,2,8,1, + 6,1,20,1,114,111,1,0,0,41,1,114,59,0,0,0, + 41,1,78,41,3,78,78,78,41,2,114,72,0,0,0,114, + 72,0,0,0,41,1,84,41,1,78,41,1,78,41,63,114, + 126,0,0,0,114,12,0,0,0,90,37,95,67,65,83,69, + 95,73,78,83,69,78,83,73,84,73,86,69,95,80,76,65, + 84,70,79,82,77,83,95,66,89,84,69,83,95,75,69,89, + 114,11,0,0,0,114,13,0,0,0,114,20,0,0,0,114, + 26,0,0,0,114,28,0,0,0,114,37,0,0,0,114,46, + 0,0,0,114,48,0,0,0,114,52,0,0,0,114,53,0, + 0,0,114,55,0,0,0,114,58,0,0,0,114,68,0,0, + 0,218,4,116,121,112,101,218,8,95,95,99,111,100,101,95, + 95,114,161,0,0,0,114,18,0,0,0,114,147,0,0,0, + 114,17,0,0,0,114,23,0,0,0,114,235,0,0,0,114, + 91,0,0,0,114,87,0,0,0,114,101,0,0,0,114,88, + 0,0,0,90,23,68,69,66,85,71,95,66,89,84,69,67, + 79,68,69,95,83,85,70,70,73,88,69,83,90,27,79,80, + 84,73,77,73,90,69,68,95,66,89,84,69,67,79,68,69, + 95,83,85,70,70,73,88,69,83,114,97,0,0,0,114,102, + 0,0,0,114,108,0,0,0,114,112,0,0,0,114,114,0, + 0,0,114,135,0,0,0,114,142,0,0,0,114,151,0,0, + 0,114,155,0,0,0,114,157,0,0,0,114,164,0,0,0, + 114,169,0,0,0,114,170,0,0,0,114,175,0,0,0,218, + 6,111,98,106,101,99,116,114,184,0,0,0,114,189,0,0, + 0,114,190,0,0,0,114,207,0,0,0,114,220,0,0,0, + 114,238,0,0,0,114,8,1,0,0,114,14,1,0,0,114, + 20,1,0,0,114,251,0,0,0,114,21,1,0,0,114,42, + 1,0,0,114,44,1,0,0,114,82,1,0,0,114,101,1, + 0,0,114,183,0,0,0,114,109,1,0,0,114,111,1,0, + 0,114,3,0,0,0,114,3,0,0,0,114,3,0,0,0, + 114,6,0,0,0,218,8,60,109,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,10,22,10,127,0,14, + 16,1,12,2,4,1,4,2,6,2,6,2,8,2,16,71, + 8,40,8,19,8,12,8,12,8,28,8,17,8,33,8,28, + 8,24,10,13,10,10,10,11,8,14,6,3,4,1,2,255, + 12,68,14,64,14,29,16,127,0,17,14,72,18,45,18,26, + 4,3,18,53,14,63,14,42,14,127,0,68,14,127,0,22, + 10,23,8,11,8,65, }; diff --git a/Python/importlib_zipimport.h b/Python/importlib_zipimport.h index 6c9c4e846552..2d10c8c9cf90 100644 --- a/Python/importlib_zipimport.h +++ b/Python/importlib_zipimport.h @@ -879,17 +879,16 @@ const unsigned char _Py_M__zipimport[] = { 10,1,2,0,2,0,2,249,114,169,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,100,0,133,2,25,0,100,2,107,6,115,22,74,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, + 0,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, + 1,124,4,124,3,131,2,124,5,102,2,87,0,83,0,4, + 0,116,2,116,3,116,4,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, 163,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, + 114,0,0,0,0,114,0,0,0,0,41,5,114,28,0,0, 0,114,169,0,0,0,114,26,0,0,0,218,10,73,110,100, 101,120,69,114,114,111,114,114,154,0,0,0,41,6,114,32, 0,0,0,114,13,0,0,0,114,54,0,0,0,114,131,0, @@ -900,184 +899,183 @@ const unsigned char _Py_M__zipimport[] = { 3,8,1,8,1,8,1,16,1,20,1,114,151,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, + 100,1,100,0,133,2,25,0,100,2,107,6,115,20,74,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, + 124,0,106,0,124,1,25,0,125,2,87,0,110,22,4,0, + 116,1,107,10,114,68,1,0,1,0,1,0,89,0,100,0, + 83,0,88,0,116,2,124,0,106,3,124,2,131,2,83,0, 100,0,83,0,41,3,78,114,14,0,0,0,114,170,0,0, - 0,41,5,114,175,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,149,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,149,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, - 1,124,0,106,4,116,5,124,6,100,2,100,3,141,5,1, - 0,122,14,124,0,106,6,124,6,25,0,125,7,87,0,110, - 20,4,0,116,7,107,10,114,88,1,0,1,0,1,0,89, - 0,113,14,88,0,124,7,100,4,25,0,125,8,116,8,124, - 0,106,4,124,7,131,2,125,9,124,4,114,132,116,9,124, - 0,124,8,124,6,124,1,124,9,131,5,125,10,110,10,116, - 10,124,8,124,9,131,2,125,10,124,10,100,0,107,8,114, - 152,113,14,124,7,100,4,25,0,125,8,124,10,124,5,124, - 8,102,3,2,0,1,0,83,0,113,14,116,11,100,5,124, - 1,155,2,157,2,124,1,100,6,141,2,130,1,100,0,83, - 0,41,7,78,122,13,116,114,121,105,110,103,32,123,125,123, - 125,123,125,114,86,0,0,0,41,1,90,9,118,101,114,98, - 111,115,105,116,121,114,0,0,0,0,114,57,0,0,0,114, - 58,0,0,0,41,12,114,36,0,0,0,114,89,0,0,0, - 114,76,0,0,0,114,77,0,0,0,114,29,0,0,0,114, - 20,0,0,0,114,28,0,0,0,114,26,0,0,0,114,52, - 0,0,0,114,155,0,0,0,114,161,0,0,0,114,3,0, - 0,0,41,11,114,32,0,0,0,114,38,0,0,0,114,13, - 0,0,0,114,90,0,0,0,114,91,0,0,0,114,47,0, - 0,0,114,63,0,0,0,114,54,0,0,0,114,40,0,0, - 0,114,126,0,0,0,114,46,0,0,0,114,9,0,0,0, - 114,9,0,0,0,114,10,0,0,0,114,44,0,0,0,186, - 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,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,109,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,177,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,177,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,178,0,0,0,41,2,114,32,0,0,0,114, - 179,0,0,0,114,9,0,0,0,114,9,0,0,0,114,10, - 0,0,0,218,13,114,101,115,111,117,114,99,101,95,112,97, - 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,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,109,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,180,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,184,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,175,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,184,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, + 0,41,4,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,149,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,149,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,1,124,0,106,4, + 116,5,124,6,100,2,100,3,141,5,1,0,122,14,124,0, + 106,6,124,6,25,0,125,7,87,0,110,20,4,0,116,7, + 107,10,114,88,1,0,1,0,1,0,89,0,113,14,88,0, + 124,7,100,4,25,0,125,8,116,8,124,0,106,4,124,7, + 131,2,125,9,124,4,114,132,116,9,124,0,124,8,124,6, + 124,1,124,9,131,5,125,10,110,10,116,10,124,8,124,9, + 131,2,125,10,124,10,100,0,107,8,114,152,113,14,124,7, + 100,4,25,0,125,8,124,10,124,5,124,8,102,3,2,0, + 1,0,83,0,113,14,116,11,100,5,124,1,155,2,157,2, + 124,1,100,6,141,2,130,1,100,0,83,0,41,7,78,122, + 13,116,114,121,105,110,103,32,123,125,123,125,123,125,114,86, + 0,0,0,41,1,90,9,118,101,114,98,111,115,105,116,121, + 114,0,0,0,0,114,57,0,0,0,114,58,0,0,0,41, + 12,114,36,0,0,0,114,89,0,0,0,114,76,0,0,0, + 114,77,0,0,0,114,29,0,0,0,114,20,0,0,0,114, + 28,0,0,0,114,26,0,0,0,114,52,0,0,0,114,155, + 0,0,0,114,161,0,0,0,114,3,0,0,0,41,11,114, + 32,0,0,0,114,38,0,0,0,114,13,0,0,0,114,90, + 0,0,0,114,91,0,0,0,114,47,0,0,0,114,63,0, + 0,0,114,54,0,0,0,114,40,0,0,0,114,126,0,0, + 0,114,46,0,0,0,114,9,0,0,0,114,9,0,0,0, + 114,10,0,0,0,114,44,0,0,0,186,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,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,109,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,176,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, + 176,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,177, + 0,0,0,41,2,114,32,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, + 114,101,115,111,117,114,99,101,95,112,97,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,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,181,0,0, - 0,114,182,0,0,0,114,183,0,0,0,114,188,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, - 148,0,0,0,114,110,0,0,0,114,152,0,0,0,114,67, - 0,0,0,114,131,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,113,0,0,0,114,115,0,0,0, - 114,117,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,122,0,0,0,114,142,0,0,0,114,144,0, - 0,0,114,52,0,0,0,114,147,0,0,0,114,155,0,0, - 0,218,8,95,95,99,111,100,101,95,95,114,153,0,0,0, - 114,159,0,0,0,114,161,0,0,0,114,169,0,0,0,114, - 151,0,0,0,114,149,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, + 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,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,109, + 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,179,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,74,0,130,1,124,3,106,8,125,4,116,9,131, + 0,125,5,124,0,106,2,106,10,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,11,107,10,114,124,1,0,1,0,1, + 0,89,0,113,78,89,0,110,2,88,0,124,7,106,8,106, + 7,125,8,116,12,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,13,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,14,90,7, + 112,97,116,104,108,105,98,114,183,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,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,183,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,180,0,0,0,114,181,0,0,0,114,182,0,0, + 0,114,187,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,148,0,0,0,114,110,0,0,0,114, + 152,0,0,0,114,67,0,0,0,114,131,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,113,0,0, + 0,114,115,0,0,0,114,117,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,122,0,0,0,114,142, + 0,0,0,114,144,0,0,0,114,52,0,0,0,114,147,0, + 0,0,114,155,0,0,0,218,8,95,95,99,111,100,101,95, + 95,114,153,0,0,0,114,159,0,0,0,114,161,0,0,0, + 114,169,0,0,0,114,151,0,0,0,114,149,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/opcode_targets.h b/Python/opcode_targets.h index e82959be0864..d39bad0bcd3b 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -73,7 +73,7 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_BUILD_CLASS, &&TARGET_YIELD_FROM, &&TARGET_GET_AWAITABLE, - &&_unknown_opcode, + &&TARGET_LOAD_ASSERTION_ERROR, &&TARGET_INPLACE_LSHIFT, &&TARGET_INPLACE_RSHIFT, &&TARGET_INPLACE_AND, From webhook-mailer at python.org Sun Aug 25 09:45:44 2019 From: webhook-mailer at python.org (Nick Coghlan) Date: Sun, 25 Aug 2019 13:45:44 -0000 Subject: [Python-checkins] bpo-37757: Disallow PEP 572 cases that expose implementation details (GH-15131) Message-ID: https://github.com/python/cpython/commit/5dbe0f59b7a4f39c7c606b48056bc29e406ebf78 commit: 5dbe0f59b7a4f39c7c606b48056bc29e406ebf78 branch: master author: Nick Coghlan committer: GitHub date: 2019-08-25T23:45:40+10:00 summary: bpo-37757: Disallow PEP 572 cases that expose implementation details (GH-15131) - drop TargetScopeError in favour of raising SyntaxError directly as per the updated PEP 572 - comprehension iteration variables are explicitly local, but named expression targets in comprehensions are nonlocal or global. Raise SyntaxError as specified in PEP 572 - named expression targets in the outermost iterable of a comprehension have an ambiguous target scope. Avoid resolving that question now by raising SyntaxError. PEP 572 originally required this only for cases where the bound name conflicts with the iteration variable in the comprehension, but CPython can't easily restrict the exception to that case (as it doesn't know the target variable names when visiting the outermost iterator expression) files: A Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757.lRv5HX.rst M Doc/c-api/exceptions.rst M Include/pyerrors.h M Include/symtable.h M Lib/_compat_pickle.py M Lib/test/exception_hierarchy.txt M Lib/test/test_named_expressions.py M Objects/exceptions.c M PC/python3.def M Python/symtable.c diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index d8173935596b..25bb657dca0e 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -809,7 +809,6 @@ the variables: single: PyExc_SystemError single: PyExc_SystemExit single: PyExc_TabError - single: PyExc_TargetScopeError single: PyExc_TimeoutError single: PyExc_TypeError single: PyExc_UnboundLocalError @@ -911,8 +910,6 @@ the variables: +-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_TabError` | :exc:`TabError` | | +-----------------------------------------+---------------------------------+----------+ -| :c:data:`PyExc_TargetScopeError` | :exc:`TargetScopeError` | | -+-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_TimeoutError` | :exc:`TimeoutError` | | +-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_TypeError` | :exc:`TypeError` | | diff --git a/Include/pyerrors.h b/Include/pyerrors.h index 94af3cb3420e..5125a51ec1aa 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -97,7 +97,6 @@ PyAPI_DATA(PyObject *) PyExc_NotImplementedError; PyAPI_DATA(PyObject *) PyExc_SyntaxError; PyAPI_DATA(PyObject *) PyExc_IndentationError; PyAPI_DATA(PyObject *) PyExc_TabError; -PyAPI_DATA(PyObject *) PyExc_TargetScopeError; PyAPI_DATA(PyObject *) PyExc_ReferenceError; PyAPI_DATA(PyObject *) PyExc_SystemError; PyAPI_DATA(PyObject *) PyExc_SystemExit; diff --git a/Include/symtable.h b/Include/symtable.h index 9392e6438779..5dcfa7e2c2bb 100644 --- a/Include/symtable.h +++ b/Include/symtable.h @@ -58,6 +58,8 @@ typedef struct _symtable_entry { unsigned ste_needs_class_closure : 1; /* for class scopes, true if a closure over __class__ should be created */ + unsigned ste_comp_iter_target : 1; /* true if visiting comprehension target */ + int ste_comp_iter_expr; /* non-zero if visiting a comprehension range expression */ int ste_lineno; /* first line of block */ int ste_col_offset; /* offset of first line of block */ int ste_opt_lineno; /* lineno of last exec or import * */ @@ -94,6 +96,7 @@ PyAPI_FUNC(void) PySymtable_Free(struct symtable *); #define DEF_FREE_CLASS 2<<5 /* free variable from class's method */ #define DEF_IMPORT 2<<6 /* assignment occurred via import */ #define DEF_ANNOT 2<<7 /* this name is annotated */ +#define DEF_COMP_ITER 2<<8 /* this name is a comprehension iteration variable */ #define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT) diff --git a/Lib/_compat_pickle.py b/Lib/_compat_pickle.py index 8bb1cf80afa5..f68496ae639f 100644 --- a/Lib/_compat_pickle.py +++ b/Lib/_compat_pickle.py @@ -128,7 +128,6 @@ "SystemError", "SystemExit", "TabError", - "TargetScopeError", "TypeError", "UnboundLocalError", "UnicodeDecodeError", diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt index 15f4491cf237..763a6c899b48 100644 --- a/Lib/test/exception_hierarchy.txt +++ b/Lib/test/exception_hierarchy.txt @@ -42,7 +42,6 @@ BaseException | +-- NotImplementedError | +-- RecursionError +-- SyntaxError - | +-- TargetScopeError | +-- IndentationError | +-- TabError +-- SystemError diff --git a/Lib/test/test_named_expressions.py b/Lib/test/test_named_expressions.py index f73e6fee70ce..b1027ce78006 100644 --- a/Lib/test/test_named_expressions.py +++ b/Lib/test/test_named_expressions.py @@ -104,15 +104,69 @@ def test_named_expression_invalid_17(self): with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) - def test_named_expression_invalid_18(self): + def test_named_expression_invalid_in_class_body(self): code = """class Foo(): [(42, 1 + ((( j := i )))) for i in range(5)] """ - with self.assertRaisesRegex(TargetScopeError, - "named expression within a comprehension cannot be used in a class body"): + with self.assertRaisesRegex(SyntaxError, + "assignment expression within a comprehension cannot be used in a class body"): exec(code, {}, {}) + def test_named_expression_invalid_rebinding_comprehension_iteration_variable(self): + cases = [ + ("Local reuse", 'i', "[i := 0 for i in range(5)]"), + ("Nested reuse", 'j', "[[(j := 0) for i in range(5)] for j in range(5)]"), + ("Reuse inner loop target", 'j', "[(j := 0) for i in range(5) for j in range(5)]"), + ("Unpacking reuse", 'i', "[i := 0 for i, j in [(0, 1)]]"), + ("Reuse in loop condition", 'i', "[i+1 for i in range(5) if (i := 0)]"), + ("Unreachable reuse", 'i', "[False or (i:=0) for i in range(5)]"), + ("Unreachable nested reuse", 'i', + "[(i, j) for i in range(5) for j in range(5) if True or (i:=10)]"), + ] + for case, target, code in cases: + msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'" + with self.subTest(case=case): + with self.assertRaisesRegex(SyntaxError, msg): + exec(code, {}, {}) + + def test_named_expression_invalid_rebinding_comprehension_inner_loop(self): + cases = [ + ("Inner reuse", 'j', "[i for i in range(5) if (j := 0) for j in range(5)]"), + ("Inner unpacking reuse", 'j', "[i for i in range(5) if (j := 0) for j, k in [(0, 1)]]"), + ] + for case, target, code in cases: + msg = f"comprehension inner loop cannot rebind assignment expression target '{target}'" + with self.subTest(case=case): + with self.assertRaisesRegex(SyntaxError, msg): + exec(code, {}) # Module scope + with self.assertRaisesRegex(SyntaxError, msg): + exec(code, {}, {}) # Class scope + with self.assertRaisesRegex(SyntaxError, msg): + exec(f"lambda: {code}", {}) # Function scope + + def test_named_expression_invalid_comprehension_iterable_expression(self): + cases = [ + ("Top level", "[i for i in (i := range(5))]"), + ("Inside tuple", "[i for i in (2, 3, i := range(5))]"), + ("Inside list", "[i for i in [2, 3, i := range(5)]]"), + ("Different name", "[i for i in (j := range(5))]"), + ("Lambda expression", "[i for i in (lambda:(j := range(5)))()]"), + ("Inner loop", "[i for i in range(5) for j in (i := range(5))]"), + ("Nested comprehension", "[i for i in [j for j in (k := range(5))]]"), + ("Nested comprehension condition", "[i for i in [j for j in range(5) if (j := True)]]"), + ("Nested comprehension body", "[i for i in [(j := True) for j in range(5)]]"), + ] + msg = "assignment expression cannot be used in a comprehension iterable expression" + for case, code in cases: + with self.subTest(case=case): + with self.assertRaisesRegex(SyntaxError, msg): + exec(code, {}) # Module scope + with self.assertRaisesRegex(SyntaxError, msg): + exec(code, {}, {}) # Class scope + with self.assertRaisesRegex(SyntaxError, msg): + exec(f"lambda: {code}", {}) # Function scope + class NamedExpressionAssignmentTest(unittest.TestCase): @@ -306,39 +360,6 @@ def test_named_expression_scope_11(self): self.assertEqual(res, [0, 1, 2, 3, 4]) self.assertEqual(j, 4) - def test_named_expression_scope_12(self): - res = [i := i for i in range(5)] - - self.assertEqual(res, [0, 1, 2, 3, 4]) - self.assertEqual(i, 4) - - def test_named_expression_scope_13(self): - res = [i := 0 for i, j in [(1, 2), (3, 4)]] - - self.assertEqual(res, [0, 0]) - self.assertEqual(i, 0) - - def test_named_expression_scope_14(self): - res = [(i := 0, j := 1) for i, j in [(1, 2), (3, 4)]] - - self.assertEqual(res, [(0, 1), (0, 1)]) - self.assertEqual(i, 0) - self.assertEqual(j, 1) - - def test_named_expression_scope_15(self): - res = [(i := i, j := j) for i, j in [(1, 2), (3, 4)]] - - self.assertEqual(res, [(1, 2), (3, 4)]) - self.assertEqual(i, 3) - self.assertEqual(j, 4) - - def test_named_expression_scope_16(self): - res = [(i := j, j := i) for i, j in [(1, 2), (3, 4)]] - - self.assertEqual(res, [(2, 2), (4, 4)]) - self.assertEqual(i, 4) - self.assertEqual(j, 4) - def test_named_expression_scope_17(self): b = 0 res = [b := i + b for i in range(5)] @@ -421,6 +442,33 @@ def spam(): self.assertEqual(ns["a"], 20) + def test_named_expression_variable_reuse_in_comprehensions(self): + # The compiler is expected to raise syntax error for comprehension + # iteration variables, but should be fine with rebinding of other + # names (e.g. globals, nonlocals, other assignment expressions) + + # The cases are all defined to produce the same expected result + # Each comprehension is checked at both function scope and module scope + rebinding = "[x := i for i in range(3) if (x := i) or not x]" + filter_ref = "[x := i for i in range(3) if x or not x]" + body_ref = "[x for i in range(3) if (x := i) or not x]" + nested_ref = "[j for i in range(3) if x or not x for j in range(3) if (x := i)][:-3]" + cases = [ + ("Rebind global", f"x = 1; result = {rebinding}"), + ("Rebind nonlocal", f"result, x = (lambda x=1: ({rebinding}, x))()"), + ("Filter global", f"x = 1; result = {filter_ref}"), + ("Filter nonlocal", f"result, x = (lambda x=1: ({filter_ref}, x))()"), + ("Body global", f"x = 1; result = {body_ref}"), + ("Body nonlocal", f"result, x = (lambda x=1: ({body_ref}, x))()"), + ("Nested global", f"x = 1; result = {nested_ref}"), + ("Nested nonlocal", f"result, x = (lambda x=1: ({nested_ref}, x))()"), + ] + for case, code in cases: + with self.subTest(case=case): + ns = {} + exec(code, ns) + self.assertEqual(ns["x"], 2) + self.assertEqual(ns["result"], [0, 1, 2]) if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757.lRv5HX.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757.lRv5HX.rst new file mode 100644 index 000000000000..258df0dc09bd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757.lRv5HX.rst @@ -0,0 +1,7 @@ +:pep:`572`: As described in the PEP, assignment expressions now raise +:exc:`SyntaxError` when their interaction with comprehension scoping results +in an ambiguous target scope. + +The ``TargetScopeError`` subclass originally proposed by the PEP has been +removed in favour of just raising regular syntax errors for the disallowed +cases. diff --git a/Objects/exceptions.c b/Objects/exceptions.c index ef9dd512dc9c..631f5375f738 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -1521,13 +1521,6 @@ MiddlingExtendsException(PyExc_SyntaxError, IndentationError, SyntaxError, "Improper indentation."); -/* - * TargetScopeError extends SyntaxError - */ -MiddlingExtendsException(PyExc_SyntaxError, TargetScopeError, SyntaxError, - "Improper scope target."); - - /* * TabError extends IndentationError */ @@ -2539,7 +2532,6 @@ _PyExc_Init(void) PRE_INIT(AttributeError); PRE_INIT(SyntaxError); PRE_INIT(IndentationError); - PRE_INIT(TargetScopeError); PRE_INIT(TabError); PRE_INIT(LookupError); PRE_INIT(IndexError); @@ -2680,7 +2672,6 @@ _PyBuiltins_AddExceptions(PyObject *bltinmod) POST_INIT(AttributeError); POST_INIT(SyntaxError); POST_INIT(IndentationError); - POST_INIT(TargetScopeError); POST_INIT(TabError); POST_INIT(LookupError); POST_INIT(IndexError); diff --git a/PC/python3.def b/PC/python3.def index 6844cf1f3b8e..1f355bffc9bd 100644 --- a/PC/python3.def +++ b/PC/python3.def @@ -235,7 +235,6 @@ EXPORTS PyExc_SystemError=python39.PyExc_SystemError DATA PyExc_SystemExit=python39.PyExc_SystemExit DATA PyExc_TabError=python39.PyExc_TabError DATA - PyExc_TargetScopeError=python39.PyExc_TargetScopeError DATA PyExc_TimeoutError=python39.PyExc_TimeoutError DATA PyExc_TypeError=python39.PyExc_TypeError DATA PyExc_UnboundLocalError=python39.PyExc_UnboundLocalError DATA diff --git a/Python/symtable.c b/Python/symtable.c index 668cc21b2df9..e48baa808d41 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -32,7 +32,16 @@ #define IMPORT_STAR_WARNING "import * only allowed at module level" #define NAMED_EXPR_COMP_IN_CLASS \ -"named expression within a comprehension cannot be used in a class body" +"assignment expression within a comprehension cannot be used in a class body" + +#define NAMED_EXPR_COMP_CONFLICT \ +"assignment expression cannot rebind comprehension iteration variable '%U'" + +#define NAMED_EXPR_COMP_INNER_LOOP_CONFLICT \ +"comprehension inner loop cannot rebind assignment expression target '%U'" + +#define NAMED_EXPR_COMP_ITER_EXPR \ +"assignment expression cannot be used in a comprehension iterable expression" static PySTEntryObject * ste_new(struct symtable *st, identifier name, _Py_block_ty block, @@ -81,6 +90,8 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_comprehension = 0; ste->ste_returns_value = 0; ste->ste_needs_class_closure = 0; + ste->ste_comp_iter_target = 0; + ste->ste_comp_iter_expr = 0; ste->ste_symbols = PyDict_New(); ste->ste_varnames = PyList_New(0); @@ -373,14 +384,21 @@ PySymtable_Lookup(struct symtable *st, void *key) return (PySTEntryObject *)v; } -int -PyST_GetScope(PySTEntryObject *ste, PyObject *name) +static long +_PyST_GetSymbol(PySTEntryObject *ste, PyObject *name) { PyObject *v = PyDict_GetItem(ste->ste_symbols, name); if (!v) return 0; assert(PyLong_Check(v)); - return (PyLong_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK; + return PyLong_AS_LONG(v); +} + +int +PyST_GetScope(PySTEntryObject *ste, PyObject *name) +{ + long symbol = _PyST_GetSymbol(ste, name); + return (symbol >> SCOPE_OFFSET) & SCOPE_MASK; } static int @@ -955,6 +973,13 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, return 0; } prev = st->st_cur; + /* bpo-37757: For now, disallow *all* assignment expressions in the + * outermost iterator expression of a comprehension, even those inside + * a nested comprehension or a lambda expression. + */ + if (prev) { + ste->ste_comp_iter_expr = prev->ste_comp_iter_expr; + } /* The entry is owned by the stack. Borrow it for st_cur. */ Py_DECREF(ste); st->st_cur = ste; @@ -971,15 +996,10 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, static long symtable_lookup(struct symtable *st, PyObject *name) { - PyObject *o; PyObject *mangled = _Py_Mangle(st->st_private, name); if (!mangled) return 0; - o = PyDict_GetItem(st->st_cur->ste_symbols, mangled); - Py_DECREF(mangled); - if (!o) - return 0; - return PyLong_AsLong(o); + return _PyST_GetSymbol(st->st_cur, mangled); } static int @@ -1012,6 +1032,22 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s else { val = flag; } + if (ste->ste_comp_iter_target) { + /* This name is an iteration variable in a comprehension, + * so check for a binding conflict with any named expressions. + * Otherwise, mark it as an iteration variable so subsequent + * named expressions can check for conflicts. + */ + if (val & (DEF_GLOBAL | DEF_NONLOCAL)) { + PyErr_Format(PyExc_SyntaxError, + NAMED_EXPR_COMP_INNER_LOOP_CONFLICT, name); + PyErr_SyntaxLocationObject(st->st_filename, + ste->ste_lineno, + ste->ste_col_offset + 1); + goto error; + } + val |= DEF_COMP_ITER; + } o = PyLong_FromLong(val); if (o == NULL) goto error; @@ -1392,7 +1428,9 @@ static int symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) { assert(st->st_stack); + assert(e->kind == Name_kind); + PyObject *target_name = e->v.Name.id; Py_ssize_t i, size; struct _symtable_entry *ste; size = PyList_GET_SIZE(st->st_stack); @@ -1402,32 +1440,42 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) for (i = size - 1; i >= 0; i--) { ste = (struct _symtable_entry *) PyList_GET_ITEM(st->st_stack, i); - /* If our current entry is a comprehension, skip it */ + /* If we find a comprehension scope, check for a target + * binding conflict with iteration variables, otherwise skip it + */ if (ste->ste_comprehension) { + long target_in_scope = _PyST_GetSymbol(ste, target_name); + if (target_in_scope & DEF_COMP_ITER) { + PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_CONFLICT, target_name); + PyErr_SyntaxLocationObject(st->st_filename, + e->lineno, + e->col_offset); + VISIT_QUIT(st, 0); + } continue; } /* If we find a FunctionBlock entry, add as NONLOCAL/LOCAL */ if (ste->ste_type == FunctionBlock) { - if (!symtable_add_def(st, e->v.Name.id, DEF_NONLOCAL)) + if (!symtable_add_def(st, target_name, DEF_NONLOCAL)) VISIT_QUIT(st, 0); - if (!symtable_record_directive(st, e->v.Name.id, e->lineno, e->col_offset)) + if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset)) VISIT_QUIT(st, 0); - return symtable_add_def_helper(st, e->v.Name.id, DEF_LOCAL, ste); + return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste); } /* If we find a ModuleBlock entry, add as GLOBAL */ if (ste->ste_type == ModuleBlock) { - if (!symtable_add_def(st, e->v.Name.id, DEF_GLOBAL)) + if (!symtable_add_def(st, target_name, DEF_GLOBAL)) VISIT_QUIT(st, 0); - if (!symtable_record_directive(st, e->v.Name.id, e->lineno, e->col_offset)) + if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset)) VISIT_QUIT(st, 0); - return symtable_add_def_helper(st, e->v.Name.id, DEF_GLOBAL, ste); + return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste); } /* Disallow usage in ClassBlock */ if (ste->ste_type == ClassBlock) { - PyErr_Format(PyExc_TargetScopeError, NAMED_EXPR_COMP_IN_CLASS, e->v.Name.id); + PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_CLASS); PyErr_SyntaxLocationObject(st->st_filename, e->lineno, e->col_offset); @@ -1442,6 +1490,26 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) return 0; } +static int +symtable_handle_namedexpr(struct symtable *st, expr_ty e) +{ + if (st->st_cur->ste_comp_iter_expr > 0) { + /* Assignment isn't allowed in a comprehension iterable expression */ + PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_ITER_EXPR); + PyErr_SyntaxLocationObject(st->st_filename, + e->lineno, + e->col_offset); + VISIT_QUIT(st, 0); + } + if (st->st_cur->ste_comprehension) { + /* Inside a comprehension body, so find the right target scope */ + if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target)) + VISIT_QUIT(st, 0); + } + VISIT(st, expr, e->v.NamedExpr.value); + VISIT(st, expr, e->v.NamedExpr.target); +} + static int symtable_visit_expr(struct symtable *st, expr_ty e) { @@ -1452,12 +1520,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) } switch (e->kind) { case NamedExpr_kind: - if (st->st_cur->ste_comprehension) { - if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target)) - VISIT_QUIT(st, 0); - } - VISIT(st, expr, e->v.NamedExpr.value); - VISIT(st, expr, e->v.NamedExpr.target); + symtable_handle_namedexpr(st, e); break; case BoolOp_kind: VISIT_SEQ(st, expr, e->v.BoolOp.values); @@ -1739,8 +1802,12 @@ symtable_visit_alias(struct symtable *st, alias_ty a) static int symtable_visit_comprehension(struct symtable *st, comprehension_ty lc) { + st->st_cur->ste_comp_iter_target = 1; VISIT(st, expr, lc->target); + st->st_cur->ste_comp_iter_target = 0; + st->st_cur->ste_comp_iter_expr++; VISIT(st, expr, lc->iter); + st->st_cur->ste_comp_iter_expr--; VISIT_SEQ(st, expr, lc->ifs); if (lc->is_async) { st->st_cur->ste_coroutine = 1; @@ -1788,7 +1855,9 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, comprehension_ty outermost = ((comprehension_ty) asdl_seq_GET(generators, 0)); /* Outermost iterator is evaluated in current scope */ + st->st_cur->ste_comp_iter_expr++; VISIT(st, expr, outermost->iter); + st->st_cur->ste_comp_iter_expr--; /* Create comprehension scope for the rest */ if (!scope_name || !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, @@ -1805,7 +1874,11 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, symtable_exit_block(st, (void *)e); return 0; } + /* Visit iteration variable target, and mark them as such */ + st->st_cur->ste_comp_iter_target = 1; VISIT(st, expr, outermost->target); + st->st_cur->ste_comp_iter_target = 0; + /* Visit the rest of the comprehension body */ VISIT_SEQ(st, expr, outermost->ifs); VISIT_SEQ_TAIL(st, comprehension, generators, 1); if (value) From webhook-mailer at python.org Sun Aug 25 10:41:51 2019 From: webhook-mailer at python.org (Nick Coghlan) Date: Sun, 25 Aug 2019 14:41:51 -0000 Subject: [Python-checkins] [3.8] bpo-37757: Disallow PEP 572 cases that expose implementation details (GH-15491) Message-ID: https://github.com/python/cpython/commit/6ca030765db49525f16b8fabff4153238148b58d commit: 6ca030765db49525f16b8fabff4153238148b58d branch: 3.8 author: Nick Coghlan committer: GitHub date: 2019-08-26T00:41:47+10:00 summary: [3.8] bpo-37757: Disallow PEP 572 cases that expose implementation details (GH-15491) - drop TargetScopeError in favour of raising SyntaxError directly as per the updated PEP 572 - comprehension iteration variables are explicitly local, but named expression targets in comprehensions are nonlocal or global. Raise SyntaxError as specified in PEP 572 - named expression targets in the outermost iterable of a comprehension have an ambiguous target scope. Avoid resolving that question now by raising SyntaxError. PEP 572 originally required this only for cases where the bound name conflicts with the iteration variable in the comprehension, but CPython can't easily restrict the exception to that case (as it doesn't know the target variable names when visiting the outermost iterator expression) (cherry picked from commit 5dbe0f59b7a4f39c7c606b48056bc29e406ebf78) files: A Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757.lRv5HX.rst M Doc/c-api/exceptions.rst M Include/pyerrors.h M Include/symtable.h M Lib/_compat_pickle.py M Lib/test/exception_hierarchy.txt M Lib/test/test_named_expressions.py M Objects/exceptions.c M PC/python3.def M Python/symtable.c diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index d8173935596b..25bb657dca0e 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -809,7 +809,6 @@ the variables: single: PyExc_SystemError single: PyExc_SystemExit single: PyExc_TabError - single: PyExc_TargetScopeError single: PyExc_TimeoutError single: PyExc_TypeError single: PyExc_UnboundLocalError @@ -911,8 +910,6 @@ the variables: +-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_TabError` | :exc:`TabError` | | +-----------------------------------------+---------------------------------+----------+ -| :c:data:`PyExc_TargetScopeError` | :exc:`TargetScopeError` | | -+-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_TimeoutError` | :exc:`TimeoutError` | | +-----------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_TypeError` | :exc:`TypeError` | | diff --git a/Include/pyerrors.h b/Include/pyerrors.h index 94af3cb3420e..5125a51ec1aa 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -97,7 +97,6 @@ PyAPI_DATA(PyObject *) PyExc_NotImplementedError; PyAPI_DATA(PyObject *) PyExc_SyntaxError; PyAPI_DATA(PyObject *) PyExc_IndentationError; PyAPI_DATA(PyObject *) PyExc_TabError; -PyAPI_DATA(PyObject *) PyExc_TargetScopeError; PyAPI_DATA(PyObject *) PyExc_ReferenceError; PyAPI_DATA(PyObject *) PyExc_SystemError; PyAPI_DATA(PyObject *) PyExc_SystemExit; diff --git a/Include/symtable.h b/Include/symtable.h index 9392e6438779..5dcfa7e2c2bb 100644 --- a/Include/symtable.h +++ b/Include/symtable.h @@ -58,6 +58,8 @@ typedef struct _symtable_entry { unsigned ste_needs_class_closure : 1; /* for class scopes, true if a closure over __class__ should be created */ + unsigned ste_comp_iter_target : 1; /* true if visiting comprehension target */ + int ste_comp_iter_expr; /* non-zero if visiting a comprehension range expression */ int ste_lineno; /* first line of block */ int ste_col_offset; /* offset of first line of block */ int ste_opt_lineno; /* lineno of last exec or import * */ @@ -94,6 +96,7 @@ PyAPI_FUNC(void) PySymtable_Free(struct symtable *); #define DEF_FREE_CLASS 2<<5 /* free variable from class's method */ #define DEF_IMPORT 2<<6 /* assignment occurred via import */ #define DEF_ANNOT 2<<7 /* this name is annotated */ +#define DEF_COMP_ITER 2<<8 /* this name is a comprehension iteration variable */ #define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT) diff --git a/Lib/_compat_pickle.py b/Lib/_compat_pickle.py index 8bb1cf80afa5..f68496ae639f 100644 --- a/Lib/_compat_pickle.py +++ b/Lib/_compat_pickle.py @@ -128,7 +128,6 @@ "SystemError", "SystemExit", "TabError", - "TargetScopeError", "TypeError", "UnboundLocalError", "UnicodeDecodeError", diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt index 15f4491cf237..763a6c899b48 100644 --- a/Lib/test/exception_hierarchy.txt +++ b/Lib/test/exception_hierarchy.txt @@ -42,7 +42,6 @@ BaseException | +-- NotImplementedError | +-- RecursionError +-- SyntaxError - | +-- TargetScopeError | +-- IndentationError | +-- TabError +-- SystemError diff --git a/Lib/test/test_named_expressions.py b/Lib/test/test_named_expressions.py index f73e6fee70ce..b1027ce78006 100644 --- a/Lib/test/test_named_expressions.py +++ b/Lib/test/test_named_expressions.py @@ -104,15 +104,69 @@ def test_named_expression_invalid_17(self): with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) - def test_named_expression_invalid_18(self): + def test_named_expression_invalid_in_class_body(self): code = """class Foo(): [(42, 1 + ((( j := i )))) for i in range(5)] """ - with self.assertRaisesRegex(TargetScopeError, - "named expression within a comprehension cannot be used in a class body"): + with self.assertRaisesRegex(SyntaxError, + "assignment expression within a comprehension cannot be used in a class body"): exec(code, {}, {}) + def test_named_expression_invalid_rebinding_comprehension_iteration_variable(self): + cases = [ + ("Local reuse", 'i', "[i := 0 for i in range(5)]"), + ("Nested reuse", 'j', "[[(j := 0) for i in range(5)] for j in range(5)]"), + ("Reuse inner loop target", 'j', "[(j := 0) for i in range(5) for j in range(5)]"), + ("Unpacking reuse", 'i', "[i := 0 for i, j in [(0, 1)]]"), + ("Reuse in loop condition", 'i', "[i+1 for i in range(5) if (i := 0)]"), + ("Unreachable reuse", 'i', "[False or (i:=0) for i in range(5)]"), + ("Unreachable nested reuse", 'i', + "[(i, j) for i in range(5) for j in range(5) if True or (i:=10)]"), + ] + for case, target, code in cases: + msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'" + with self.subTest(case=case): + with self.assertRaisesRegex(SyntaxError, msg): + exec(code, {}, {}) + + def test_named_expression_invalid_rebinding_comprehension_inner_loop(self): + cases = [ + ("Inner reuse", 'j', "[i for i in range(5) if (j := 0) for j in range(5)]"), + ("Inner unpacking reuse", 'j', "[i for i in range(5) if (j := 0) for j, k in [(0, 1)]]"), + ] + for case, target, code in cases: + msg = f"comprehension inner loop cannot rebind assignment expression target '{target}'" + with self.subTest(case=case): + with self.assertRaisesRegex(SyntaxError, msg): + exec(code, {}) # Module scope + with self.assertRaisesRegex(SyntaxError, msg): + exec(code, {}, {}) # Class scope + with self.assertRaisesRegex(SyntaxError, msg): + exec(f"lambda: {code}", {}) # Function scope + + def test_named_expression_invalid_comprehension_iterable_expression(self): + cases = [ + ("Top level", "[i for i in (i := range(5))]"), + ("Inside tuple", "[i for i in (2, 3, i := range(5))]"), + ("Inside list", "[i for i in [2, 3, i := range(5)]]"), + ("Different name", "[i for i in (j := range(5))]"), + ("Lambda expression", "[i for i in (lambda:(j := range(5)))()]"), + ("Inner loop", "[i for i in range(5) for j in (i := range(5))]"), + ("Nested comprehension", "[i for i in [j for j in (k := range(5))]]"), + ("Nested comprehension condition", "[i for i in [j for j in range(5) if (j := True)]]"), + ("Nested comprehension body", "[i for i in [(j := True) for j in range(5)]]"), + ] + msg = "assignment expression cannot be used in a comprehension iterable expression" + for case, code in cases: + with self.subTest(case=case): + with self.assertRaisesRegex(SyntaxError, msg): + exec(code, {}) # Module scope + with self.assertRaisesRegex(SyntaxError, msg): + exec(code, {}, {}) # Class scope + with self.assertRaisesRegex(SyntaxError, msg): + exec(f"lambda: {code}", {}) # Function scope + class NamedExpressionAssignmentTest(unittest.TestCase): @@ -306,39 +360,6 @@ def test_named_expression_scope_11(self): self.assertEqual(res, [0, 1, 2, 3, 4]) self.assertEqual(j, 4) - def test_named_expression_scope_12(self): - res = [i := i for i in range(5)] - - self.assertEqual(res, [0, 1, 2, 3, 4]) - self.assertEqual(i, 4) - - def test_named_expression_scope_13(self): - res = [i := 0 for i, j in [(1, 2), (3, 4)]] - - self.assertEqual(res, [0, 0]) - self.assertEqual(i, 0) - - def test_named_expression_scope_14(self): - res = [(i := 0, j := 1) for i, j in [(1, 2), (3, 4)]] - - self.assertEqual(res, [(0, 1), (0, 1)]) - self.assertEqual(i, 0) - self.assertEqual(j, 1) - - def test_named_expression_scope_15(self): - res = [(i := i, j := j) for i, j in [(1, 2), (3, 4)]] - - self.assertEqual(res, [(1, 2), (3, 4)]) - self.assertEqual(i, 3) - self.assertEqual(j, 4) - - def test_named_expression_scope_16(self): - res = [(i := j, j := i) for i, j in [(1, 2), (3, 4)]] - - self.assertEqual(res, [(2, 2), (4, 4)]) - self.assertEqual(i, 4) - self.assertEqual(j, 4) - def test_named_expression_scope_17(self): b = 0 res = [b := i + b for i in range(5)] @@ -421,6 +442,33 @@ def spam(): self.assertEqual(ns["a"], 20) + def test_named_expression_variable_reuse_in_comprehensions(self): + # The compiler is expected to raise syntax error for comprehension + # iteration variables, but should be fine with rebinding of other + # names (e.g. globals, nonlocals, other assignment expressions) + + # The cases are all defined to produce the same expected result + # Each comprehension is checked at both function scope and module scope + rebinding = "[x := i for i in range(3) if (x := i) or not x]" + filter_ref = "[x := i for i in range(3) if x or not x]" + body_ref = "[x for i in range(3) if (x := i) or not x]" + nested_ref = "[j for i in range(3) if x or not x for j in range(3) if (x := i)][:-3]" + cases = [ + ("Rebind global", f"x = 1; result = {rebinding}"), + ("Rebind nonlocal", f"result, x = (lambda x=1: ({rebinding}, x))()"), + ("Filter global", f"x = 1; result = {filter_ref}"), + ("Filter nonlocal", f"result, x = (lambda x=1: ({filter_ref}, x))()"), + ("Body global", f"x = 1; result = {body_ref}"), + ("Body nonlocal", f"result, x = (lambda x=1: ({body_ref}, x))()"), + ("Nested global", f"x = 1; result = {nested_ref}"), + ("Nested nonlocal", f"result, x = (lambda x=1: ({nested_ref}, x))()"), + ] + for case, code in cases: + with self.subTest(case=case): + ns = {} + exec(code, ns) + self.assertEqual(ns["x"], 2) + self.assertEqual(ns["result"], [0, 1, 2]) if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757.lRv5HX.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757.lRv5HX.rst new file mode 100644 index 000000000000..258df0dc09bd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757.lRv5HX.rst @@ -0,0 +1,7 @@ +:pep:`572`: As described in the PEP, assignment expressions now raise +:exc:`SyntaxError` when their interaction with comprehension scoping results +in an ambiguous target scope. + +The ``TargetScopeError`` subclass originally proposed by the PEP has been +removed in favour of just raising regular syntax errors for the disallowed +cases. diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 568d4959e3a0..38723d93653c 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -1521,13 +1521,6 @@ MiddlingExtendsException(PyExc_SyntaxError, IndentationError, SyntaxError, "Improper indentation."); -/* - * TargetScopeError extends SyntaxError - */ -MiddlingExtendsException(PyExc_SyntaxError, TargetScopeError, SyntaxError, - "Improper scope target."); - - /* * TabError extends IndentationError */ @@ -2539,7 +2532,6 @@ _PyExc_Init(void) PRE_INIT(AttributeError); PRE_INIT(SyntaxError); PRE_INIT(IndentationError); - PRE_INIT(TargetScopeError); PRE_INIT(TabError); PRE_INIT(LookupError); PRE_INIT(IndexError); @@ -2680,7 +2672,6 @@ _PyBuiltins_AddExceptions(PyObject *bltinmod) POST_INIT(AttributeError); POST_INIT(SyntaxError); POST_INIT(IndentationError); - POST_INIT(TargetScopeError); POST_INIT(TabError); POST_INIT(LookupError); POST_INIT(IndexError); diff --git a/PC/python3.def b/PC/python3.def index e317864d0cd8..5d93c18af87e 100644 --- a/PC/python3.def +++ b/PC/python3.def @@ -235,7 +235,6 @@ EXPORTS PyExc_SystemError=python38.PyExc_SystemError DATA PyExc_SystemExit=python38.PyExc_SystemExit DATA PyExc_TabError=python38.PyExc_TabError DATA - PyExc_TargetScopeError=python38.PyExc_TargetScopeError DATA PyExc_TimeoutError=python38.PyExc_TimeoutError DATA PyExc_TypeError=python38.PyExc_TypeError DATA PyExc_UnboundLocalError=python38.PyExc_UnboundLocalError DATA diff --git a/Python/symtable.c b/Python/symtable.c index 668cc21b2df9..e48baa808d41 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -32,7 +32,16 @@ #define IMPORT_STAR_WARNING "import * only allowed at module level" #define NAMED_EXPR_COMP_IN_CLASS \ -"named expression within a comprehension cannot be used in a class body" +"assignment expression within a comprehension cannot be used in a class body" + +#define NAMED_EXPR_COMP_CONFLICT \ +"assignment expression cannot rebind comprehension iteration variable '%U'" + +#define NAMED_EXPR_COMP_INNER_LOOP_CONFLICT \ +"comprehension inner loop cannot rebind assignment expression target '%U'" + +#define NAMED_EXPR_COMP_ITER_EXPR \ +"assignment expression cannot be used in a comprehension iterable expression" static PySTEntryObject * ste_new(struct symtable *st, identifier name, _Py_block_ty block, @@ -81,6 +90,8 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_comprehension = 0; ste->ste_returns_value = 0; ste->ste_needs_class_closure = 0; + ste->ste_comp_iter_target = 0; + ste->ste_comp_iter_expr = 0; ste->ste_symbols = PyDict_New(); ste->ste_varnames = PyList_New(0); @@ -373,14 +384,21 @@ PySymtable_Lookup(struct symtable *st, void *key) return (PySTEntryObject *)v; } -int -PyST_GetScope(PySTEntryObject *ste, PyObject *name) +static long +_PyST_GetSymbol(PySTEntryObject *ste, PyObject *name) { PyObject *v = PyDict_GetItem(ste->ste_symbols, name); if (!v) return 0; assert(PyLong_Check(v)); - return (PyLong_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK; + return PyLong_AS_LONG(v); +} + +int +PyST_GetScope(PySTEntryObject *ste, PyObject *name) +{ + long symbol = _PyST_GetSymbol(ste, name); + return (symbol >> SCOPE_OFFSET) & SCOPE_MASK; } static int @@ -955,6 +973,13 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, return 0; } prev = st->st_cur; + /* bpo-37757: For now, disallow *all* assignment expressions in the + * outermost iterator expression of a comprehension, even those inside + * a nested comprehension or a lambda expression. + */ + if (prev) { + ste->ste_comp_iter_expr = prev->ste_comp_iter_expr; + } /* The entry is owned by the stack. Borrow it for st_cur. */ Py_DECREF(ste); st->st_cur = ste; @@ -971,15 +996,10 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, static long symtable_lookup(struct symtable *st, PyObject *name) { - PyObject *o; PyObject *mangled = _Py_Mangle(st->st_private, name); if (!mangled) return 0; - o = PyDict_GetItem(st->st_cur->ste_symbols, mangled); - Py_DECREF(mangled); - if (!o) - return 0; - return PyLong_AsLong(o); + return _PyST_GetSymbol(st->st_cur, mangled); } static int @@ -1012,6 +1032,22 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s else { val = flag; } + if (ste->ste_comp_iter_target) { + /* This name is an iteration variable in a comprehension, + * so check for a binding conflict with any named expressions. + * Otherwise, mark it as an iteration variable so subsequent + * named expressions can check for conflicts. + */ + if (val & (DEF_GLOBAL | DEF_NONLOCAL)) { + PyErr_Format(PyExc_SyntaxError, + NAMED_EXPR_COMP_INNER_LOOP_CONFLICT, name); + PyErr_SyntaxLocationObject(st->st_filename, + ste->ste_lineno, + ste->ste_col_offset + 1); + goto error; + } + val |= DEF_COMP_ITER; + } o = PyLong_FromLong(val); if (o == NULL) goto error; @@ -1392,7 +1428,9 @@ static int symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) { assert(st->st_stack); + assert(e->kind == Name_kind); + PyObject *target_name = e->v.Name.id; Py_ssize_t i, size; struct _symtable_entry *ste; size = PyList_GET_SIZE(st->st_stack); @@ -1402,32 +1440,42 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) for (i = size - 1; i >= 0; i--) { ste = (struct _symtable_entry *) PyList_GET_ITEM(st->st_stack, i); - /* If our current entry is a comprehension, skip it */ + /* If we find a comprehension scope, check for a target + * binding conflict with iteration variables, otherwise skip it + */ if (ste->ste_comprehension) { + long target_in_scope = _PyST_GetSymbol(ste, target_name); + if (target_in_scope & DEF_COMP_ITER) { + PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_CONFLICT, target_name); + PyErr_SyntaxLocationObject(st->st_filename, + e->lineno, + e->col_offset); + VISIT_QUIT(st, 0); + } continue; } /* If we find a FunctionBlock entry, add as NONLOCAL/LOCAL */ if (ste->ste_type == FunctionBlock) { - if (!symtable_add_def(st, e->v.Name.id, DEF_NONLOCAL)) + if (!symtable_add_def(st, target_name, DEF_NONLOCAL)) VISIT_QUIT(st, 0); - if (!symtable_record_directive(st, e->v.Name.id, e->lineno, e->col_offset)) + if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset)) VISIT_QUIT(st, 0); - return symtable_add_def_helper(st, e->v.Name.id, DEF_LOCAL, ste); + return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste); } /* If we find a ModuleBlock entry, add as GLOBAL */ if (ste->ste_type == ModuleBlock) { - if (!symtable_add_def(st, e->v.Name.id, DEF_GLOBAL)) + if (!symtable_add_def(st, target_name, DEF_GLOBAL)) VISIT_QUIT(st, 0); - if (!symtable_record_directive(st, e->v.Name.id, e->lineno, e->col_offset)) + if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset)) VISIT_QUIT(st, 0); - return symtable_add_def_helper(st, e->v.Name.id, DEF_GLOBAL, ste); + return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste); } /* Disallow usage in ClassBlock */ if (ste->ste_type == ClassBlock) { - PyErr_Format(PyExc_TargetScopeError, NAMED_EXPR_COMP_IN_CLASS, e->v.Name.id); + PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_CLASS); PyErr_SyntaxLocationObject(st->st_filename, e->lineno, e->col_offset); @@ -1442,6 +1490,26 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) return 0; } +static int +symtable_handle_namedexpr(struct symtable *st, expr_ty e) +{ + if (st->st_cur->ste_comp_iter_expr > 0) { + /* Assignment isn't allowed in a comprehension iterable expression */ + PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_ITER_EXPR); + PyErr_SyntaxLocationObject(st->st_filename, + e->lineno, + e->col_offset); + VISIT_QUIT(st, 0); + } + if (st->st_cur->ste_comprehension) { + /* Inside a comprehension body, so find the right target scope */ + if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target)) + VISIT_QUIT(st, 0); + } + VISIT(st, expr, e->v.NamedExpr.value); + VISIT(st, expr, e->v.NamedExpr.target); +} + static int symtable_visit_expr(struct symtable *st, expr_ty e) { @@ -1452,12 +1520,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) } switch (e->kind) { case NamedExpr_kind: - if (st->st_cur->ste_comprehension) { - if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target)) - VISIT_QUIT(st, 0); - } - VISIT(st, expr, e->v.NamedExpr.value); - VISIT(st, expr, e->v.NamedExpr.target); + symtable_handle_namedexpr(st, e); break; case BoolOp_kind: VISIT_SEQ(st, expr, e->v.BoolOp.values); @@ -1739,8 +1802,12 @@ symtable_visit_alias(struct symtable *st, alias_ty a) static int symtable_visit_comprehension(struct symtable *st, comprehension_ty lc) { + st->st_cur->ste_comp_iter_target = 1; VISIT(st, expr, lc->target); + st->st_cur->ste_comp_iter_target = 0; + st->st_cur->ste_comp_iter_expr++; VISIT(st, expr, lc->iter); + st->st_cur->ste_comp_iter_expr--; VISIT_SEQ(st, expr, lc->ifs); if (lc->is_async) { st->st_cur->ste_coroutine = 1; @@ -1788,7 +1855,9 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, comprehension_ty outermost = ((comprehension_ty) asdl_seq_GET(generators, 0)); /* Outermost iterator is evaluated in current scope */ + st->st_cur->ste_comp_iter_expr++; VISIT(st, expr, outermost->iter); + st->st_cur->ste_comp_iter_expr--; /* Create comprehension scope for the rest */ if (!scope_name || !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, @@ -1805,7 +1874,11 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, symtable_exit_block(st, (void *)e); return 0; } + /* Visit iteration variable target, and mark them as such */ + st->st_cur->ste_comp_iter_target = 1; VISIT(st, expr, outermost->target); + st->st_cur->ste_comp_iter_target = 0; + /* Visit the rest of the comprehension body */ VISIT_SEQ(st, expr, outermost->ifs); VISIT_SEQ_TAIL(st, comprehension, generators, 1); if (value) From webhook-mailer at python.org Sun Aug 25 15:06:50 2019 From: webhook-mailer at python.org (Berker Peksag) Date: Sun, 25 Aug 2019 19:06:50 -0000 Subject: [Python-checkins] bpo-29553: Fix ArgumentParser.format_usage() for mutually exclusive groups (GH-14976) Message-ID: https://github.com/python/cpython/commit/da27d9b9dc44913ffee8f28d9638985eaaa03755 commit: da27d9b9dc44913ffee8f28d9638985eaaa03755 branch: master author: Flavian Hautbois committer: Berker Peksag date: 2019-08-25T22:06:45+03:00 summary: bpo-29553: Fix ArgumentParser.format_usage() for mutually exclusive groups (GH-14976) Co-authored-by: Andrew Nester files: A Misc/NEWS.d/next/Library/2019-07-27-10-14-45.bpo-29553.TVeIDe.rst M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index a300828f9e3d..d29f161b666a 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -404,13 +404,19 @@ def _format_actions_usage(self, actions, groups): inserts[start] += ' [' else: inserts[start] = '[' - inserts[end] = ']' + if end in inserts: + inserts[end] += ']' + else: + inserts[end] = ']' else: if start in inserts: inserts[start] += ' (' else: inserts[start] = '(' - inserts[end] = ')' + if end in inserts: + inserts[end] += ')' + else: + inserts[end] = ')' for i in range(start + 1, end): inserts[i] = '|' diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index d6d16090eb02..86ec6cca51ac 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2813,6 +2813,46 @@ def get_parser(self, required): -c c help ''' +class TestMutuallyExclusiveNested(MEMixin, TestCase): + + def get_parser(self, required): + parser = ErrorRaisingArgumentParser(prog='PROG') + group = parser.add_mutually_exclusive_group(required=required) + group.add_argument('-a') + group.add_argument('-b') + group2 = group.add_mutually_exclusive_group(required=required) + group2.add_argument('-c') + group2.add_argument('-d') + group3 = group2.add_mutually_exclusive_group(required=required) + group3.add_argument('-e') + group3.add_argument('-f') + return parser + + usage_when_not_required = '''\ + usage: PROG [-h] [-a A | -b B | [-c C | -d D | [-e E | -f F]]] + ''' + usage_when_required = '''\ + usage: PROG [-h] (-a A | -b B | (-c C | -d D | (-e E | -f F))) + ''' + + help = '''\ + + optional arguments: + -h, --help show this help message and exit + -a A + -b B + -c C + -d D + -e E + -f F + ''' + + # We are only interested in testing the behavior of format_usage(). + test_failures_when_not_required = None + test_failures_when_required = None + test_successes_when_not_required = None + test_successes_when_required = None + # ================================================= # Mutually exclusive group in parent parser tests # ================================================= diff --git a/Misc/NEWS.d/next/Library/2019-07-27-10-14-45.bpo-29553.TVeIDe.rst b/Misc/NEWS.d/next/Library/2019-07-27-10-14-45.bpo-29553.TVeIDe.rst new file mode 100644 index 000000000000..3472db7bf209 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-27-10-14-45.bpo-29553.TVeIDe.rst @@ -0,0 +1,2 @@ +Fixed :meth:`argparse.ArgumentParser.format_usage` for mutually exclusive groups. +Patch by Andrew Nester. From webhook-mailer at python.org Sun Aug 25 17:30:58 2019 From: webhook-mailer at python.org (Berker Peksag) Date: Sun, 25 Aug 2019 21:30:58 -0000 Subject: [Python-checkins] bpo-29553: Fix ArgumentParser.format_usage() for mutually exclusive groups (GH-14976) Message-ID: https://github.com/python/cpython/commit/31ea447ffe591736af1d7a3178c0f7ca3eb50d70 commit: 31ea447ffe591736af1d7a3178c0f7ca3eb50d70 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Berker Peksag date: 2019-08-26T00:30:49+03:00 summary: bpo-29553: Fix ArgumentParser.format_usage() for mutually exclusive groups (GH-14976) Co-authored-by: Andrew Nester Co-authored-by: Flavian Hautbois (cherry picked from commit da27d9b9dc44913ffee8f28d9638985eaaa03755) files: A Misc/NEWS.d/next/Library/2019-07-27-10-14-45.bpo-29553.TVeIDe.rst M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index a03074924762..24af355b7441 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -407,13 +407,19 @@ def _format_actions_usage(self, actions, groups): inserts[start] += ' [' else: inserts[start] = '[' - inserts[end] = ']' + if end in inserts: + inserts[end] += ']' + else: + inserts[end] = ']' else: if start in inserts: inserts[start] += ' (' else: inserts[start] = '(' - inserts[end] = ')' + if end in inserts: + inserts[end] += ')' + else: + inserts[end] = ')' for i in range(start + 1, end): inserts[i] = '|' diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 51f0effaf2ff..3cdaff61c7cc 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2772,6 +2772,46 @@ def get_parser(self, required): -c c help ''' +class TestMutuallyExclusiveNested(MEMixin, TestCase): + + def get_parser(self, required): + parser = ErrorRaisingArgumentParser(prog='PROG') + group = parser.add_mutually_exclusive_group(required=required) + group.add_argument('-a') + group.add_argument('-b') + group2 = group.add_mutually_exclusive_group(required=required) + group2.add_argument('-c') + group2.add_argument('-d') + group3 = group2.add_mutually_exclusive_group(required=required) + group3.add_argument('-e') + group3.add_argument('-f') + return parser + + usage_when_not_required = '''\ + usage: PROG [-h] [-a A | -b B | [-c C | -d D | [-e E | -f F]]] + ''' + usage_when_required = '''\ + usage: PROG [-h] (-a A | -b B | (-c C | -d D | (-e E | -f F))) + ''' + + help = '''\ + + optional arguments: + -h, --help show this help message and exit + -a A + -b B + -c C + -d D + -e E + -f F + ''' + + # We are only interested in testing the behavior of format_usage(). + test_failures_when_not_required = None + test_failures_when_required = None + test_successes_when_not_required = None + test_successes_when_required = None + # ================================================= # Mutually exclusive group in parent parser tests # ================================================= diff --git a/Misc/NEWS.d/next/Library/2019-07-27-10-14-45.bpo-29553.TVeIDe.rst b/Misc/NEWS.d/next/Library/2019-07-27-10-14-45.bpo-29553.TVeIDe.rst new file mode 100644 index 000000000000..3472db7bf209 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-27-10-14-45.bpo-29553.TVeIDe.rst @@ -0,0 +1,2 @@ +Fixed :meth:`argparse.ArgumentParser.format_usage` for mutually exclusive groups. +Patch by Andrew Nester. From webhook-mailer at python.org Mon Aug 26 02:11:54 2019 From: webhook-mailer at python.org (Ned Deily) Date: Mon, 26 Aug 2019 06:11:54 -0000 Subject: [Python-checkins] Doc: Keep the venv/* exclude pattern. (GH-15229) Message-ID: https://github.com/python/cpython/commit/73e054970193fc421c533564a4189be522f9c331 commit: 73e054970193fc421c533564a4189be522f9c331 branch: master author: Julien Palard committer: Ned Deily date: 2019-08-26T02:11:43-04:00 summary: Doc: Keep the venv/* exclude pattern. (GH-15229) In case it has been previously created. files: M Doc/conf.py diff --git a/Doc/conf.py b/Doc/conf.py index e85ea5b2d2ff..abaa760c98c1 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -48,8 +48,10 @@ needs_sphinx = '1.8' # Ignore any .rst files in the venv/ directory. -venvdir = os.getenv('VENVDIR', 'venv') -exclude_patterns = [venvdir+'/*', 'README.rst'] +exclude_patterns = ['venv/*', 'README.rst'] +venvdir = os.getenv('VENVDIR') +if venvdir is not None: + exclude_patterns.append(venvdir + '/*') # Disable Docutils smartquotes for several translations smartquotes_excludes = { From webhook-mailer at python.org Mon Aug 26 02:19:50 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 06:19:50 -0000 Subject: [Python-checkins] Doc: Keep the venv/* exclude pattern. (GH-15229) Message-ID: https://github.com/python/cpython/commit/352a1239ff4af51ea7468646ce964bafa9bc380d commit: 352a1239ff4af51ea7468646ce964bafa9bc380d branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-25T23:19:45-07:00 summary: Doc: Keep the venv/* exclude pattern. (GH-15229) In case it has been previously created. (cherry picked from commit 73e054970193fc421c533564a4189be522f9c331) Co-authored-by: Julien Palard files: M Doc/conf.py diff --git a/Doc/conf.py b/Doc/conf.py index e85ea5b2d2ff..abaa760c98c1 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -48,8 +48,10 @@ needs_sphinx = '1.8' # Ignore any .rst files in the venv/ directory. -venvdir = os.getenv('VENVDIR', 'venv') -exclude_patterns = [venvdir+'/*', 'README.rst'] +exclude_patterns = ['venv/*', 'README.rst'] +venvdir = os.getenv('VENVDIR') +if venvdir is not None: + exclude_patterns.append(venvdir + '/*') # Disable Docutils smartquotes for several translations smartquotes_excludes = { From webhook-mailer at python.org Mon Aug 26 02:20:02 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 06:20:02 -0000 Subject: [Python-checkins] Doc: Keep the venv/* exclude pattern. (GH-15229) Message-ID: https://github.com/python/cpython/commit/ae31b640c46173269ae712f418a0214f67c75292 commit: ae31b640c46173269ae712f418a0214f67c75292 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-25T23:19:58-07:00 summary: Doc: Keep the venv/* exclude pattern. (GH-15229) In case it has been previously created. (cherry picked from commit 73e054970193fc421c533564a4189be522f9c331) Co-authored-by: Julien Palard files: M Doc/conf.py diff --git a/Doc/conf.py b/Doc/conf.py index da8b9d7b2a65..ce2d47f5f893 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -38,8 +38,10 @@ needs_sphinx = "1.6.6" # Ignore any .rst files in the venv/ directory. -venvdir = os.getenv('VENVDIR', 'venv') -exclude_patterns = [venvdir+'/*', 'README.rst'] +exclude_patterns = ['venv/*', 'README.rst'] +venvdir = os.getenv('VENVDIR') +if venvdir is not None: + exclude_patterns.append(venvdir + '/*') # Disable Docutils smartquotes for several translations smartquotes_excludes = { From webhook-mailer at python.org Mon Aug 26 02:28:00 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 26 Aug 2019 06:28:00 -0000 Subject: [Python-checkins] bpo-37824: Properly handle user input warnings in IDLE shell. (GH-15500) Message-ID: https://github.com/python/cpython/commit/1039f39c9c6edb4c185856c19316d3a4eb561c38 commit: 1039f39c9c6edb4c185856c19316d3a4eb561c38 branch: master author: Terry Jan Reedy committer: GitHub date: 2019-08-26T02:27:56-04:00 summary: bpo-37824: Properly handle user input warnings in IDLE shell. (GH-15500) Cease turning SyntaxWarnings into SyntaxErrors. files: A Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/pyshell.py diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 45918cf36b41..949b30bd99ca 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,12 @@ Released on 2019-10-20? ====================================== +bpo-37824: Properly handle user input warnings in IDLE shell. +Cease turning SyntaxWarnings into SyntaxErrors. + +bpo-37929: IDLE Settings dialog now closes properly when there is no +shell window. + bpo-37849: Fix completions list appearing too high or low when shown above the current line. diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py index 87401f33f55f..ea9465568bd9 100755 --- a/Lib/idlelib/pyshell.py +++ b/Lib/idlelib/pyshell.py @@ -394,7 +394,6 @@ def __init__(self, tkconsole): self.tkconsole = tkconsole locals = sys.modules['__main__'].__dict__ InteractiveInterpreter.__init__(self, locals=locals) - self.save_warnings_filters = None self.restarting = False self.subprocess_arglist = None self.port = PORT @@ -665,8 +664,6 @@ def runsource(self, source): "Extend base class method: Stuff the source in the line cache first" filename = self.stuffsource(source) self.more = 0 - self.save_warnings_filters = warnings.filters[:] - warnings.filterwarnings(action="error", category=SyntaxWarning) # at the moment, InteractiveInterpreter expects str assert isinstance(source, str) #if isinstance(source, str): @@ -677,14 +674,9 @@ def runsource(self, source): # self.tkconsole.resetoutput() # self.write("Unsupported characters in input\n") # return - try: - # InteractiveInterpreter.runsource() calls its runcode() method, - # which is overridden (see below) - return InteractiveInterpreter.runsource(self, source, filename) - finally: - if self.save_warnings_filters is not None: - warnings.filters[:] = self.save_warnings_filters - self.save_warnings_filters = None + # InteractiveInterpreter.runsource() calls its runcode() method, + # which is overridden (see below) + return InteractiveInterpreter.runsource(self, source, filename) def stuffsource(self, source): "Stuff source in the filename cache" @@ -763,9 +755,6 @@ def runcode(self, code): if self.tkconsole.executing: self.interp.restart_subprocess() self.checklinecache() - if self.save_warnings_filters is not None: - warnings.filters[:] = self.save_warnings_filters - self.save_warnings_filters = None debugger = self.debugger try: self.tkconsole.beginexecuting() diff --git a/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst b/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst new file mode 100644 index 000000000000..1a1e8a59816a --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst @@ -0,0 +1,2 @@ +Properly handle user input warnings in IDLE shell. Cease turning +SyntaxWarnings into SyntaxErrors. From webhook-mailer at python.org Mon Aug 26 02:52:50 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 26 Aug 2019 06:52:50 -0000 Subject: [Python-checkins] bpo-37824: Properly handle user input warnings in IDLE shell. (GH-15500) Message-ID: https://github.com/python/cpython/commit/077887059a5b3d38161dfd74b160c701445a1ef0 commit: 077887059a5b3d38161dfd74b160c701445a1ef0 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2019-08-26T02:52:45-04:00 summary: bpo-37824: Properly handle user input warnings in IDLE shell. (GH-15500) Cease turning SyntaxWarnings into SyntaxErrors. (cherry picked from commit 1039f39c9c6edb4c185856c19316d3a4eb561c38) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/pyshell.py diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 45918cf36b41..949b30bd99ca 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,12 @@ Released on 2019-10-20? ====================================== +bpo-37824: Properly handle user input warnings in IDLE shell. +Cease turning SyntaxWarnings into SyntaxErrors. + +bpo-37929: IDLE Settings dialog now closes properly when there is no +shell window. + bpo-37849: Fix completions list appearing too high or low when shown above the current line. diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py index 87401f33f55f..ea9465568bd9 100755 --- a/Lib/idlelib/pyshell.py +++ b/Lib/idlelib/pyshell.py @@ -394,7 +394,6 @@ def __init__(self, tkconsole): self.tkconsole = tkconsole locals = sys.modules['__main__'].__dict__ InteractiveInterpreter.__init__(self, locals=locals) - self.save_warnings_filters = None self.restarting = False self.subprocess_arglist = None self.port = PORT @@ -665,8 +664,6 @@ def runsource(self, source): "Extend base class method: Stuff the source in the line cache first" filename = self.stuffsource(source) self.more = 0 - self.save_warnings_filters = warnings.filters[:] - warnings.filterwarnings(action="error", category=SyntaxWarning) # at the moment, InteractiveInterpreter expects str assert isinstance(source, str) #if isinstance(source, str): @@ -677,14 +674,9 @@ def runsource(self, source): # self.tkconsole.resetoutput() # self.write("Unsupported characters in input\n") # return - try: - # InteractiveInterpreter.runsource() calls its runcode() method, - # which is overridden (see below) - return InteractiveInterpreter.runsource(self, source, filename) - finally: - if self.save_warnings_filters is not None: - warnings.filters[:] = self.save_warnings_filters - self.save_warnings_filters = None + # InteractiveInterpreter.runsource() calls its runcode() method, + # which is overridden (see below) + return InteractiveInterpreter.runsource(self, source, filename) def stuffsource(self, source): "Stuff source in the filename cache" @@ -763,9 +755,6 @@ def runcode(self, code): if self.tkconsole.executing: self.interp.restart_subprocess() self.checklinecache() - if self.save_warnings_filters is not None: - warnings.filters[:] = self.save_warnings_filters - self.save_warnings_filters = None debugger = self.debugger try: self.tkconsole.beginexecuting() diff --git a/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst b/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst new file mode 100644 index 000000000000..1a1e8a59816a --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst @@ -0,0 +1,2 @@ +Properly handle user input warnings in IDLE shell. Cease turning +SyntaxWarnings into SyntaxErrors. From webhook-mailer at python.org Mon Aug 26 02:53:16 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Mon, 26 Aug 2019 06:53:16 -0000 Subject: [Python-checkins] bpo-15542: Documentation incorrectly suggests __init__ called after direct __new__ call (GH-15478) Message-ID: https://github.com/python/cpython/commit/6b16d938d6d1ccb443815e20e8812deed274dc09 commit: 6b16d938d6d1ccb443815e20e8812deed274dc09 branch: master author: Joannah Nanjekye <33177550+nanjekyejoannah at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-25T23:53:11-07:00 summary: bpo-15542: Documentation incorrectly suggests __init__ called after direct __new__ call (GH-15478) files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 1dd8e42ef87e..d1702ccb6417 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1166,10 +1166,10 @@ Basic customization with appropriate arguments and then modifying the newly-created instance as necessary before returning it. - If :meth:`__new__` returns an instance of *cls*, then the new instance's - :meth:`__init__` method will be invoked like ``__init__(self[, ...])``, where - *self* is the new instance and the remaining arguments are the same as were - passed to :meth:`__new__`. + If :meth:`__new__` is invoked during object construction and it returns an + instance or subclass of *cls*, then the new instance?s :meth:`__init__` method + will be invoked like ``__init__(self[, ...])``, where *self* is the new instance + and the remaining arguments are the same as were passed to the object constructor. If :meth:`__new__` does not return an instance of *cls*, then the new instance's :meth:`__init__` method will not be invoked. From webhook-mailer at python.org Mon Aug 26 02:53:42 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 06:53:42 -0000 Subject: [Python-checkins] bpo-37824: Properly handle user input warnings in IDLE shell. (GH-15500) Message-ID: https://github.com/python/cpython/commit/1b15914ebb46e549ff0965c789ef03b4bac2a890 commit: 1b15914ebb46e549ff0965c789ef03b4bac2a890 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-25T23:53:38-07:00 summary: bpo-37824: Properly handle user input warnings in IDLE shell. (GH-15500) Cease turning SyntaxWarnings into SyntaxErrors. (cherry picked from commit 1039f39c9c6edb4c185856c19316d3a4eb561c38) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/pyshell.py diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index b579c2c1a6dd..e414ead0762f 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,12 @@ Released on 2019-09-30? ====================================== +bpo-37824: Properly handle user input warnings in IDLE shell. +Cease turning SyntaxWarnings into SyntaxErrors. + +bpo-37929: IDLE Settings dialog now closes properly when there is no +shell window. + bpo-37849: Fix completions list appearing too high or low when shown above the current line. diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py index 87401f33f55f..ea9465568bd9 100755 --- a/Lib/idlelib/pyshell.py +++ b/Lib/idlelib/pyshell.py @@ -394,7 +394,6 @@ def __init__(self, tkconsole): self.tkconsole = tkconsole locals = sys.modules['__main__'].__dict__ InteractiveInterpreter.__init__(self, locals=locals) - self.save_warnings_filters = None self.restarting = False self.subprocess_arglist = None self.port = PORT @@ -665,8 +664,6 @@ def runsource(self, source): "Extend base class method: Stuff the source in the line cache first" filename = self.stuffsource(source) self.more = 0 - self.save_warnings_filters = warnings.filters[:] - warnings.filterwarnings(action="error", category=SyntaxWarning) # at the moment, InteractiveInterpreter expects str assert isinstance(source, str) #if isinstance(source, str): @@ -677,14 +674,9 @@ def runsource(self, source): # self.tkconsole.resetoutput() # self.write("Unsupported characters in input\n") # return - try: - # InteractiveInterpreter.runsource() calls its runcode() method, - # which is overridden (see below) - return InteractiveInterpreter.runsource(self, source, filename) - finally: - if self.save_warnings_filters is not None: - warnings.filters[:] = self.save_warnings_filters - self.save_warnings_filters = None + # InteractiveInterpreter.runsource() calls its runcode() method, + # which is overridden (see below) + return InteractiveInterpreter.runsource(self, source, filename) def stuffsource(self, source): "Stuff source in the filename cache" @@ -763,9 +755,6 @@ def runcode(self, code): if self.tkconsole.executing: self.interp.restart_subprocess() self.checklinecache() - if self.save_warnings_filters is not None: - warnings.filters[:] = self.save_warnings_filters - self.save_warnings_filters = None debugger = self.debugger try: self.tkconsole.beginexecuting() diff --git a/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst b/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst new file mode 100644 index 000000000000..1a1e8a59816a --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst @@ -0,0 +1,2 @@ +Properly handle user input warnings in IDLE shell. Cease turning +SyntaxWarnings into SyntaxErrors. From webhook-mailer at python.org Mon Aug 26 03:04:39 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 07:04:39 -0000 Subject: [Python-checkins] bpo-37805: Add tests for json.dump(..., skipkeys=True) (GH-15489) Message-ID: https://github.com/python/cpython/commit/44cd86bbdddb1f7b05deba2c1986a1e98f992429 commit: 44cd86bbdddb1f7b05deba2c1986a1e98f992429 branch: master author: Dong-hee Na committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-26T00:04:35-07:00 summary: bpo-37805: Add tests for json.dump(..., skipkeys=True) (GH-15489) https://bugs.python.org/issue37805 Automerge-Triggered-By: @methane files: A Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst M Lib/test/test_json/test_dump.py diff --git a/Lib/test/test_json/test_dump.py b/Lib/test/test_json/test_dump.py index fd0d86b392ce..13b40020781b 100644 --- a/Lib/test/test_json/test_dump.py +++ b/Lib/test/test_json/test_dump.py @@ -12,6 +12,16 @@ def test_dump(self): def test_dumps(self): self.assertEqual(self.dumps({}), '{}') + def test_dump_skipkeys(self): + v = {b'invalid_key': False, 'valid_key': True} + with self.assertRaises(TypeError): + self.json.dumps(v) + + s = self.json.dumps(v, skipkeys=True) + o = self.json.loads(s) + self.assertIn('valid_key', o) + self.assertNotIn(b'invalid_key', o) + def test_encode_truefalse(self): self.assertEqual(self.dumps( {True: False, False: True}, sort_keys=True), diff --git a/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst b/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst new file mode 100644 index 000000000000..478c38c3d4c5 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst @@ -0,0 +1 @@ +Add tests for json.dump(..., skipkeys=True). Patch by Dong-hee Na. From webhook-mailer at python.org Mon Aug 26 03:13:26 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 26 Aug 2019 07:13:26 -0000 Subject: [Python-checkins] bpo-36917: Add default implementation of ast.NodeVisitor.visit_Constant(). (GH-15490) Message-ID: https://github.com/python/cpython/commit/c3ea41e9bf100a5396b851488c3efe208e5e2179 commit: c3ea41e9bf100a5396b851488c3efe208e5e2179 branch: master author: Serhiy Storchaka committer: GitHub date: 2019-08-26T10:13:19+03:00 summary: bpo-36917: Add default implementation of ast.NodeVisitor.visit_Constant(). (GH-15490) It emits a deprecation warning and calls corresponding method visit_Num(), visit_Str(), etc. files: A Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst M Doc/library/ast.rst M Doc/whatsnew/3.8.rst M Lib/ast.py M Lib/test/test_ast.py diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 1e718382589c..3d2c420bc224 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -275,6 +275,13 @@ and classes for traversing abstract syntax trees: during traversal. For this a special visitor exists (:class:`NodeTransformer`) that allows modifications. + .. deprecated:: 3.8 + + Methods :meth:`visit_Num`, :meth:`visit_Str`, :meth:`visit_Bytes`, + :meth:`visit_NameConstant` and :meth:`visit_Ellipsis` are deprecated + now and will not be called in future Python versions. Add the + :meth:`visit_Constant` method to handle all constant nodes. + .. class:: NodeTransformer() diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 0294e9a0830b..cd31cf6db6e8 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -1360,6 +1360,13 @@ Deprecated versions. :class:`~ast.Constant` should be used instead. (Contributed by Serhiy Storchaka in :issue:`32892`.) +* :class:`ast.NodeVisitor` methods ``visit_Num()``, ``visit_Str()``, + ``visit_Bytes()``, ``visit_NameConstant()`` and ``visit_Ellipsis()`` are + deprecated now and will not be called in future Python versions. + Add the :meth:`~ast.NodeVisitor.visit_Constant` method to handle all + constant nodes. + (Contributed by Serhiy Storchaka in :issue:`36917`.) + * The following functions and methods are deprecated in the :mod:`gettext` module: :func:`~gettext.lgettext`, :func:`~gettext.ldgettext`, :func:`~gettext.lngettext` and :func:`~gettext.ldngettext`. diff --git a/Lib/ast.py b/Lib/ast.py index ffeba179e510..1e639d11feec 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -360,6 +360,27 @@ def generic_visit(self, node): elif isinstance(value, AST): self.visit(value) + def visit_Constant(self, node): + value = node.value + type_name = _const_node_type_names.get(type(value)) + if type_name is None: + for cls, name in _const_node_type_names.items(): + if isinstance(value, cls): + type_name = name + break + if type_name is not None: + method = 'visit_' + type_name + try: + visitor = getattr(self, method) + except AttributeError: + pass + else: + import warnings + warnings.warn(f"{method} is deprecated; add visit_Constant", + DeprecationWarning, 2) + return visitor(node) + return self.generic_visit(node) + class NodeTransformer(NodeVisitor): """ @@ -487,3 +508,13 @@ def __new__(cls, *args, **kwargs): _const_types_not = { Num: (bool,), } +_const_node_type_names = { + bool: 'NameConstant', # should be before int + type(None): 'NameConstant', + int: 'Num', + float: 'Num', + complex: 'Num', + str: 'Str', + bytes: 'Bytes', + type(...): 'Ellipsis', +} diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index f35d9e6f5451..3d12397ef683 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -3,6 +3,7 @@ import os import sys import unittest +import warnings import weakref from textwrap import dedent @@ -1662,6 +1663,56 @@ class C: self.assertEqual(ast.get_source_segment(s, cdef.body[0], padded=True), s_method) +class NodeVisitorTests(unittest.TestCase): + def test_old_constant_nodes(self): + class Visitor(ast.NodeVisitor): + def visit_Num(self, node): + log.append((node.lineno, 'Num', node.n)) + def visit_Str(self, node): + log.append((node.lineno, 'Str', node.s)) + def visit_Bytes(self, node): + log.append((node.lineno, 'Bytes', node.s)) + def visit_NameConstant(self, node): + log.append((node.lineno, 'NameConstant', node.value)) + def visit_Ellipsis(self, node): + log.append((node.lineno, 'Ellipsis', ...)) + mod = ast.parse(dedent('''\ + i = 42 + f = 4.25 + c = 4.25j + s = 'string' + b = b'bytes' + t = True + n = None + e = ... + ''')) + visitor = Visitor() + log = [] + with warnings.catch_warnings(record=True) as wlog: + warnings.filterwarnings('always', '', DeprecationWarning) + visitor.visit(mod) + self.assertEqual(log, [ + (1, 'Num', 42), + (2, 'Num', 4.25), + (3, 'Num', 4.25j), + (4, 'Str', 'string'), + (5, 'Bytes', b'bytes'), + (6, 'NameConstant', True), + (7, 'NameConstant', None), + (8, 'Ellipsis', ...), + ]) + self.assertEqual([str(w.message) for w in wlog], [ + 'visit_Num is deprecated; add visit_Constant', + 'visit_Num is deprecated; add visit_Constant', + 'visit_Num is deprecated; add visit_Constant', + 'visit_Str is deprecated; add visit_Constant', + 'visit_Bytes is deprecated; add visit_Constant', + 'visit_NameConstant is deprecated; add visit_Constant', + 'visit_NameConstant is deprecated; add visit_Constant', + 'visit_Ellipsis is deprecated; add visit_Constant', + ]) + + def main(): if __name__ != '__main__': return diff --git a/Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst b/Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst new file mode 100644 index 000000000000..3509a7530b89 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst @@ -0,0 +1,3 @@ +Add default implementation of the :meth:`ast.NodeVisitor.visit_Constant` +method which emits a deprecation warning and calls corresponding methody +``visit_Num()``, ``visit_Str()``, etc. From webhook-mailer at python.org Mon Aug 26 03:17:47 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Mon, 26 Aug 2019 07:17:47 -0000 Subject: [Python-checkins] bpo-27575: port set intersection logic into dictview intersection (GH-7696) Message-ID: https://github.com/python/cpython/commit/998cf1f03a61de8a0cd3811faa97973d4022bc55 commit: 998cf1f03a61de8a0cd3811faa97973d4022bc55 branch: master author: Forest Gregg committer: Raymond Hettinger date: 2019-08-26T00:17:43-07:00 summary: bpo-27575: port set intersection logic into dictview intersection (GH-7696) files: A Misc/NEWS.d/next/Core and Builtins/2018-06-14-13-55-45.bpo-27575.mMYgzv.rst M Lib/test/test_dictviews.py M Objects/dictobject.c diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py index 2763cbfb4bbc..b15cfebc9891 100644 --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -92,6 +92,12 @@ def test_keys_set_operations(self): d1 = {'a': 1, 'b': 2} d2 = {'b': 3, 'c': 2} d3 = {'d': 4, 'e': 5} + d4 = {'d': 4} + + class CustomSet(set): + def intersection(self, other): + return CustomSet(super().intersection(other)) + self.assertEqual(d1.keys() & d1.keys(), {'a', 'b'}) self.assertEqual(d1.keys() & d2.keys(), {'b'}) self.assertEqual(d1.keys() & d3.keys(), set()) @@ -99,6 +105,14 @@ def test_keys_set_operations(self): self.assertEqual(d1.keys() & set(d2.keys()), {'b'}) self.assertEqual(d1.keys() & set(d3.keys()), set()) self.assertEqual(d1.keys() & tuple(d1.keys()), {'a', 'b'}) + self.assertEqual(d3.keys() & d4.keys(), {'d'}) + self.assertEqual(d4.keys() & d3.keys(), {'d'}) + self.assertEqual(d4.keys() & set(d3.keys()), {'d'}) + self.assertIsInstance(d4.keys() & frozenset(d3.keys()), set) + self.assertIsInstance(frozenset(d3.keys()) & d4.keys(), set) + self.assertIs(type(d4.keys() & CustomSet(d3.keys())), set) + self.assertIs(type(d1.keys() & []), set) + self.assertIs(type([] & d1.keys()), set) self.assertEqual(d1.keys() | d1.keys(), {'a', 'b'}) self.assertEqual(d1.keys() | d2.keys(), {'a', 'b', 'c'}) diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-06-14-13-55-45.bpo-27575.mMYgzv.rst b/Misc/NEWS.d/next/Core and Builtins/2018-06-14-13-55-45.bpo-27575.mMYgzv.rst new file mode 100644 index 000000000000..2c250dcceb28 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-06-14-13-55-45.bpo-27575.mMYgzv.rst @@ -0,0 +1,2 @@ +Improve speed of dictview intersection by directly using set intersection +logic. Patch by David Su. diff --git a/Objects/dictobject.c b/Objects/dictobject.c index f168ad5d2f00..fec3a87e9f5d 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -4169,24 +4169,97 @@ dictviews_sub(PyObject* self, PyObject *other) return result; } -PyObject* +static int +dictitems_contains(_PyDictViewObject *dv, PyObject *obj); + +PyObject * _PyDictView_Intersect(PyObject* self, PyObject *other) { - PyObject *result = PySet_New(self); + PyObject *result; + PyObject *it; + PyObject *key; + Py_ssize_t len_self; + int rv; + int (*dict_contains)(_PyDictViewObject *, PyObject *); PyObject *tmp; - _Py_IDENTIFIER(intersection_update); + /* Python interpreter swaps parameters when dict view + is on right side of & */ + if (!PyDictViewSet_Check(self)) { + PyObject *tmp = other; + other = self; + self = tmp; + } + + len_self = dictview_len((_PyDictViewObject *)self); + + /* if other is a set and self is smaller than other, + reuse set intersection logic */ + if (Py_TYPE(other) == &PySet_Type && len_self <= PyObject_Size(other)) { + _Py_IDENTIFIER(intersection); + return _PyObject_CallMethodIdObjArgs(other, &PyId_intersection, self, NULL); + } + + /* if other is another dict view, and it is bigger than self, + swap them */ + if (PyDictViewSet_Check(other)) { + Py_ssize_t len_other = dictview_len((_PyDictViewObject *)other); + if (len_other > len_self) { + PyObject *tmp = other; + other = self; + self = tmp; + } + } + + /* at this point, two things should be true + 1. self is a dictview + 2. if other is a dictview then it is smaller than self */ + result = PySet_New(NULL); if (result == NULL) return NULL; + it = PyObject_GetIter(other); + + _Py_IDENTIFIER(intersection_update); tmp = _PyObject_CallMethodIdOneArg(result, &PyId_intersection_update, other); if (tmp == NULL) { Py_DECREF(result); return NULL; } - Py_DECREF(tmp); + + if (PyDictKeys_Check(self)) { + dict_contains = dictkeys_contains; + } + /* else PyDictItems_Check(self) */ + else { + dict_contains = dictitems_contains; + } + + while ((key = PyIter_Next(it)) != NULL) { + rv = dict_contains((_PyDictViewObject *)self, key); + if (rv < 0) { + goto error; + } + if (rv) { + if (PySet_Add(result, key)) { + goto error; + } + } + Py_DECREF(key); + } + Py_DECREF(it); + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } return result; + +error: + Py_DECREF(it); + Py_DECREF(result); + Py_DECREF(key); + return NULL; } static PyObject* From webhook-mailer at python.org Mon Aug 26 03:19:24 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Mon, 26 Aug 2019 07:19:24 -0000 Subject: [Python-checkins] bpo-15542: Documentation incorrectly suggests __init__ called after direct __new__ call (GH-15478) (GH-15506) Message-ID: https://github.com/python/cpython/commit/c841fb9e065c393bba5d5505238f7e286f1dcfc6 commit: c841fb9e065c393bba5d5505238f7e286f1dcfc6 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-26T00:19:17-07:00 summary: bpo-15542: Documentation incorrectly suggests __init__ called after direct __new__ call (GH-15478) (GH-15506) (cherry picked from commit 6b16d938d6d1ccb443815e20e8812deed274dc09) Co-authored-by: Joannah Nanjekye <33177550+nanjekyejoannah at users.noreply.github.com> files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 1dd8e42ef87e..d1702ccb6417 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1166,10 +1166,10 @@ Basic customization with appropriate arguments and then modifying the newly-created instance as necessary before returning it. - If :meth:`__new__` returns an instance of *cls*, then the new instance's - :meth:`__init__` method will be invoked like ``__init__(self[, ...])``, where - *self* is the new instance and the remaining arguments are the same as were - passed to :meth:`__new__`. + If :meth:`__new__` is invoked during object construction and it returns an + instance or subclass of *cls*, then the new instance?s :meth:`__init__` method + will be invoked like ``__init__(self[, ...])``, where *self* is the new instance + and the remaining arguments are the same as were passed to the object constructor. If :meth:`__new__` does not return an instance of *cls*, then the new instance's :meth:`__init__` method will not be invoked. From webhook-mailer at python.org Mon Aug 26 03:27:35 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 07:27:35 -0000 Subject: [Python-checkins] bpo-37805: Add tests for json.dump(..., skipkeys=True) (GH-15489) Message-ID: https://github.com/python/cpython/commit/a3875171d746f90f49adfcaa015525b20a3874d3 commit: a3875171d746f90f49adfcaa015525b20a3874d3 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T00:27:31-07:00 summary: bpo-37805: Add tests for json.dump(..., skipkeys=True) (GH-15489) https://bugs.python.org/issue37805 Automerge-Triggered-By: @methane (cherry picked from commit 44cd86bbdddb1f7b05deba2c1986a1e98f992429) Co-authored-by: Dong-hee Na files: A Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst M Lib/test/test_json/test_dump.py diff --git a/Lib/test/test_json/test_dump.py b/Lib/test/test_json/test_dump.py index fd0d86b392ce..13b40020781b 100644 --- a/Lib/test/test_json/test_dump.py +++ b/Lib/test/test_json/test_dump.py @@ -12,6 +12,16 @@ def test_dump(self): def test_dumps(self): self.assertEqual(self.dumps({}), '{}') + def test_dump_skipkeys(self): + v = {b'invalid_key': False, 'valid_key': True} + with self.assertRaises(TypeError): + self.json.dumps(v) + + s = self.json.dumps(v, skipkeys=True) + o = self.json.loads(s) + self.assertIn('valid_key', o) + self.assertNotIn(b'invalid_key', o) + def test_encode_truefalse(self): self.assertEqual(self.dumps( {True: False, False: True}, sort_keys=True), diff --git a/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst b/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst new file mode 100644 index 000000000000..478c38c3d4c5 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst @@ -0,0 +1 @@ +Add tests for json.dump(..., skipkeys=True). Patch by Dong-hee Na. From webhook-mailer at python.org Mon Aug 26 03:36:41 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 07:36:41 -0000 Subject: [Python-checkins] bpo-37805: Add tests for json.dump(..., skipkeys=True) (GH-15489) Message-ID: https://github.com/python/cpython/commit/a976283821ab73ba080da47cbe95802ce66bb0a4 commit: a976283821ab73ba080da47cbe95802ce66bb0a4 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T00:36:36-07:00 summary: bpo-37805: Add tests for json.dump(..., skipkeys=True) (GH-15489) https://bugs.python.org/issue37805 Automerge-Triggered-By: @methane (cherry picked from commit 44cd86bbdddb1f7b05deba2c1986a1e98f992429) Co-authored-by: Dong-hee Na files: A Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst M Lib/test/test_json/test_dump.py diff --git a/Lib/test/test_json/test_dump.py b/Lib/test/test_json/test_dump.py index fd0d86b392ce..13b40020781b 100644 --- a/Lib/test/test_json/test_dump.py +++ b/Lib/test/test_json/test_dump.py @@ -12,6 +12,16 @@ def test_dump(self): def test_dumps(self): self.assertEqual(self.dumps({}), '{}') + def test_dump_skipkeys(self): + v = {b'invalid_key': False, 'valid_key': True} + with self.assertRaises(TypeError): + self.json.dumps(v) + + s = self.json.dumps(v, skipkeys=True) + o = self.json.loads(s) + self.assertIn('valid_key', o) + self.assertNotIn(b'invalid_key', o) + def test_encode_truefalse(self): self.assertEqual(self.dumps( {True: False, False: True}, sort_keys=True), diff --git a/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst b/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst new file mode 100644 index 000000000000..478c38c3d4c5 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst @@ -0,0 +1 @@ +Add tests for json.dump(..., skipkeys=True). Patch by Dong-hee Na. From webhook-mailer at python.org Mon Aug 26 03:43:40 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 26 Aug 2019 07:43:40 -0000 Subject: [Python-checkins] [3.8] bpo-36917: Add default implementation of ast.NodeVisitor.visit_Constant(). (GH-15490) (GH-15509) Message-ID: https://github.com/python/cpython/commit/522a394a72f107ca55701371529b5e4ed20c9fff commit: 522a394a72f107ca55701371529b5e4ed20c9fff branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2019-08-26T10:43:33+03:00 summary: [3.8] bpo-36917: Add default implementation of ast.NodeVisitor.visit_Constant(). (GH-15490) (GH-15509) It emits a deprecation warning and calls corresponding method visit_Num(), visit_Str(), etc. (cherry picked from commit c3ea41e9bf100a5396b851488c3efe208e5e2179) files: A Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst M Doc/library/ast.rst M Doc/whatsnew/3.8.rst M Lib/ast.py M Lib/test/test_ast.py diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 1e718382589c..3d2c420bc224 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -275,6 +275,13 @@ and classes for traversing abstract syntax trees: during traversal. For this a special visitor exists (:class:`NodeTransformer`) that allows modifications. + .. deprecated:: 3.8 + + Methods :meth:`visit_Num`, :meth:`visit_Str`, :meth:`visit_Bytes`, + :meth:`visit_NameConstant` and :meth:`visit_Ellipsis` are deprecated + now and will not be called in future Python versions. Add the + :meth:`visit_Constant` method to handle all constant nodes. + .. class:: NodeTransformer() diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 0294e9a0830b..cd31cf6db6e8 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -1360,6 +1360,13 @@ Deprecated versions. :class:`~ast.Constant` should be used instead. (Contributed by Serhiy Storchaka in :issue:`32892`.) +* :class:`ast.NodeVisitor` methods ``visit_Num()``, ``visit_Str()``, + ``visit_Bytes()``, ``visit_NameConstant()`` and ``visit_Ellipsis()`` are + deprecated now and will not be called in future Python versions. + Add the :meth:`~ast.NodeVisitor.visit_Constant` method to handle all + constant nodes. + (Contributed by Serhiy Storchaka in :issue:`36917`.) + * The following functions and methods are deprecated in the :mod:`gettext` module: :func:`~gettext.lgettext`, :func:`~gettext.ldgettext`, :func:`~gettext.lngettext` and :func:`~gettext.ldngettext`. diff --git a/Lib/ast.py b/Lib/ast.py index ffeba179e510..da47825be272 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -360,6 +360,27 @@ def generic_visit(self, node): elif isinstance(value, AST): self.visit(value) + def visit_Constant(self, node): + value = node.value + type_name = _const_node_type_names.get(type(value)) + if type_name is None: + for cls, name in _const_node_type_names.items(): + if isinstance(value, cls): + type_name = name + break + if type_name is not None: + method = 'visit_' + type_name + try: + visitor = getattr(self, method) + except AttributeError: + pass + else: + import warnings + warnings.warn(f"{method} is deprecated; add visit_Constant", + PendingDeprecationWarning, 2) + return visitor(node) + return self.generic_visit(node) + class NodeTransformer(NodeVisitor): """ @@ -487,3 +508,13 @@ def __new__(cls, *args, **kwargs): _const_types_not = { Num: (bool,), } +_const_node_type_names = { + bool: 'NameConstant', # should be before int + type(None): 'NameConstant', + int: 'Num', + float: 'Num', + complex: 'Num', + str: 'Str', + bytes: 'Bytes', + type(...): 'Ellipsis', +} diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 5c37a5fbed6e..47571c915eb7 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -3,6 +3,7 @@ import os import sys import unittest +import warnings import weakref from textwrap import dedent @@ -1662,6 +1663,56 @@ class C: self.assertEqual(ast.get_source_segment(s, cdef.body[0], padded=True), s_method) +class NodeVisitorTests(unittest.TestCase): + def test_old_constant_nodes(self): + class Visitor(ast.NodeVisitor): + def visit_Num(self, node): + log.append((node.lineno, 'Num', node.n)) + def visit_Str(self, node): + log.append((node.lineno, 'Str', node.s)) + def visit_Bytes(self, node): + log.append((node.lineno, 'Bytes', node.s)) + def visit_NameConstant(self, node): + log.append((node.lineno, 'NameConstant', node.value)) + def visit_Ellipsis(self, node): + log.append((node.lineno, 'Ellipsis', ...)) + mod = ast.parse(dedent('''\ + i = 42 + f = 4.25 + c = 4.25j + s = 'string' + b = b'bytes' + t = True + n = None + e = ... + ''')) + visitor = Visitor() + log = [] + with warnings.catch_warnings(record=True) as wlog: + warnings.filterwarnings('always', '', PendingDeprecationWarning) + visitor.visit(mod) + self.assertEqual(log, [ + (1, 'Num', 42), + (2, 'Num', 4.25), + (3, 'Num', 4.25j), + (4, 'Str', 'string'), + (5, 'Bytes', b'bytes'), + (6, 'NameConstant', True), + (7, 'NameConstant', None), + (8, 'Ellipsis', ...), + ]) + self.assertEqual([str(w.message) for w in wlog], [ + 'visit_Num is deprecated; add visit_Constant', + 'visit_Num is deprecated; add visit_Constant', + 'visit_Num is deprecated; add visit_Constant', + 'visit_Str is deprecated; add visit_Constant', + 'visit_Bytes is deprecated; add visit_Constant', + 'visit_NameConstant is deprecated; add visit_Constant', + 'visit_NameConstant is deprecated; add visit_Constant', + 'visit_Ellipsis is deprecated; add visit_Constant', + ]) + + def main(): if __name__ != '__main__': return diff --git a/Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst b/Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst new file mode 100644 index 000000000000..3509a7530b89 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst @@ -0,0 +1,3 @@ +Add default implementation of the :meth:`ast.NodeVisitor.visit_Constant` +method which emits a deprecation warning and calls corresponding methody +``visit_Num()``, ``visit_Str()``, etc. From webhook-mailer at python.org Mon Aug 26 05:51:18 2019 From: webhook-mailer at python.org (Andrew Svetlov) Date: Mon, 26 Aug 2019 09:51:18 -0000 Subject: [Python-checkins] bpo-34679: Restore instantiation Windows IOCP event loop from non-main thread (#15492) Message-ID: https://github.com/python/cpython/commit/1c0600998681295735a18690fae184b0c9a4ca51 commit: 1c0600998681295735a18690fae184b0c9a4ca51 branch: master author: Andrew Svetlov committer: GitHub date: 2019-08-26T12:51:08+03:00 summary: bpo-34679: Restore instantiation Windows IOCP event loop from non-main thread (#15492) * Restore running proactor event loop from non-main thread Co-Authored-By: Kyle Stanley files: A Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst M Lib/asyncio/proactor_events.py M Lib/test/test_asyncio/test_windows_events.py diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 9b8ae064a892..229f56e6bb9e 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -11,6 +11,7 @@ import socket import warnings import signal +import threading import collections from . import base_events @@ -627,7 +628,9 @@ def __init__(self, proactor): proactor.set_loop(self) self._make_self_pipe() self_no = self._csock.fileno() - signal.set_wakeup_fd(self_no) + if threading.current_thread() is threading.main_thread(): + # wakeup fd can only be installed to a file descriptor from the main thread + signal.set_wakeup_fd(self_no) def _make_socket_transport(self, sock, protocol, waiter=None, extra=None, server=None): diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index 64543268b1ef..d0ba19391fa0 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -59,6 +59,25 @@ def SIGINT_after_delay(): thread.join() +class ProactorMultithreading(test_utils.TestCase): + def test_run_from_nonmain_thread(self): + finished = False + + async def coro(): + await asyncio.sleep(0) + + def func(): + nonlocal finished + loop = asyncio.new_event_loop() + loop.run_until_complete(coro()) + finished = True + + thread = threading.Thread(target=func) + thread.start() + thread.join() + self.assertTrue(finished) + + class ProactorTests(test_utils.TestCase): def setUp(self): diff --git a/Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst b/Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst new file mode 100644 index 000000000000..785b06b6482c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst @@ -0,0 +1 @@ +Restores instantiation of Windows IOCP event loops from the non-main thread. From webhook-mailer at python.org Mon Aug 26 06:14:59 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 10:14:59 -0000 Subject: [Python-checkins] bpo-34679: Restore instantiation Windows IOCP event loop from non-main thread (GH-15492) Message-ID: https://github.com/python/cpython/commit/69d22b8fee442c12829a1032a72489c8133de271 commit: 69d22b8fee442c12829a1032a72489c8133de271 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T03:14:54-07:00 summary: bpo-34679: Restore instantiation Windows IOCP event loop from non-main thread (GH-15492) * Restore running proactor event loop from non-main thread Co-Authored-By: Kyle Stanley (cherry picked from commit 1c0600998681295735a18690fae184b0c9a4ca51) Co-authored-by: Andrew Svetlov files: A Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst M Lib/asyncio/proactor_events.py M Lib/test/test_asyncio/test_windows_events.py diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 9b8ae064a892..229f56e6bb9e 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -11,6 +11,7 @@ import socket import warnings import signal +import threading import collections from . import base_events @@ -627,7 +628,9 @@ def __init__(self, proactor): proactor.set_loop(self) self._make_self_pipe() self_no = self._csock.fileno() - signal.set_wakeup_fd(self_no) + if threading.current_thread() is threading.main_thread(): + # wakeup fd can only be installed to a file descriptor from the main thread + signal.set_wakeup_fd(self_no) def _make_socket_transport(self, sock, protocol, waiter=None, extra=None, server=None): diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index 64543268b1ef..d0ba19391fa0 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -59,6 +59,25 @@ def SIGINT_after_delay(): thread.join() +class ProactorMultithreading(test_utils.TestCase): + def test_run_from_nonmain_thread(self): + finished = False + + async def coro(): + await asyncio.sleep(0) + + def func(): + nonlocal finished + loop = asyncio.new_event_loop() + loop.run_until_complete(coro()) + finished = True + + thread = threading.Thread(target=func) + thread.start() + thread.join() + self.assertTrue(finished) + + class ProactorTests(test_utils.TestCase): def setUp(self): diff --git a/Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst b/Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst new file mode 100644 index 000000000000..785b06b6482c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst @@ -0,0 +1 @@ +Restores instantiation of Windows IOCP event loops from the non-main thread. From webhook-mailer at python.org Mon Aug 26 07:49:13 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 26 Aug 2019 11:49:13 -0000 Subject: [Python-checkins] bpo-36917: Backport basic test for ast.NodeVisitor. (GH-15511) Message-ID: https://github.com/python/cpython/commit/c2388622923c81b5f06b0c9a5ce821fc03c624b9 commit: c2388622923c81b5f06b0c9a5ce821fc03c624b9 branch: 3.7 author: Serhiy Storchaka committer: GitHub date: 2019-08-26T14:48:55+03:00 summary: bpo-36917: Backport basic test for ast.NodeVisitor. (GH-15511) files: M Lib/test/test_ast.py diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 72f8467847e8..7614d40e3e5c 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -4,6 +4,7 @@ import sys import unittest import weakref +from textwrap import dedent from test import support @@ -1123,6 +1124,44 @@ def test_literal_eval(self): self.assertEqual(ast.literal_eval(binop), 10+20j) +class NodeVisitorTests(unittest.TestCase): + def test_old_constant_nodes(self): + class Visitor(ast.NodeVisitor): + def visit_Num(self, node): + log.append((node.lineno, 'Num', node.n)) + def visit_Str(self, node): + log.append((node.lineno, 'Str', node.s)) + def visit_Bytes(self, node): + log.append((node.lineno, 'Bytes', node.s)) + def visit_NameConstant(self, node): + log.append((node.lineno, 'NameConstant', node.value)) + def visit_Ellipsis(self, node): + log.append((node.lineno, 'Ellipsis', ...)) + mod = ast.parse(dedent('''\ + i = 42 + f = 4.25 + c = 4.25j + s = 'string' + b = b'bytes' + t = True + n = None + e = ... + ''')) + visitor = Visitor() + log = [] + visitor.visit(mod) + self.assertEqual(log, [ + (1, 'Num', 42), + (2, 'Num', 4.25), + (3, 'Num', 4.25j), + (4, 'Str', 'string'), + (5, 'Bytes', b'bytes'), + (6, 'NameConstant', True), + (7, 'NameConstant', None), + (8, 'Ellipsis', ...), + ]) + + def main(): if __name__ != '__main__': return From webhook-mailer at python.org Mon Aug 26 10:52:47 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 26 Aug 2019 14:52:47 -0000 Subject: [Python-checkins] bpo-37947: Adjust correctly the recursion level in symtable for named expressions (GH-15499) Message-ID: https://github.com/python/cpython/commit/0e4ea16336685cf3fa353d8c54af59b45b2d5c33 commit: 0e4ea16336685cf3fa353d8c54af59b45b2d5c33 branch: master author: Pablo Galindo committer: GitHub date: 2019-08-26T15:52:25+01:00 summary: bpo-37947: Adjust correctly the recursion level in symtable for named expressions (GH-15499) files: A Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947.mzAQtB.rst M Python/symtable.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947.mzAQtB.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947.mzAQtB.rst new file mode 100644 index 000000000000..2b3b72367030 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947.mzAQtB.rst @@ -0,0 +1,2 @@ +Adjust correctly the recursion level in the symtable generation for named +expressions. Patch by Pablo Galindo. diff --git a/Python/symtable.c b/Python/symtable.c index e48baa808d41..18ea57690b5d 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1508,6 +1508,7 @@ symtable_handle_namedexpr(struct symtable *st, expr_ty e) } VISIT(st, expr, e->v.NamedExpr.value); VISIT(st, expr, e->v.NamedExpr.target); + VISIT_QUIT(st, 1); } static int @@ -1520,7 +1521,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e) } switch (e->kind) { case NamedExpr_kind: - symtable_handle_namedexpr(st, e); + if(!symtable_handle_namedexpr(st, e)) + VISIT_QUIT(st, 0); break; case BoolOp_kind: VISIT_SEQ(st, expr, e->v.BoolOp.values); From webhook-mailer at python.org Mon Aug 26 11:12:54 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 26 Aug 2019 15:12:54 -0000 Subject: [Python-checkins] Remove leftovers from the times when long long wasn't required (GH-15501) Message-ID: https://github.com/python/cpython/commit/52c1a6a15a471f75b775309ed1120d05f69010ca commit: 52c1a6a15a471f75b775309ed1120d05f69010ca branch: master author: Sergey Fedoseev committer: Pablo Galindo date: 2019-08-26T16:12:47+01:00 summary: Remove leftovers from the times when long long wasn't required (GH-15501) In a38e9d139929a227e3899fbb638bc46c6cc6d8ba pyconfig.h.in was manually edited and that edit was overwritten when running autoreconf. files: M configure.ac M pyconfig.h.in diff --git a/configure.ac b/configure.ac index 8566d4338469..49ee3f6898cc 100644 --- a/configure.ac +++ b/configure.ac @@ -2313,7 +2313,7 @@ if test "$ac_cv_sizeof_off_t" -gt "$ac_cv_sizeof_long" -a \ "$ac_cv_sizeof_long_long" -ge "$ac_cv_sizeof_off_t"; then AC_DEFINE(HAVE_LARGEFILE_SUPPORT, 1, [Defined to enable large file support when an off_t is bigger than a long - and long long is available and at least as big as an off_t. You may need + and long long is at least as big as an off_t. You may need to add some flags for configuration and compilation to enable this mode. (For Solaris and Linux, the necessary defines are already defined.)]) AC_MSG_RESULT(yes) diff --git a/pyconfig.h.in b/pyconfig.h.in index ffdc49514e29..840fbcdb2a6f 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -569,9 +569,9 @@ #undef HAVE_LANGINFO_H /* Defined to enable large file support when an off_t is bigger than a long - and long long is at least as big as an off_t. You may need to - add some flags for configuration and compilation to enable this mode. (For - Solaris and Linux, the necessary defines are already defined.) */ + and long long is at least as big as an off_t. You may need to add some + flags for configuration and compilation to enable this mode. (For Solaris + and Linux, the necessary defines are already defined.) */ #undef HAVE_LARGEFILE_SUPPORT /* Define to 1 if you have the 'lchflags' function. */ From webhook-mailer at python.org Mon Aug 26 11:14:11 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 26 Aug 2019 15:14:11 -0000 Subject: [Python-checkins] bpo-37954: Fix reference leak in the symtable (GH-15514) Message-ID: https://github.com/python/cpython/commit/4901dc46da5ecb131f8d902a0fbd704934f209e1 commit: 4901dc46da5ecb131f8d902a0fbd704934f209e1 branch: master author: Pablo Galindo committer: GitHub date: 2019-08-26T16:14:07+01:00 summary: bpo-37954: Fix reference leak in the symtable (GH-15514) files: M Python/symtable.c diff --git a/Python/symtable.c b/Python/symtable.c index 18ea57690b5d..2795e0f1115b 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -999,7 +999,9 @@ symtable_lookup(struct symtable *st, PyObject *name) PyObject *mangled = _Py_Mangle(st->st_private, name); if (!mangled) return 0; - return _PyST_GetSymbol(st->st_cur, mangled); + long ret = _PyST_GetSymbol(st->st_cur, mangled); + Py_DECREF(mangled); + return ret; } static int From webhook-mailer at python.org Mon Aug 26 11:20:46 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 26 Aug 2019 15:20:46 -0000 Subject: [Python-checkins] Fix typo: Pyssize_t => Py_ssize_t (GH-15411) Message-ID: https://github.com/python/cpython/commit/b3b9619f5e1e7ebe3fbb73eae4ec878312056a90 commit: b3b9619f5e1e7ebe3fbb73eae4ec878312056a90 branch: master author: Sergey Fedoseev committer: Pablo Galindo date: 2019-08-26T16:20:42+01:00 summary: Fix typo: Pyssize_t => Py_ssize_t (GH-15411) files: M Doc/data/refcounts.dat diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index fda347eab102..cfed1bd50311 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2462,7 +2462,7 @@ PyUnicode_FromWideChar:Py_ssize_t:size:: PyUnicode_AsWideChar:Py_ssize_t::: PyUnicode_AsWideChar:PyObject*:*unicode:0: PyUnicode_AsWideChar:wchar_t*:w:: -PyUnicode_AsWideChar:Pyssize_t:size:: +PyUnicode_AsWideChar:Py_ssize_t:size:: PyUnicode_AsWideCharString:wchar_t*::: PyUnicode_AsWideCharString:PyObject*:unicode:0: From webhook-mailer at python.org Mon Aug 26 11:27:35 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 26 Aug 2019 15:27:35 -0000 Subject: [Python-checkins] [3.8] bpo-37947: Adjust correctly the recursion level in symtable for named expressions (GH-15499) (GH-15515) Message-ID: https://github.com/python/cpython/commit/3769425abd8da9a59b9645baf90ef49b9c69c140 commit: 3769425abd8da9a59b9645baf90ef49b9c69c140 branch: 3.8 author: Pablo Galindo committer: GitHub date: 2019-08-26T16:27:31+01:00 summary: [3.8] bpo-37947: Adjust correctly the recursion level in symtable for named expressions (GH-15499) (GH-15515) (cherry picked from commit 0e4ea16336685cf3fa353d8c54af59b45b2d5c33) Co-authored-by: Pablo Galindo files: A Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947.mzAQtB.rst M Python/symtable.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947.mzAQtB.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947.mzAQtB.rst new file mode 100644 index 000000000000..2b3b72367030 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947.mzAQtB.rst @@ -0,0 +1,2 @@ +Adjust correctly the recursion level in the symtable generation for named +expressions. Patch by Pablo Galindo. diff --git a/Python/symtable.c b/Python/symtable.c index e48baa808d41..18ea57690b5d 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1508,6 +1508,7 @@ symtable_handle_namedexpr(struct symtable *st, expr_ty e) } VISIT(st, expr, e->v.NamedExpr.value); VISIT(st, expr, e->v.NamedExpr.target); + VISIT_QUIT(st, 1); } static int @@ -1520,7 +1521,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e) } switch (e->kind) { case NamedExpr_kind: - symtable_handle_namedexpr(st, e); + if(!symtable_handle_namedexpr(st, e)) + VISIT_QUIT(st, 0); break; case BoolOp_kind: VISIT_SEQ(st, expr, e->v.BoolOp.values); From webhook-mailer at python.org Mon Aug 26 11:33:54 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 15:33:54 -0000 Subject: [Python-checkins] Remove leftovers from the times when long long wasn't required (GH-15501) Message-ID: https://github.com/python/cpython/commit/82f4bfdbb053eea1c67159b2d73717a21eb89893 commit: 82f4bfdbb053eea1c67159b2d73717a21eb89893 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T08:33:49-07:00 summary: Remove leftovers from the times when long long wasn't required (GH-15501) In a38e9d139929a227e3899fbb638bc46c6cc6d8ba pyconfig.h.in was manually edited and that edit was overwritten when running autoreconf. (cherry picked from commit 52c1a6a15a471f75b775309ed1120d05f69010ca) Co-authored-by: Sergey Fedoseev files: M configure.ac M pyconfig.h.in diff --git a/configure.ac b/configure.ac index a2088897fc13..033a93cd3f3b 100644 --- a/configure.ac +++ b/configure.ac @@ -2313,7 +2313,7 @@ if test "$ac_cv_sizeof_off_t" -gt "$ac_cv_sizeof_long" -a \ "$ac_cv_sizeof_long_long" -ge "$ac_cv_sizeof_off_t"; then AC_DEFINE(HAVE_LARGEFILE_SUPPORT, 1, [Defined to enable large file support when an off_t is bigger than a long - and long long is available and at least as big as an off_t. You may need + and long long is at least as big as an off_t. You may need to add some flags for configuration and compilation to enable this mode. (For Solaris and Linux, the necessary defines are already defined.)]) AC_MSG_RESULT(yes) diff --git a/pyconfig.h.in b/pyconfig.h.in index ffdc49514e29..840fbcdb2a6f 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -569,9 +569,9 @@ #undef HAVE_LANGINFO_H /* Defined to enable large file support when an off_t is bigger than a long - and long long is at least as big as an off_t. You may need to - add some flags for configuration and compilation to enable this mode. (For - Solaris and Linux, the necessary defines are already defined.) */ + and long long is at least as big as an off_t. You may need to add some + flags for configuration and compilation to enable this mode. (For Solaris + and Linux, the necessary defines are already defined.) */ #undef HAVE_LARGEFILE_SUPPORT /* Define to 1 if you have the 'lchflags' function. */ From webhook-mailer at python.org Mon Aug 26 11:49:49 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 15:49:49 -0000 Subject: [Python-checkins] bpo-37954: Fix reference leak in the symtable (GH-15514) Message-ID: https://github.com/python/cpython/commit/ed8af33cce5554545d2bd079b23fe551d26fb4bd commit: ed8af33cce5554545d2bd079b23fe551d26fb4bd branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T08:49:44-07:00 summary: bpo-37954: Fix reference leak in the symtable (GH-15514) (cherry picked from commit 4901dc46da5ecb131f8d902a0fbd704934f209e1) Co-authored-by: Pablo Galindo files: M Python/symtable.c diff --git a/Python/symtable.c b/Python/symtable.c index 18ea57690b5d..2795e0f1115b 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -999,7 +999,9 @@ symtable_lookup(struct symtable *st, PyObject *name) PyObject *mangled = _Py_Mangle(st->st_private, name); if (!mangled) return 0; - return _PyST_GetSymbol(st->st_cur, mangled); + long ret = _PyST_GetSymbol(st->st_cur, mangled); + Py_DECREF(mangled); + return ret; } static int From webhook-mailer at python.org Mon Aug 26 11:54:30 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 15:54:30 -0000 Subject: [Python-checkins] Fix typo: Pyssize_t => Py_ssize_t (GH-15411) Message-ID: https://github.com/python/cpython/commit/54449dacc46721b1118721bf2b7e85500c7e44b2 commit: 54449dacc46721b1118721bf2b7e85500c7e44b2 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T08:54:26-07:00 summary: Fix typo: Pyssize_t => Py_ssize_t (GH-15411) (cherry picked from commit b3b9619f5e1e7ebe3fbb73eae4ec878312056a90) Co-authored-by: Sergey Fedoseev files: M Doc/data/refcounts.dat diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index fda347eab102..cfed1bd50311 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2462,7 +2462,7 @@ PyUnicode_FromWideChar:Py_ssize_t:size:: PyUnicode_AsWideChar:Py_ssize_t::: PyUnicode_AsWideChar:PyObject*:*unicode:0: PyUnicode_AsWideChar:wchar_t*:w:: -PyUnicode_AsWideChar:Pyssize_t:size:: +PyUnicode_AsWideChar:Py_ssize_t:size:: PyUnicode_AsWideCharString:wchar_t*::: PyUnicode_AsWideCharString:PyObject*:unicode:0: From webhook-mailer at python.org Mon Aug 26 12:12:55 2019 From: webhook-mailer at python.org (Ethan Furman) Date: Mon, 26 Aug 2019 16:12:55 -0000 Subject: [Python-checkins] correct roman numeral VII description (GH-15523) Message-ID: https://github.com/python/cpython/commit/77df9a157338f694b10961c44dfe48f7a39b3ad2 commit: 77df9a157338f694b10961c44dfe48f7a39b3ad2 branch: master author: Ethan Furman committer: GitHub date: 2019-08-26T09:12:50-07:00 summary: correct roman numeral VII description (GH-15523) files: M Doc/howto/unicode.rst diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst index 24c3235e4add..d5632bc799d2 100644 --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -57,7 +57,7 @@ their corresponding code points: ... 007B '{'; LEFT CURLY BRACKET ... - 2167 '?': ROMAN NUMERAL EIGHT + 2167 '?': ROMAN NUMERAL SEVEN 2168 '?': ROMAN NUMERAL NINE ... 265E '?': BLACK CHESS KNIGHT From webhook-mailer at python.org Mon Aug 26 13:52:40 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 17:52:40 -0000 Subject: [Python-checkins] bpo-37055: fix warnings in _blake2 module (GH-14646) Message-ID: https://github.com/python/cpython/commit/b27cbec801e17a13d7fef49116a8fc279930d2b1 commit: b27cbec801e17a13d7fef49116a8fc279930d2b1 branch: master author: Inada Naoki committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-26T10:52:36-07:00 summary: bpo-37055: fix warnings in _blake2 module (GH-14646) https://bugs.python.org/issue37055 Automerge-Triggered-By: @tiran files: M Modules/_blake2/impl/blake2.h M Modules/_blake2/impl/blake2b.c M Modules/_blake2/impl/blake2s.c diff --git a/Modules/_blake2/impl/blake2.h b/Modules/_blake2/impl/blake2.h index 5ca17f610742..a08d82efefe0 100644 --- a/Modules/_blake2/impl/blake2.h +++ b/Modules/_blake2/impl/blake2.h @@ -169,11 +169,6 @@ extern "C" { BLAKE2_API int blake2sp( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen ); BLAKE2_API int blake2bp( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen ); - static inline int blake2( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen ) - { - return blake2b( out, in, key, outlen, inlen, keylen ); - } - #if defined(__cplusplus) } #endif diff --git a/Modules/_blake2/impl/blake2b.c b/Modules/_blake2/impl/blake2b.c index ca1504622354..3d3e46506f2e 100644 --- a/Modules/_blake2/impl/blake2b.c +++ b/Modules/_blake2/impl/blake2b.c @@ -189,13 +189,6 @@ static inline int blake2b_init0( blake2b_state *S ) -#define blake2b_init BLAKE2_IMPL_NAME(blake2b_init) -#define blake2b_init_param BLAKE2_IMPL_NAME(blake2b_init_param) -#define blake2b_init_key BLAKE2_IMPL_NAME(blake2b_init_key) -#define blake2b_update BLAKE2_IMPL_NAME(blake2b_update) -#define blake2b_final BLAKE2_IMPL_NAME(blake2b_final) -#define blake2b BLAKE2_IMPL_NAME(blake2b) - #if defined(__cplusplus) extern "C" { #endif diff --git a/Modules/_blake2/impl/blake2s.c b/Modules/_blake2/impl/blake2s.c index 0c3636ef6fc5..3a04328ab8a4 100644 --- a/Modules/_blake2/impl/blake2s.c +++ b/Modules/_blake2/impl/blake2s.c @@ -175,13 +175,6 @@ static inline int blake2s_init0( blake2s_state *S ) return 0; } -#define blake2s_init BLAKE2_IMPL_NAME(blake2s_init) -#define blake2s_init_param BLAKE2_IMPL_NAME(blake2s_init_param) -#define blake2s_init_key BLAKE2_IMPL_NAME(blake2s_init_key) -#define blake2s_update BLAKE2_IMPL_NAME(blake2s_update) -#define blake2s_final BLAKE2_IMPL_NAME(blake2s_final) -#define blake2s BLAKE2_IMPL_NAME(blake2s) - #if defined(__cplusplus) extern "C" { #endif From webhook-mailer at python.org Mon Aug 26 14:19:34 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 18:19:34 -0000 Subject: [Python-checkins] bpo-37664: Update ensurepip bundled wheels, again (GH-15483) Message-ID: https://github.com/python/cpython/commit/10c452b894d95fed06056fe11e8fe8e1a2a60040 commit: 10c452b894d95fed06056fe11e8fe8e1a2a60040 branch: master author: Pradyun Gedam committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-26T11:19:30-07:00 summary: bpo-37664: Update ensurepip bundled wheels, again (GH-15483) /cc @ambv since this needs to be included in 3.8 -- see https://github.com/pypa/pip/issues/6885. Sorry about the last minute PR! https://bugs.python.org/issue37664 Automerge-Triggered-By: @zooba files: A Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl A Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl D Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl D Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl M Lib/ensurepip/__init__.py M Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 63de20e28873..fc0edec6e3de 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "41.0.1" +_SETUPTOOLS_VERSION = "41.2.0" -_PIP_VERSION = "19.2.1" +_PIP_VERSION = "19.2.3" _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION), diff --git a/Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl similarity index 93% rename from Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl rename to Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl index 1690eb3f4f2a..8118df8ac194 100644 Binary files a/Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl and b/Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl differ diff --git a/Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl similarity index 87% rename from Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl rename to Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl index 92836e984026..82df6f63f4ee 100644 Binary files a/Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl and b/Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl differ diff --git a/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst b/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst index 3343d9100946..f12590540eb7 100644 --- a/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst +++ b/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst @@ -1 +1 @@ -Update wheels bundled with ensurepip (pip 19.2.1 and setuptools 41.0.1) +Update wheels bundled with ensurepip (pip 19.2.3 and setuptools 41.2.0) From webhook-mailer at python.org Mon Aug 26 14:23:59 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 18:23:59 -0000 Subject: [Python-checkins] bpo-37055: fix warnings in _blake2 module (GH-14646) Message-ID: https://github.com/python/cpython/commit/2bb4fc379b14377e1cdcefad8d5f2fbbb1172524 commit: 2bb4fc379b14377e1cdcefad8d5f2fbbb1172524 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T11:23:55-07:00 summary: bpo-37055: fix warnings in _blake2 module (GH-14646) https://bugs.python.org/issue37055 Automerge-Triggered-By: @tiran (cherry picked from commit b27cbec801e17a13d7fef49116a8fc279930d2b1) Co-authored-by: Inada Naoki files: M Modules/_blake2/impl/blake2.h M Modules/_blake2/impl/blake2b.c M Modules/_blake2/impl/blake2s.c diff --git a/Modules/_blake2/impl/blake2.h b/Modules/_blake2/impl/blake2.h index 5ca17f610742..a08d82efefe0 100644 --- a/Modules/_blake2/impl/blake2.h +++ b/Modules/_blake2/impl/blake2.h @@ -169,11 +169,6 @@ extern "C" { BLAKE2_API int blake2sp( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen ); BLAKE2_API int blake2bp( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen ); - static inline int blake2( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen ) - { - return blake2b( out, in, key, outlen, inlen, keylen ); - } - #if defined(__cplusplus) } #endif diff --git a/Modules/_blake2/impl/blake2b.c b/Modules/_blake2/impl/blake2b.c index ca1504622354..3d3e46506f2e 100644 --- a/Modules/_blake2/impl/blake2b.c +++ b/Modules/_blake2/impl/blake2b.c @@ -189,13 +189,6 @@ static inline int blake2b_init0( blake2b_state *S ) -#define blake2b_init BLAKE2_IMPL_NAME(blake2b_init) -#define blake2b_init_param BLAKE2_IMPL_NAME(blake2b_init_param) -#define blake2b_init_key BLAKE2_IMPL_NAME(blake2b_init_key) -#define blake2b_update BLAKE2_IMPL_NAME(blake2b_update) -#define blake2b_final BLAKE2_IMPL_NAME(blake2b_final) -#define blake2b BLAKE2_IMPL_NAME(blake2b) - #if defined(__cplusplus) extern "C" { #endif diff --git a/Modules/_blake2/impl/blake2s.c b/Modules/_blake2/impl/blake2s.c index 0c3636ef6fc5..3a04328ab8a4 100644 --- a/Modules/_blake2/impl/blake2s.c +++ b/Modules/_blake2/impl/blake2s.c @@ -175,13 +175,6 @@ static inline int blake2s_init0( blake2s_state *S ) return 0; } -#define blake2s_init BLAKE2_IMPL_NAME(blake2s_init) -#define blake2s_init_param BLAKE2_IMPL_NAME(blake2s_init_param) -#define blake2s_init_key BLAKE2_IMPL_NAME(blake2s_init_key) -#define blake2s_update BLAKE2_IMPL_NAME(blake2s_update) -#define blake2s_final BLAKE2_IMPL_NAME(blake2s_final) -#define blake2s BLAKE2_IMPL_NAME(blake2s) - #if defined(__cplusplus) extern "C" { #endif From webhook-mailer at python.org Mon Aug 26 14:26:01 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Mon, 26 Aug 2019 18:26:01 -0000 Subject: [Python-checkins] bpo-37798: Minor code formatting and comment clean-ups. (GH-15526) Message-ID: https://github.com/python/cpython/commit/6fee0f8ea72fa68155a32b33b6c0ed9e5a740e45 commit: 6fee0f8ea72fa68155a32b33b6c0ed9e5a740e45 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-26T11:25:58-07:00 summary: bpo-37798: Minor code formatting and comment clean-ups. (GH-15526) files: M Modules/_statisticsmodule.c diff --git a/Modules/_statisticsmodule.c b/Modules/_statisticsmodule.c index 78ec90a66b0f..676d3fb33803 100644 --- a/Modules/_statisticsmodule.c +++ b/Modules/_statisticsmodule.c @@ -1,4 +1,4 @@ -/* statistics accelerator C extensor: _statistics module. */ +/* statistics accelerator C extension: _statistics module. */ #include "Python.h" #include "structmember.h" @@ -10,11 +10,13 @@ module _statistics [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=864a6f59b76123b2]*/ - -static PyMethodDef speedups_methods[] = { - _STATISTICS__NORMAL_DIST_INV_CDF_METHODDEF - {NULL, NULL, 0, NULL} -}; +/* + * There is no closed-form solution to the inverse CDF for the normal + * distribution, so we use a rational approximation instead: + * Wichura, M.J. (1988). "Algorithm AS241: The Percentage Points of the + * Normal Distribution". Applied Statistics. Blackwell Publishing. 37 + * (3): 477?484. doi:10.2307/2347330. JSTOR 2347330. + */ /*[clinic input] _statistics._normal_dist_inv_cdf -> double @@ -34,7 +36,7 @@ _statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, // Algorithm AS 241: The Percentage Points of the Normal Distribution if(fabs(q) <= 0.425) { r = 0.180625 - q * q; - // Hash sum AB: 55.88319 28806 14901 4439 + // Hash sum-55.8831928806149014439 num = (((((((2.5090809287301226727e+3 * r + 3.3430575583588128105e+4) * r + 6.7265770927008700853e+4) * r + @@ -54,11 +56,11 @@ _statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, x = num / den; return mu + (x * sigma); } - r = q <= 0.0? p : 1.0-p; + r = (q <= 0.0) ? p : (1.0 - p); r = sqrt(-log(r)); if (r <= 5.0) { r = r - 1.6; - // Hash sum CD: 49.33206 50330 16102 89036 + // Hash sum-49.33206503301610289036 num = (((((((7.74545014278341407640e-4 * r + 2.27238449892691845833e-2) * r + 2.41780725177450611770e-1) * r + @@ -77,7 +79,7 @@ _statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, 1.0); } else { r -= 5.0; - // Hash sum EF: 47.52583 31754 92896 71629 + // Hash sum-47.52583317549289671629 num = (((((((2.01033439929228813265e-7 * r + 2.71155556874348757815e-5) * r + 1.24266094738807843860e-3) * r + @@ -96,23 +98,30 @@ _statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, 1.0); } x = num / den; - if (q < 0.0) x = -x; + if (q < 0.0) { + x = -x; + } return mu + (x * sigma); } + +static PyMethodDef statistics_methods[] = { + _STATISTICS__NORMAL_DIST_INV_CDF_METHODDEF + {NULL, NULL, 0, NULL} +}; + static struct PyModuleDef statisticsmodule = { PyModuleDef_HEAD_INIT, "_statistics", _statistics__normal_dist_inv_cdf__doc__, -1, - speedups_methods, + statistics_methods, NULL, NULL, NULL, NULL }; - PyMODINIT_FUNC PyInit__statistics(void) { From webhook-mailer at python.org Mon Aug 26 15:10:04 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Mon, 26 Aug 2019 19:10:04 -0000 Subject: [Python-checkins] bpo-37798: Minor code formatting and comment clean-ups. (GH-15526) (GH-15527) Message-ID: https://github.com/python/cpython/commit/56c4d2d057de0dcb968148fa1286e587e91f5c91 commit: 56c4d2d057de0dcb968148fa1286e587e91f5c91 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-26T12:10:00-07:00 summary: bpo-37798: Minor code formatting and comment clean-ups. (GH-15526) (GH-15527) (cherry picked from commit 6fee0f8ea72fa68155a32b33b6c0ed9e5a740e45) Co-authored-by: Raymond Hettinger files: M Modules/_statisticsmodule.c diff --git a/Modules/_statisticsmodule.c b/Modules/_statisticsmodule.c index 78ec90a66b0f..676d3fb33803 100644 --- a/Modules/_statisticsmodule.c +++ b/Modules/_statisticsmodule.c @@ -1,4 +1,4 @@ -/* statistics accelerator C extensor: _statistics module. */ +/* statistics accelerator C extension: _statistics module. */ #include "Python.h" #include "structmember.h" @@ -10,11 +10,13 @@ module _statistics [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=864a6f59b76123b2]*/ - -static PyMethodDef speedups_methods[] = { - _STATISTICS__NORMAL_DIST_INV_CDF_METHODDEF - {NULL, NULL, 0, NULL} -}; +/* + * There is no closed-form solution to the inverse CDF for the normal + * distribution, so we use a rational approximation instead: + * Wichura, M.J. (1988). "Algorithm AS241: The Percentage Points of the + * Normal Distribution". Applied Statistics. Blackwell Publishing. 37 + * (3): 477?484. doi:10.2307/2347330. JSTOR 2347330. + */ /*[clinic input] _statistics._normal_dist_inv_cdf -> double @@ -34,7 +36,7 @@ _statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, // Algorithm AS 241: The Percentage Points of the Normal Distribution if(fabs(q) <= 0.425) { r = 0.180625 - q * q; - // Hash sum AB: 55.88319 28806 14901 4439 + // Hash sum-55.8831928806149014439 num = (((((((2.5090809287301226727e+3 * r + 3.3430575583588128105e+4) * r + 6.7265770927008700853e+4) * r + @@ -54,11 +56,11 @@ _statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, x = num / den; return mu + (x * sigma); } - r = q <= 0.0? p : 1.0-p; + r = (q <= 0.0) ? p : (1.0 - p); r = sqrt(-log(r)); if (r <= 5.0) { r = r - 1.6; - // Hash sum CD: 49.33206 50330 16102 89036 + // Hash sum-49.33206503301610289036 num = (((((((7.74545014278341407640e-4 * r + 2.27238449892691845833e-2) * r + 2.41780725177450611770e-1) * r + @@ -77,7 +79,7 @@ _statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, 1.0); } else { r -= 5.0; - // Hash sum EF: 47.52583 31754 92896 71629 + // Hash sum-47.52583317549289671629 num = (((((((2.01033439929228813265e-7 * r + 2.71155556874348757815e-5) * r + 1.24266094738807843860e-3) * r + @@ -96,23 +98,30 @@ _statistics__normal_dist_inv_cdf_impl(PyObject *module, double p, double mu, 1.0); } x = num / den; - if (q < 0.0) x = -x; + if (q < 0.0) { + x = -x; + } return mu + (x * sigma); } + +static PyMethodDef statistics_methods[] = { + _STATISTICS__NORMAL_DIST_INV_CDF_METHODDEF + {NULL, NULL, 0, NULL} +}; + static struct PyModuleDef statisticsmodule = { PyModuleDef_HEAD_INIT, "_statistics", _statistics__normal_dist_inv_cdf__doc__, -1, - speedups_methods, + statistics_methods, NULL, NULL, NULL, NULL }; - PyMODINIT_FUNC PyInit__statistics(void) { From webhook-mailer at python.org Mon Aug 26 15:19:57 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 19:19:57 -0000 Subject: [Python-checkins] [3.7] bpo-37664: Update ensurepip bundled wheels, again (GH-15483) (GH-15529) Message-ID: https://github.com/python/cpython/commit/c1c1a3396391dcc948d332607a0f673e4434da97 commit: c1c1a3396391dcc948d332607a0f673e4434da97 branch: 3.7 author: Steve Dower committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-26T12:19:53-07:00 summary: [3.7] bpo-37664: Update ensurepip bundled wheels, again (GH-15483) (GH-15529) https://bugs.python.org/issue37664 Automerge-Triggered-By: @zooba files: A Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl A Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl D Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl D Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl M Lib/ensurepip/__init__.py M Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 8ccf587257f3..7a0d3ee0db94 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "41.0.1" +_SETUPTOOLS_VERSION = "41.2.0" -_PIP_VERSION = "19.2.1" +_PIP_VERSION = "19.2.3" _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION), diff --git a/Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl similarity index 93% rename from Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl rename to Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl index 1690eb3f4f2a..8118df8ac194 100644 Binary files a/Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl and b/Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl differ diff --git a/Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl similarity index 87% rename from Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl rename to Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl index 92836e984026..82df6f63f4ee 100644 Binary files a/Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl and b/Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl differ diff --git a/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst b/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst index 3343d9100946..f12590540eb7 100644 --- a/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst +++ b/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst @@ -1 +1 @@ -Update wheels bundled with ensurepip (pip 19.2.1 and setuptools 41.0.1) +Update wheels bundled with ensurepip (pip 19.2.3 and setuptools 41.2.0) From webhook-mailer at python.org Mon Aug 26 15:58:07 2019 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 26 Aug 2019 19:58:07 -0000 Subject: [Python-checkins] bpo-37664: Update ensurepip bundled wheels, again (GH-15483) Message-ID: https://github.com/python/cpython/commit/04b750740be6e7c4a7693f1135c4788b40a028c1 commit: 04b750740be6e7c4a7693f1135c4788b40a028c1 branch: 3.8 author: Steve Dower committer: GitHub date: 2019-08-26T12:57:57-07:00 summary: bpo-37664: Update ensurepip bundled wheels, again (GH-15483) files: A Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl A Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl A Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst D Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl D Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl M Lib/ensurepip/__init__.py diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 63de20e28873..fc0edec6e3de 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "41.0.1" +_SETUPTOOLS_VERSION = "41.2.0" -_PIP_VERSION = "19.2.1" +_PIP_VERSION = "19.2.3" _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION), diff --git a/Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl similarity index 93% rename from Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl rename to Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl index 1690eb3f4f2a..8118df8ac194 100644 Binary files a/Lib/ensurepip/_bundled/pip-19.2.1-py2.py3-none-any.whl and b/Lib/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl differ diff --git a/Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl similarity index 87% rename from Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl rename to Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl index 92836e984026..82df6f63f4ee 100644 Binary files a/Lib/ensurepip/_bundled/setuptools-41.0.1-py2.py3-none-any.whl and b/Lib/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl differ diff --git a/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst b/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst new file mode 100644 index 000000000000..f12590540eb7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst @@ -0,0 +1 @@ +Update wheels bundled with ensurepip (pip 19.2.3 and setuptools 41.2.0) From webhook-mailer at python.org Mon Aug 26 17:45:40 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 26 Aug 2019 21:45:40 -0000 Subject: [Python-checkins] bpo-37925: Mention --embed in python-config usage (GH-15458) Message-ID: https://github.com/python/cpython/commit/d3cc189b17c86f670198aca109b5ffa2d526d87a commit: d3cc189b17c86f670198aca109b5ffa2d526d87a branch: master author: Batuhan Ta?kaya <47358913+isidentical at users.noreply.github.com> committer: Victor Stinner date: 2019-08-26T23:45:36+02:00 summary: bpo-37925: Mention --embed in python-config usage (GH-15458) files: M Misc/python-config.sh.in diff --git a/Misc/python-config.sh.in b/Misc/python-config.sh.in index 59101d5a5580..2602fe24c040 100644 --- a/Misc/python-config.sh.in +++ b/Misc/python-config.sh.in @@ -4,7 +4,7 @@ exit_with_usage () { - echo "Usage: $0 --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--help|--abiflags|--configdir" + echo "Usage: $0 --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--help|--abiflags|--configdir|--embed" exit $1 } From webhook-mailer at python.org Mon Aug 26 17:55:35 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 21:55:35 -0000 Subject: [Python-checkins] bpo-37925: Mention --embed in python-config usage (GH-15458) Message-ID: https://github.com/python/cpython/commit/b8a22ac856944d1dded46ed4caa795e07bfaf0c6 commit: b8a22ac856944d1dded46ed4caa795e07bfaf0c6 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T14:55:31-07:00 summary: bpo-37925: Mention --embed in python-config usage (GH-15458) (cherry picked from commit d3cc189b17c86f670198aca109b5ffa2d526d87a) Co-authored-by: Batuhan Ta?kaya <47358913+isidentical at users.noreply.github.com> files: M Misc/python-config.sh.in diff --git a/Misc/python-config.sh.in b/Misc/python-config.sh.in index 59101d5a5580..2602fe24c040 100644 --- a/Misc/python-config.sh.in +++ b/Misc/python-config.sh.in @@ -4,7 +4,7 @@ exit_with_usage () { - echo "Usage: $0 --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--help|--abiflags|--configdir" + echo "Usage: $0 --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--help|--abiflags|--configdir|--embed" exit $1 } From webhook-mailer at python.org Mon Aug 26 18:12:36 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 26 Aug 2019 22:12:36 -0000 Subject: [Python-checkins] Make PyXXX_Fini() functions private (GH-15531) Message-ID: https://github.com/python/cpython/commit/bed4817d52d7b5a383b1b61269c1337b61acc493 commit: bed4817d52d7b5a383b1b61269c1337b61acc493 branch: master author: Victor Stinner committer: GitHub date: 2019-08-27T00:12:32+02:00 summary: Make PyXXX_Fini() functions private (GH-15531) For example, rename PyTuple_Fini() to _PyTuple_Fini(). These functions are only declared in the internal C API. files: M Include/internal/pycore_pylifecycle.h M Objects/bytesobject.c M Objects/classobject.c M Objects/dictobject.c M Objects/floatobject.c M Objects/frameobject.c M Objects/genobject.c M Objects/listobject.c M Objects/longobject.c M Objects/methodobject.c M Objects/setobject.c M Objects/sliceobject.c M Objects/tupleobject.c M Python/pylifecycle.c diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index bdc4bf5a46d4..495742959433 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -62,18 +62,19 @@ extern PyStatus _PyImportZip_Init(PyThreadState *tstate); /* Various internal finalizers */ -extern void PyMethod_Fini(void); -extern void PyFrame_Fini(void); -extern void PyCFunction_Fini(void); -extern void PyDict_Fini(void); -extern void PyTuple_Fini(void); -extern void PyList_Fini(void); -extern void PySet_Fini(void); -extern void PyBytes_Fini(void); -extern void PyFloat_Fini(void); +extern void _PyMethod_Fini(void); +extern void _PyFrame_Fini(void); +extern void _PyCFunction_Fini(void); +extern void _PyDict_Fini(void); +extern void _PyTuple_Fini(void); +extern void _PyList_Fini(void); +extern void _PySet_Fini(void); +extern void _PyBytes_Fini(void); +extern void _PyFloat_Fini(void); +extern void _PySlice_Fini(void); +extern void _PyAsyncGen_Fini(void); + extern void PyOS_FiniInterrupts(void); -extern void PySlice_Fini(void); -extern void PyAsyncGen_Fini(void); extern void _PyExc_Fini(void); extern void _PyImport_Fini(void); @@ -82,7 +83,7 @@ extern void _PyGC_Fini(_PyRuntimeState *runtime); extern void _PyType_Fini(void); extern void _Py_HashRandomization_Fini(void); extern void _PyUnicode_Fini(void); -extern void PyLong_Fini(void); +extern void _PyLong_Fini(void); extern void _PyFaulthandler_Fini(void); extern void _PyHash_Fini(void); extern int _PyTraceMalloc_Fini(void); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index c4edcca4f761..6d553304a403 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3047,7 +3047,7 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize) } void -PyBytes_Fini(void) +_PyBytes_Fini(void) { int i; for (i = 0; i < UCHAR_MAX + 1; i++) diff --git a/Objects/classobject.c b/Objects/classobject.c index 40cbeaa9f2aa..4a9add1229e3 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -375,7 +375,7 @@ PyMethod_ClearFreeList(void) } void -PyMethod_Fini(void) +_PyMethod_Fini(void) { (void)PyMethod_ClearFreeList(); } diff --git a/Objects/dictobject.c b/Objects/dictobject.c index fec3a87e9f5d..73956df4ab2a 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -282,7 +282,7 @@ _PyDict_DebugMallocStats(FILE *out) void -PyDict_Fini(void) +_PyDict_Fini(void) { PyDict_ClearFreeList(); } diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 689e92907d03..6643ff340ea5 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -2031,7 +2031,7 @@ PyFloat_ClearFreeList(void) } void -PyFloat_Fini(void) +_PyFloat_Fini(void) { (void)PyFloat_ClearFreeList(); } diff --git a/Objects/frameobject.c b/Objects/frameobject.c index a796a59eee9e..27ef9ff25902 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -997,7 +997,7 @@ PyFrame_ClearFreeList(void) } void -PyFrame_Fini(void) +_PyFrame_Fini(void) { (void)PyFrame_ClearFreeList(); } diff --git a/Objects/genobject.c b/Objects/genobject.c index 5d1f9c7dd13e..5e0bfa4f43de 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -1463,7 +1463,7 @@ PyAsyncGen_ClearFreeLists(void) } void -PyAsyncGen_Fini(void) +_PyAsyncGen_Fini(void) { PyAsyncGen_ClearFreeLists(); } diff --git a/Objects/listobject.c b/Objects/listobject.c index cea9b24a3b2f..5fca08ea363a 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -138,7 +138,7 @@ PyList_ClearFreeList(void) } void -PyList_Fini(void) +_PyList_Fini(void) { PyList_ClearFreeList(); } diff --git a/Objects/longobject.c b/Objects/longobject.c index 74037be7a1ea..475b9bda59f9 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5869,7 +5869,7 @@ _PyLong_Init(void) } void -PyLong_Fini(void) +_PyLong_Fini(void) { /* Integers are currently statically allocated. Py_DECREF is not needed, but Python must forget about the reference or multiple diff --git a/Objects/methodobject.c b/Objects/methodobject.c index b9977467ac08..7d70cc04a238 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -319,7 +319,7 @@ PyCFunction_ClearFreeList(void) } void -PyCFunction_Fini(void) +_PyCFunction_Fini(void) { (void)PyCFunction_ClearFreeList(); } diff --git a/Objects/setobject.c b/Objects/setobject.c index 8cd95ba890dd..56858dbccfe1 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -2318,7 +2318,7 @@ PySet_ClearFreeList(void) } void -PySet_Fini(void) +_PySet_Fini(void) { Py_CLEAR(emptyfrozenset); } diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index 7c10eb6f638d..e884a5894356 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -100,7 +100,8 @@ PyObject _Py_EllipsisObject = { * created and then deleted again */ static PySliceObject *slice_cache = NULL; -void PySlice_Fini(void) + +void _PySlice_Fini(void) { PySliceObject *obj = slice_cache; if (obj != NULL) { diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 79a5d55749be..3419baa529a6 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -989,7 +989,7 @@ PyTuple_ClearFreeList(void) } void -PyTuple_Fini(void) +_PyTuple_Fini(void) { #if PyTuple_MAXSAVESIZE > 0 /* empty tuples are used all over the place and applications may diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index e3333db4328a..7cda44dc29d3 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1307,22 +1307,22 @@ Py_FinalizeEx(void) _PyExc_Fini(); /* Sundry finalizers */ - PyMethod_Fini(); - PyFrame_Fini(); - PyCFunction_Fini(); - PyTuple_Fini(); - PyList_Fini(); - PySet_Fini(); - PyBytes_Fini(); - PyLong_Fini(); - PyFloat_Fini(); - PyDict_Fini(); - PySlice_Fini(); + _PyMethod_Fini(); + _PyFrame_Fini(); + _PyCFunction_Fini(); + _PyTuple_Fini(); + _PyList_Fini(); + _PySet_Fini(); + _PyBytes_Fini(); + _PyLong_Fini(); + _PyFloat_Fini(); + _PyDict_Fini(); + _PySlice_Fini(); _PyGC_Fini(runtime); _PyWarnings_Fini(interp); _Py_HashRandomization_Fini(); _PyArg_Fini(); - PyAsyncGen_Fini(); + _PyAsyncGen_Fini(); _PyContext_Fini(); /* Cleanup Unicode implementation */ From webhook-mailer at python.org Mon Aug 26 18:35:11 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 26 Aug 2019 22:35:11 -0000 Subject: [Python-checkins] Remove leftovers from the times when long long wasn't required (GH-15501) (GH-15517) Message-ID: https://github.com/python/cpython/commit/b4e83a350ece3f29b8feef8fcb3e4337ff3e5e7d commit: b4e83a350ece3f29b8feef8fcb3e4337ff3e5e7d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Pablo Galindo date: 2019-08-26T23:35:06+01:00 summary: Remove leftovers from the times when long long wasn't required (GH-15501) (GH-15517) In a38e9d139929a227e3899fbb638bc46c6cc6d8ba pyconfig.h.in was manually edited and that edit was overwritten when running autoreconf. (cherry picked from commit 52c1a6a15a471f75b775309ed1120d05f69010ca) Co-authored-by: Sergey Fedoseev files: M configure.ac M pyconfig.h.in diff --git a/configure.ac b/configure.ac index e5fb7e7b0b13..378d1bd17571 100644 --- a/configure.ac +++ b/configure.ac @@ -2333,7 +2333,7 @@ if test "$ac_cv_sizeof_off_t" -gt "$ac_cv_sizeof_long" -a \ "$ac_cv_sizeof_long_long" -ge "$ac_cv_sizeof_off_t"; then AC_DEFINE(HAVE_LARGEFILE_SUPPORT, 1, [Defined to enable large file support when an off_t is bigger than a long - and long long is available and at least as big as an off_t. You may need + and long long is at least as big as an off_t. You may need to add some flags for configuration and compilation to enable this mode. (For Solaris and Linux, the necessary defines are already defined.)]) AC_MSG_RESULT(yes) diff --git a/pyconfig.h.in b/pyconfig.h.in index 1ed9479ee474..d36fc933f48c 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -540,9 +540,9 @@ #undef HAVE_LANGINFO_H /* Defined to enable large file support when an off_t is bigger than a long - and long long is at least as big as an off_t. You may need to - add some flags for configuration and compilation to enable this mode. (For - Solaris and Linux, the necessary defines are already defined.) */ + and long long is at least as big as an off_t. You may need to add some + flags for configuration and compilation to enable this mode. (For Solaris + and Linux, the necessary defines are already defined.) */ #undef HAVE_LARGEFILE_SUPPORT /* Define to 1 if you have the 'lchflags' function. */ From webhook-mailer at python.org Mon Aug 26 18:41:15 2019 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 26 Aug 2019 22:41:15 -0000 Subject: [Python-checkins] Fix an invalid assertEqual() call in test_descr.py (GH-15318) Message-ID: https://github.com/python/cpython/commit/6b2e3256b6752055498f41f343fb22100845bc9d commit: 6b2e3256b6752055498f41f343fb22100845bc9d branch: master author: Zackery Spytz committer: Pablo Galindo date: 2019-08-26T23:41:11+01:00 summary: Fix an invalid assertEqual() call in test_descr.py (GH-15318) files: M Lib/test/test_descr.py diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 0b43549efb83..770e0c496e28 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -2659,12 +2659,8 @@ def test(klass): self.assertEqual(Sub.test(), Base.aProp) # Verify that super() doesn't allow keyword args - try: + with self.assertRaises(TypeError): super(Base, kw=1) - except TypeError: - pass - else: - self.assertEqual("super shouldn't accept keyword args") def test_basic_inheritance(self): # Testing inheritance from basic types... From webhook-mailer at python.org Mon Aug 26 18:45:48 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 26 Aug 2019 22:45:48 -0000 Subject: [Python-checkins] bpo-36763: Make Py_BytesMain() public (GH-15532) Message-ID: https://github.com/python/cpython/commit/9a943b4ce13fac26873b8100e89c818c5c47ac4b commit: 9a943b4ce13fac26873b8100e89c818c5c47ac4b branch: master author: Victor Stinner committer: GitHub date: 2019-08-27T00:45:45+02:00 summary: bpo-36763: Make Py_BytesMain() public (GH-15532) Declare Py_BytesMain() in Include/pylifecycle.h, rather in Include/internal/pycore_pylifecycle.h. files: M Include/internal/pycore_pylifecycle.h M Include/pylifecycle.h diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 495742959433..7ea4488a9364 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -15,8 +15,6 @@ extern "C" { * KeyboardInterrupt exception, suggesting the user pressed ^C. */ PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt; -PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); - extern int _Py_SetFileSystemEncoding( const char *encoding, const char *errors); diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 1df114a73de3..c5368b3c5eda 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -32,6 +32,8 @@ PyAPI_FUNC(void) _Py_NO_RETURN Py_Exit(int); /* Bootstrap __main__ (defined in Modules/main.c) */ PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv); +PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); + /* In pathconfig.c */ PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); PyAPI_FUNC(wchar_t *) Py_GetProgramName(void); From webhook-mailer at python.org Mon Aug 26 18:59:25 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 22:59:25 -0000 Subject: [Python-checkins] Fix an invalid assertEqual() call in test_descr.py (GH-15318) Message-ID: https://github.com/python/cpython/commit/31ce015db893be60ae60e963e58c902ac87f5085 commit: 31ce015db893be60ae60e963e58c902ac87f5085 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T15:59:18-07:00 summary: Fix an invalid assertEqual() call in test_descr.py (GH-15318) (cherry picked from commit 6b2e3256b6752055498f41f343fb22100845bc9d) Co-authored-by: Zackery Spytz files: M Lib/test/test_descr.py diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 675f9748e805..87304749974f 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -2627,12 +2627,8 @@ def test(klass): self.assertEqual(Sub.test(), Base.aProp) # Verify that super() doesn't allow keyword args - try: + with self.assertRaises(TypeError): super(Base, kw=1) - except TypeError: - pass - else: - self.assertEqual("super shouldn't accept keyword args") def test_basic_inheritance(self): # Testing inheritance from basic types... From webhook-mailer at python.org Mon Aug 26 19:02:26 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 23:02:26 -0000 Subject: [Python-checkins] Fix an invalid assertEqual() call in test_descr.py (GH-15318) Message-ID: https://github.com/python/cpython/commit/c75f0e5bdee3cfaba9fd5b3a8549dec0aba01ebe commit: c75f0e5bdee3cfaba9fd5b3a8549dec0aba01ebe branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T16:02:21-07:00 summary: Fix an invalid assertEqual() call in test_descr.py (GH-15318) (cherry picked from commit 6b2e3256b6752055498f41f343fb22100845bc9d) Co-authored-by: Zackery Spytz files: M Lib/test/test_descr.py diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 9998a3cc77a2..0d0c1dd1acbe 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -2659,12 +2659,8 @@ def test(klass): self.assertEqual(Sub.test(), Base.aProp) # Verify that super() doesn't allow keyword args - try: + with self.assertRaises(TypeError): super(Base, kw=1) - except TypeError: - pass - else: - self.assertEqual("super shouldn't accept keyword args") def test_basic_inheritance(self): # Testing inheritance from basic types... From webhook-mailer at python.org Mon Aug 26 19:18:00 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Aug 2019 23:18:00 -0000 Subject: [Python-checkins] bpo-36763: Make Py_BytesMain() public (GH-15532) Message-ID: https://github.com/python/cpython/commit/1d4285a042772c7a31c4e19f8dbcbcf9b2ee3b95 commit: 1d4285a042772c7a31c4e19f8dbcbcf9b2ee3b95 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T16:17:56-07:00 summary: bpo-36763: Make Py_BytesMain() public (GH-15532) Declare Py_BytesMain() in Include/pylifecycle.h, rather in Include/internal/pycore_pylifecycle.h. (cherry picked from commit 9a943b4ce13fac26873b8100e89c818c5c47ac4b) Co-authored-by: Victor Stinner files: M Include/internal/pycore_pylifecycle.h M Include/pylifecycle.h diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 51f05b389e35..a21eb0142233 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -15,8 +15,6 @@ extern "C" { * KeyboardInterrupt exception, suggesting the user pressed ^C. */ PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt; -PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); - extern int _Py_SetFileSystemEncoding( const char *encoding, const char *errors); diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 1df114a73de3..c5368b3c5eda 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -32,6 +32,8 @@ PyAPI_FUNC(void) _Py_NO_RETURN Py_Exit(int); /* Bootstrap __main__ (defined in Modules/main.c) */ PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv); +PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); + /* In pathconfig.c */ PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); PyAPI_FUNC(wchar_t *) Py_GetProgramName(void); From webhook-mailer at python.org Mon Aug 26 22:48:10 2019 From: webhook-mailer at python.org (Inada Naoki) Date: Tue, 27 Aug 2019 02:48:10 -0000 Subject: [Python-checkins] bpo-37328: remove deprecated HTMLParser.unescape (GH-14186) Message-ID: https://github.com/python/cpython/commit/fae0ed5099de594a9204071d555cb8b76368cbf4 commit: fae0ed5099de594a9204071d555cb8b76368cbf4 branch: master author: Inada Naoki committer: GitHub date: 2019-08-27T11:48:06+09:00 summary: bpo-37328: remove deprecated HTMLParser.unescape (GH-14186) It is deprecated since Python 3.4. files: A Misc/NEWS.d/next/Library/2019-06-18-15-31-33.bpo-37328.2PW1-l.rst M Lib/html/parser.py M Lib/test/test_htmlparser.py diff --git a/Lib/html/parser.py b/Lib/html/parser.py index de81879a631a..60830779816a 100644 --- a/Lib/html/parser.py +++ b/Lib/html/parser.py @@ -9,7 +9,6 @@ import re -import warnings import _markupbase from html import unescape @@ -461,10 +460,3 @@ def handle_pi(self, data): def unknown_decl(self, data): pass - - # Internal -- helper to remove special character quoting - def unescape(self, s): - warnings.warn('The unescape method is deprecated and will be removed ' - 'in 3.5, use html.unescape() instead.', - DeprecationWarning, stacklevel=2) - return unescape(s) diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py index 326e34290ff1..a2bfb39d16a5 100644 --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -573,13 +573,6 @@ def test_EOF_in_charref(self): for html, expected in data: self._run_check(html, expected) - def test_unescape_method(self): - from html import unescape - p = self.get_collector() - with self.assertWarns(DeprecationWarning): - s = '""""""&#bad;' - self.assertEqual(p.unescape(s), unescape(s)) - def test_broken_comments(self): html = ('' '' diff --git a/Misc/NEWS.d/next/Library/2019-06-18-15-31-33.bpo-37328.2PW1-l.rst b/Misc/NEWS.d/next/Library/2019-06-18-15-31-33.bpo-37328.2PW1-l.rst new file mode 100644 index 000000000000..d91ab1b295d3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-06-18-15-31-33.bpo-37328.2PW1-l.rst @@ -0,0 +1,2 @@ +``HTMLParser.unescape`` is removed. It was undocumented and deprecated +since Python 3.4. From webhook-mailer at python.org Tue Aug 27 00:13:17 2019 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 27 Aug 2019 04:13:17 -0000 Subject: [Python-checkins] bpo-36205: Fix the rusage implementation of time.process_time() (GH-15538) Message-ID: https://github.com/python/cpython/commit/8bf5fef8737fdd12724b9340d76a4ed391c4ad8a commit: 8bf5fef8737fdd12724b9340d76a4ed391c4ad8a branch: master author: vrajivk <3413293+vrajivk at users.noreply.github.com> committer: Ned Deily date: 2019-08-27T00:13:12-04:00 summary: bpo-36205: Fix the rusage implementation of time.process_time() (GH-15538) files: A Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst M Modules/timemodule.c diff --git a/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst b/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst new file mode 100644 index 000000000000..50cda34fbbd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst @@ -0,0 +1 @@ +Fix the rusage implementation of time.process_time() to correctly report the sum of the system and user CPU time. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index bdc93a2b7ec1..5e0010c8a819 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1208,7 +1208,7 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) return -1; } - _PyTime_t total = utime + utime; + _PyTime_t total = utime + stime; *tp = total; return 0; } From webhook-mailer at python.org Tue Aug 27 00:31:31 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Aug 2019 04:31:31 -0000 Subject: [Python-checkins] bpo-36205: Fix the rusage implementation of time.process_time() (GH-15538) Message-ID: https://github.com/python/cpython/commit/1bf672f53a83c471e6fc4599d2d5149fd6842ff2 commit: 1bf672f53a83c471e6fc4599d2d5149fd6842ff2 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T21:31:27-07:00 summary: bpo-36205: Fix the rusage implementation of time.process_time() (GH-15538) (cherry picked from commit 8bf5fef8737fdd12724b9340d76a4ed391c4ad8a) Co-authored-by: vrajivk <3413293+vrajivk at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst M Modules/timemodule.c diff --git a/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst b/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst new file mode 100644 index 000000000000..50cda34fbbd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst @@ -0,0 +1 @@ +Fix the rusage implementation of time.process_time() to correctly report the sum of the system and user CPU time. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 4c8e2cb2344b..0ae4fcc32364 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1189,7 +1189,7 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) return -1; } - _PyTime_t total = utime + utime; + _PyTime_t total = utime + stime; *tp = total; return 0; } From webhook-mailer at python.org Tue Aug 27 00:34:36 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Aug 2019 04:34:36 -0000 Subject: [Python-checkins] bpo-36205: Fix the rusage implementation of time.process_time() (GH-15538) Message-ID: https://github.com/python/cpython/commit/91020fade6ca0f22eef2d338be1380b17385e715 commit: 91020fade6ca0f22eef2d338be1380b17385e715 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-26T21:34:32-07:00 summary: bpo-36205: Fix the rusage implementation of time.process_time() (GH-15538) (cherry picked from commit 8bf5fef8737fdd12724b9340d76a4ed391c4ad8a) Co-authored-by: vrajivk <3413293+vrajivk at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst M Modules/timemodule.c diff --git a/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst b/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst new file mode 100644 index 000000000000..50cda34fbbd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst @@ -0,0 +1 @@ +Fix the rusage implementation of time.process_time() to correctly report the sum of the system and user CPU time. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index bdc93a2b7ec1..5e0010c8a819 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1208,7 +1208,7 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) return -1; } - _PyTime_t total = utime + utime; + _PyTime_t total = utime + stime; *tp = total; return 0; } From webhook-mailer at python.org Tue Aug 27 12:55:21 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Tue, 27 Aug 2019 16:55:21 -0000 Subject: [Python-checkins] Fix unused variable and signed/unsigned warnings (GH-15537) Message-ID: https://github.com/python/cpython/commit/0138c4ceab1e10d42d0aa962d2ae079b46da7671 commit: 0138c4ceab1e10d42d0aa962d2ae079b46da7671 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-27T09:55:13-07:00 summary: Fix unused variable and signed/unsigned warnings (GH-15537) files: M Objects/unicodeobject.c M Python/peephole.c M Python/pystrhex.c diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index aa933773233b..d4b2c93a8452 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -500,10 +500,14 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) } else { PyCompactUnicodeObject *compact = (PyCompactUnicodeObject *)op; +#ifndef NDEBUG void *data; +#endif if (ascii->state.compact == 1) { +#ifndef NDEBUG data = compact + 1; +#endif _PyObject_ASSERT(op, kind == PyUnicode_1BYTE_KIND || kind == PyUnicode_2BYTE_KIND || kind == PyUnicode_4BYTE_KIND); @@ -512,9 +516,11 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) _PyObject_ASSERT(op, compact->utf8 != data); } else { +#ifndef NDEBUG PyUnicodeObject *unicode = (PyUnicodeObject *)op; data = unicode->data.any; +#endif if (kind == PyUnicode_WCHAR_KIND) { _PyObject_ASSERT(op, ascii->length == 0); _PyObject_ASSERT(op, ascii->hash == -1); diff --git a/Python/peephole.c b/Python/peephole.c index 3e56e788b007..d859648411fa 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -255,8 +255,8 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, than +255 (encoded as multiple bytes), just to keep the peephole optimizer simple. The optimizer leaves line number deltas unchanged. */ - for (j = 0; j < tabsiz; j += 2) { - if (lnotab[j] == 255) { + for (i = 0; i < tabsiz; i += 2) { + if (lnotab[i] == 255) { goto exitUnchanged; } } diff --git a/Python/pystrhex.c b/Python/pystrhex.c index 5dc7c9613796..9d34f71a2e9c 100644 --- a/Python/pystrhex.c +++ b/Python/pystrhex.c @@ -57,7 +57,7 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, } resultlen += arglen * 2; - if (abs_bytes_per_sep >= arglen) { + if ((size_t)abs_bytes_per_sep >= (size_t)arglen) { bytes_per_sep_group = 0; abs_bytes_per_sep = 0; } From webhook-mailer at python.org Tue Aug 27 13:13:56 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Tue, 27 Aug 2019 17:13:56 -0000 Subject: [Python-checkins] Fix unused variable and signed/unsigned warnings (GH-15537) (GH-15551) Message-ID: https://github.com/python/cpython/commit/d5ba8bbdae9a59c10c1275f71415732d68fe9661 commit: d5ba8bbdae9a59c10c1275f71415732d68fe9661 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-27T10:13:52-07:00 summary: Fix unused variable and signed/unsigned warnings (GH-15537) (GH-15551) (cherry picked from commit 0138c4ceab1e10d42d0aa962d2ae079b46da7671) Co-authored-by: Raymond Hettinger files: M Objects/unicodeobject.c M Python/peephole.c M Python/pystrhex.c diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index c28f36fb4618..8521a4c9d7de 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -456,10 +456,14 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) } else { PyCompactUnicodeObject *compact = (PyCompactUnicodeObject *)op; +#ifndef NDEBUG void *data; +#endif if (ascii->state.compact == 1) { +#ifndef NDEBUG data = compact + 1; +#endif _PyObject_ASSERT(op, kind == PyUnicode_1BYTE_KIND || kind == PyUnicode_2BYTE_KIND || kind == PyUnicode_4BYTE_KIND); @@ -468,9 +472,11 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) _PyObject_ASSERT(op, compact->utf8 != data); } else { +#ifndef NDEBUG PyUnicodeObject *unicode = (PyUnicodeObject *)op; data = unicode->data.any; +#endif if (kind == PyUnicode_WCHAR_KIND) { _PyObject_ASSERT(op, ascii->length == 0); _PyObject_ASSERT(op, ascii->hash == -1); diff --git a/Python/peephole.c b/Python/peephole.c index 3e56e788b007..d859648411fa 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -255,8 +255,8 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, than +255 (encoded as multiple bytes), just to keep the peephole optimizer simple. The optimizer leaves line number deltas unchanged. */ - for (j = 0; j < tabsiz; j += 2) { - if (lnotab[j] == 255) { + for (i = 0; i < tabsiz; i += 2) { + if (lnotab[i] == 255) { goto exitUnchanged; } } diff --git a/Python/pystrhex.c b/Python/pystrhex.c index 5dc7c9613796..9d34f71a2e9c 100644 --- a/Python/pystrhex.c +++ b/Python/pystrhex.c @@ -57,7 +57,7 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, } resultlen += arglen * 2; - if (abs_bytes_per_sep >= arglen) { + if ((size_t)abs_bytes_per_sep >= (size_t)arglen) { bytes_per_sep_group = 0; abs_bytes_per_sep = 0; } From webhook-mailer at python.org Tue Aug 27 14:16:48 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Aug 2019 18:16:48 -0000 Subject: [Python-checkins] bpo-37936: Remove some .gitignore rules that were intended locally. (GH-15542) Message-ID: https://github.com/python/cpython/commit/8c9e9b0cd5b24dfbf1424d1f253d02de80e8f5ef commit: 8c9e9b0cd5b24dfbf1424d1f253d02de80e8f5ef branch: master author: Greg Price committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-27T11:16:31-07:00 summary: bpo-37936: Remove some .gitignore rules that were intended locally. (GH-15542) These appeared in commit c5ae169e1. The comment on them, as well as the presence among them of a rule for the .gitignore file itself, indicate that the author intended these lines to remain only in their own local working tree -- not to get committed even to their own repo, let alone merged upstream. They did nevertheless get committed, because it turns out that Git takes no notice of what .gitignore says about files that it's already tracking... for example, this .gitignore file itself. Give effect to these lines' original intention, by deleting them. :-) Git tip, for reference: the `.git/info/exclude` file is a handy way to do exactly what these lines were originally intended to do. A related handy file is `~/.config/git/ignore`. See gitignore(5), aka `git help ignore`, for details. https://bugs.python.org/issue37936 Automerge-Triggered-By: @zware files: M .gitignore diff --git a/.gitignore b/.gitignore index 5f1ba0b92ceb..9f3b1ac83b51 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,8 @@ -# added for local development -.buildaix/ -Modules/python.exp -buildaix/ -installp/ -.gitignore - # Two-trick pony for OSX and other case insensitive file systems: # Ignore ./python binary on Unix but still look into ./Python/ directory. /python !/Python/ + *.cover *.iml *.o From webhook-mailer at python.org Tue Aug 27 14:35:16 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Aug 2019 18:35:16 -0000 Subject: [Python-checkins] bpo-37936: Remove some .gitignore rules that were intended locally. (GH-15542) Message-ID: https://github.com/python/cpython/commit/caf7a30efecef21def997ab214dc6c1604d90a84 commit: caf7a30efecef21def997ab214dc6c1604d90a84 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-27T11:35:11-07:00 summary: bpo-37936: Remove some .gitignore rules that were intended locally. (GH-15542) These appeared in commit c5ae169e1. The comment on them, as well as the presence among them of a rule for the .gitignore file itself, indicate that the author intended these lines to remain only in their own local working tree -- not to get committed even to their own repo, let alone merged upstream. They did nevertheless get committed, because it turns out that Git takes no notice of what .gitignore says about files that it's already tracking... for example, this .gitignore file itself. Give effect to these lines' original intention, by deleting them. :-) Git tip, for reference: the `.git/info/exclude` file is a handy way to do exactly what these lines were originally intended to do. A related handy file is `~/.config/git/ignore`. See gitignore(5), aka `git help ignore`, for details. https://bugs.python.org/issue37936 Automerge-Triggered-By: @zware (cherry picked from commit 8c9e9b0cd5b24dfbf1424d1f253d02de80e8f5ef) Co-authored-by: Greg Price files: M .gitignore diff --git a/.gitignore b/.gitignore index 9445ef1e2c52..9c0c2ef07a1d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,8 @@ -# added for local development -.buildaix/ -Modules/python.exp -buildaix/ -installp/ -.gitignore - # Two-trick pony for OSX and other case insensitive file systems: # Ignore ./python binary on Unix but still look into ./Python/ directory. /python !/Python/ + *.cover *.iml *.o From webhook-mailer at python.org Tue Aug 27 14:41:42 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Aug 2019 18:41:42 -0000 Subject: [Python-checkins] bpo-37936: Remove some .gitignore rules that were intended locally. (GH-15542) Message-ID: https://github.com/python/cpython/commit/2f0440e6dba248ff1e2b46c063adfd8fcb923a34 commit: 2f0440e6dba248ff1e2b46c063adfd8fcb923a34 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-27T11:41:38-07:00 summary: bpo-37936: Remove some .gitignore rules that were intended locally. (GH-15542) These appeared in commit c5ae169e1. The comment on them, as well as the presence among them of a rule for the .gitignore file itself, indicate that the author intended these lines to remain only in their own local working tree -- not to get committed even to their own repo, let alone merged upstream. They did nevertheless get committed, because it turns out that Git takes no notice of what .gitignore says about files that it's already tracking... for example, this .gitignore file itself. Give effect to these lines' original intention, by deleting them. :-) Git tip, for reference: the `.git/info/exclude` file is a handy way to do exactly what these lines were originally intended to do. A related handy file is `~/.config/git/ignore`. See gitignore(5), aka `git help ignore`, for details. https://bugs.python.org/issue37936 Automerge-Triggered-By: @zware (cherry picked from commit 8c9e9b0cd5b24dfbf1424d1f253d02de80e8f5ef) Co-authored-by: Greg Price files: M .gitignore diff --git a/.gitignore b/.gitignore index 58f8bf72f2b9..cdfe476088a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,8 @@ -# added for local development -.buildaix/ -Modules/python.exp -buildaix/ -installp/ -.gitignore - # Two-trick pony for OSX and other case insensitive file systems: # Ignore ./python binary on Unix but still look into ./Python/ directory. /python !/Python/ + *.cover *.iml *.o From webhook-mailer at python.org Tue Aug 27 17:18:10 2019 From: webhook-mailer at python.org (Ethan Furman) Date: Tue, 27 Aug 2019 21:18:10 -0000 Subject: [Python-checkins] Add Florian Ernst to ACKS (GH-15524) Message-ID: https://github.com/python/cpython/commit/3224e1a6bb23b1b322f5b9424b10ab68c9127dcc commit: 3224e1a6bb23b1b322f5b9424b10ab68c9127dcc branch: master author: Ethan Furman committer: GitHub date: 2019-08-27T14:18:05-07:00 summary: Add Florian Ernst to ACKS (GH-15524) files: M Misc/ACKS diff --git a/Misc/ACKS b/Misc/ACKS index 3a796860b798..4f5ebd67f863 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -458,6 +458,7 @@ Tom Epperly G?kcen Eraslan Stoffel Erasmus J?rgen A. Erhard +Florian Ernst Michael Ernst Ben Escoto Andy Eskilsson From webhook-mailer at python.org Tue Aug 27 17:37:01 2019 From: webhook-mailer at python.org (Christian Heimes) Date: Tue, 27 Aug 2019 21:37:01 -0000 Subject: [Python-checkins] bpo-37951: Lift subprocess's fork() restriction (GH-15544) Message-ID: https://github.com/python/cpython/commit/98d90f745d35d5d07bffcb46788b50e05eea56c6 commit: 98d90f745d35d5d07bffcb46788b50e05eea56c6 branch: master author: Christian Heimes committer: GitHub date: 2019-08-27T23:36:56+02:00 summary: bpo-37951: Lift subprocess's fork() restriction (GH-15544) files: A Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst M Doc/library/subprocess.rst M Doc/whatsnew/3.8.rst M Modules/_posixsubprocess.c diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 7e1e3f942c1c..167ed9a6ead4 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -483,6 +483,13 @@ functions. The *start_new_session* parameter can take the place of a previously common use of *preexec_fn* to call os.setsid() in the child. + .. versionchanged:: 3.8 + + The *preexec_fn* parameter is no longer supported in subinterpreters. + The use of the parameter in a subinterpreter raises + :exc:`RuntimeError`. The new restriction may affect applications that + are deployed in mod_wsgi, uWSGI, and other embedded environments. + If *close_fds* is true, all file descriptors except :const:`0`, :const:`1` and :const:`2` will be closed before the child process is executed. Otherwise when *close_fds* is false, file descriptors obey their inheritable flag diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index cd31cf6db6e8..bcdb60d86d85 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -1531,6 +1531,12 @@ Changes in the Python API non-zero :attr:`~Popen.returncode`. (Contributed by Joannah Nanjekye and Victor Stinner in :issue:`35537`.) +* The *preexec_fn* argument of * :class:`subprocess.Popen` is no longer + compatible with subinterpreters. The use of the parameter in a + subinterpreter now raises :exc:`RuntimeError`. + (Contributed by Eric Snow in :issue:`34651`, modified by Christian Heimes + in :issue:`37951`.) + * The :meth:`imap.IMAP4.logout` method no longer ignores silently arbitrary exceptions. diff --git a/Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst b/Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst new file mode 100644 index 000000000000..18e4c620bdea --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst @@ -0,0 +1,2 @@ +Most features of the subprocess module now work again in subinterpreters. +Only *preexec_fn* is restricted in subinterpreters. diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index 60c8eab90a15..f68d362acc04 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -583,8 +583,10 @@ subprocess_fork_exec(PyObject* self, PyObject *args) &restore_signals, &call_setsid, &preexec_fn)) return NULL; - if (_PyInterpreterState_Get() != PyInterpreterState_Main()) { - PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); + if ((preexec_fn != Py_None) && + (_PyInterpreterState_Get() != PyInterpreterState_Main())) { + PyErr_SetString(PyExc_RuntimeError, + "preexec_fn not supported within subinterpreters"); return NULL; } From webhook-mailer at python.org Tue Aug 27 17:56:31 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Aug 2019 21:56:31 -0000 Subject: [Python-checkins] bpo-37951: Lift subprocess's fork() restriction (GH-15544) Message-ID: https://github.com/python/cpython/commit/03c52f2f63a8abeb4afb75e9da46c7d6c0a8afd5 commit: 03c52f2f63a8abeb4afb75e9da46c7d6c0a8afd5 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-27T14:56:27-07:00 summary: bpo-37951: Lift subprocess's fork() restriction (GH-15544) (cherry picked from commit 98d90f745d35d5d07bffcb46788b50e05eea56c6) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst M Doc/library/subprocess.rst M Doc/whatsnew/3.8.rst M Modules/_posixsubprocess.c diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 7e1e3f942c1c..167ed9a6ead4 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -483,6 +483,13 @@ functions. The *start_new_session* parameter can take the place of a previously common use of *preexec_fn* to call os.setsid() in the child. + .. versionchanged:: 3.8 + + The *preexec_fn* parameter is no longer supported in subinterpreters. + The use of the parameter in a subinterpreter raises + :exc:`RuntimeError`. The new restriction may affect applications that + are deployed in mod_wsgi, uWSGI, and other embedded environments. + If *close_fds* is true, all file descriptors except :const:`0`, :const:`1` and :const:`2` will be closed before the child process is executed. Otherwise when *close_fds* is false, file descriptors obey their inheritable flag diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index cd31cf6db6e8..bcdb60d86d85 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -1531,6 +1531,12 @@ Changes in the Python API non-zero :attr:`~Popen.returncode`. (Contributed by Joannah Nanjekye and Victor Stinner in :issue:`35537`.) +* The *preexec_fn* argument of * :class:`subprocess.Popen` is no longer + compatible with subinterpreters. The use of the parameter in a + subinterpreter now raises :exc:`RuntimeError`. + (Contributed by Eric Snow in :issue:`34651`, modified by Christian Heimes + in :issue:`37951`.) + * The :meth:`imap.IMAP4.logout` method no longer ignores silently arbitrary exceptions. diff --git a/Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst b/Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst new file mode 100644 index 000000000000..18e4c620bdea --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst @@ -0,0 +1,2 @@ +Most features of the subprocess module now work again in subinterpreters. +Only *preexec_fn* is restricted in subinterpreters. diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index 81a23c6d3300..e693e5320690 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -583,8 +583,10 @@ subprocess_fork_exec(PyObject* self, PyObject *args) &restore_signals, &call_setsid, &preexec_fn)) return NULL; - if (_PyInterpreterState_Get() != PyInterpreterState_Main()) { - PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); + if ((preexec_fn != Py_None) && + (_PyInterpreterState_Get() != PyInterpreterState_Main())) { + PyErr_SetString(PyExc_RuntimeError, + "preexec_fn not supported within subinterpreters"); return NULL; } From webhook-mailer at python.org Wed Aug 28 00:38:13 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Wed, 28 Aug 2019 04:38:13 -0000 Subject: [Python-checkins] bpo-36582: Make collections.UserString.encode() return bytes, not str (GH-13138) Message-ID: https://github.com/python/cpython/commit/2a16eea71f56c2d8f38c295c8ce71a9a9a140aff commit: 2a16eea71f56c2d8f38c295c8ce71a9a9a140aff branch: master author: Daniel Fortunov committer: Raymond Hettinger date: 2019-08-27T21:38:09-07:00 summary: bpo-36582: Make collections.UserString.encode() return bytes, not str (GH-13138) files: A Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst M Lib/collections/__init__.py M Lib/test/test_userstring.py M Misc/ACKS diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 6a3e599a91e6..859b8460e48d 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -1184,12 +1184,10 @@ def count(self, sub, start=0, end=_sys.maxsize): if isinstance(sub, UserString): sub = sub.data return self.data.count(sub, start, end) - def encode(self, encoding=None, errors=None): # XXX improve this? - if encoding: - if errors: - return self.__class__(self.data.encode(encoding, errors)) - return self.__class__(self.data.encode(encoding)) - return self.__class__(self.data.encode()) + def encode(self, encoding='utf-8', errors='strict'): + encoding = 'utf-8' if encoding is None else encoding + errors = 'strict' if errors is None else errors + return self.data.encode(encoding, errors) def endswith(self, suffix, start=0, end=_sys.maxsize): return self.data.endswith(suffix, start, end) def expandtabs(self, tabsize=8): diff --git a/Lib/test/test_userstring.py b/Lib/test/test_userstring.py index 19b0acfc760f..4d1d8b6b6fe2 100644 --- a/Lib/test/test_userstring.py +++ b/Lib/test/test_userstring.py @@ -51,6 +51,20 @@ def __rmod__(self, other): str3 = ustr3('TEST') self.assertEqual(fmt2 % str3, 'value is TEST') + def test_encode_default_args(self): + self.checkequal(b'hello', 'hello', 'encode') + # Check that encoding defaults to utf-8 + self.checkequal(b'\xf0\xa3\x91\x96', '\U00023456', 'encode') + # Check that errors defaults to 'strict' + self.checkraises(UnicodeError, '\ud800', 'encode') + + def test_encode_explicit_none_args(self): + self.checkequal(b'hello', 'hello', 'encode', None, None) + # Check that encoding defaults to utf-8 + self.checkequal(b'\xf0\xa3\x91\x96', '\U00023456', 'encode', None, None) + # Check that errors defaults to 'strict' + self.checkraises(UnicodeError, '\ud800', 'encode', None, None) + if __name__ == "__main__": unittest.main() diff --git a/Misc/ACKS b/Misc/ACKS index 4f5ebd67f863..d5064f644e24 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -512,6 +512,7 @@ Arnaud Fontaine Michael Foord Amaury Forgeot d'Arc Doug Fort +Daniel Fortunov Evens Fortun? Chris Foster John Fouhy diff --git a/Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst b/Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst new file mode 100644 index 000000000000..34f16fcde879 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst @@ -0,0 +1 @@ +Fix ``UserString.encode()`` to correctly return ``bytes`` rather than a ``UserString`` instance. \ No newline at end of file From webhook-mailer at python.org Wed Aug 28 00:59:58 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Wed, 28 Aug 2019 04:59:58 -0000 Subject: [Python-checkins] bpo-36582: Make collections.UserString.encode() return bytes, not str (GH-13138) (GH-15557) Message-ID: https://github.com/python/cpython/commit/2cb82d2a88710b0af10b9d9721a9710ecc037e72 commit: 2cb82d2a88710b0af10b9d9721a9710ecc037e72 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-27T21:59:54-07:00 summary: bpo-36582: Make collections.UserString.encode() return bytes, not str (GH-13138) (GH-15557) (cherry picked from commit 2a16eea71f56c2d8f38c295c8ce71a9a9a140aff) Co-authored-by: Daniel Fortunov files: A Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst M Lib/collections/__init__.py M Lib/test/test_userstring.py M Misc/ACKS diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 469690be8c8e..cadf1c72f08d 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -1200,12 +1200,10 @@ def count(self, sub, start=0, end=_sys.maxsize): if isinstance(sub, UserString): sub = sub.data return self.data.count(sub, start, end) - def encode(self, encoding=None, errors=None): # XXX improve this? - if encoding: - if errors: - return self.__class__(self.data.encode(encoding, errors)) - return self.__class__(self.data.encode(encoding)) - return self.__class__(self.data.encode()) + def encode(self, encoding='utf-8', errors='strict'): + encoding = 'utf-8' if encoding is None else encoding + errors = 'strict' if errors is None else errors + return self.data.encode(encoding, errors) def endswith(self, suffix, start=0, end=_sys.maxsize): return self.data.endswith(suffix, start, end) def expandtabs(self, tabsize=8): diff --git a/Lib/test/test_userstring.py b/Lib/test/test_userstring.py index 19b0acfc760f..4d1d8b6b6fe2 100644 --- a/Lib/test/test_userstring.py +++ b/Lib/test/test_userstring.py @@ -51,6 +51,20 @@ def __rmod__(self, other): str3 = ustr3('TEST') self.assertEqual(fmt2 % str3, 'value is TEST') + def test_encode_default_args(self): + self.checkequal(b'hello', 'hello', 'encode') + # Check that encoding defaults to utf-8 + self.checkequal(b'\xf0\xa3\x91\x96', '\U00023456', 'encode') + # Check that errors defaults to 'strict' + self.checkraises(UnicodeError, '\ud800', 'encode') + + def test_encode_explicit_none_args(self): + self.checkequal(b'hello', 'hello', 'encode', None, None) + # Check that encoding defaults to utf-8 + self.checkequal(b'\xf0\xa3\x91\x96', '\U00023456', 'encode', None, None) + # Check that errors defaults to 'strict' + self.checkraises(UnicodeError, '\ud800', 'encode', None, None) + if __name__ == "__main__": unittest.main() diff --git a/Misc/ACKS b/Misc/ACKS index ab874e929931..5a8494f1a827 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -509,6 +509,7 @@ Arnaud Fontaine Michael Foord Amaury Forgeot d'Arc Doug Fort +Daniel Fortunov Evens Fortun? Chris Foster John Fouhy diff --git a/Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst b/Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst new file mode 100644 index 000000000000..34f16fcde879 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst @@ -0,0 +1 @@ +Fix ``UserString.encode()`` to correctly return ``bytes`` rather than a ``UserString`` instance. \ No newline at end of file From webhook-mailer at python.org Wed Aug 28 13:11:13 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 28 Aug 2019 17:11:13 -0000 Subject: [Python-checkins] closes bpo-37965: Fix compiler warning of distutils CCompiler.test_function. (GH-15560) Message-ID: https://github.com/python/cpython/commit/55aabee07501e1468082b3237620e4ecd75c5da6 commit: 55aabee07501e1468082b3237620e4ecd75c5da6 branch: master author: Anonymous Maarten committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-28T10:11:03-07:00 summary: closes bpo-37965: Fix compiler warning of distutils CCompiler.test_function. (GH-15560) https://bugs.python.org/issue37965 https://bugs.python.org/issue37965 Automerge-Triggered-By: @benjaminp files: A Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst M Lib/distutils/ccompiler.py diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py index 1a411ed11132..4cfc6c7065e9 100644 --- a/Lib/distutils/ccompiler.py +++ b/Lib/distutils/ccompiler.py @@ -781,8 +781,9 @@ def has_function(self, funcname, includes=None, include_dirs=None, for incl in includes: f.write("""#include "%s"\n""" % incl) f.write("""\ -main (int argc, char **argv) { +int main (int argc, char **argv) { %s(); + return 0; } """ % funcname) finally: diff --git a/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst b/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst new file mode 100644 index 000000000000..116a9e49dccc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst @@ -0,0 +1 @@ +Fix C compiler warning caused by distutils.ccompiler.CCompiler.has_function. From webhook-mailer at python.org Wed Aug 28 13:32:38 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 28 Aug 2019 17:32:38 -0000 Subject: [Python-checkins] closes bpo-37965: Fix compiler warning of distutils CCompiler.test_function. (GH-15561) Message-ID: https://github.com/python/cpython/commit/23985c6a64222df46cd7e21b9b21c0e37aa95e10 commit: 23985c6a64222df46cd7e21b9b21c0e37aa95e10 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2019-08-28T10:32:34-07:00 summary: closes bpo-37965: Fix compiler warning of distutils CCompiler.test_function. (GH-15561) https://bugs.python.org/issue37965 https://bugs.python.org/issue37965 Automerge-Triggered-By: @benjaminp (cherry picked from commit 55aabee07501e1468082b3237620e4ecd75c5da6) Co-authored-by: Anonymous Maarten files: A Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst M Lib/distutils/ccompiler.py diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py index 1a411ed11132..4cfc6c7065e9 100644 --- a/Lib/distutils/ccompiler.py +++ b/Lib/distutils/ccompiler.py @@ -781,8 +781,9 @@ def has_function(self, funcname, includes=None, include_dirs=None, for incl in includes: f.write("""#include "%s"\n""" % incl) f.write("""\ -main (int argc, char **argv) { +int main (int argc, char **argv) { %s(); + return 0; } """ % funcname) finally: diff --git a/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst b/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst new file mode 100644 index 000000000000..116a9e49dccc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst @@ -0,0 +1 @@ +Fix C compiler warning caused by distutils.ccompiler.CCompiler.has_function. From webhook-mailer at python.org Wed Aug 28 13:36:22 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 28 Aug 2019 17:36:22 -0000 Subject: [Python-checkins] closes bpo-37965: Fix compiler warning of distutils CCompiler.test_function. (GH-15560) Message-ID: https://github.com/python/cpython/commit/0229b56d8c0cb65b8ad789e69dcd281fd92a6d96 commit: 0229b56d8c0cb65b8ad789e69dcd281fd92a6d96 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-28T10:36:18-07:00 summary: closes bpo-37965: Fix compiler warning of distutils CCompiler.test_function. (GH-15560) https://bugs.python.org/issue37965 https://bugs.python.org/issue37965 Automerge-Triggered-By: @benjaminp (cherry picked from commit 55aabee07501e1468082b3237620e4ecd75c5da6) Co-authored-by: Anonymous Maarten files: A Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst M Lib/distutils/ccompiler.py diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py index 88a910c6810f..3a7b5b84e1a8 100644 --- a/Lib/distutils/ccompiler.py +++ b/Lib/distutils/ccompiler.py @@ -748,8 +748,9 @@ def has_function(self, funcname, includes=None, include_dirs=None, for incl in includes: f.write("""#include "%s"\n""" % incl) f.write("""\ -main (int argc, char **argv) { +int main (int argc, char **argv) { %s(); + return 0; } """ % funcname) finally: diff --git a/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst b/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst new file mode 100644 index 000000000000..116a9e49dccc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst @@ -0,0 +1 @@ +Fix C compiler warning caused by distutils.ccompiler.CCompiler.has_function. From webhook-mailer at python.org Wed Aug 28 13:37:42 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 28 Aug 2019 17:37:42 -0000 Subject: [Python-checkins] closes bpo-37965: Fix compiler warning of distutils CCompiler.test_function. (GH-15560) Message-ID: https://github.com/python/cpython/commit/ea48966e5d868e2863d896ee909460d482a0513c commit: ea48966e5d868e2863d896ee909460d482a0513c branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-28T10:37:38-07:00 summary: closes bpo-37965: Fix compiler warning of distutils CCompiler.test_function. (GH-15560) https://bugs.python.org/issue37965 https://bugs.python.org/issue37965 Automerge-Triggered-By: @benjaminp (cherry picked from commit 55aabee07501e1468082b3237620e4ecd75c5da6) Co-authored-by: Anonymous Maarten files: A Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst M Lib/distutils/ccompiler.py diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py index b71d1d39bcda..b70e5e4b5f03 100644 --- a/Lib/distutils/ccompiler.py +++ b/Lib/distutils/ccompiler.py @@ -781,8 +781,9 @@ def has_function(self, funcname, includes=None, include_dirs=None, for incl in includes: f.write("""#include "%s"\n""" % incl) f.write("""\ -main (int argc, char **argv) { +int main (int argc, char **argv) { %s(); + return 0; } """ % funcname) finally: diff --git a/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst b/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst new file mode 100644 index 000000000000..116a9e49dccc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst @@ -0,0 +1 @@ +Fix C compiler warning caused by distutils.ccompiler.CCompiler.has_function. From webhook-mailer at python.org Wed Aug 28 14:55:04 2019 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 28 Aug 2019 18:55:04 -0000 Subject: [Python-checkins] Fix typo: Pyssize_t => Py_ssize_t (GH-15411) (#15520) Message-ID: https://github.com/python/cpython/commit/e72dcaa33a528cda82d85d1f4890118710162b23 commit: e72dcaa33a528cda82d85d1f4890118710162b23 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2019-08-28T14:54:57-04:00 summary: Fix typo: Pyssize_t => Py_ssize_t (GH-15411) (#15520) (cherry picked from commit b3b9619f5e1e7ebe3fbb73eae4ec878312056a90) Co-authored-by: Sergey Fedoseev files: M Doc/data/refcounts.dat diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 213ddcb61fae..ec8094ef2486 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2444,7 +2444,7 @@ PyUnicode_FromWideChar:Py_ssize_t:size:: PyUnicode_AsWideChar:Py_ssize_t::: PyUnicode_AsWideChar:PyObject*:*unicode:0: PyUnicode_AsWideChar:wchar_t*:w:: -PyUnicode_AsWideChar:Pyssize_t:size:: +PyUnicode_AsWideChar:Py_ssize_t:size:: PyUnicode_AsWideCharString:wchar_t*::: PyUnicode_AsWideCharString:PyObject*:unicode:0: From webhook-mailer at python.org Wed Aug 28 17:54:08 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 28 Aug 2019 21:54:08 -0000 Subject: [Python-checkins] bpo-23878: Remove an unneeded fseek() call in _Py_FindEnvConfigValue() (GH-15424) Message-ID: https://github.com/python/cpython/commit/e4a5e9b5bb69025eb879cb133259667241d61a1f commit: e4a5e9b5bb69025eb879cb133259667241d61a1f branch: master author: Zackery Spytz committer: Victor Stinner date: 2019-08-28T23:54:02+02:00 summary: bpo-23878: Remove an unneeded fseek() call in _Py_FindEnvConfigValue() (GH-15424) files: M Python/pathconfig.c diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 79ec4af00d83..ee220611357e 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -741,7 +741,6 @@ _Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key, char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */ buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0'; - fseek(env_file, 0, SEEK_SET); while (!feof(env_file)) { char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file); From webhook-mailer at python.org Wed Aug 28 21:56:23 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 01:56:23 -0000 Subject: [Python-checkins] closes bpo-37964: add F_GETPATH command to fcntl (GH-15550) Message-ID: https://github.com/python/cpython/commit/13f37f2ba8b1fa39f312dca920e847d9c0313c77 commit: 13f37f2ba8b1fa39f312dca920e847d9c0313c77 branch: master author: Vinay Sharma committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-28T18:56:17-07:00 summary: closes bpo-37964: add F_GETPATH command to fcntl (GH-15550) https://bugs.python.org/issue37964 Automerge-Triggered-By: @benjaminp files: A Misc/NEWS.d/next/Library/2019-08-27-21-19-28.bpo-37964.SxdnsF.rst M Doc/library/fcntl.rst M Lib/test/test_fcntl.py M Modules/fcntlmodule.c diff --git a/Doc/library/fcntl.rst b/Doc/library/fcntl.rst index 2db9674952d7..6a66f5b66481 100644 --- a/Doc/library/fcntl.rst +++ b/Doc/library/fcntl.rst @@ -33,6 +33,10 @@ descriptor. ``F_SEAL_*`` constants for sealing of :func:`os.memfd_create` file descriptors. +.. versionchanged:: 3.9 + On macOS, the fcntl module exposes the ``F_GETPATH`` constant, which obtains + the path of a file from a file descriptor. + The module defines the following functions: diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index 5d4abe388f78..38097dbdfb97 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -144,6 +144,12 @@ def test_flock_overflow(self): self.assertRaises(OverflowError, fcntl.flock, _testcapi.INT_MAX+1, fcntl.LOCK_SH) + @unittest.skipIf(sys.platform != 'darwin', "F_GETPATH is only available on macos") + def test_fcntl_f_getpath(self): + self.f = open(TESTFN, 'wb') + abspath = os.path.abspath(TESTFN) + res = fcntl.fcntl(self.f.fileno(), fcntl.F_GETPATH, bytes(len(abspath))) + self.assertEqual(abspath, res.decode('utf-8')) def test_main(): run_unittest(TestFcntl) diff --git a/Misc/NEWS.d/next/Library/2019-08-27-21-19-28.bpo-37964.SxdnsF.rst b/Misc/NEWS.d/next/Library/2019-08-27-21-19-28.bpo-37964.SxdnsF.rst new file mode 100644 index 000000000000..c25e64329c4c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-27-21-19-28.bpo-37964.SxdnsF.rst @@ -0,0 +1 @@ +Add ``F_GETPATH`` command to :mod:`fcntl`. diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index 0fbf7876c3e2..cfa122568404 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -501,6 +501,9 @@ all_ins(PyObject* m) #ifdef F_SETOWN if (PyModule_AddIntMacro(m, F_SETOWN)) return -1; #endif +#ifdef F_GETPATH + if (PyModule_AddIntMacro(m, F_GETPATH)) return -1; +#endif #ifdef F_GETSIG if (PyModule_AddIntMacro(m, F_GETSIG)) return -1; #endif From webhook-mailer at python.org Wed Aug 28 23:39:37 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 03:39:37 -0000 Subject: [Python-checkins] Raise a RuntimeError when tee iterator is consumed from different threads (GH-15567) Message-ID: https://github.com/python/cpython/commit/fa220ec7633e9674baccc28dde987f29d7f65141 commit: fa220ec7633e9674baccc28dde987f29d7f65141 branch: master author: HongWeipeng <961365124 at qq.com> committer: Raymond Hettinger date: 2019-08-28T20:39:25-07:00 summary: Raise a RuntimeError when tee iterator is consumed from different threads (GH-15567) files: A Misc/NEWS.d/next/Library/2019-08-29-10-26-57.bpo-34410.ttCIpm.rst M Doc/library/itertools.rst M Modules/itertoolsmodule.c diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index a3f403a5b40b..8e7899e6b613 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -643,7 +643,8 @@ loops that truncate the stream. Once :func:`tee` has made a split, the original *iterable* should not be used anywhere else; otherwise, the *iterable* could get advanced without - the tee objects being informed. + the tee objects being informed. the :func:`tee` iterator can not be consumed + from different threads, even if an underlying iterator is thread-safe. This itertool may require significant auxiliary storage (depending on how much temporary data needs to be stored). In general, if one iterator uses diff --git a/Misc/NEWS.d/next/Library/2019-08-29-10-26-57.bpo-34410.ttCIpm.rst b/Misc/NEWS.d/next/Library/2019-08-29-10-26-57.bpo-34410.ttCIpm.rst new file mode 100644 index 000000000000..caddada835fc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-29-10-26-57.bpo-34410.ttCIpm.rst @@ -0,0 +1,2 @@ +Raise a RuntimeError when itertools.tee() iterator is consumed from different +threads. Patch by hongweipeng. diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 781d0cca5419..101addcfd3a9 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -452,6 +452,7 @@ typedef struct { teedataobject *dataobj; int index; /* 0 <= index <= LINKCELLS */ PyObject *weakreflist; + unsigned long thread_id; } teeobject; static PyTypeObject teedataobject_type; @@ -680,6 +681,11 @@ tee_next(teeobject *to) { PyObject *value, *link; + if (to->thread_id != PyThread_get_thread_ident()) { + PyErr_SetString(PyExc_RuntimeError, + "tee() iterator can not be consumed from different threads."); + return NULL; + } if (to->index >= LINKCELLS) { link = teedataobject_jumplink(to->dataobj); if (link == NULL) @@ -713,6 +719,7 @@ tee_copy(teeobject *to, PyObject *Py_UNUSED(ignored)) newto->dataobj = to->dataobj; newto->index = to->index; newto->weakreflist = NULL; + newto->thread_id = to->thread_id; PyObject_GC_Track(newto); return (PyObject *)newto; } @@ -745,6 +752,7 @@ tee_fromiterable(PyObject *iterable) to->index = 0; to->weakreflist = NULL; + to->thread_id = PyThread_get_thread_ident(); PyObject_GC_Track(to); done: Py_XDECREF(it); From webhook-mailer at python.org Thu Aug 29 00:33:56 2019 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 29 Aug 2019 04:33:56 -0000 Subject: [Python-checkins] bpo-18378: Recognize "UTF-8" as a valid name in locale._parse_localename (GH-14736) Message-ID: https://github.com/python/cpython/commit/b0caf329815120acf50287e29858093d328b0e3c commit: b0caf329815120acf50287e29858093d328b0e3c branch: master author: Ronald Oussoren committer: Ned Deily date: 2019-08-29T00:33:52-04:00 summary: bpo-18378: Recognize "UTF-8" as a valid name in locale._parse_localename (GH-14736) files: A Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst M Lib/locale.py M Lib/test/test_locale.py diff --git a/Lib/locale.py b/Lib/locale.py index f3d3973d038c..dd8a08524a01 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -492,6 +492,10 @@ def _parse_localename(localename): return tuple(code.split('.')[:2]) elif code == 'C': return None, None + elif code == 'UTF-8': + # On macOS "LC_CTYPE=UTF-8" is a valid locale setting + # for getting UTF-8 handling for text. + return None, 'UTF-8' raise ValueError('unknown locale: %s' % localename) def _build_localename(localetuple): diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index 792a15c50f92..c5d8e269d631 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -493,6 +493,42 @@ def test_japanese(self): class TestMiscellaneous(unittest.TestCase): + def test_defaults_UTF8(self): + # Issue #18378: on (at least) macOS setting LC_CTYPE to "UTF-8" is + # valid. Futhermore LC_CTYPE=UTF is used by the UTF-8 locale coercing + # during interpreter startup (on macOS). + import _locale + import os + + self.assertEqual(locale._parse_localename('UTF-8'), (None, 'UTF-8')) + + if hasattr(_locale, '_getdefaultlocale'): + orig_getlocale = _locale._getdefaultlocale + del _locale._getdefaultlocale + else: + orig_getlocale = None + + orig_env = {} + try: + for key in ('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE'): + if key in os.environ: + orig_env[key] = os.environ[key] + del os.environ[key] + + os.environ['LC_CTYPE'] = 'UTF-8' + + self.assertEqual(locale.getdefaultlocale(), (None, 'UTF-8')) + + finally: + for k in orig_env: + os.environ[k] = orig_env[k] + + if 'LC_CTYPE' not in orig_env: + del os.environ['LC_CTYPE'] + + if orig_getlocale is not None: + _locale._getdefaultlocale = orig_getlocale + def test_getpreferredencoding(self): # Invoke getpreferredencoding to make sure it does not cause exceptions. enc = locale.getpreferredencoding() diff --git a/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst b/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst new file mode 100644 index 000000000000..6dda8abf15d5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst @@ -0,0 +1 @@ +Recognize "UTF-8" as a valid value for LC_CTYPE in locale._parse_localename. From webhook-mailer at python.org Thu Aug 29 00:47:20 2019 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 29 Aug 2019 04:47:20 -0000 Subject: [Python-checkins] [3.8] bpo-37482: Fix email address name with encoded words and special chars (GH-14561) (GH-15380) Message-ID: https://github.com/python/cpython/commit/bd127b1b7dd50c76c4419d9c87c12901527d19da commit: bd127b1b7dd50c76c4419d9c87c12901527d19da branch: 3.8 author: bsiem <52461103+bsiem at users.noreply.github.com> committer: Ned Deily date: 2019-08-29T00:47:15-04:00 summary: [3.8] bpo-37482: Fix email address name with encoded words and special chars (GH-14561) (GH-15380) Special characters in email address header display names are normally put within double quotes. However, encoded words (=?charset?x?...?=) are not allowed withing double quotes. When the header contains a word with special characters and another word that must be encoded, the first one must also be encoded. In the next example, the display name in the From header is quoted and therefore the comma is allowed; in the To header, the comma is not within quotes and not encoded, which is not allowed and therefore rejected by some mail servers. From: "Foo Bar, France" To: Foo Bar, =?utf-8?q?Espa=C3=B1a?= https://bugs.python.org/issue37482 (cherry picked from commit df0c21ff46c5c37b6913828ef8c7651f523432f8) Co-authored-by: bsiem <52461103+bsiem at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst M Lib/email/_header_value_parser.py M Lib/test/test_email/test_headerregistry.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 3d369e4822cd..ea7083fc88b8 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2722,6 +2722,9 @@ def _refold_parse_tree(parse_tree, *, policy): wrap_as_ew_blocked -= 1 continue tstr = str(part) + if part.token_type == 'ptext' and set(tstr) & SPECIALS: + # Encode if tstr contains special characters. + want_encoding = True try: tstr.encode(encoding) charset = encoding diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index 75505460aba8..a6b48385aeac 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1527,6 +1527,30 @@ def test_set_message_header_from_group(self): class TestFolding(TestHeaderBase): + def test_address_display_names(self): + """Test the folding and encoding of address headers.""" + for name, result in ( + ('Foo Bar, France', '"Foo Bar, France"'), + ('Foo Bar (France)', '"Foo Bar (France)"'), + ('Foo Bar, Espa?a', 'Foo =?utf-8?q?Bar=2C_Espa=C3=B1a?='), + ('Foo Bar (Espa?a)', 'Foo Bar =?utf-8?b?KEVzcGHDsWEp?='), + ('Foo, Bar Espa?a', '=?utf-8?q?Foo=2C_Bar_Espa=C3=B1a?='), + ('Foo, Bar [Espa?a]', '=?utf-8?q?Foo=2C_Bar_=5BEspa=C3=B1a=5D?='), + ('Foo B?r, France', 'Foo =?utf-8?q?B=C3=A4r=2C?= France'), + ('Foo B?r ', 'Foo =?utf-8?q?B=C3=A4r_=3CFrance=3E?='), + ( + 'L?rem ipsum d?l?r sit amet, c?nsectetuer adipiscing. ' + 'Suspendisse p?tenti. Aliquam nibh. Suspendisse p?tenti.', + '=?utf-8?q?L=C3=B4rem_ipsum_d=C3=B4l=C3=B4r_sit_amet=2C_c' + '=C3=B4nsectetuer?=\n =?utf-8?q?adipiscing=2E_Suspendisse' + '_p=C3=B4tenti=2E_Aliquam_nibh=2E?=\n Suspendisse =?utf-8' + '?q?p=C3=B4tenti=2E?=', + ), + ): + h = self.make_header('To', Address(name, addr_spec='a at b.com')) + self.assertEqual(h.fold(policy=policy.default), + 'To: %s
\n' % result) + def test_short_unstructured(self): h = self.make_header('subject', 'this is a test') self.assertEqual(h.fold(policy=policy.default), diff --git a/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst b/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst new file mode 100644 index 000000000000..e09ff63eedc4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst @@ -0,0 +1 @@ +Fix serialization of display name in originator or destination address fields with both encoded words and special chars. From webhook-mailer at python.org Thu Aug 29 00:52:46 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 04:52:46 -0000 Subject: [Python-checkins] bpo-18378: Recognize "UTF-8" as a valid name in locale._parse_localename (GH-14736) Message-ID: https://github.com/python/cpython/commit/554143ebc2546e0b8b722dfafe397c0316f29980 commit: 554143ebc2546e0b8b722dfafe397c0316f29980 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-28T21:52:43-07:00 summary: bpo-18378: Recognize "UTF-8" as a valid name in locale._parse_localename (GH-14736) (cherry picked from commit b0caf329815120acf50287e29858093d328b0e3c) Co-authored-by: Ronald Oussoren files: A Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst M Lib/locale.py M Lib/test/test_locale.py diff --git a/Lib/locale.py b/Lib/locale.py index f3d3973d038c..dd8a08524a01 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -492,6 +492,10 @@ def _parse_localename(localename): return tuple(code.split('.')[:2]) elif code == 'C': return None, None + elif code == 'UTF-8': + # On macOS "LC_CTYPE=UTF-8" is a valid locale setting + # for getting UTF-8 handling for text. + return None, 'UTF-8' raise ValueError('unknown locale: %s' % localename) def _build_localename(localetuple): diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index e2c2178ae6cc..9a05029b42a4 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -493,6 +493,42 @@ def test_japanese(self): class TestMiscellaneous(unittest.TestCase): + def test_defaults_UTF8(self): + # Issue #18378: on (at least) macOS setting LC_CTYPE to "UTF-8" is + # valid. Futhermore LC_CTYPE=UTF is used by the UTF-8 locale coercing + # during interpreter startup (on macOS). + import _locale + import os + + self.assertEqual(locale._parse_localename('UTF-8'), (None, 'UTF-8')) + + if hasattr(_locale, '_getdefaultlocale'): + orig_getlocale = _locale._getdefaultlocale + del _locale._getdefaultlocale + else: + orig_getlocale = None + + orig_env = {} + try: + for key in ('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE'): + if key in os.environ: + orig_env[key] = os.environ[key] + del os.environ[key] + + os.environ['LC_CTYPE'] = 'UTF-8' + + self.assertEqual(locale.getdefaultlocale(), (None, 'UTF-8')) + + finally: + for k in orig_env: + os.environ[k] = orig_env[k] + + if 'LC_CTYPE' not in orig_env: + del os.environ['LC_CTYPE'] + + if orig_getlocale is not None: + _locale._getdefaultlocale = orig_getlocale + def test_getpreferredencoding(self): # Invoke getpreferredencoding to make sure it does not cause exceptions. enc = locale.getpreferredencoding() diff --git a/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst b/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst new file mode 100644 index 000000000000..6dda8abf15d5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst @@ -0,0 +1 @@ +Recognize "UTF-8" as a valid value for LC_CTYPE in locale._parse_localename. From webhook-mailer at python.org Thu Aug 29 00:56:04 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 04:56:04 -0000 Subject: [Python-checkins] bpo-18378: Recognize "UTF-8" as a valid name in locale._parse_localename (GH-14736) Message-ID: https://github.com/python/cpython/commit/e471a543a4f7c52a8d0081ec5142adab3416d8fb commit: e471a543a4f7c52a8d0081ec5142adab3416d8fb branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-28T21:56:00-07:00 summary: bpo-18378: Recognize "UTF-8" as a valid name in locale._parse_localename (GH-14736) (cherry picked from commit b0caf329815120acf50287e29858093d328b0e3c) Co-authored-by: Ronald Oussoren files: A Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst M Lib/locale.py M Lib/test/test_locale.py diff --git a/Lib/locale.py b/Lib/locale.py index f3d3973d038c..dd8a08524a01 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -492,6 +492,10 @@ def _parse_localename(localename): return tuple(code.split('.')[:2]) elif code == 'C': return None, None + elif code == 'UTF-8': + # On macOS "LC_CTYPE=UTF-8" is a valid locale setting + # for getting UTF-8 handling for text. + return None, 'UTF-8' raise ValueError('unknown locale: %s' % localename) def _build_localename(localetuple): diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index 792a15c50f92..c5d8e269d631 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -493,6 +493,42 @@ def test_japanese(self): class TestMiscellaneous(unittest.TestCase): + def test_defaults_UTF8(self): + # Issue #18378: on (at least) macOS setting LC_CTYPE to "UTF-8" is + # valid. Futhermore LC_CTYPE=UTF is used by the UTF-8 locale coercing + # during interpreter startup (on macOS). + import _locale + import os + + self.assertEqual(locale._parse_localename('UTF-8'), (None, 'UTF-8')) + + if hasattr(_locale, '_getdefaultlocale'): + orig_getlocale = _locale._getdefaultlocale + del _locale._getdefaultlocale + else: + orig_getlocale = None + + orig_env = {} + try: + for key in ('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE'): + if key in os.environ: + orig_env[key] = os.environ[key] + del os.environ[key] + + os.environ['LC_CTYPE'] = 'UTF-8' + + self.assertEqual(locale.getdefaultlocale(), (None, 'UTF-8')) + + finally: + for k in orig_env: + os.environ[k] = orig_env[k] + + if 'LC_CTYPE' not in orig_env: + del os.environ['LC_CTYPE'] + + if orig_getlocale is not None: + _locale._getdefaultlocale = orig_getlocale + def test_getpreferredencoding(self): # Invoke getpreferredencoding to make sure it does not cause exceptions. enc = locale.getpreferredencoding() diff --git a/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst b/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst new file mode 100644 index 000000000000..6dda8abf15d5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst @@ -0,0 +1 @@ +Recognize "UTF-8" as a valid value for LC_CTYPE in locale._parse_localename. From webhook-mailer at python.org Thu Aug 29 01:06:04 2019 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 29 Aug 2019 05:06:04 -0000 Subject: [Python-checkins] bpo-34775: Return NotImplemented in PurePath division. (GH-9509) (GH-15172) Message-ID: https://github.com/python/cpython/commit/4adcaf81513e57a2a4e278073a89efb1375af8df commit: 4adcaf81513e57a2a4e278073a89efb1375af8df branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2019-08-29T01:05:59-04:00 summary: bpo-34775: Return NotImplemented in PurePath division. (GH-9509) (GH-15172) (cherry picked from commit 4c69be22df3852f17873a74d015528d9a8ae92d6) Co-authored-by: aiudirog files: A Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst M Lib/pathlib.py M Lib/test/test_pathlib.py diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 6369c4b2218d..6355ae864108 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -907,10 +907,16 @@ def joinpath(self, *args): return self._make_child(args) def __truediv__(self, key): - return self._make_child((key,)) + try: + return self._make_child((key,)) + except TypeError: + return NotImplemented def __rtruediv__(self, key): - return self._from_parts([key] + self._parts) + try: + return self._from_parts([key] + self._parts) + except TypeError: + return NotImplemented @property def parent(self): diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 069467a8459f..f74524d992a1 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2329,5 +2329,46 @@ def check(): check() +class CompatiblePathTest(unittest.TestCase): + """ + Test that a type can be made compatible with PurePath + derivatives by implementing division operator overloads. + """ + + class CompatPath: + """ + Minimum viable class to test PurePath compatibility. + Simply uses the division operator to join a given + string and the string value of another object with + a forward slash. + """ + def __init__(self, string): + self.string = string + + def __truediv__(self, other): + return type(self)(f"{self.string}/{other}") + + def __rtruediv__(self, other): + return type(self)(f"{other}/{self.string}") + + def test_truediv(self): + result = pathlib.PurePath("test") / self.CompatPath("right") + self.assertIsInstance(result, self.CompatPath) + self.assertEqual(result.string, "test/right") + + with self.assertRaises(TypeError): + # Verify improper operations still raise a TypeError + pathlib.PurePath("test") / 10 + + def test_rtruediv(self): + result = self.CompatPath("left") / pathlib.PurePath("test") + self.assertIsInstance(result, self.CompatPath) + self.assertEqual(result.string, "left/test") + + with self.assertRaises(TypeError): + # Verify improper operations still raise a TypeError + 10 / pathlib.PurePath("test") + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst b/Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst new file mode 100644 index 000000000000..f99bf5b39f95 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst @@ -0,0 +1,3 @@ +Division handling of PurePath now returns NotImplemented instead of raising +a TypeError when passed something other than an instance of str or PurePath. +Patch by Roger Aiudi. From webhook-mailer at python.org Thu Aug 29 01:06:53 2019 From: webhook-mailer at python.org (Benjamin Peterson) Date: Thu, 29 Aug 2019 05:06:53 -0000 Subject: [Python-checkins] bpo-37964: Make sure test works if TESTFN is in a non-ASCII directory. (GH-15568) Message-ID: https://github.com/python/cpython/commit/465e5d5bcbfd42be058d3584ccb421405eba1594 commit: 465e5d5bcbfd42be058d3584ccb421405eba1594 branch: master author: Benjamin Peterson committer: GitHub date: 2019-08-28T22:06:49-07:00 summary: bpo-37964: Make sure test works if TESTFN is in a non-ASCII directory. (GH-15568) files: M Lib/test/test_fcntl.py diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index 38097dbdfb97..a2b599706753 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -147,9 +147,9 @@ def test_flock_overflow(self): @unittest.skipIf(sys.platform != 'darwin', "F_GETPATH is only available on macos") def test_fcntl_f_getpath(self): self.f = open(TESTFN, 'wb') - abspath = os.path.abspath(TESTFN) - res = fcntl.fcntl(self.f.fileno(), fcntl.F_GETPATH, bytes(len(abspath))) - self.assertEqual(abspath, res.decode('utf-8')) + expected = os.path.abspath(TESTFN).encode('utf-8') + res = fcntl.fcntl(self.f.fileno(), fcntl.F_GETPATH, bytes(len(expected))) + self.assertEqual(expected, res) def test_main(): run_unittest(TestFcntl) From webhook-mailer at python.org Thu Aug 29 01:18:19 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 05:18:19 -0000 Subject: [Python-checkins] bpo-36511: Fix failures in Windows ARM32 buildbot (GH-15181) Message-ID: https://github.com/python/cpython/commit/ed00fee7d4c28489b5d6e4580b1e1fe0855687ca commit: ed00fee7d4c28489b5d6e4580b1e1fe0855687ca branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-28T22:18:15-07:00 summary: bpo-36511: Fix failures in Windows ARM32 buildbot (GH-15181) (cherry picked from commit ed70a344b5fbddea85726ebc1964ee0cfdef9c40) Co-authored-by: Paul Monson files: M Tools/buildbot/remoteDeploy.bat diff --git a/Tools/buildbot/remoteDeploy.bat b/Tools/buildbot/remoteDeploy.bat index 8b0ce239e1a4..6b86e1e59b07 100644 --- a/Tools/buildbot/remoteDeploy.bat +++ b/Tools/buildbot/remoteDeploy.bat @@ -36,6 +36,7 @@ for /f "USEBACKQ" %%i in (`dir PCbuild\arm32\*.pyd /b`) do @scp PCBuild\arm32\%% for /f "USEBACKQ" %%i in (`dir PCbuild\arm32\*.dll /b`) do @scp PCBuild\arm32\%%i "%SSH_SERVER%:%REMOTE_PYTHON_DIR%PCBuild\arm32" scp -r "%PYTHON_SOURCE%Include" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%Include" scp -r "%PYTHON_SOURCE%Lib" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%Lib" +scp -r "%PYTHON_SOURCE%Parser" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%Parser" scp -r "%PYTHON_SOURCE%Tools" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%Tools" scp "%PYTHON_SOURCE%Modules\Setup" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%Modules" scp "%PYTHON_SOURCE%PC\pyconfig.h" "%SSH_SERVER%:%REMOTE_PYTHON_DIR%PC" From webhook-mailer at python.org Thu Aug 29 01:35:45 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 05:35:45 -0000 Subject: [Python-checkins] bpo-18049: Define THREAD_STACK_SIZE for AIX to pass default recursion limit test (GH-15081) Message-ID: https://github.com/python/cpython/commit/f92bb6ed336c49cabf30717c3b741b1b4284f491 commit: f92bb6ed336c49cabf30717c3b741b1b4284f491 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-28T22:35:41-07:00 summary: bpo-18049: Define THREAD_STACK_SIZE for AIX to pass default recursion limit test (GH-15081) * Define THREAD_STACK_SIZE for AIX to pass default recursion limit test (cherry picked from commit 9670ce76b83bde950020f8d89c4d27168aaaf912) Co-authored-by: Michael Felt files: A Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst M Python/thread_pthread.h diff --git a/Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst b/Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst new file mode 100644 index 000000000000..36a4de384cc0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst @@ -0,0 +1,3 @@ +Add definition of THREAD_STACK_SIZE for AIX in Python/thread_pthread.h +The default thread stacksize caused crashes with the default recursion limit +Patch by M Felt diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 994e35b2cc08..5678b05ced36 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -47,6 +47,10 @@ #undef THREAD_STACK_SIZE #define THREAD_STACK_SIZE 0x400000 #endif +#if defined(_AIX) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 +#undef THREAD_STACK_SIZE +#define THREAD_STACK_SIZE 0x200000 +#endif /* for safety, ensure a viable minimum stacksize */ #define THREAD_STACK_MIN 0x8000 /* 32 KiB */ #else /* !_POSIX_THREAD_ATTR_STACKSIZE */ From webhook-mailer at python.org Thu Aug 29 01:40:54 2019 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 29 Aug 2019 05:40:54 -0000 Subject: [Python-checkins] bpo-36167: fix an incorrect capitalization (GH-14482) Message-ID: https://github.com/python/cpython/commit/3aa48b88c7485aca1fdfa54b3d8e53931ff067fd commit: 3aa48b88c7485aca1fdfa54b3d8e53931ff067fd branch: master author: avinassh committer: Ned Deily date: 2019-08-29T01:40:50-04:00 summary: bpo-36167: fix an incorrect capitalization (GH-14482) files: M Doc/faq/programming.rst diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index a36fa4aefe88..2ff7236df1dc 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -659,7 +659,7 @@ How can my code discover the name of an object? ----------------------------------------------- Generally speaking, it can't, because objects don't really have names. -Essentially, assignment always binds a name to a value; The same is true of +Essentially, assignment always binds a name to a value; the same is true of ``def`` and ``class`` statements, but in that case the value is a callable. Consider the following code:: From webhook-mailer at python.org Thu Aug 29 01:47:48 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 05:47:48 -0000 Subject: [Python-checkins] bpo-36167: fix an incorrect capitalization (GH-14482) Message-ID: https://github.com/python/cpython/commit/e009a91607e7a81302b98d1b322d564ddc1fce9d commit: e009a91607e7a81302b98d1b322d564ddc1fce9d branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-28T22:47:42-07:00 summary: bpo-36167: fix an incorrect capitalization (GH-14482) (cherry picked from commit 3aa48b88c7485aca1fdfa54b3d8e53931ff067fd) Co-authored-by: avinassh files: M Doc/faq/programming.rst diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index a36fa4aefe88..2ff7236df1dc 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -659,7 +659,7 @@ How can my code discover the name of an object? ----------------------------------------------- Generally speaking, it can't, because objects don't really have names. -Essentially, assignment always binds a name to a value; The same is true of +Essentially, assignment always binds a name to a value; the same is true of ``def`` and ``class`` statements, but in that case the value is a callable. Consider the following code:: From webhook-mailer at python.org Thu Aug 29 01:49:24 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 05:49:24 -0000 Subject: [Python-checkins] bpo-36167: fix an incorrect capitalization (GH-14482) Message-ID: https://github.com/python/cpython/commit/409493d0acdb8dec55868bb5c6af427ce31ff555 commit: 409493d0acdb8dec55868bb5c6af427ce31ff555 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-28T22:49:20-07:00 summary: bpo-36167: fix an incorrect capitalization (GH-14482) (cherry picked from commit 3aa48b88c7485aca1fdfa54b3d8e53931ff067fd) Co-authored-by: avinassh files: M Doc/faq/programming.rst diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index f14e8cc824ef..a8aaebf7558e 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -659,7 +659,7 @@ How can my code discover the name of an object? ----------------------------------------------- Generally speaking, it can't, because objects don't really have names. -Essentially, assignment always binds a name to a value; The same is true of +Essentially, assignment always binds a name to a value; the same is true of ``def`` and ``class`` statements, but in that case the value is a callable. Consider the following code:: From webhook-mailer at python.org Thu Aug 29 01:59:47 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 05:59:47 -0000 Subject: [Python-checkins] bpo-25777: Wording describes a lookup, not a call (GH-15573) Message-ID: https://github.com/python/cpython/commit/03acba6f1a851064ba1fa78965ece4354d499c04 commit: 03acba6f1a851064ba1fa78965ece4354d499c04 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-28T22:59:43-07:00 summary: bpo-25777: Wording describes a lookup, not a call (GH-15573) files: M Doc/howto/descriptor.rst diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 324625d7b3e8..6928917dbe42 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -117,7 +117,7 @@ The important points to remember are: * non-data descriptors may be overridden by instance dictionaries. The object returned by ``super()`` also has a custom :meth:`__getattribute__` -method for invoking descriptors. The call ``super(B, obj).m()`` searches +method for invoking descriptors. The attribute lookup ``super(B, obj).m`` searches ``obj.__class__.__mro__`` for the base class ``A`` immediately following ``B`` and then returns ``A.__dict__['m'].__get__(obj, B)``. If not a descriptor, ``m`` is returned unchanged. If not in the dictionary, ``m`` reverts to a From webhook-mailer at python.org Thu Aug 29 02:09:06 2019 From: webhook-mailer at python.org (Chris Withers) Date: Thu, 29 Aug 2019 06:09:06 -0000 Subject: [Python-checkins] bpo-36871: Ensure method signature is used when asserting mock calls to a method (GH13261) Message-ID: https://github.com/python/cpython/commit/c96127821ebda50760e788b1213975a0d5bea37f commit: c96127821ebda50760e788b1213975a0d5bea37f branch: master author: Xtreak committer: Chris Withers date: 2019-08-29T07:09:01+01:00 summary: bpo-36871: Ensure method signature is used when asserting mock calls to a method (GH13261) * Fix call_matcher for mock when using methods * Add NEWS entry * Use None check and convert doctest to unittest * Use better name for mock in tests. Handle _SpecState when the attribute was not accessed and add tests. * Use reset_mock instead of reinitialization. Change inner class constructor signature for check * Reword comment regarding call object lookup logic files: A Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst M Lib/unittest/mock.py M Lib/unittest/test/testmock/testmock.py diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 298b41e0d7e4..5846eeb404d2 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -804,6 +804,35 @@ def _format_mock_failure_message(self, args, kwargs, action='call'): return message % (action, expected_string, actual_string) + def _get_call_signature_from_name(self, name): + """ + * If call objects are asserted against a method/function like obj.meth1 + then there could be no name for the call object to lookup. Hence just + return the spec_signature of the method/function being asserted against. + * If the name is not empty then remove () and split by '.' to get + list of names to iterate through the children until a potential + match is found. A child mock is created only during attribute access + so if we get a _SpecState then no attributes of the spec were accessed + and can be safely exited. + """ + if not name: + return self._spec_signature + + sig = None + names = name.replace('()', '').split('.') + children = self._mock_children + + for name in names: + child = children.get(name) + if child is None or isinstance(child, _SpecState): + break + else: + children = child._mock_children + sig = child._spec_signature + + return sig + + def _call_matcher(self, _call): """ Given a call (or simply an (args, kwargs) tuple), return a @@ -811,7 +840,12 @@ def _call_matcher(self, _call): This is a best effort method which relies on the spec's signature, if available, or falls back on the arguments themselves. """ - sig = self._spec_signature + + if isinstance(_call, tuple) and len(_call) > 2: + sig = self._get_call_signature_from_name(_call[0]) + else: + sig = self._spec_signature + if sig is not None: if len(_call) == 2: name = '' diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index 69b34e9c4fb7..265eb1bba56c 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1347,6 +1347,54 @@ def test_assert_has_calls(self): ) + def test_assert_has_calls_nested_spec(self): + class Something: + + def __init__(self): pass + def meth(self, a, b, c, d=None): pass + + class Foo: + + def __init__(self, a): pass + def meth1(self, a, b): pass + + mock_class = create_autospec(Something) + + for m in [mock_class, mock_class()]: + m.meth(1, 2, 3, d=1) + m.assert_has_calls([call.meth(1, 2, 3, d=1)]) + m.assert_has_calls([call.meth(1, 2, 3, 1)]) + + mock_class.reset_mock() + + for m in [mock_class, mock_class()]: + self.assertRaises(AssertionError, m.assert_has_calls, [call.Foo()]) + m.Foo(1).meth1(1, 2) + m.assert_has_calls([call.Foo(1), call.Foo(1).meth1(1, 2)]) + m.Foo.assert_has_calls([call(1), call().meth1(1, 2)]) + + mock_class.reset_mock() + + invalid_calls = [call.meth(1), + call.non_existent(1), + call.Foo().non_existent(1), + call.Foo().meth(1, 2, 3, 4)] + + for kall in invalid_calls: + self.assertRaises(AssertionError, + mock_class.assert_has_calls, + [kall] + ) + + + def test_assert_has_calls_nested_without_spec(self): + m = MagicMock() + m().foo().bar().baz() + m.one().two().three() + calls = call.one().two().three().call_list() + m.assert_has_calls(calls) + + def test_assert_has_calls_with_function_spec(self): def f(a, b, c, d=None): pass diff --git a/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst b/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst new file mode 100644 index 000000000000..218795f203be --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst @@ -0,0 +1,3 @@ +Ensure method signature is used instead of constructor signature of a class +while asserting mock object against method calls. Patch by Karthikeyan +Singaravelan. From webhook-mailer at python.org Thu Aug 29 02:12:17 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 06:12:17 -0000 Subject: [Python-checkins] bpo-25777: Wording describes a lookup, not a call (GH-15573) (GH-15576) Message-ID: https://github.com/python/cpython/commit/f3dca6acee609a3a12f22152fd98602c1cbadde0 commit: f3dca6acee609a3a12f22152fd98602c1cbadde0 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-28T23:12:13-07:00 summary: bpo-25777: Wording describes a lookup, not a call (GH-15573) (GH-15576) (cherry picked from commit 03acba6f1a851064ba1fa78965ece4354d499c04) Co-authored-by: Raymond Hettinger files: M Doc/howto/descriptor.rst diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index b29e590b20cb..9856e6caec09 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -117,7 +117,7 @@ The important points to remember are: * non-data descriptors may be overridden by instance dictionaries. The object returned by ``super()`` also has a custom :meth:`__getattribute__` -method for invoking descriptors. The call ``super(B, obj).m()`` searches +method for invoking descriptors. The attribute lookup ``super(B, obj).m`` searches ``obj.__class__.__mro__`` for the base class ``A`` immediately following ``B`` and then returns ``A.__dict__['m'].__get__(obj, B)``. If not a descriptor, ``m`` is returned unchanged. If not in the dictionary, ``m`` reverts to a From webhook-mailer at python.org Thu Aug 29 02:15:57 2019 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 29 Aug 2019 06:15:57 -0000 Subject: [Python-checkins] bpo-35946: Improve assert_called_with documentation (GH-11796) Message-ID: https://github.com/python/cpython/commit/f5896a05edf5df91fb1b55bd481ba5b2a3682f4e commit: f5896a05edf5df91fb1b55bd481ba5b2a3682f4e branch: master author: R?mi Lapeyre committer: Ned Deily date: 2019-08-29T02:15:53-04:00 summary: bpo-35946: Improve assert_called_with documentation (GH-11796) files: M Doc/library/unittest.mock.rst M Lib/unittest/mock.py diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index 19e9715102bf..304ba532274d 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -317,8 +317,8 @@ the *new_callable* argument to :func:`patch`. .. method:: assert_called_with(*args, **kwargs) - This method is a convenient way of asserting that calls are made in a - particular way: + This method is a convenient way of asserting that the last call has been + made in a particular way: >>> mock = Mock() >>> mock.method(1, 2, 3, test='wow') diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 5846eeb404d2..c6771ce5291a 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -888,7 +888,7 @@ def assert_called_once(self): raise AssertionError(msg) def assert_called_with(self, /, *args, **kwargs): - """assert that the mock was called with the specified arguments. + """assert that the last call was made with the specified arguments. Raises an AssertionError if the args and keyword args passed in are different to the last call to the mock.""" From webhook-mailer at python.org Thu Aug 29 02:25:28 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 29 Aug 2019 06:25:28 -0000 Subject: [Python-checkins] bpo-37960: Silence only necessary errors in repr() of buffered and text streams. (GH-15543) Message-ID: https://github.com/python/cpython/commit/b235a1b47394eedc5f8ea4cf214f56c4c6932e59 commit: b235a1b47394eedc5f8ea4cf214f56c4c6932e59 branch: master author: Serhiy Storchaka committer: GitHub date: 2019-08-29T09:25:22+03:00 summary: bpo-37960: Silence only necessary errors in repr() of buffered and text streams. (GH-15543) files: A Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst M Lib/_pyio.py M Modules/_io/bufferedio.c M Modules/_io/textio.c diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 40e0c9f9e2c6..1b24ef9f0e10 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -409,7 +409,7 @@ def __del__(self): """Destructor. Calls close().""" try: closed = self.closed - except Exception: + except AttributeError: # If getting closed fails, then the object is probably # in an unusable state, so ignore. return @@ -867,7 +867,7 @@ def __repr__(self): clsname = self.__class__.__qualname__ try: name = self.name - except Exception: + except AttributeError: return "<{}.{}>".format(modname, clsname) else: return "<{}.{} name={!r}>".format(modname, clsname, name) @@ -2083,13 +2083,13 @@ def __repr__(self): self.__class__.__qualname__) try: name = self.name - except Exception: + except AttributeError: pass else: result += " name={0!r}".format(name) try: mode = self.mode - except Exception: + except AttributeError: pass else: result += " mode={0!r}".format(mode) diff --git a/Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst b/Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst new file mode 100644 index 000000000000..421cfb9c38e1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst @@ -0,0 +1,2 @@ +``repr()`` of buffered and text streams now silences only expected +exceptions when get the value of "name" and "mode" attributes. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 86dd277f94c1..586e93f25e28 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1378,12 +1378,14 @@ buffered_repr(buffered *self) { PyObject *nameobj, *res; - nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name); - if (nameobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_Exception)) - PyErr_Clear(); - else + if (_PyObject_LookupAttrId((PyObject *) self, &PyId_name, &nameobj) < 0) { + if (!PyErr_ExceptionMatches(PyExc_ValueError)) { return NULL; + } + /* Ignore ValueError raised if the underlying stream was detached */ + PyErr_Clear(); + } + if (nameobj == NULL) { res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name); } else { diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 05911d9222ff..7ddac8062a96 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -2899,14 +2899,14 @@ textiowrapper_repr(textio *self) } goto error; } - nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name); - if (nameobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_Exception)) - PyErr_Clear(); - else + if (_PyObject_LookupAttrId((PyObject *) self, &PyId_name, &nameobj) < 0) { + if (!PyErr_ExceptionMatches(PyExc_ValueError)) { goto error; + } + /* Ignore ValueError raised if the underlying stream was detached */ + PyErr_Clear(); } - else { + if (nameobj != NULL) { s = PyUnicode_FromFormat(" name=%R", nameobj); Py_DECREF(nameobj); if (s == NULL) @@ -2915,14 +2915,10 @@ textiowrapper_repr(textio *self) if (res == NULL) goto error; } - modeobj = _PyObject_GetAttrId((PyObject *) self, &PyId_mode); - if (modeobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_Exception)) - PyErr_Clear(); - else - goto error; + if (_PyObject_LookupAttrId((PyObject *) self, &PyId_mode, &modeobj) < 0) { + goto error; } - else { + if (modeobj != NULL) { s = PyUnicode_FromFormat(" mode=%R", modeobj); Py_DECREF(modeobj); if (s == NULL) From webhook-mailer at python.org Thu Aug 29 02:30:27 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 29 Aug 2019 06:30:27 -0000 Subject: [Python-checkins] bpo-37950: Fix ast.dump() when call with incompletely initialized node. (GH-15510) Message-ID: https://github.com/python/cpython/commit/e64f948e762a6b9fd02e2902ccf42438df6fcb61 commit: e64f948e762a6b9fd02e2902ccf42438df6fcb61 branch: master author: Serhiy Storchaka committer: GitHub date: 2019-08-29T09:30:23+03:00 summary: bpo-37950: Fix ast.dump() when call with incompletely initialized node. (GH-15510) files: A Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst M Doc/library/ast.rst M Lib/ast.py M Lib/test/test_ast.py diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 3d2c420bc224..92bf8912eb53 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -322,11 +322,12 @@ and classes for traversing abstract syntax trees: .. function:: dump(node, annotate_fields=True, include_attributes=False) Return a formatted dump of the tree in *node*. This is mainly useful for - debugging purposes. The returned string will show the names and the values - for fields. This makes the code impossible to evaluate, so if evaluation is - wanted *annotate_fields* must be set to ``False``. Attributes such as line + debugging purposes. If *annotate_fields* is true (by default), + the returned string will show the names and the values for fields. + If *annotate_fields* is false, the result string will be more compact by + omitting unambiguous field names. Attributes such as line numbers and column offsets are not dumped by default. If this is wanted, - *include_attributes* can be set to ``True``. + *include_attributes* can be set to true. .. seealso:: diff --git a/Lib/ast.py b/Lib/ast.py index 1e639d11feec..5ab023f6c3c0 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -98,26 +98,35 @@ def _convert(node): def dump(node, annotate_fields=True, include_attributes=False): """ - Return a formatted dump of the tree in *node*. This is mainly useful for - debugging purposes. The returned string will show the names and the values - for fields. This makes the code impossible to evaluate, so if evaluation is - wanted *annotate_fields* must be set to False. Attributes such as line + Return a formatted dump of the tree in node. This is mainly useful for + debugging purposes. If annotate_fields is true (by default), + the returned string will show the names and the values for fields. + If annotate_fields is false, the result string will be more compact by + omitting unambiguous field names. Attributes such as line numbers and column offsets are not dumped by default. If this is wanted, - *include_attributes* can be set to True. + include_attributes can be set to true. """ def _format(node): if isinstance(node, AST): - fields = [(a, _format(b)) for a, b in iter_fields(node)] - rv = '%s(%s' % (node.__class__.__name__, ', '.join( - ('%s=%s' % field for field in fields) - if annotate_fields else - (b for a, b in fields) - )) + args = [] + keywords = annotate_fields + for field in node._fields: + try: + value = getattr(node, field) + except AttributeError: + keywords = True + else: + if keywords: + args.append('%s=%s' % (field, _format(value))) + else: + args.append(_format(value)) if include_attributes and node._attributes: - rv += fields and ', ' or ' ' - rv += ', '.join('%s=%s' % (a, _format(getattr(node, a))) - for a in node._attributes) - return rv + ')' + for a in node._attributes: + try: + args.append('%s=%s' % (a, _format(getattr(node, a)))) + except AttributeError: + pass + return '%s(%s)' % (node.__class__.__name__, ', '.join(args)) elif isinstance(node, list): return '[%s]' % ', '.join(_format(x) for x in node) return repr(node) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 3d12397ef683..07bbb4cc7723 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -645,6 +645,35 @@ def test_dump(self): "lineno=1, col_offset=0, end_lineno=1, end_col_offset=24)], type_ignores=[])" ) + def test_dump_incomplete(self): + node = ast.Raise(lineno=3, col_offset=4) + self.assertEqual(ast.dump(node), + "Raise()" + ) + self.assertEqual(ast.dump(node, include_attributes=True), + "Raise(lineno=3, col_offset=4)" + ) + node = ast.Raise(exc=ast.Name(id='e', ctx=ast.Load()), lineno=3, col_offset=4) + self.assertEqual(ast.dump(node), + "Raise(exc=Name(id='e', ctx=Load()))" + ) + self.assertEqual(ast.dump(node, annotate_fields=False), + "Raise(Name('e', Load()))" + ) + self.assertEqual(ast.dump(node, include_attributes=True), + "Raise(exc=Name(id='e', ctx=Load()), lineno=3, col_offset=4)" + ) + self.assertEqual(ast.dump(node, annotate_fields=False, include_attributes=True), + "Raise(Name('e', Load()), lineno=3, col_offset=4)" + ) + node = ast.Raise(cause=ast.Name(id='e', ctx=ast.Load())) + self.assertEqual(ast.dump(node), + "Raise(cause=Name(id='e', ctx=Load()))" + ) + self.assertEqual(ast.dump(node, annotate_fields=False), + "Raise(cause=Name('e', Load()))" + ) + def test_copy_location(self): src = ast.parse('1 + 1', mode='eval') src.body.right = ast.copy_location(ast.Num(2), src.body.right) diff --git a/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst b/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst new file mode 100644 index 000000000000..ded80d3b00ef --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst @@ -0,0 +1 @@ +Fix :func:`ast.dump` when call with incompletely initialized node. From webhook-mailer at python.org Thu Aug 29 02:39:51 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 06:39:51 -0000 Subject: [Python-checkins] bpo-35946: Improve assert_called_with documentation (GH-11796) Message-ID: https://github.com/python/cpython/commit/612d3935ec0b2fbe88b3fae8167f0c503c61a9ca commit: 612d3935ec0b2fbe88b3fae8167f0c503c61a9ca branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-28T23:39:47-07:00 summary: bpo-35946: Improve assert_called_with documentation (GH-11796) (cherry picked from commit f5896a05edf5df91fb1b55bd481ba5b2a3682f4e) Co-authored-by: R?mi Lapeyre files: M Doc/library/unittest.mock.rst M Lib/unittest/mock.py diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index 19e9715102bf..304ba532274d 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -317,8 +317,8 @@ the *new_callable* argument to :func:`patch`. .. method:: assert_called_with(*args, **kwargs) - This method is a convenient way of asserting that calls are made in a - particular way: + This method is a convenient way of asserting that the last call has been + made in a particular way: >>> mock = Mock() >>> mock.method(1, 2, 3, test='wow') diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index b3dc640f8fe5..3faeb4c9af1f 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -854,7 +854,7 @@ def assert_called_once(self): raise AssertionError(msg) def assert_called_with(self, /, *args, **kwargs): - """assert that the mock was called with the specified arguments. + """assert that the last call was made with the specified arguments. Raises an AssertionError if the args and keyword args passed in are different to the last call to the mock.""" From webhook-mailer at python.org Thu Aug 29 02:57:42 2019 From: webhook-mailer at python.org (Chris Withers) Date: Thu, 29 Aug 2019 06:57:42 -0000 Subject: [Python-checkins] bpo-36871: Ensure method signature is used when asserting mock calls to a method (GH15577) Message-ID: https://github.com/python/cpython/commit/be310e03d0b84ef56e9d35b0b1b21d685b7ea371 commit: be310e03d0b84ef56e9d35b0b1b21d685b7ea371 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Chris Withers date: 2019-08-29T07:57:37+01:00 summary: bpo-36871: Ensure method signature is used when asserting mock calls to a method (GH15577) * Fix call_matcher for mock when using methods * Add NEWS entry * Use None check and convert doctest to unittest * Use better name for mock in tests. Handle _SpecState when the attribute was not accessed and add tests. * Use reset_mock instead of reinitialization. Change inner class constructor signature for check * Reword comment regarding call object lookup logic (cherry picked from commit c96127821ebda50760e788b1213975a0d5bea37f) Co-authored-by: Xtreak files: A Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst M Lib/unittest/mock.py M Lib/unittest/test/testmock/testmock.py diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index ee291fc89a10..1ec998ccd1a7 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -771,6 +771,35 @@ def _format_mock_failure_message(self, args, kwargs): return message % (expected_string, actual_string) + def _get_call_signature_from_name(self, name): + """ + * If call objects are asserted against a method/function like obj.meth1 + then there could be no name for the call object to lookup. Hence just + return the spec_signature of the method/function being asserted against. + * If the name is not empty then remove () and split by '.' to get + list of names to iterate through the children until a potential + match is found. A child mock is created only during attribute access + so if we get a _SpecState then no attributes of the spec were accessed + and can be safely exited. + """ + if not name: + return self._spec_signature + + sig = None + names = name.replace('()', '').split('.') + children = self._mock_children + + for name in names: + child = children.get(name) + if child is None or isinstance(child, _SpecState): + break + else: + children = child._mock_children + sig = child._spec_signature + + return sig + + def _call_matcher(self, _call): """ Given a call (or simply an (args, kwargs) tuple), return a @@ -778,7 +807,12 @@ def _call_matcher(self, _call): This is a best effort method which relies on the spec's signature, if available, or falls back on the arguments themselves. """ - sig = self._spec_signature + + if isinstance(_call, tuple) and len(_call) > 2: + sig = self._get_call_signature_from_name(_call[0]) + else: + sig = self._spec_signature + if sig is not None: if len(_call) == 2: name = '' diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index 8329e5f50217..4e0f4694b771 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1314,6 +1314,54 @@ def test_assert_has_calls(self): ) + def test_assert_has_calls_nested_spec(self): + class Something: + + def __init__(self): pass + def meth(self, a, b, c, d=None): pass + + class Foo: + + def __init__(self, a): pass + def meth1(self, a, b): pass + + mock_class = create_autospec(Something) + + for m in [mock_class, mock_class()]: + m.meth(1, 2, 3, d=1) + m.assert_has_calls([call.meth(1, 2, 3, d=1)]) + m.assert_has_calls([call.meth(1, 2, 3, 1)]) + + mock_class.reset_mock() + + for m in [mock_class, mock_class()]: + self.assertRaises(AssertionError, m.assert_has_calls, [call.Foo()]) + m.Foo(1).meth1(1, 2) + m.assert_has_calls([call.Foo(1), call.Foo(1).meth1(1, 2)]) + m.Foo.assert_has_calls([call(1), call().meth1(1, 2)]) + + mock_class.reset_mock() + + invalid_calls = [call.meth(1), + call.non_existent(1), + call.Foo().non_existent(1), + call.Foo().meth(1, 2, 3, 4)] + + for kall in invalid_calls: + self.assertRaises(AssertionError, + mock_class.assert_has_calls, + [kall] + ) + + + def test_assert_has_calls_nested_without_spec(self): + m = MagicMock() + m().foo().bar().baz() + m.one().two().three() + calls = call.one().two().three().call_list() + m.assert_has_calls(calls) + + def test_assert_has_calls_with_function_spec(self): def f(a, b, c, d=None): pass diff --git a/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst b/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst new file mode 100644 index 000000000000..218795f203be --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst @@ -0,0 +1,3 @@ +Ensure method signature is used instead of constructor signature of a class +while asserting mock object against method calls. Patch by Karthikeyan +Singaravelan. From webhook-mailer at python.org Thu Aug 29 02:58:30 2019 From: webhook-mailer at python.org (Chris Withers) Date: Thu, 29 Aug 2019 06:58:30 -0000 Subject: [Python-checkins] bpo-36871: Ensure method signature is used when asserting mock calls to a method (GH15578) Message-ID: https://github.com/python/cpython/commit/38d311d79e57479f7a684c2cd298293033dc4990 commit: 38d311d79e57479f7a684c2cd298293033dc4990 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Chris Withers date: 2019-08-29T07:58:27+01:00 summary: bpo-36871: Ensure method signature is used when asserting mock calls to a method (GH15578) * Fix call_matcher for mock when using methods * Add NEWS entry * Use None check and convert doctest to unittest * Use better name for mock in tests. Handle _SpecState when the attribute was not accessed and add tests. * Use reset_mock instead of reinitialization. Change inner class constructor signature for check * Reword comment regarding call object lookup logic (cherry picked from commit c96127821ebda50760e788b1213975a0d5bea37f) Co-authored-by: Xtreak files: A Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst M Lib/unittest/mock.py M Lib/unittest/test/testmock/testmock.py diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 3faeb4c9af1f..7ab68125918d 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -804,6 +804,35 @@ def _format_mock_failure_message(self, args, kwargs, action='call'): return message % (action, expected_string, actual_string) + def _get_call_signature_from_name(self, name): + """ + * If call objects are asserted against a method/function like obj.meth1 + then there could be no name for the call object to lookup. Hence just + return the spec_signature of the method/function being asserted against. + * If the name is not empty then remove () and split by '.' to get + list of names to iterate through the children until a potential + match is found. A child mock is created only during attribute access + so if we get a _SpecState then no attributes of the spec were accessed + and can be safely exited. + """ + if not name: + return self._spec_signature + + sig = None + names = name.replace('()', '').split('.') + children = self._mock_children + + for name in names: + child = children.get(name) + if child is None or isinstance(child, _SpecState): + break + else: + children = child._mock_children + sig = child._spec_signature + + return sig + + def _call_matcher(self, _call): """ Given a call (or simply an (args, kwargs) tuple), return a @@ -811,7 +840,12 @@ def _call_matcher(self, _call): This is a best effort method which relies on the spec's signature, if available, or falls back on the arguments themselves. """ - sig = self._spec_signature + + if isinstance(_call, tuple) and len(_call) > 2: + sig = self._get_call_signature_from_name(_call[0]) + else: + sig = self._spec_signature + if sig is not None: if len(_call) == 2: name = '' diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py index 090da45fb660..d3a1e89da81a 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1339,6 +1339,54 @@ def test_assert_has_calls(self): ) + def test_assert_has_calls_nested_spec(self): + class Something: + + def __init__(self): pass + def meth(self, a, b, c, d=None): pass + + class Foo: + + def __init__(self, a): pass + def meth1(self, a, b): pass + + mock_class = create_autospec(Something) + + for m in [mock_class, mock_class()]: + m.meth(1, 2, 3, d=1) + m.assert_has_calls([call.meth(1, 2, 3, d=1)]) + m.assert_has_calls([call.meth(1, 2, 3, 1)]) + + mock_class.reset_mock() + + for m in [mock_class, mock_class()]: + self.assertRaises(AssertionError, m.assert_has_calls, [call.Foo()]) + m.Foo(1).meth1(1, 2) + m.assert_has_calls([call.Foo(1), call.Foo(1).meth1(1, 2)]) + m.Foo.assert_has_calls([call(1), call().meth1(1, 2)]) + + mock_class.reset_mock() + + invalid_calls = [call.meth(1), + call.non_existent(1), + call.Foo().non_existent(1), + call.Foo().meth(1, 2, 3, 4)] + + for kall in invalid_calls: + self.assertRaises(AssertionError, + mock_class.assert_has_calls, + [kall] + ) + + + def test_assert_has_calls_nested_without_spec(self): + m = MagicMock() + m().foo().bar().baz() + m.one().two().three() + calls = call.one().two().three().call_list() + m.assert_has_calls(calls) + + def test_assert_has_calls_with_function_spec(self): def f(a, b, c, d=None): pass diff --git a/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst b/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst new file mode 100644 index 000000000000..218795f203be --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst @@ -0,0 +1,3 @@ +Ensure method signature is used instead of constructor signature of a class +while asserting mock object against method calls. Patch by Karthikeyan +Singaravelan. From webhook-mailer at python.org Thu Aug 29 03:04:48 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 07:04:48 -0000 Subject: [Python-checkins] bpo-37950: Fix ast.dump() when call with incompletely initialized node. (GH-15510) Message-ID: https://github.com/python/cpython/commit/d3d2650cf84e6be0f84d6d0d538999d1e0cfdd43 commit: d3d2650cf84e6be0f84d6d0d538999d1e0cfdd43 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-29T00:04:44-07:00 summary: bpo-37950: Fix ast.dump() when call with incompletely initialized node. (GH-15510) (cherry picked from commit e64f948e762a6b9fd02e2902ccf42438df6fcb61) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst M Doc/library/ast.rst M Lib/ast.py M Lib/test/test_ast.py diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 3c73f748acbe..699ad0456a02 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -262,11 +262,12 @@ and classes for traversing abstract syntax trees: .. function:: dump(node, annotate_fields=True, include_attributes=False) Return a formatted dump of the tree in *node*. This is mainly useful for - debugging purposes. The returned string will show the names and the values - for fields. This makes the code impossible to evaluate, so if evaluation is - wanted *annotate_fields* must be set to ``False``. Attributes such as line + debugging purposes. If *annotate_fields* is true (by default), + the returned string will show the names and the values for fields. + If *annotate_fields* is false, the result string will be more compact by + omitting unambiguous field names. Attributes such as line numbers and column offsets are not dumped by default. If this is wanted, - *include_attributes* can be set to ``True``. + *include_attributes* can be set to true. .. seealso:: diff --git a/Lib/ast.py b/Lib/ast.py index bfe346bba8e3..1bc6b38da8d5 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -93,26 +93,35 @@ def _convert(node): def dump(node, annotate_fields=True, include_attributes=False): """ - Return a formatted dump of the tree in *node*. This is mainly useful for - debugging purposes. The returned string will show the names and the values - for fields. This makes the code impossible to evaluate, so if evaluation is - wanted *annotate_fields* must be set to False. Attributes such as line + Return a formatted dump of the tree in node. This is mainly useful for + debugging purposes. If annotate_fields is true (by default), + the returned string will show the names and the values for fields. + If annotate_fields is false, the result string will be more compact by + omitting unambiguous field names. Attributes such as line numbers and column offsets are not dumped by default. If this is wanted, - *include_attributes* can be set to True. + include_attributes can be set to true. """ def _format(node): if isinstance(node, AST): - fields = [(a, _format(b)) for a, b in iter_fields(node)] - rv = '%s(%s' % (node.__class__.__name__, ', '.join( - ('%s=%s' % field for field in fields) - if annotate_fields else - (b for a, b in fields) - )) + args = [] + keywords = annotate_fields + for field in node._fields: + try: + value = getattr(node, field) + except AttributeError: + keywords = True + else: + if keywords: + args.append('%s=%s' % (field, _format(value))) + else: + args.append(_format(value)) if include_attributes and node._attributes: - rv += fields and ', ' or ' ' - rv += ', '.join('%s=%s' % (a, _format(getattr(node, a))) - for a in node._attributes) - return rv + ')' + for a in node._attributes: + try: + args.append('%s=%s' % (a, _format(getattr(node, a)))) + except AttributeError: + pass + return '%s(%s)' % (node.__class__.__name__, ', '.join(args)) elif isinstance(node, list): return '[%s]' % ', '.join(_format(x) for x in node) return repr(node) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 7614d40e3e5c..2d0b5b24ee7d 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -462,6 +462,35 @@ def test_dump(self): "lineno=1, col_offset=0), lineno=1, col_offset=0)])" ) + def test_dump_incomplete(self): + node = ast.Raise(lineno=3, col_offset=4) + self.assertEqual(ast.dump(node), + "Raise()" + ) + self.assertEqual(ast.dump(node, include_attributes=True), + "Raise(lineno=3, col_offset=4)" + ) + node = ast.Raise(exc=ast.Name(id='e', ctx=ast.Load()), lineno=3, col_offset=4) + self.assertEqual(ast.dump(node), + "Raise(exc=Name(id='e', ctx=Load()))" + ) + self.assertEqual(ast.dump(node, annotate_fields=False), + "Raise(Name('e', Load()))" + ) + self.assertEqual(ast.dump(node, include_attributes=True), + "Raise(exc=Name(id='e', ctx=Load()), lineno=3, col_offset=4)" + ) + self.assertEqual(ast.dump(node, annotate_fields=False, include_attributes=True), + "Raise(Name('e', Load()), lineno=3, col_offset=4)" + ) + node = ast.Raise(cause=ast.Name(id='e', ctx=ast.Load())) + self.assertEqual(ast.dump(node), + "Raise(cause=Name(id='e', ctx=Load()))" + ) + self.assertEqual(ast.dump(node, annotate_fields=False), + "Raise(cause=Name('e', Load()))" + ) + def test_copy_location(self): src = ast.parse('1 + 1', mode='eval') src.body.right = ast.copy_location(ast.Num(2), src.body.right) diff --git a/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst b/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst new file mode 100644 index 000000000000..ded80d3b00ef --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst @@ -0,0 +1 @@ +Fix :func:`ast.dump` when call with incompletely initialized node. From webhook-mailer at python.org Thu Aug 29 03:36:21 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 29 Aug 2019 07:36:21 -0000 Subject: [Python-checkins] bpo-37372: Fix error unpickling datetime.time objects from Python 2 with seconds>=24. (GH-14307) Message-ID: https://github.com/python/cpython/commit/122376df550b71dd3bec0513c7483cc1714212fa commit: 122376df550b71dd3bec0513c7483cc1714212fa branch: master author: Justin Blanchard committer: Serhiy Storchaka date: 2019-08-29T10:36:15+03:00 summary: bpo-37372: Fix error unpickling datetime.time objects from Python 2 with seconds>=24. (GH-14307) files: A Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst M Lib/test/datetimetester.py M Misc/ACKS M Modules/_datetimemodule.c diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 58004870a00f..b440e5ab5fa6 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -3324,16 +3324,25 @@ def test_pickling_subclass_time(self): def test_compat_unpickle(self): tests = [ - b"cdatetime\ntime\n(S'\\x14;\\x10\\x00\\x10\\x00'\ntR.", - b'cdatetime\ntime\n(U\x06\x14;\x10\x00\x10\x00tR.', - b'\x80\x02cdatetime\ntime\nU\x06\x14;\x10\x00\x10\x00\x85R.', + (b"cdatetime\ntime\n(S'\\x14;\\x10\\x00\\x10\\x00'\ntR.", + (20, 59, 16, 64**2)), + (b'cdatetime\ntime\n(U\x06\x14;\x10\x00\x10\x00tR.', + (20, 59, 16, 64**2)), + (b'\x80\x02cdatetime\ntime\nU\x06\x14;\x10\x00\x10\x00\x85R.', + (20, 59, 16, 64**2)), + (b"cdatetime\ntime\n(S'\\x14;\\x19\\x00\\x10\\x00'\ntR.", + (20, 59, 25, 64**2)), + (b'cdatetime\ntime\n(U\x06\x14;\x19\x00\x10\x00tR.', + (20, 59, 25, 64**2)), + (b'\x80\x02cdatetime\ntime\nU\x06\x14;\x19\x00\x10\x00\x85R.', + (20, 59, 25, 64**2)), ] - args = 20, 59, 16, 64**2 - expected = self.theclass(*args) - for data in tests: - for loads in pickle_loads: - derived = loads(data, encoding='latin1') - self.assertEqual(derived, expected) + for i, (data, args) in enumerate(tests): + with self.subTest(i=i): + expected = self.theclass(*args) + for loads in pickle_loads: + derived = loads(data, encoding='latin1') + self.assertEqual(derived, expected) def test_bool(self): # time is always True. diff --git a/Misc/ACKS b/Misc/ACKS index d5064f644e24..e9ae0ed56b0d 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -162,6 +162,7 @@ Roy Bixler Daniel Black Jonathan Black Renaud Blanch +Justin Blanchard Mike Bland Martin Bless Pablo Bleyer diff --git a/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst b/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst new file mode 100644 index 000000000000..b958d8fed40a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst @@ -0,0 +1,2 @@ +Fix error unpickling datetime.time objects from Python 2 with seconds>=24. +Patch by Justin Blanchard. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 56eaccdf1723..8f4fa21da141 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -4078,7 +4078,7 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw) return NULL; } if (PyUnicode_GET_LENGTH(state) == _PyDateTime_TIME_DATASIZE && - (0x7F & PyUnicode_READ_CHAR(state, 2)) < 24) + (0x7F & PyUnicode_READ_CHAR(state, 0)) < 24) { state = PyUnicode_AsLatin1String(state); if (state == NULL) { From webhook-mailer at python.org Thu Aug 29 03:44:07 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 07:44:07 -0000 Subject: [Python-checkins] bpo-23674: Clarify ambiguities in super() docs (#15564) Message-ID: https://github.com/python/cpython/commit/cd81f0500fe98c7f4cddb06530fffabd14f036b8 commit: cd81f0500fe98c7f4cddb06530fffabd14f036b8 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-29T00:44:02-07:00 summary: bpo-23674: Clarify ambiguities in super() docs (#15564) files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index a7b6610ebdf1..ce026ebb4b0f 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1589,10 +1589,17 @@ are always available. They are listed here in alphabetical order. Return a proxy object that delegates method calls to a parent or sibling class of *type*. This is useful for accessing inherited methods that have - been overridden in a class. The search order is same as that used by - :func:`getattr` except that the *type* itself is skipped. + been overridden in a class. - The :attr:`~class.__mro__` attribute of the *type* lists the method + The *object-or-type* determines the :term:`method resolution order` + to be searched. The search starts from the class right after the + *type*. + + For example, if :attr:`~class.__mro__` of *object-or-type* is + ``D -> B -> C -> A -> object`` and the value of *type* is ``B``, + then :func:`super` searches ``C -> A -> object``. + + The :attr:`~class.__mro__` attribute of the *object-or-type* lists the method resolution search order used by both :func:`getattr` and :func:`super`. The attribute is dynamic and can change whenever the inheritance hierarchy is updated. From webhook-mailer at python.org Thu Aug 29 03:50:38 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 29 Aug 2019 07:50:38 -0000 Subject: [Python-checkins] [3.8] bpo-37950: Fix ast.dump() when call with incompletely initialized node. (GH-15510) (GH-15582) Message-ID: https://github.com/python/cpython/commit/097eae5b9b4801d34bb900c01b5e6a80f028bc12 commit: 097eae5b9b4801d34bb900c01b5e6a80f028bc12 branch: 3.8 author: Serhiy Storchaka committer: GitHub date: 2019-08-29T10:50:28+03:00 summary: [3.8] bpo-37950: Fix ast.dump() when call with incompletely initialized node. (GH-15510) (GH-15582) (cherry picked from commit e64f948e762a6b9fd02e2902ccf42438df6fcb61) files: A Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst M Doc/library/ast.rst M Lib/ast.py M Lib/test/test_ast.py diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 3d2c420bc224..92bf8912eb53 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -322,11 +322,12 @@ and classes for traversing abstract syntax trees: .. function:: dump(node, annotate_fields=True, include_attributes=False) Return a formatted dump of the tree in *node*. This is mainly useful for - debugging purposes. The returned string will show the names and the values - for fields. This makes the code impossible to evaluate, so if evaluation is - wanted *annotate_fields* must be set to ``False``. Attributes such as line + debugging purposes. If *annotate_fields* is true (by default), + the returned string will show the names and the values for fields. + If *annotate_fields* is false, the result string will be more compact by + omitting unambiguous field names. Attributes such as line numbers and column offsets are not dumped by default. If this is wanted, - *include_attributes* can be set to ``True``. + *include_attributes* can be set to true. .. seealso:: diff --git a/Lib/ast.py b/Lib/ast.py index da47825be272..b45f1e47c197 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -98,26 +98,35 @@ def _convert(node): def dump(node, annotate_fields=True, include_attributes=False): """ - Return a formatted dump of the tree in *node*. This is mainly useful for - debugging purposes. The returned string will show the names and the values - for fields. This makes the code impossible to evaluate, so if evaluation is - wanted *annotate_fields* must be set to False. Attributes such as line + Return a formatted dump of the tree in node. This is mainly useful for + debugging purposes. If annotate_fields is true (by default), + the returned string will show the names and the values for fields. + If annotate_fields is false, the result string will be more compact by + omitting unambiguous field names. Attributes such as line numbers and column offsets are not dumped by default. If this is wanted, - *include_attributes* can be set to True. + include_attributes can be set to true. """ def _format(node): if isinstance(node, AST): - fields = [(a, _format(b)) for a, b in iter_fields(node)] - rv = '%s(%s' % (node.__class__.__name__, ', '.join( - ('%s=%s' % field for field in fields) - if annotate_fields else - (b for a, b in fields) - )) + args = [] + keywords = annotate_fields + for field in node._fields: + try: + value = getattr(node, field) + except AttributeError: + keywords = True + else: + if keywords: + args.append('%s=%s' % (field, _format(value))) + else: + args.append(_format(value)) if include_attributes and node._attributes: - rv += fields and ', ' or ' ' - rv += ', '.join('%s=%s' % (a, _format(getattr(node, a))) - for a in node._attributes) - return rv + ')' + for a in node._attributes: + try: + args.append('%s=%s' % (a, _format(getattr(node, a)))) + except AttributeError: + pass + return '%s(%s)' % (node.__class__.__name__, ', '.join(args)) elif isinstance(node, list): return '[%s]' % ', '.join(_format(x) for x in node) return repr(node) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 47571c915eb7..30460e72268c 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -645,6 +645,35 @@ def test_dump(self): "lineno=1, col_offset=0, end_lineno=1, end_col_offset=24)], type_ignores=[])" ) + def test_dump_incomplete(self): + node = ast.Raise(lineno=3, col_offset=4) + self.assertEqual(ast.dump(node), + "Raise()" + ) + self.assertEqual(ast.dump(node, include_attributes=True), + "Raise(lineno=3, col_offset=4)" + ) + node = ast.Raise(exc=ast.Name(id='e', ctx=ast.Load()), lineno=3, col_offset=4) + self.assertEqual(ast.dump(node), + "Raise(exc=Name(id='e', ctx=Load()))" + ) + self.assertEqual(ast.dump(node, annotate_fields=False), + "Raise(Name('e', Load()))" + ) + self.assertEqual(ast.dump(node, include_attributes=True), + "Raise(exc=Name(id='e', ctx=Load()), lineno=3, col_offset=4)" + ) + self.assertEqual(ast.dump(node, annotate_fields=False, include_attributes=True), + "Raise(Name('e', Load()), lineno=3, col_offset=4)" + ) + node = ast.Raise(cause=ast.Name(id='e', ctx=ast.Load())) + self.assertEqual(ast.dump(node), + "Raise(cause=Name(id='e', ctx=Load()))" + ) + self.assertEqual(ast.dump(node, annotate_fields=False), + "Raise(cause=Name('e', Load()))" + ) + def test_copy_location(self): src = ast.parse('1 + 1', mode='eval') src.body.right = ast.copy_location(ast.Num(2), src.body.right) diff --git a/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst b/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst new file mode 100644 index 000000000000..ded80d3b00ef --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst @@ -0,0 +1 @@ +Fix :func:`ast.dump` when call with incompletely initialized node. From webhook-mailer at python.org Thu Aug 29 03:56:10 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 07:56:10 -0000 Subject: [Python-checkins] bpo-37372: Fix error unpickling datetime.time objects from Python 2 with seconds>=24. (GH-14307) Message-ID: https://github.com/python/cpython/commit/d1d42bf4a404f092fe90fe8984481c507a64ef0a commit: d1d42bf4a404f092fe90fe8984481c507a64ef0a branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-29T00:56:04-07:00 summary: bpo-37372: Fix error unpickling datetime.time objects from Python 2 with seconds>=24. (GH-14307) (cherry picked from commit 122376df550b71dd3bec0513c7483cc1714212fa) Co-authored-by: Justin Blanchard files: A Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst M Lib/test/datetimetester.py M Misc/ACKS M Modules/_datetimemodule.c diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 58004870a00f..b440e5ab5fa6 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -3324,16 +3324,25 @@ def test_pickling_subclass_time(self): def test_compat_unpickle(self): tests = [ - b"cdatetime\ntime\n(S'\\x14;\\x10\\x00\\x10\\x00'\ntR.", - b'cdatetime\ntime\n(U\x06\x14;\x10\x00\x10\x00tR.', - b'\x80\x02cdatetime\ntime\nU\x06\x14;\x10\x00\x10\x00\x85R.', + (b"cdatetime\ntime\n(S'\\x14;\\x10\\x00\\x10\\x00'\ntR.", + (20, 59, 16, 64**2)), + (b'cdatetime\ntime\n(U\x06\x14;\x10\x00\x10\x00tR.', + (20, 59, 16, 64**2)), + (b'\x80\x02cdatetime\ntime\nU\x06\x14;\x10\x00\x10\x00\x85R.', + (20, 59, 16, 64**2)), + (b"cdatetime\ntime\n(S'\\x14;\\x19\\x00\\x10\\x00'\ntR.", + (20, 59, 25, 64**2)), + (b'cdatetime\ntime\n(U\x06\x14;\x19\x00\x10\x00tR.', + (20, 59, 25, 64**2)), + (b'\x80\x02cdatetime\ntime\nU\x06\x14;\x19\x00\x10\x00\x85R.', + (20, 59, 25, 64**2)), ] - args = 20, 59, 16, 64**2 - expected = self.theclass(*args) - for data in tests: - for loads in pickle_loads: - derived = loads(data, encoding='latin1') - self.assertEqual(derived, expected) + for i, (data, args) in enumerate(tests): + with self.subTest(i=i): + expected = self.theclass(*args) + for loads in pickle_loads: + derived = loads(data, encoding='latin1') + self.assertEqual(derived, expected) def test_bool(self): # time is always True. diff --git a/Misc/ACKS b/Misc/ACKS index 5a8494f1a827..24e327a5f86e 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -162,6 +162,7 @@ Roy Bixler Daniel Black Jonathan Black Renaud Blanch +Justin Blanchard Mike Bland Martin Bless Pablo Bleyer diff --git a/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst b/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst new file mode 100644 index 000000000000..b958d8fed40a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst @@ -0,0 +1,2 @@ +Fix error unpickling datetime.time objects from Python 2 with seconds>=24. +Patch by Justin Blanchard. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index e6abfc2cb223..d3c3f0905386 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -4081,7 +4081,7 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw) return NULL; } if (PyUnicode_GET_LENGTH(state) == _PyDateTime_TIME_DATASIZE && - (0x7F & PyUnicode_READ_CHAR(state, 2)) < 24) + (0x7F & PyUnicode_READ_CHAR(state, 0)) < 24) { state = PyUnicode_AsLatin1String(state); if (state == NULL) { From webhook-mailer at python.org Thu Aug 29 03:57:45 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 07:57:45 -0000 Subject: [Python-checkins] bpo-37372: Fix error unpickling datetime.time objects from Python 2 with seconds>=24. (GH-14307) Message-ID: https://github.com/python/cpython/commit/6b50c10f675a9e8438024c5fcc592b0d38d8c62d commit: 6b50c10f675a9e8438024c5fcc592b0d38d8c62d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-29T00:57:41-07:00 summary: bpo-37372: Fix error unpickling datetime.time objects from Python 2 with seconds>=24. (GH-14307) (cherry picked from commit 122376df550b71dd3bec0513c7483cc1714212fa) Co-authored-by: Justin Blanchard files: A Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst M Lib/test/datetimetester.py M Misc/ACKS M Modules/_datetimemodule.c diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 0c621f0f47c7..3cce953a5823 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -3185,16 +3185,25 @@ def test_pickling_subclass_time(self): def test_compat_unpickle(self): tests = [ - b"cdatetime\ntime\n(S'\\x14;\\x10\\x00\\x10\\x00'\ntR.", - b'cdatetime\ntime\n(U\x06\x14;\x10\x00\x10\x00tR.', - b'\x80\x02cdatetime\ntime\nU\x06\x14;\x10\x00\x10\x00\x85R.', + (b"cdatetime\ntime\n(S'\\x14;\\x10\\x00\\x10\\x00'\ntR.", + (20, 59, 16, 64**2)), + (b'cdatetime\ntime\n(U\x06\x14;\x10\x00\x10\x00tR.', + (20, 59, 16, 64**2)), + (b'\x80\x02cdatetime\ntime\nU\x06\x14;\x10\x00\x10\x00\x85R.', + (20, 59, 16, 64**2)), + (b"cdatetime\ntime\n(S'\\x14;\\x19\\x00\\x10\\x00'\ntR.", + (20, 59, 25, 64**2)), + (b'cdatetime\ntime\n(U\x06\x14;\x19\x00\x10\x00tR.', + (20, 59, 25, 64**2)), + (b'\x80\x02cdatetime\ntime\nU\x06\x14;\x19\x00\x10\x00\x85R.', + (20, 59, 25, 64**2)), ] - args = 20, 59, 16, 64**2 - expected = self.theclass(*args) - for data in tests: - for loads in pickle_loads: - derived = loads(data, encoding='latin1') - self.assertEqual(derived, expected) + for i, (data, args) in enumerate(tests): + with self.subTest(i=i): + expected = self.theclass(*args) + for loads in pickle_loads: + derived = loads(data, encoding='latin1') + self.assertEqual(derived, expected) def test_bool(self): # time is always True. diff --git a/Misc/ACKS b/Misc/ACKS index 0283c85b174e..ade26f5e86d2 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -160,6 +160,7 @@ Roy Bixler Daniel Black Jonathan Black Renaud Blanch +Justin Blanchard Mike Bland Martin Bless Pablo Bleyer diff --git a/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst b/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst new file mode 100644 index 000000000000..b958d8fed40a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst @@ -0,0 +1,2 @@ +Fix error unpickling datetime.time objects from Python 2 with seconds>=24. +Patch by Justin Blanchard. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 6bed29ee5cf3..42caf0826202 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3982,7 +3982,7 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw) return NULL; } if (PyUnicode_GET_LENGTH(state) == _PyDateTime_TIME_DATASIZE && - (0x7F & PyUnicode_READ_CHAR(state, 2)) < 24) + (0x7F & PyUnicode_READ_CHAR(state, 0)) < 24) { state = PyUnicode_AsLatin1String(state); if (state == NULL) { From webhook-mailer at python.org Thu Aug 29 03:58:12 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 07:58:12 -0000 Subject: [Python-checkins] bpo-16468: Clarify which objects can be passed to "choices" in argparse (GH-15566) Message-ID: https://github.com/python/cpython/commit/84125fed2a45a9e454d7e870d8bbaf6ece3d41e8 commit: 84125fed2a45a9e454d7e870d8bbaf6ece3d41e8 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-29T00:58:08-07:00 summary: bpo-16468: Clarify which objects can be passed to "choices" in argparse (GH-15566) files: M Doc/library/argparse.rst diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index ef2fd42783c8..368b1cfebf05 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1102,9 +1102,8 @@ container should match the type_ specified:: usage: doors.py [-h] {1,2,3} doors.py: error: argument door: invalid choice: 4 (choose from 1, 2, 3) -Any object that supports the ``in`` operator can be passed as the *choices* -value, so :class:`dict` objects, :class:`set` objects, custom containers, -etc. are all supported. +Any container can be passed as the *choices* value, so :class:`list` objects, +:class:`set` objects, and custom containers are all supported. required From webhook-mailer at python.org Thu Aug 29 04:03:05 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 08:03:05 -0000 Subject: [Python-checkins] bpo-23674: Clarify ambiguities in super() docs (GH-15564) (GH-15586) Message-ID: https://github.com/python/cpython/commit/43b7ed77a8224c378b436ad3385733454198be41 commit: 43b7ed77a8224c378b436ad3385733454198be41 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-29T01:02:58-07:00 summary: bpo-23674: Clarify ambiguities in super() docs (GH-15564) (GH-15586) (cherry picked from commit cd81f0500fe98c7f4cddb06530fffabd14f036b8) Co-authored-by: Raymond Hettinger files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index c225f3dee921..c748b086d8ac 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1587,10 +1587,17 @@ are always available. They are listed here in alphabetical order. Return a proxy object that delegates method calls to a parent or sibling class of *type*. This is useful for accessing inherited methods that have - been overridden in a class. The search order is same as that used by - :func:`getattr` except that the *type* itself is skipped. + been overridden in a class. - The :attr:`~class.__mro__` attribute of the *type* lists the method + The *object-or-type* determines the :term:`method resolution order` + to be searched. The search starts from the class right after the + *type*. + + For example, if :attr:`~class.__mro__` of *object-or-type* is + ``D -> B -> C -> A -> object`` and the value of *type* is ``B``, + then :func:`super` searches ``C -> A -> object``. + + The :attr:`~class.__mro__` attribute of the *object-or-type* lists the method resolution search order used by both :func:`getattr` and :func:`super`. The attribute is dynamic and can change whenever the inheritance hierarchy is updated. From webhook-mailer at python.org Thu Aug 29 04:13:35 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 08:13:35 -0000 Subject: [Python-checkins] bpo-37960: Silence only necessary errors in repr() of buffered and text streams. (GH-15543) Message-ID: https://github.com/python/cpython/commit/102130a63c93fde7bcabbbf4fae1ebce38888981 commit: 102130a63c93fde7bcabbbf4fae1ebce38888981 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-29T01:13:29-07:00 summary: bpo-37960: Silence only necessary errors in repr() of buffered and text streams. (GH-15543) (cherry picked from commit b235a1b47394eedc5f8ea4cf214f56c4c6932e59) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst M Lib/_pyio.py M Modules/_io/bufferedio.c M Modules/_io/textio.c diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 0b6493bc8dc9..650109295fe8 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -407,7 +407,7 @@ def __del__(self): """Destructor. Calls close().""" try: closed = self.closed - except Exception: + except AttributeError: # If getting closed fails, then the object is probably # in an unusable state, so ignore. return @@ -865,7 +865,7 @@ def __repr__(self): clsname = self.__class__.__qualname__ try: name = self.name - except Exception: + except AttributeError: return "<{}.{}>".format(modname, clsname) else: return "<{}.{} name={!r}>".format(modname, clsname, name) @@ -2079,13 +2079,13 @@ def __repr__(self): self.__class__.__qualname__) try: name = self.name - except Exception: + except AttributeError: pass else: result += " name={0!r}".format(name) try: mode = self.mode - except Exception: + except AttributeError: pass else: result += " mode={0!r}".format(mode) diff --git a/Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst b/Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst new file mode 100644 index 000000000000..421cfb9c38e1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst @@ -0,0 +1,2 @@ +``repr()`` of buffered and text streams now silences only expected +exceptions when get the value of "name" and "mode" attributes. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 44e12db6a30e..8e8ff97ff8c6 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1378,12 +1378,14 @@ buffered_repr(buffered *self) { PyObject *nameobj, *res; - nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name); - if (nameobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_Exception)) - PyErr_Clear(); - else + if (_PyObject_LookupAttrId((PyObject *) self, &PyId_name, &nameobj) < 0) { + if (!PyErr_ExceptionMatches(PyExc_ValueError)) { return NULL; + } + /* Ignore ValueError raised if the underlying stream was detached */ + PyErr_Clear(); + } + if (nameobj == NULL) { res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name); } else { diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 73b2756afce5..4fe1b295f885 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -2860,14 +2860,14 @@ textiowrapper_repr(textio *self) } goto error; } - nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name); - if (nameobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_Exception)) - PyErr_Clear(); - else + if (_PyObject_LookupAttrId((PyObject *) self, &PyId_name, &nameobj) < 0) { + if (!PyErr_ExceptionMatches(PyExc_ValueError)) { goto error; + } + /* Ignore ValueError raised if the underlying stream was detached */ + PyErr_Clear(); } - else { + if (nameobj != NULL) { s = PyUnicode_FromFormat(" name=%R", nameobj); Py_DECREF(nameobj); if (s == NULL) @@ -2876,14 +2876,10 @@ textiowrapper_repr(textio *self) if (res == NULL) goto error; } - modeobj = _PyObject_GetAttrId((PyObject *) self, &PyId_mode); - if (modeobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_Exception)) - PyErr_Clear(); - else - goto error; + if (_PyObject_LookupAttrId((PyObject *) self, &PyId_mode, &modeobj) < 0) { + goto error; } - else { + if (modeobj != NULL) { s = PyUnicode_FromFormat(" mode=%R", modeobj); Py_DECREF(modeobj); if (s == NULL) From webhook-mailer at python.org Thu Aug 29 04:15:25 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 08:15:25 -0000 Subject: [Python-checkins] bpo-16468: Clarify which objects can be passed to "choices" in argparse (GH-15566) (GH-15587) Message-ID: https://github.com/python/cpython/commit/0d45d50e421b46b56195821580c3760b43813106 commit: 0d45d50e421b46b56195821580c3760b43813106 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-29T01:15:18-07:00 summary: bpo-16468: Clarify which objects can be passed to "choices" in argparse (GH-15566) (GH-15587) (cherry picked from commit 84125fed2a45a9e454d7e870d8bbaf6ece3d41e8) Co-authored-by: Raymond Hettinger files: M Doc/library/argparse.rst diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index ef2fd42783c8..368b1cfebf05 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1102,9 +1102,8 @@ container should match the type_ specified:: usage: doors.py [-h] {1,2,3} doors.py: error: argument door: invalid choice: 4 (choose from 1, 2, 3) -Any object that supports the ``in`` operator can be passed as the *choices* -value, so :class:`dict` objects, :class:`set` objects, custom containers, -etc. are all supported. +Any container can be passed as the *choices* value, so :class:`list` objects, +:class:`set` objects, and custom containers are all supported. required From webhook-mailer at python.org Thu Aug 29 04:27:46 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 08:27:46 -0000 Subject: [Python-checkins] bpo-36743: __get__ is sometimes called without the owner argument (#12992) Message-ID: https://github.com/python/cpython/commit/0dac68f1e593c11612ed54af9edb865d398f3b05 commit: 0dac68f1e593c11612ed54af9edb865d398f3b05 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-29T01:27:42-07:00 summary: bpo-36743: __get__ is sometimes called without the owner argument (#12992) files: M Doc/reference/datamodel.rst M Lib/_pyio.py M Lib/functools.py M Lib/unittest/mock.py M Tools/demo/eiffel.py diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index d1702ccb6417..8813f57587f0 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1618,21 +1618,32 @@ refers to the attribute whose name is the key of the property in the owner class' :attr:`~object.__dict__`. -.. method:: object.__get__(self, instance, owner) +.. method:: object.__get__(self, instance, owner=None) - Called to get the attribute of the owner class (class attribute access) or of an - instance of that class (instance attribute access). *owner* is always the owner - class, while *instance* is the instance that the attribute was accessed through, - or ``None`` when the attribute is accessed through the *owner*. This method - should return the (computed) attribute value or raise an :exc:`AttributeError` - exception. + Called to get the attribute of the owner class (class attribute access) or + of an instance of that class (instance attribute access). The optional + *owner* argument is the owner class, while *instance* is the instance that + the attribute was accessed through, or ``None`` when the attribute is + accessed through the *owner*. + This method should return the computed attribute value or raise an + :exc:`AttributeError` exception. + + :PEP:`252` specifies that :meth:`__get__` is callable with one or two + arguments. Python's own built-in descriptors support this specification; + however, it is likely that some third-party tools have descriptors + that require both arguments. Python's own :meth:`__getattribute__` + implementation always passes in both arguments whether they are required + or not. .. method:: object.__set__(self, instance, value) Called to set the attribute on an instance *instance* of the owner class to a new value, *value*. + Note, adding :meth:`__set__` or :meth:`__delete__` changes the kind of + descriptor to a "data descriptor". See :ref:`descriptor-invocation` for + more details. .. method:: object.__delete__(self, instance) diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 1b24ef9f0e10..0d3f974c0724 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -283,7 +283,7 @@ def _open_code_with_warning(path): class DocDescriptor: """Helper for builtins.open.__doc__ """ - def __get__(self, obj, typ): + def __get__(self, obj, typ=None): return ( "open(file, mode='r', buffering=-1, encoding=None, " "errors=None, newline=None, closefd=True)\n\n" + diff --git a/Lib/functools.py b/Lib/functools.py index 9495fbe56eba..f87d9c571873 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -383,7 +383,7 @@ def _method(cls_or_self, /, *args, **keywords): _method._partialmethod = self return _method - def __get__(self, obj, cls): + def __get__(self, obj, cls=None): get = getattr(self.func, "__get__", None) result = None if get is not None: @@ -888,7 +888,7 @@ def register(self, cls, method=None): """ return self.dispatcher.register(cls, func=method) - def __get__(self, obj, cls): + def __get__(self, obj, cls=None): def _method(*args, **kwargs): method = self.dispatcher.dispatch(args[0].__class__) return method.__get__(obj, cls)(*args, **kwargs) @@ -926,7 +926,7 @@ def __set_name__(self, owner, name): f"({self.attrname!r} and {name!r})." ) - def __get__(self, instance, owner): + def __get__(self, instance, owner=None): if instance is None: return self if self.attrname is None: diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index c6771ce5291a..89312f18c967 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2804,7 +2804,7 @@ class PropertyMock(Mock): def _get_child_mock(self, /, **kwargs): return MagicMock(**kwargs) - def __get__(self, obj, obj_type): + def __get__(self, obj, obj_type=None): return self() def __set__(self, obj, val): self(val) diff --git a/Tools/demo/eiffel.py b/Tools/demo/eiffel.py index 736abea81738..a76c2324dd6a 100755 --- a/Tools/demo/eiffel.py +++ b/Tools/demo/eiffel.py @@ -78,7 +78,7 @@ def __init__(self, func, pre, post): self.__name__ = func.__name__ self.__doc__ = func.__doc__ - def __get__(self, obj, cls): + def __get__(self, obj, cls=None): return EiffelMethodWrapper(obj, self) def callmethod(self, inst, args, kwargs): From webhook-mailer at python.org Thu Aug 29 04:45:30 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 08:45:30 -0000 Subject: [Python-checkins] bpo-10978: Semaphores can release multiple threads at a time (GH-15588) Message-ID: https://github.com/python/cpython/commit/35f6301d68bdb0517be284421782d64407dfe72c commit: 35f6301d68bdb0517be284421782d64407dfe72c branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-29T01:45:19-07:00 summary: bpo-10978: Semaphores can release multiple threads at a time (GH-15588) files: A Misc/NEWS.d/next/Library/2019-08-29-01-19-13.bpo-10978.J6FQYY.rst M Doc/library/threading.rst M Lib/test/lock_tests.py M Lib/threading.py diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index 7de12fbf9dcd..0489421cdf60 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -802,11 +802,14 @@ Semaphores also support the :ref:`context management protocol `. .. versionchanged:: 3.2 The *timeout* parameter is new. - .. method:: release() + .. method:: release(n=1) + + Release a semaphore, incrementing the internal counter by *n*. When it + was zero on entry and other threads are waiting for it to become larger + than zero again, wake up *n* of those threads. - Release a semaphore, incrementing the internal counter by one. When it - was zero on entry and another thread is waiting for it to become larger - than zero again, wake up that thread. + .. versionchanged:: 3.9 + Added the *n* parameter to release multiple waiting threads at once. .. class:: BoundedSemaphore(value=1) diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py index 23a02e0b4eb2..888586840f2c 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -663,6 +663,38 @@ def f(): b.wait_for_finished() self.assertEqual(sem_results, [True] * (6 + 7 + 6 + 1)) + def test_multirelease(self): + sem = self.semtype(7) + sem.acquire() + results1 = [] + results2 = [] + phase_num = 0 + def f(): + sem.acquire() + results1.append(phase_num) + sem.acquire() + results2.append(phase_num) + b = Bunch(f, 10) + b.wait_for_started() + while len(results1) + len(results2) < 6: + _wait() + self.assertEqual(results1 + results2, [0] * 6) + phase_num = 1 + sem.release(7) + while len(results1) + len(results2) < 13: + _wait() + self.assertEqual(sorted(results1 + results2), [0] * 6 + [1] * 7) + phase_num = 2 + sem.release(6) + while len(results1) + len(results2) < 19: + _wait() + self.assertEqual(sorted(results1 + results2), [0] * 6 + [1] * 7 + [2] * 6) + # The semaphore is still locked + self.assertFalse(sem.acquire(False)) + # Final release, to let the last thread finish + sem.release() + b.wait_for_finished() + def test_try_acquire(self): sem = self.semtype(2) self.assertTrue(sem.acquire(False)) diff --git a/Lib/threading.py b/Lib/threading.py index 32a3d7c30336..c3bbb19acbe2 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -439,16 +439,19 @@ def acquire(self, blocking=True, timeout=None): __enter__ = acquire - def release(self): - """Release a semaphore, incrementing the internal counter by one. + def release(self, n=1): + """Release a semaphore, incrementing the internal counter by one or more. When the counter is zero on entry and another thread is waiting for it to become larger than zero again, wake up that thread. """ + if n < 1: + raise ValueError('n must be one or more') with self._cond: - self._value += 1 - self._cond.notify() + self._value += n + for i in range(n): + self._cond.notify() def __exit__(self, t, v, tb): self.release() @@ -475,8 +478,8 @@ def __init__(self, value=1): Semaphore.__init__(self, value) self._initial_value = value - def release(self): - """Release a semaphore, incrementing the internal counter by one. + def release(self, n=1): + """Release a semaphore, incrementing the internal counter by one or more. When the counter is zero on entry and another thread is waiting for it to become larger than zero again, wake up that thread. @@ -485,11 +488,14 @@ def release(self): raise a ValueError. """ + if n < 1: + raise ValueError('n must be one or more') with self._cond: - if self._value >= self._initial_value: + if self._value + n > self._initial_value: raise ValueError("Semaphore released too many times") - self._value += 1 - self._cond.notify() + self._value += n + for i in range(n): + self._cond.notify() class Event: diff --git a/Misc/NEWS.d/next/Library/2019-08-29-01-19-13.bpo-10978.J6FQYY.rst b/Misc/NEWS.d/next/Library/2019-08-29-01-19-13.bpo-10978.J6FQYY.rst new file mode 100644 index 000000000000..2b8f300fc280 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-29-01-19-13.bpo-10978.J6FQYY.rst @@ -0,0 +1,2 @@ +Semaphores and BoundedSemaphores can now release more than one waiting +thread at a time. From webhook-mailer at python.org Thu Aug 29 05:02:56 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 09:02:56 -0000 Subject: [Python-checkins] bpo-36743: __get__ is sometimes called without the owner argument (GH-12992) (GH-15589) Message-ID: https://github.com/python/cpython/commit/c71ae1a45bd6e6d0f5aebc470b35f5a7dc0d8078 commit: c71ae1a45bd6e6d0f5aebc470b35f5a7dc0d8078 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-29T02:02:51-07:00 summary: bpo-36743: __get__ is sometimes called without the owner argument (GH-12992) (GH-15589) (cherry picked from commit 0dac68f1e593c11612ed54af9edb865d398f3b05) Co-authored-by: Raymond Hettinger files: M Doc/reference/datamodel.rst M Lib/_pyio.py M Lib/functools.py M Lib/unittest/mock.py M Tools/demo/eiffel.py diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index d1702ccb6417..8813f57587f0 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1618,21 +1618,32 @@ refers to the attribute whose name is the key of the property in the owner class' :attr:`~object.__dict__`. -.. method:: object.__get__(self, instance, owner) +.. method:: object.__get__(self, instance, owner=None) - Called to get the attribute of the owner class (class attribute access) or of an - instance of that class (instance attribute access). *owner* is always the owner - class, while *instance* is the instance that the attribute was accessed through, - or ``None`` when the attribute is accessed through the *owner*. This method - should return the (computed) attribute value or raise an :exc:`AttributeError` - exception. + Called to get the attribute of the owner class (class attribute access) or + of an instance of that class (instance attribute access). The optional + *owner* argument is the owner class, while *instance* is the instance that + the attribute was accessed through, or ``None`` when the attribute is + accessed through the *owner*. + This method should return the computed attribute value or raise an + :exc:`AttributeError` exception. + + :PEP:`252` specifies that :meth:`__get__` is callable with one or two + arguments. Python's own built-in descriptors support this specification; + however, it is likely that some third-party tools have descriptors + that require both arguments. Python's own :meth:`__getattribute__` + implementation always passes in both arguments whether they are required + or not. .. method:: object.__set__(self, instance, value) Called to set the attribute on an instance *instance* of the owner class to a new value, *value*. + Note, adding :meth:`__set__` or :meth:`__delete__` changes the kind of + descriptor to a "data descriptor". See :ref:`descriptor-invocation` for + more details. .. method:: object.__delete__(self, instance) diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 650109295fe8..eb4e6620fc65 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -281,7 +281,7 @@ def _open_code_with_warning(path): class DocDescriptor: """Helper for builtins.open.__doc__ """ - def __get__(self, obj, typ): + def __get__(self, obj, typ=None): return ( "open(file, mode='r', buffering=-1, encoding=None, " "errors=None, newline=None, closefd=True)\n\n" + diff --git a/Lib/functools.py b/Lib/functools.py index 64d120182bb0..a674a685df65 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -400,7 +400,7 @@ def _method(cls_or_self, /, *args, **keywords): _method._partialmethod = self return _method - def __get__(self, obj, cls): + def __get__(self, obj, cls=None): get = getattr(self.func, "__get__", None) result = None if get is not None: @@ -905,7 +905,7 @@ def register(self, cls, method=None): """ return self.dispatcher.register(cls, func=method) - def __get__(self, obj, cls): + def __get__(self, obj, cls=None): def _method(*args, **kwargs): method = self.dispatcher.dispatch(args[0].__class__) return method.__get__(obj, cls)(*args, **kwargs) @@ -943,7 +943,7 @@ def __set_name__(self, owner, name): f"({self.attrname!r} and {name!r})." ) - def __get__(self, instance, owner): + def __get__(self, instance, owner=None): if instance is None: return self if self.attrname is None: diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 7ab68125918d..4c76f53f3870 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -2806,7 +2806,7 @@ class PropertyMock(Mock): def _get_child_mock(self, /, **kwargs): return MagicMock(**kwargs) - def __get__(self, obj, obj_type): + def __get__(self, obj, obj_type=None): return self() def __set__(self, obj, val): self(val) diff --git a/Tools/demo/eiffel.py b/Tools/demo/eiffel.py index 736abea81738..a76c2324dd6a 100755 --- a/Tools/demo/eiffel.py +++ b/Tools/demo/eiffel.py @@ -78,7 +78,7 @@ def __init__(self, func, pre, post): self.__name__ = func.__name__ self.__doc__ = func.__doc__ - def __get__(self, obj, cls): + def __get__(self, obj, cls=None): return EiffelMethodWrapper(obj, self) def callmethod(self, inst, args, kwargs): From webhook-mailer at python.org Thu Aug 29 08:54:50 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 29 Aug 2019 12:54:50 -0000 Subject: [Python-checkins] bpo-36833: Add tests for Datetime C API Macros (GH-14842) Message-ID: https://github.com/python/cpython/commit/2c5fb1711818926862d0d7b2e5effcaa5a5eb002 commit: 2c5fb1711818926862d0d7b2e5effcaa5a5eb002 branch: master author: Joannah Nanjekye <33177550+nanjekyejoannah at users.noreply.github.com> committer: Victor Stinner date: 2019-08-29T14:54:46+02:00 summary: bpo-36833: Add tests for Datetime C API Macros (GH-14842) Added tests for PyDateTime_xxx_GET_xxx() macros of the C API of the datetime module. files: A Misc/NEWS.d/next/Tests/2019-07-18-14-52-58.bpo-36833.Zoe9ek.rst M Lib/test/datetimetester.py M Modules/_testcapimodule.c diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index b440e5ab5fa6..d09255d79bfb 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -5941,6 +5941,65 @@ def test_timezones_capi(self): self.assertEqual(dt1.astimezone(timezone.utc), dt_utc) + def test_PyDateTime_DELTA_GET(self): + class TimeDeltaSubclass(timedelta): + pass + + for klass in [timedelta, TimeDeltaSubclass]: + for args in [(26, 55, 99999), (26, 55, 99999)]: + d = klass(*args) + with self.subTest(cls=klass, date=args): + days, seconds, microseconds = _testcapi.PyDateTime_DELTA_GET(d) + + self.assertEqual(days, d.days) + self.assertEqual(seconds, d.seconds) + self.assertEqual(microseconds, d.microseconds) + + def test_PyDateTime_GET(self): + class DateSubclass(date): + pass + + for klass in [date, DateSubclass]: + for args in [(2000, 1, 2), (2012, 2, 29)]: + d = klass(*args) + with self.subTest(cls=klass, date=args): + year, month, day = _testcapi.PyDateTime_GET(d) + + self.assertEqual(year, d.year) + self.assertEqual(month, d.month) + self.assertEqual(day, d.day) + + def test_PyDateTime_DATE_GET(self): + class DateTimeSubclass(datetime): + pass + + for klass in [datetime, DateTimeSubclass]: + for args in [(1993, 8, 26, 22, 12, 55, 99999), + (1993, 8, 26, 22, 12, 55, 99999)]: + d = klass(*args) + with self.subTest(cls=klass, date=args): + hour, minute, second, microsecond = _testcapi.PyDateTime_DATE_GET(d) + + self.assertEqual(hour, d.hour) + self.assertEqual(minute, d.minute) + self.assertEqual(second, d.second) + self.assertEqual(microsecond, d.microsecond) + + def test_PyDateTime_TIME_GET(self): + class TimeSubclass(time): + pass + + for klass in [time, TimeSubclass]: + for args in [(12, 30, 20, 10), (12, 30, 20, 10)]: + d = klass(*args) + with self.subTest(cls=klass, date=args): + hour, minute, second, microsecond = _testcapi.PyDateTime_TIME_GET(d) + + self.assertEqual(hour, d.hour) + self.assertEqual(minute, d.minute) + self.assertEqual(second, d.second) + self.assertEqual(microsecond, d.microsecond) + def test_timezones_offset_zero(self): utc0, utc1, non_utc = _testcapi.get_timezones_offset_zero() diff --git a/Misc/NEWS.d/next/Tests/2019-07-18-14-52-58.bpo-36833.Zoe9ek.rst b/Misc/NEWS.d/next/Tests/2019-07-18-14-52-58.bpo-36833.Zoe9ek.rst new file mode 100644 index 000000000000..3632f98f34f0 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-07-18-14-52-58.bpo-36833.Zoe9ek.rst @@ -0,0 +1,2 @@ +Added tests for PyDateTime_xxx_GET_xxx() macros of the C API of +the :mod:`datetime` module. Patch by Joannah Nanjekye. \ No newline at end of file diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 84f2651641c7..cc3b089a0d7d 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2629,6 +2629,55 @@ get_datetime_fromtimestamp(PyObject* self, PyObject *args) return rv; } +static PyObject * +test_PyDateTime_GET(PyObject *self, PyObject *obj) +{ + int year, month, day; + + year = PyDateTime_GET_YEAR(obj); + month = PyDateTime_GET_MONTH(obj); + day = PyDateTime_GET_DAY(obj); + + return Py_BuildValue("(lll)", year, month, day); +} + +static PyObject * +test_PyDateTime_DATE_GET(PyObject *self, PyObject *obj) +{ + int hour, minute, second, microsecond; + + hour = PyDateTime_DATE_GET_HOUR(obj); + minute = PyDateTime_DATE_GET_MINUTE(obj); + second = PyDateTime_DATE_GET_SECOND(obj); + microsecond = PyDateTime_DATE_GET_MICROSECOND(obj); + + return Py_BuildValue("(llll)", hour, minute, second, microsecond); +} + +static PyObject * +test_PyDateTime_TIME_GET(PyObject *self, PyObject *obj) +{ + int hour, minute, second, microsecond; + + hour = PyDateTime_TIME_GET_HOUR(obj); + minute = PyDateTime_TIME_GET_MINUTE(obj); + second = PyDateTime_TIME_GET_SECOND(obj); + microsecond = PyDateTime_TIME_GET_MICROSECOND(obj); + + return Py_BuildValue("(llll)", hour, minute, second, microsecond); +} + +static PyObject * +test_PyDateTime_DELTA_GET(PyObject *self, PyObject *obj) +{ + int days, seconds, microseconds; + + days = PyDateTime_DELTA_GET_DAYS(obj); + seconds = PyDateTime_DELTA_GET_SECONDS(obj); + microseconds = PyDateTime_DELTA_GET_MICROSECONDS(obj); + + return Py_BuildValue("(lll)", days, seconds, microseconds); +} /* 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 @@ -5138,6 +5187,10 @@ static PyMethodDef TestMethods[] = { {"get_delta_fromdsu", get_delta_fromdsu, METH_VARARGS}, {"get_date_fromtimestamp", get_date_fromtimestamp, METH_VARARGS}, {"get_datetime_fromtimestamp", get_datetime_fromtimestamp, METH_VARARGS}, + {"PyDateTime_GET", test_PyDateTime_GET, METH_O}, + {"PyDateTime_DATE_GET", test_PyDateTime_DATE_GET, METH_O}, + {"PyDateTime_TIME_GET", test_PyDateTime_TIME_GET, METH_O}, + {"PyDateTime_DELTA_GET", test_PyDateTime_DELTA_GET, METH_O}, {"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 webhook-mailer at python.org Thu Aug 29 09:27:02 2019 From: webhook-mailer at python.org (Nick Coghlan) Date: Thu, 29 Aug 2019 13:27:02 -0000 Subject: [Python-checkins] bpo-37947: Avoid double-decrement in symtable recursion counting (GH-15593) Message-ID: https://github.com/python/cpython/commit/06145230c833c3db5dab8858e11bcd550a37c57f commit: 06145230c833c3db5dab8858e11bcd550a37c57f branch: master author: Nick Coghlan committer: GitHub date: 2019-08-29T23:26:53+10:00 summary: bpo-37947: Avoid double-decrement in symtable recursion counting (GH-15593) With `symtable_visit_expr` now correctly adjusting the recursion depth for named expressions, `symtable_handle_namedexpr` should be leaving it alone. Also adds a new check to `PySymtable_BuildObject` that raises `SystemError` if a successful first symbol analysis pass fails to keep the stack depth accounting clean. files: M Python/symtable.c diff --git a/Python/symtable.c b/Python/symtable.c index 2795e0f1115b..f2453db69dd7 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -266,6 +266,7 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) int i; PyThreadState *tstate; int recursion_limit = Py_GetRecursionLimit(); + int starting_recursion_depth; if (st == NULL) return NULL; @@ -284,8 +285,9 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) return NULL; } /* Be careful here to prevent overflow. */ - st->recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? + starting_recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth; + st->recursion_depth = starting_recursion_depth; st->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit; @@ -329,6 +331,14 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) PySymtable_Free(st); return NULL; } + /* Check that the recursion depth counting balanced correctly */ + if (st->recursion_depth != starting_recursion_depth) { + PyErr_Format(PyExc_SystemError, + "symtable analysis recursion depth mismatch (before=%d, after=%d)", + starting_recursion_depth, st->recursion_depth); + PySymtable_Free(st); + return NULL; + } /* Make the second symbol analysis pass */ if (symtable_analyze(st)) return st; @@ -1501,16 +1511,16 @@ symtable_handle_namedexpr(struct symtable *st, expr_ty e) PyErr_SyntaxLocationObject(st->st_filename, e->lineno, e->col_offset); - VISIT_QUIT(st, 0); + return 0; } if (st->st_cur->ste_comprehension) { /* Inside a comprehension body, so find the right target scope */ if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target)) - VISIT_QUIT(st, 0); + return 0; } VISIT(st, expr, e->v.NamedExpr.value); VISIT(st, expr, e->v.NamedExpr.target); - VISIT_QUIT(st, 1); + return 1; } static int From webhook-mailer at python.org Thu Aug 29 09:46:26 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 13:46:26 -0000 Subject: [Python-checkins] bpo-37947: Avoid double-decrement in symtable recursion counting (GH-15593) Message-ID: https://github.com/python/cpython/commit/384c6d72d9a12764282ccc2d3935232a34a7cfbe commit: 384c6d72d9a12764282ccc2d3935232a34a7cfbe branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-29T06:46:20-07:00 summary: bpo-37947: Avoid double-decrement in symtable recursion counting (GH-15593) With `symtable_visit_expr` now correctly adjusting the recursion depth for named expressions, `symtable_handle_namedexpr` should be leaving it alone. Also adds a new check to `PySymtable_BuildObject` that raises `SystemError` if a successful first symbol analysis pass fails to keep the stack depth accounting clean. (cherry picked from commit 06145230c833c3db5dab8858e11bcd550a37c57f) Co-authored-by: Nick Coghlan files: M Python/symtable.c diff --git a/Python/symtable.c b/Python/symtable.c index 2795e0f1115b..f2453db69dd7 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -266,6 +266,7 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) int i; PyThreadState *tstate; int recursion_limit = Py_GetRecursionLimit(); + int starting_recursion_depth; if (st == NULL) return NULL; @@ -284,8 +285,9 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) return NULL; } /* Be careful here to prevent overflow. */ - st->recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? + starting_recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth; + st->recursion_depth = starting_recursion_depth; st->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit; @@ -329,6 +331,14 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) PySymtable_Free(st); return NULL; } + /* Check that the recursion depth counting balanced correctly */ + if (st->recursion_depth != starting_recursion_depth) { + PyErr_Format(PyExc_SystemError, + "symtable analysis recursion depth mismatch (before=%d, after=%d)", + starting_recursion_depth, st->recursion_depth); + PySymtable_Free(st); + return NULL; + } /* Make the second symbol analysis pass */ if (symtable_analyze(st)) return st; @@ -1501,16 +1511,16 @@ symtable_handle_namedexpr(struct symtable *st, expr_ty e) PyErr_SyntaxLocationObject(st->st_filename, e->lineno, e->col_offset); - VISIT_QUIT(st, 0); + return 0; } if (st->st_cur->ste_comprehension) { /* Inside a comprehension body, so find the right target scope */ if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target)) - VISIT_QUIT(st, 0); + return 0; } VISIT(st, expr, e->v.NamedExpr.value); VISIT(st, expr, e->v.NamedExpr.target); - VISIT_QUIT(st, 1); + return 1; } static int From webhook-mailer at python.org Thu Aug 29 10:47:56 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 14:47:56 -0000 Subject: [Python-checkins] bpo-37979: Add alternative to fromisoformat in documentation (GH-15596) Message-ID: https://github.com/python/cpython/commit/59725f3badb3028636c8906ecac4ceb0a37f3982 commit: 59725f3badb3028636c8906ecac4ceb0a37f3982 branch: master author: Paul Ganssle committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-29T07:47:48-07:00 summary: bpo-37979: Add alternative to fromisoformat in documentation (GH-15596) Adds a link to `dateutil.parser.isoparse` in the documentation. It would be nice to set up intersphinx for things like this, but I think we can leave that for a separate PR. CC: @pitrou [bpo-37979](https://bugs.python.org/issue37979) https://bugs.python.org/issue37979 Automerge-Triggered-By: @pitrou files: A Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 0135fa4b0218..50f1b9e74949 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -857,7 +857,9 @@ Other constructors, all class methods: .. caution:: This does not support parsing arbitrary ISO 8601 strings - it is only intended - as the inverse operation of :meth:`datetime.isoformat`. + as the inverse operation of :meth:`datetime.isoformat`. A more full-featured + ISO 8601 parser, ``dateutil.parser.isoparse`` is available in the third-party package + `dateutil `_. .. versionadded:: 3.7 diff --git a/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst b/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst new file mode 100644 index 000000000000..d8d70d613706 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst @@ -0,0 +1,2 @@ +Added a link to dateutil.parser.isoparse in the datetime.fromisoformat +documentation. Patch by Paul Ganssle From webhook-mailer at python.org Thu Aug 29 10:49:13 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 29 Aug 2019 14:49:13 -0000 Subject: [Python-checkins] bpo-37034: Display argument name on errors with keyword arguments with Argument Clinic. (GH-13593) Message-ID: https://github.com/python/cpython/commit/4901fe274bc82b95dc89bcb3de8802a3dfedab32 commit: 4901fe274bc82b95dc89bcb3de8802a3dfedab32 branch: master author: R?mi Lapeyre committer: Serhiy Storchaka date: 2019-08-29T17:49:08+03:00 summary: bpo-37034: Display argument name on errors with keyword arguments with Argument Clinic. (GH-13593) files: A Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst M Include/modsupport.h M Lib/test/clinic.test M Lib/test/test_pyexpat.py M Modules/_blake2/clinic/blake2b_impl.c.h M Modules/_blake2/clinic/blake2s_impl.c.h M Modules/_io/clinic/_iomodule.c.h M Modules/_io/clinic/bufferedio.c.h M Modules/_io/clinic/bytesio.c.h M Modules/_io/clinic/fileio.c.h M Modules/_io/clinic/textio.c.h M Modules/_io/clinic/winconsoleio.c.h M Modules/_multiprocessing/clinic/posixshmem.c.h M Modules/cjkcodecs/clinic/multibytecodec.c.h M Modules/clinic/_bz2module.c.h M Modules/clinic/_codecsmodule.c.h M Modules/clinic/_cryptmodule.c.h M Modules/clinic/_curses_panel.c.h M Modules/clinic/_cursesmodule.c.h M Modules/clinic/_dbmmodule.c.h M Modules/clinic/_elementtree.c.h M Modules/clinic/_gdbmmodule.c.h M Modules/clinic/_hashopenssl.c.h M Modules/clinic/_lzmamodule.c.h M Modules/clinic/_pickle.c.h M Modules/clinic/_sre.c.h M Modules/clinic/_ssl.c.h M Modules/clinic/_struct.c.h M Modules/clinic/_tkinter.c.h M Modules/clinic/_weakref.c.h M Modules/clinic/arraymodule.c.h M Modules/clinic/audioop.c.h M Modules/clinic/binascii.c.h M Modules/clinic/grpmodule.c.h M Modules/clinic/itertoolsmodule.c.h M Modules/clinic/posixmodule.c.h M Modules/clinic/pwdmodule.c.h M Modules/clinic/pyexpat.c.h M Modules/clinic/signalmodule.c.h M Modules/clinic/spwdmodule.c.h M Modules/clinic/symtablemodule.c.h M Modules/clinic/unicodedata.c.h M Modules/clinic/zlibmodule.c.h M Objects/clinic/bytearrayobject.c.h M Objects/clinic/bytesobject.c.h M Objects/clinic/codeobject.c.h M Objects/clinic/floatobject.c.h M Objects/clinic/funcobject.c.h M Objects/clinic/longobject.c.h M Objects/clinic/moduleobject.c.h M Objects/clinic/typeobject.c.h M Objects/clinic/unicodeobject.c.h M Objects/stringlib/clinic/transmogrify.h.h M PC/clinic/_testconsole.c.h M PC/clinic/msvcrtmodule.c.h M Python/clinic/bltinmodule.c.h M Python/clinic/import.c.h M Python/clinic/marshal.c.h M Python/clinic/sysmodule.c.h M Python/clinic/traceback.c.h M Python/getargs.c M Tools/clinic/clinic.py diff --git a/Include/modsupport.h b/Include/modsupport.h index 66a5ec839e2a..f90ede4831e3 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -66,7 +66,7 @@ PyAPI_FUNC(int) _PyArg_NoPositional(const char *funcname, PyObject *args); #define _PyArg_NoPositional(funcname, args) \ ((args) == NULL || _PyArg_NoPositional((funcname), (args))) -PyAPI_FUNC(void) _PyArg_BadArgument(const char *, int, const char *, PyObject *); +PyAPI_FUNC(void) _PyArg_BadArgument(const char *, const char *, const char *, PyObject *); PyAPI_FUNC(int) _PyArg_CheckPositional(const char *, Py_ssize_t, Py_ssize_t, Py_ssize_t); #define _PyArg_CheckPositional(funcname, nargs, min, max) \ diff --git a/Lib/test/clinic.test b/Lib/test/clinic.test index ac6f419c0d3a..f9c55e2a577f 100644 --- a/Lib/test/clinic.test +++ b/Lib/test/clinic.test @@ -44,7 +44,7 @@ test_object_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("test_object_converter", 3, "str", args[2]); + _PyArg_BadArgument("test_object_converter", "argument 3", "str", args[2]); goto exit; } c = args[2]; @@ -58,7 +58,7 @@ exit: static PyObject * test_object_converter_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, PyUnicode_Object *d) -/*[clinic end generated code: output=f2c26174b3d46e94 input=005e6a8a711a869b]*/ +/*[clinic end generated code: output=a78312d933df9ea1 input=005e6a8a711a869b]*/ /*[clinic input] @@ -180,52 +180,52 @@ test_object_converter_subclass_of(PyObject *module, PyObject *const *args, Py_ss goto exit; } if (!PyLong_Check(args[0])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 1, "int", args[0]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 1", "int", args[0]); goto exit; } a = args[0]; if (!PyTuple_Check(args[1])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 2, "tuple", args[1]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 2", "tuple", args[1]); goto exit; } b = args[1]; if (!PyList_Check(args[2])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 3, "list", args[2]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 3", "list", args[2]); goto exit; } c = args[2]; if (!PySet_Check(args[3])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 4, "set", args[3]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 4", "set", args[3]); goto exit; } d = args[3]; if (!PyFrozenSet_Check(args[4])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 5, "frozenset", args[4]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 5", "frozenset", args[4]); goto exit; } e = args[4]; if (!PyDict_Check(args[5])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 6, "dict", args[5]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 6", "dict", args[5]); goto exit; } f = args[5]; if (!PyUnicode_Check(args[6])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 7, "str", args[6]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 7", "str", args[6]); goto exit; } g = args[6]; if (!PyBytes_Check(args[7])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 8, "bytes", args[7]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 8", "bytes", args[7]); goto exit; } h = args[7]; if (!PyByteArray_Check(args[8])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 9, "bytearray", args[8]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 9", "bytearray", args[8]); goto exit; } i = args[8]; if (!PyObject_TypeCheck(args[9], &MyType)) { - _PyArg_BadArgument("test_object_converter_subclass_of", 10, (&MyType)->tp_name, args[9]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 10", (&MyType)->tp_name, args[9]); goto exit; } j = args[9]; @@ -240,7 +240,7 @@ test_object_converter_subclass_of_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, PyObject *d, PyObject *e, PyObject *f, PyObject *g, PyObject *h, PyObject *i, PyObject *j) -/*[clinic end generated code: output=99691bda8eeda6d6 input=31b06b772d5f983e]*/ +/*[clinic end generated code: output=dcf7772bf0c876dd input=31b06b772d5f983e]*/ /*[clinic input] @@ -269,7 +269,7 @@ test_PyBytesObject_converter(PyObject *module, PyObject *arg) PyBytesObject *a; if (!PyBytes_Check(arg)) { - _PyArg_BadArgument("test_PyBytesObject_converter", 0, "bytes", arg); + _PyArg_BadArgument("test_PyBytesObject_converter", "argument", "bytes", arg); goto exit; } a = (PyBytesObject *)arg; @@ -281,7 +281,7 @@ exit: static PyObject * test_PyBytesObject_converter_impl(PyObject *module, PyBytesObject *a) -/*[clinic end generated code: output=5d9a301c1df24eb5 input=12b10c7cb5750400]*/ +/*[clinic end generated code: output=7539d628e6fceace input=12b10c7cb5750400]*/ /*[clinic input] @@ -310,7 +310,7 @@ test_PyByteArrayObject_converter(PyObject *module, PyObject *arg) PyByteArrayObject *a; if (!PyByteArray_Check(arg)) { - _PyArg_BadArgument("test_PyByteArrayObject_converter", 0, "bytearray", arg); + _PyArg_BadArgument("test_PyByteArrayObject_converter", "argument", "bytearray", arg); goto exit; } a = (PyByteArrayObject *)arg; @@ -322,7 +322,7 @@ exit: static PyObject * test_PyByteArrayObject_converter_impl(PyObject *module, PyByteArrayObject *a) -/*[clinic end generated code: output=9455d06f4f09637b input=5a657da535d194ae]*/ +/*[clinic end generated code: output=1245af9f5b3e355e input=5a657da535d194ae]*/ /*[clinic input] @@ -351,7 +351,7 @@ test_unicode_converter(PyObject *module, PyObject *arg) PyObject *a; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("test_unicode_converter", 0, "str", arg); + _PyArg_BadArgument("test_unicode_converter", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -366,7 +366,7 @@ exit: static PyObject * test_unicode_converter_impl(PyObject *module, PyObject *a) -/*[clinic end generated code: output=9275c04fe204f4c5 input=aa33612df92aa9c5]*/ +/*[clinic end generated code: output=18f1e3880c862611 input=aa33612df92aa9c5]*/ /*[clinic input] @@ -507,7 +507,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) a = PyByteArray_AS_STRING(args[0])[0]; } else { - _PyArg_BadArgument("test_char_converter", 1, "a byte string of length 1", args[0]); + _PyArg_BadArgument("test_char_converter", "argument 1", "a byte string of length 1", args[0]); goto exit; } if (nargs < 2) { @@ -520,7 +520,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) b = PyByteArray_AS_STRING(args[1])[0]; } else { - _PyArg_BadArgument("test_char_converter", 2, "a byte string of length 1", args[1]); + _PyArg_BadArgument("test_char_converter", "argument 2", "a byte string of length 1", args[1]); goto exit; } if (nargs < 3) { @@ -533,7 +533,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) c = PyByteArray_AS_STRING(args[2])[0]; } else { - _PyArg_BadArgument("test_char_converter", 3, "a byte string of length 1", args[2]); + _PyArg_BadArgument("test_char_converter", "argument 3", "a byte string of length 1", args[2]); goto exit; } if (nargs < 4) { @@ -546,7 +546,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) d = PyByteArray_AS_STRING(args[3])[0]; } else { - _PyArg_BadArgument("test_char_converter", 4, "a byte string of length 1", args[3]); + _PyArg_BadArgument("test_char_converter", "argument 4", "a byte string of length 1", args[3]); goto exit; } if (nargs < 5) { @@ -559,7 +559,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) e = PyByteArray_AS_STRING(args[4])[0]; } else { - _PyArg_BadArgument("test_char_converter", 5, "a byte string of length 1", args[4]); + _PyArg_BadArgument("test_char_converter", "argument 5", "a byte string of length 1", args[4]); goto exit; } if (nargs < 6) { @@ -572,7 +572,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) f = PyByteArray_AS_STRING(args[5])[0]; } else { - _PyArg_BadArgument("test_char_converter", 6, "a byte string of length 1", args[5]); + _PyArg_BadArgument("test_char_converter", "argument 6", "a byte string of length 1", args[5]); goto exit; } if (nargs < 7) { @@ -585,7 +585,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) g = PyByteArray_AS_STRING(args[6])[0]; } else { - _PyArg_BadArgument("test_char_converter", 7, "a byte string of length 1", args[6]); + _PyArg_BadArgument("test_char_converter", "argument 7", "a byte string of length 1", args[6]); goto exit; } if (nargs < 8) { @@ -598,7 +598,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) h = PyByteArray_AS_STRING(args[7])[0]; } else { - _PyArg_BadArgument("test_char_converter", 8, "a byte string of length 1", args[7]); + _PyArg_BadArgument("test_char_converter", "argument 8", "a byte string of length 1", args[7]); goto exit; } if (nargs < 9) { @@ -611,7 +611,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) i = PyByteArray_AS_STRING(args[8])[0]; } else { - _PyArg_BadArgument("test_char_converter", 9, "a byte string of length 1", args[8]); + _PyArg_BadArgument("test_char_converter", "argument 9", "a byte string of length 1", args[8]); goto exit; } if (nargs < 10) { @@ -624,7 +624,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) j = PyByteArray_AS_STRING(args[9])[0]; } else { - _PyArg_BadArgument("test_char_converter", 10, "a byte string of length 1", args[9]); + _PyArg_BadArgument("test_char_converter", "argument 10", "a byte string of length 1", args[9]); goto exit; } if (nargs < 11) { @@ -637,7 +637,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) k = PyByteArray_AS_STRING(args[10])[0]; } else { - _PyArg_BadArgument("test_char_converter", 11, "a byte string of length 1", args[10]); + _PyArg_BadArgument("test_char_converter", "argument 11", "a byte string of length 1", args[10]); goto exit; } if (nargs < 12) { @@ -650,7 +650,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) l = PyByteArray_AS_STRING(args[11])[0]; } else { - _PyArg_BadArgument("test_char_converter", 12, "a byte string of length 1", args[11]); + _PyArg_BadArgument("test_char_converter", "argument 12", "a byte string of length 1", args[11]); goto exit; } if (nargs < 13) { @@ -663,7 +663,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) m = PyByteArray_AS_STRING(args[12])[0]; } else { - _PyArg_BadArgument("test_char_converter", 13, "a byte string of length 1", args[12]); + _PyArg_BadArgument("test_char_converter", "argument 13", "a byte string of length 1", args[12]); goto exit; } if (nargs < 14) { @@ -676,7 +676,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) n = PyByteArray_AS_STRING(args[13])[0]; } else { - _PyArg_BadArgument("test_char_converter", 14, "a byte string of length 1", args[13]); + _PyArg_BadArgument("test_char_converter", "argument 14", "a byte string of length 1", args[13]); goto exit; } skip_optional: @@ -690,7 +690,7 @@ static PyObject * test_char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, char f, char g, char h, char i, char j, char k, char l, char m, char n) -/*[clinic end generated code: output=e041d687555e0a5d input=e42330417a44feac]*/ +/*[clinic end generated code: output=9d3aaf5d6857ec9e input=e42330417a44feac]*/ /*[clinic input] @@ -1009,14 +1009,14 @@ test_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("test_int_converter", 3, "a unicode character", args[2]); + _PyArg_BadArgument("test_int_converter", "argument 3", "a unicode character", args[2]); goto exit; } if (PyUnicode_READY(args[2])) { goto exit; } if (PyUnicode_GET_LENGTH(args[2]) != 1) { - _PyArg_BadArgument("test_int_converter", 3, "a unicode character", args[2]); + _PyArg_BadArgument("test_int_converter", "argument 3", "a unicode character", args[2]); goto exit; } c = PyUnicode_READ_CHAR(args[2], 0); @@ -1041,7 +1041,7 @@ exit: static PyObject * test_int_converter_impl(PyObject *module, int a, int b, int c, myenum d) -/*[clinic end generated code: output=de74e24e85a669a5 input=d20541fc1ca0553e]*/ +/*[clinic end generated code: output=10a2e48a34af5d7a input=d20541fc1ca0553e]*/ /*[clinic input] @@ -1215,7 +1215,7 @@ test_unsigned_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t goto skip_optional; } if (!PyLong_Check(args[2])) { - _PyArg_BadArgument("test_unsigned_long_converter", 3, "int", args[2]); + _PyArg_BadArgument("test_unsigned_long_converter", "argument 3", "int", args[2]); goto exit; } c = PyLong_AsUnsignedLongMask(args[2]); @@ -1229,7 +1229,7 @@ exit: static PyObject * test_unsigned_long_converter_impl(PyObject *module, unsigned long a, unsigned long b, unsigned long c) -/*[clinic end generated code: output=1c05c871c0309e08 input=f450d94cae1ef73b]*/ +/*[clinic end generated code: output=87c6b29fa217026e input=f450d94cae1ef73b]*/ /*[clinic input] @@ -1335,7 +1335,7 @@ test_unsigned_long_long_converter(PyObject *module, PyObject *const *args, Py_ss goto skip_optional; } if (!PyLong_Check(args[2])) { - _PyArg_BadArgument("test_unsigned_long_long_converter", 3, "int", args[2]); + _PyArg_BadArgument("test_unsigned_long_long_converter", "argument 3", "int", args[2]); goto exit; } c = PyLong_AsUnsignedLongLongMask(args[2]); @@ -1351,7 +1351,7 @@ test_unsigned_long_long_converter_impl(PyObject *module, unsigned long long a, unsigned long long b, unsigned long long c) -/*[clinic end generated code: output=0a9b17fb824e28eb input=a15115dc41866ff4]*/ +/*[clinic end generated code: output=aad2c7b43db2f190 input=a15115dc41866ff4]*/ /*[clinic input] @@ -3207,3 +3207,56 @@ test_posonly_opt_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *d, PyObject *e, PyObject *f) /*[clinic end generated code: output=719e4f6c224402d4 input=9914857713c5bbf8]*/ + +/*[clinic input] +test_keyword_only_parameter + + + * + co_lnotab: PyBytesObject(c_default="(PyBytesObject *)self->co_lnotab") = None + +[clinic start generated code]*/ + +PyDoc_STRVAR(test_keyword_only_parameter__doc__, +"test_keyword_only_parameter($module, /, *, co_lnotab=None)\n" +"--\n" +"\n"); + +#define TEST_KEYWORD_ONLY_PARAMETER_METHODDEF \ + {"test_keyword_only_parameter", (PyCFunction)(void(*)(void))test_keyword_only_parameter, METH_FASTCALL|METH_KEYWORDS, test_keyword_only_parameter__doc__}, + +static PyObject * +test_keyword_only_parameter_impl(PyObject *module, PyBytesObject *co_lnotab); + +static PyObject * +test_keyword_only_parameter(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"co_lnotab", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "test_keyword_only_parameter", 0}; + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyBytesObject *co_lnotab = (PyBytesObject *)self->co_lnotab; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!PyBytes_Check(args[0])) { + _PyArg_BadArgument("test_keyword_only_parameter", "argument 'co_lnotab'", "bytes", args[0]); + goto exit; + } + co_lnotab = (PyBytesObject *)args[0]; +skip_optional_kwonly: + return_value = test_keyword_only_parameter_impl(module, co_lnotab); + +exit: + return return_value; +} + +static PyObject * +test_keyword_only_parameter_impl(PyObject *module, PyBytesObject *co_lnotab) +/*[clinic end generated code: output=f25914b402039493 input=303df5046c7e37a3]*/ diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index 082d85a3d2b9..a0ba59008ece 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -286,7 +286,7 @@ def test_illegal(self): self.fail() except TypeError as e: self.assertEqual(str(e), - 'ParserCreate() argument 2 must be str or None, not int') + "ParserCreate() argument 'namespace_separator' must be str or None, not int") try: expat.ParserCreate(namespace_separator='too long') diff --git a/Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst b/Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst new file mode 100644 index 000000000000..3457789635b4 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst @@ -0,0 +1,2 @@ +Argument Clinic now uses the argument name on errors with keyword-only +argument instead of their position. Patch contributed by R?mi Lapeyre. diff --git a/Modules/_blake2/clinic/blake2b_impl.c.h b/Modules/_blake2/clinic/blake2b_impl.c.h index 09fe00457f35..cd329c07c999 100644 --- a/Modules/_blake2/clinic/blake2b_impl.c.h +++ b/Modules/_blake2/clinic/blake2b_impl.c.h @@ -72,7 +72,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&key, 'C')) { - _PyArg_BadArgument("blake2b", 3, "contiguous buffer", fastargs[2]); + _PyArg_BadArgument("blake2b", "argument 'key'", "contiguous buffer", fastargs[2]); goto exit; } if (!--noptargs) { @@ -84,7 +84,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("blake2b", 4, "contiguous buffer", fastargs[3]); + _PyArg_BadArgument("blake2b", "argument 'salt'", "contiguous buffer", fastargs[3]); goto exit; } if (!--noptargs) { @@ -96,7 +96,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&person, 'C')) { - _PyArg_BadArgument("blake2b", 5, "contiguous buffer", fastargs[4]); + _PyArg_BadArgument("blake2b", "argument 'person'", "contiguous buffer", fastargs[4]); goto exit; } if (!--noptargs) { @@ -261,4 +261,4 @@ _blake2_blake2b_hexdigest(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2_blake2b_hexdigest_impl(self); } -/*[clinic end generated code: output=a91d182ce1109f34 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cbb625d7f60c288c input=a9049054013a1b77]*/ diff --git a/Modules/_blake2/clinic/blake2s_impl.c.h b/Modules/_blake2/clinic/blake2s_impl.c.h index 92739a1feb32..560bd68160b0 100644 --- a/Modules/_blake2/clinic/blake2s_impl.c.h +++ b/Modules/_blake2/clinic/blake2s_impl.c.h @@ -72,7 +72,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&key, 'C')) { - _PyArg_BadArgument("blake2s", 3, "contiguous buffer", fastargs[2]); + _PyArg_BadArgument("blake2s", "argument 'key'", "contiguous buffer", fastargs[2]); goto exit; } if (!--noptargs) { @@ -84,7 +84,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("blake2s", 4, "contiguous buffer", fastargs[3]); + _PyArg_BadArgument("blake2s", "argument 'salt'", "contiguous buffer", fastargs[3]); goto exit; } if (!--noptargs) { @@ -96,7 +96,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&person, 'C')) { - _PyArg_BadArgument("blake2s", 5, "contiguous buffer", fastargs[4]); + _PyArg_BadArgument("blake2s", "argument 'person'", "contiguous buffer", fastargs[4]); goto exit; } if (!--noptargs) { @@ -261,4 +261,4 @@ _blake2_blake2s_hexdigest(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2_blake2s_hexdigest_impl(self); } -/*[clinic end generated code: output=ae8e9b7301d092b4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=39af5a74c8805b36 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/_iomodule.c.h b/Modules/_io/clinic/_iomodule.c.h index 00ad616b41fe..1a9651d34081 100644 --- a/Modules/_io/clinic/_iomodule.c.h +++ b/Modules/_io/clinic/_iomodule.c.h @@ -161,7 +161,7 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } if (args[1]) { if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("open", 2, "str", args[1]); + _PyArg_BadArgument("open", "argument 'mode'", "str", args[1]); goto exit; } Py_ssize_t mode_length; @@ -207,7 +207,7 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } } else { - _PyArg_BadArgument("open", 4, "str or None", args[3]); + _PyArg_BadArgument("open", "argument 'encoding'", "str or None", args[3]); goto exit; } if (!--noptargs) { @@ -230,7 +230,7 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } } else { - _PyArg_BadArgument("open", 5, "str or None", args[4]); + _PyArg_BadArgument("open", "argument 'errors'", "str or None", args[4]); goto exit; } if (!--noptargs) { @@ -253,7 +253,7 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } } else { - _PyArg_BadArgument("open", 6, "str or None", args[5]); + _PyArg_BadArgument("open", "argument 'newline'", "str or None", args[5]); goto exit; } if (!--noptargs) { @@ -311,7 +311,7 @@ _io_open_code(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("open_code", 1, "str", args[0]); + _PyArg_BadArgument("open_code", "argument 'path'", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -323,4 +323,4 @@ _io_open_code(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=d479285078750d68 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3df6bc6d91697545 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h index d5e8c8a74813..72841fcb6779 100644 --- a/Modules/_io/clinic/bufferedio.c.h +++ b/Modules/_io/clinic/bufferedio.c.h @@ -21,11 +21,11 @@ _io__BufferedIOBase_readinto(PyObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__BufferedIOBase_readinto_impl(self, &buffer); @@ -58,11 +58,11 @@ _io__BufferedIOBase_readinto1(PyObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto1", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto1", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto1", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto1", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__BufferedIOBase_readinto1_impl(self, &buffer); @@ -243,11 +243,11 @@ _io__Buffered_readinto(buffered *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__Buffered_readinto_impl(self, &buffer); @@ -280,11 +280,11 @@ _io__Buffered_readinto1(buffered *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto1", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto1", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto1", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto1", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__Buffered_readinto1_impl(self, &buffer); @@ -538,7 +538,7 @@ _io_BufferedWriter_write(buffered *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("write", 0, "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); goto exit; } return_value = _io_BufferedWriter_write_impl(self, &buffer); @@ -672,4 +672,4 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=b22b4aedd53c340a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7246104f6c7d3167 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bytesio.c.h b/Modules/_io/clinic/bytesio.c.h index 8dd68f56137f..83cd490dc598 100644 --- a/Modules/_io/clinic/bytesio.c.h +++ b/Modules/_io/clinic/bytesio.c.h @@ -319,11 +319,11 @@ _io_BytesIO_readinto(bytesio *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); goto exit; } return_value = _io_BytesIO_readinto_impl(self, &buffer); @@ -515,4 +515,4 @@ _io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=22e8fb54874b6ee5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4ec2506def9c8eb9 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/fileio.c.h b/Modules/_io/clinic/fileio.c.h index 8016e9888624..64addde57f3e 100644 --- a/Modules/_io/clinic/fileio.c.h +++ b/Modules/_io/clinic/fileio.c.h @@ -70,7 +70,7 @@ _io_FileIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) } if (fastargs[1]) { if (!PyUnicode_Check(fastargs[1])) { - _PyArg_BadArgument("FileIO", 2, "str", fastargs[1]); + _PyArg_BadArgument("FileIO", "argument 'mode'", "str", fastargs[1]); goto exit; } Py_ssize_t mode_length; @@ -200,11 +200,11 @@ _io_FileIO_readinto(fileio *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); goto exit; } return_value = _io_FileIO_readinto_impl(self, &buffer); @@ -303,7 +303,7 @@ _io_FileIO_write(fileio *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", 0, "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); goto exit; } return_value = _io_FileIO_write_impl(self, &b); @@ -447,4 +447,4 @@ _io_FileIO_isatty(fileio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO_FILEIO_TRUNCATE_METHODDEF #define _IO_FILEIO_TRUNCATE_METHODDEF #endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */ -/*[clinic end generated code: output=7ee4f3ae584fc6d2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a7e9cca3613660fb input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h index cec9defea025..b8b507543ea8 100644 --- a/Modules/_io/clinic/textio.c.h +++ b/Modules/_io/clinic/textio.c.h @@ -229,7 +229,7 @@ _io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs) } } else { - _PyArg_BadArgument("TextIOWrapper", 2, "str or None", fastargs[1]); + _PyArg_BadArgument("TextIOWrapper", "argument 'encoding'", "str or None", fastargs[1]); goto exit; } if (!--noptargs) { @@ -258,7 +258,7 @@ _io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs) } } else { - _PyArg_BadArgument("TextIOWrapper", 4, "str or None", fastargs[3]); + _PyArg_BadArgument("TextIOWrapper", "argument 'newline'", "str or None", fastargs[3]); goto exit; } if (!--noptargs) { @@ -401,7 +401,7 @@ _io_TextIOWrapper_write(textio *self, PyObject *arg) PyObject *text; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("write", 0, "str", arg); + _PyArg_BadArgument("write", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -701,4 +701,4 @@ _io_TextIOWrapper_close(textio *self, PyObject *Py_UNUSED(ignored)) { return _io_TextIOWrapper_close_impl(self); } -/*[clinic end generated code: output=b651e056e3000f88 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b1bae4f4cdf6019e input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/winconsoleio.c.h b/Modules/_io/clinic/winconsoleio.c.h index bb0cdc4558dd..3e501a585371 100644 --- a/Modules/_io/clinic/winconsoleio.c.h +++ b/Modules/_io/clinic/winconsoleio.c.h @@ -69,7 +69,7 @@ _io__WindowsConsoleIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) } if (fastargs[1]) { if (!PyUnicode_Check(fastargs[1])) { - _PyArg_BadArgument("_WindowsConsoleIO", 2, "str", fastargs[1]); + _PyArg_BadArgument("_WindowsConsoleIO", "argument 'mode'", "str", fastargs[1]); goto exit; } Py_ssize_t mode_length; @@ -200,11 +200,11 @@ _io__WindowsConsoleIO_readinto(winconsoleio *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__WindowsConsoleIO_readinto_impl(self, &buffer); @@ -313,7 +313,7 @@ _io__WindowsConsoleIO_write(winconsoleio *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", 0, "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__WindowsConsoleIO_write_impl(self, &b); @@ -386,4 +386,4 @@ _io__WindowsConsoleIO_isatty(winconsoleio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #define _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #endif /* !defined(_IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF) */ -/*[clinic end generated code: output=57bf2c09a42bd330 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f5b8860a658a001a input=a9049054013a1b77]*/ diff --git a/Modules/_multiprocessing/clinic/posixshmem.c.h b/Modules/_multiprocessing/clinic/posixshmem.c.h index 0ebfa2fe3789..a99f0d2aae1d 100644 --- a/Modules/_multiprocessing/clinic/posixshmem.c.h +++ b/Modules/_multiprocessing/clinic/posixshmem.c.h @@ -35,7 +35,7 @@ _posixshmem_shm_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("shm_open", 1, "str", args[0]); + _PyArg_BadArgument("shm_open", "argument 'path'", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -108,7 +108,7 @@ _posixshmem_shm_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("shm_unlink", 1, "str", args[0]); + _PyArg_BadArgument("shm_unlink", "argument 'path'", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -130,4 +130,4 @@ _posixshmem_shm_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs #ifndef _POSIXSHMEM_SHM_UNLINK_METHODDEF #define _POSIXSHMEM_SHM_UNLINK_METHODDEF #endif /* !defined(_POSIXSHMEM_SHM_UNLINK_METHODDEF) */ -/*[clinic end generated code: output=be42e23c18677c0f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9132861c61d8c2d8 input=a9049054013a1b77]*/ diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h index 84774f007600..5ddbbe221b98 100644 --- a/Modules/cjkcodecs/clinic/multibytecodec.c.h +++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h @@ -55,7 +55,7 @@ _multibytecodec_MultibyteCodec_encode(MultibyteCodecObject *self, PyObject *cons } } else { - _PyArg_BadArgument("encode", 2, "str or None", args[1]); + _PyArg_BadArgument("encode", "argument 'errors'", "str or None", args[1]); goto exit; } skip_optional_pos: @@ -103,7 +103,7 @@ _multibytecodec_MultibyteCodec_decode(MultibyteCodecObject *self, PyObject *cons goto exit; } if (!PyBuffer_IsContiguous(&input, 'C')) { - _PyArg_BadArgument("decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decode", "argument 'input'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -124,7 +124,7 @@ _multibytecodec_MultibyteCodec_decode(MultibyteCodecObject *self, PyObject *cons } } else { - _PyArg_BadArgument("decode", 2, "str or None", args[1]); + _PyArg_BadArgument("decode", "argument 'errors'", "str or None", args[1]); goto exit; } skip_optional_pos: @@ -223,7 +223,7 @@ _multibytecodec_MultibyteIncrementalEncoder_setstate(MultibyteIncrementalEncoder PyLongObject *statelong; if (!PyLong_Check(arg)) { - _PyArg_BadArgument("setstate", 0, "int", arg); + _PyArg_BadArgument("setstate", "argument", "int", arg); goto exit; } statelong = (PyLongObject *)arg; @@ -282,7 +282,7 @@ _multibytecodec_MultibyteIncrementalDecoder_decode(MultibyteIncrementalDecoderOb goto exit; } if (!PyBuffer_IsContiguous(&input, 'C')) { - _PyArg_BadArgument("decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decode", "argument 'input'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -345,7 +345,7 @@ _multibytecodec_MultibyteIncrementalDecoder_setstate(MultibyteIncrementalDecoder PyObject *state; if (!PyTuple_Check(arg)) { - _PyArg_BadArgument("setstate", 0, "tuple", arg); + _PyArg_BadArgument("setstate", "argument", "tuple", arg); goto exit; } state = arg; @@ -525,4 +525,4 @@ PyDoc_STRVAR(_multibytecodec___create_codec__doc__, #define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \ {"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__}, -/*[clinic end generated code: output=eb95a408c4ddbfff input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5ce6fd4ca1f95620 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_bz2module.c.h b/Modules/clinic/_bz2module.c.h index cc16d8bb228f..ac826bd9b598 100644 --- a/Modules/clinic/_bz2module.c.h +++ b/Modules/clinic/_bz2module.c.h @@ -29,7 +29,7 @@ _bz2_BZ2Compressor_compress(BZ2Compressor *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", 0, "contiguous buffer", arg); + _PyArg_BadArgument("compress", "argument", "contiguous buffer", arg); goto exit; } return_value = _bz2_BZ2Compressor_compress_impl(self, &data); @@ -156,7 +156,7 @@ _bz2_BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject *const *args, Py goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decompress", "argument 'data'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -220,4 +220,4 @@ _bz2_BZ2Decompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=8e123f4eec497655 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ec3d1b3652c98823 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h index 65e24832fff6..be1d2f70cf1b 100644 --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -34,7 +34,7 @@ _codecs_lookup(PyObject *module, PyObject *arg) const char *encoding; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("lookup", 0, "str", arg); + _PyArg_BadArgument("lookup", "argument", "str", arg); goto exit; } Py_ssize_t encoding_length; @@ -93,7 +93,7 @@ _codecs_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[1]) { if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("encode", 2, "str", args[1]); + _PyArg_BadArgument("encode", "argument 'encoding'", "str", args[1]); goto exit; } Py_ssize_t encoding_length; @@ -110,7 +110,7 @@ _codecs_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("encode", 3, "str", args[2]); + _PyArg_BadArgument("encode", "argument 'errors'", "str", args[2]); goto exit; } Py_ssize_t errors_length; @@ -170,7 +170,7 @@ _codecs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[1]) { if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("decode", 2, "str", args[1]); + _PyArg_BadArgument("decode", "argument 'encoding'", "str", args[1]); goto exit; } Py_ssize_t encoding_length; @@ -187,7 +187,7 @@ _codecs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("decode", 3, "str", args[2]); + _PyArg_BadArgument("decode", "argument 'errors'", "str", args[2]); goto exit; } Py_ssize_t errors_length; @@ -225,7 +225,7 @@ _codecs__forget_codec(PyObject *module, PyObject *arg) const char *encoding; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("_forget_codec", 0, "str", arg); + _PyArg_BadArgument("_forget_codec", "argument", "str", arg); goto exit; } Py_ssize_t encoding_length; @@ -278,7 +278,7 @@ _codecs_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("escape_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("escape_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } } @@ -300,7 +300,7 @@ _codecs_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("escape_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("escape_decode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -338,7 +338,7 @@ _codecs_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBytes_Check(args[0])) { - _PyArg_BadArgument("escape_encode", 1, "bytes", args[0]); + _PyArg_BadArgument("escape_encode", "argument 1", "bytes", args[0]); goto exit; } data = args[0]; @@ -360,7 +360,7 @@ _codecs_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("escape_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("escape_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -397,7 +397,7 @@ _codecs_utf_7_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_7_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_7_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -418,7 +418,7 @@ _codecs_utf_7_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_7_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_7_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -472,7 +472,7 @@ _codecs_utf_8_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_8_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_8_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -493,7 +493,7 @@ _codecs_utf_8_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_8_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_8_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -547,7 +547,7 @@ _codecs_utf_16_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_16_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -568,7 +568,7 @@ _codecs_utf_16_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_16_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -622,7 +622,7 @@ _codecs_utf_16_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_le_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_16_le_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -643,7 +643,7 @@ _codecs_utf_16_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_16_le_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_le_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -697,7 +697,7 @@ _codecs_utf_16_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_be_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_16_be_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -718,7 +718,7 @@ _codecs_utf_16_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_16_be_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_be_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -774,7 +774,7 @@ _codecs_utf_16_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_ex_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_16_ex_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -795,7 +795,7 @@ _codecs_utf_16_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_16_ex_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_ex_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -861,7 +861,7 @@ _codecs_utf_32_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_32_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -882,7 +882,7 @@ _codecs_utf_32_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_32_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -936,7 +936,7 @@ _codecs_utf_32_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_le_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_32_le_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -957,7 +957,7 @@ _codecs_utf_32_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_32_le_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_le_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1011,7 +1011,7 @@ _codecs_utf_32_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_be_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_32_be_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1032,7 +1032,7 @@ _codecs_utf_32_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_32_be_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_be_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1088,7 +1088,7 @@ _codecs_utf_32_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_ex_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_32_ex_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1109,7 +1109,7 @@ _codecs_utf_32_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_32_ex_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_ex_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1183,7 +1183,7 @@ _codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_ goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("unicode_escape_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("unicode_escape_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } } @@ -1205,7 +1205,7 @@ _codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_ } } else { - _PyArg_BadArgument("unicode_escape_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("unicode_escape_decode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1255,7 +1255,7 @@ _codecs_raw_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ss goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("raw_unicode_escape_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("raw_unicode_escape_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } } @@ -1277,7 +1277,7 @@ _codecs_raw_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ss } } else { - _PyArg_BadArgument("raw_unicode_escape_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("raw_unicode_escape_decode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1318,7 +1318,7 @@ _codecs_latin_1_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("latin_1_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("latin_1_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1339,7 +1339,7 @@ _codecs_latin_1_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs } } else { - _PyArg_BadArgument("latin_1_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("latin_1_decode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1380,7 +1380,7 @@ _codecs_ascii_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("ascii_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("ascii_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1401,7 +1401,7 @@ _codecs_ascii_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("ascii_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("ascii_decode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1443,7 +1443,7 @@ _codecs_charmap_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("charmap_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("charmap_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1464,7 +1464,7 @@ _codecs_charmap_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs } } else { - _PyArg_BadArgument("charmap_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("charmap_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1512,7 +1512,7 @@ _codecs_mbcs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("mbcs_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("mbcs_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1533,7 +1533,7 @@ _codecs_mbcs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("mbcs_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("mbcs_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1591,7 +1591,7 @@ _codecs_oem_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("oem_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("oem_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1612,7 +1612,7 @@ _codecs_oem_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("oem_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("oem_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1680,7 +1680,7 @@ _codecs_code_page_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("code_page_decode", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("code_page_decode", "argument 2", "contiguous buffer", args[1]); goto exit; } if (nargs < 3) { @@ -1701,7 +1701,7 @@ _codecs_code_page_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("code_page_decode", 3, "str or None", args[2]); + _PyArg_BadArgument("code_page_decode", "argument 3", "str or None", args[2]); goto exit; } if (nargs < 4) { @@ -1765,7 +1765,7 @@ _codecs_readbuffer_encode(PyObject *module, PyObject *const *args, Py_ssize_t na goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("readbuffer_encode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("readbuffer_encode", "argument 1", "contiguous buffer", args[0]); goto exit; } } @@ -1787,7 +1787,7 @@ _codecs_readbuffer_encode(PyObject *module, PyObject *const *args, Py_ssize_t na } } else { - _PyArg_BadArgument("readbuffer_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("readbuffer_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1825,7 +1825,7 @@ _codecs_utf_7_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_7_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_7_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -1850,7 +1850,7 @@ _codecs_utf_7_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_7_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_7_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1883,7 +1883,7 @@ _codecs_utf_8_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_8_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_8_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -1908,7 +1908,7 @@ _codecs_utf_8_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_8_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_8_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1942,7 +1942,7 @@ _codecs_utf_16_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_16_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_16_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -1967,7 +1967,7 @@ _codecs_utf_16_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_16_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_encode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -2012,7 +2012,7 @@ _codecs_utf_16_le_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_16_le_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_16_le_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2037,7 +2037,7 @@ _codecs_utf_16_le_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_16_le_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_le_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2070,7 +2070,7 @@ _codecs_utf_16_be_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_16_be_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_16_be_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2095,7 +2095,7 @@ _codecs_utf_16_be_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_16_be_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_be_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2129,7 +2129,7 @@ _codecs_utf_32_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_32_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_32_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2154,7 +2154,7 @@ _codecs_utf_32_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_32_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_encode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -2199,7 +2199,7 @@ _codecs_utf_32_le_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_32_le_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_32_le_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2224,7 +2224,7 @@ _codecs_utf_32_le_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_32_le_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_le_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2257,7 +2257,7 @@ _codecs_utf_32_be_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_32_be_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_32_be_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2282,7 +2282,7 @@ _codecs_utf_32_be_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_32_be_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_be_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2315,7 +2315,7 @@ _codecs_unicode_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_ goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("unicode_escape_encode", 1, "str", args[0]); + _PyArg_BadArgument("unicode_escape_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2340,7 +2340,7 @@ _codecs_unicode_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_ } } else { - _PyArg_BadArgument("unicode_escape_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("unicode_escape_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2373,7 +2373,7 @@ _codecs_raw_unicode_escape_encode(PyObject *module, PyObject *const *args, Py_ss goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("raw_unicode_escape_encode", 1, "str", args[0]); + _PyArg_BadArgument("raw_unicode_escape_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2398,7 +2398,7 @@ _codecs_raw_unicode_escape_encode(PyObject *module, PyObject *const *args, Py_ss } } else { - _PyArg_BadArgument("raw_unicode_escape_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("raw_unicode_escape_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2431,7 +2431,7 @@ _codecs_latin_1_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("latin_1_encode", 1, "str", args[0]); + _PyArg_BadArgument("latin_1_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2456,7 +2456,7 @@ _codecs_latin_1_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs } } else { - _PyArg_BadArgument("latin_1_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("latin_1_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2489,7 +2489,7 @@ _codecs_ascii_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("ascii_encode", 1, "str", args[0]); + _PyArg_BadArgument("ascii_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2514,7 +2514,7 @@ _codecs_ascii_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("ascii_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("ascii_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2548,7 +2548,7 @@ _codecs_charmap_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("charmap_encode", 1, "str", args[0]); + _PyArg_BadArgument("charmap_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2573,7 +2573,7 @@ _codecs_charmap_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs } } else { - _PyArg_BadArgument("charmap_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("charmap_encode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -2605,7 +2605,7 @@ _codecs_charmap_build(PyObject *module, PyObject *arg) PyObject *map; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("charmap_build", 0, "str", arg); + _PyArg_BadArgument("charmap_build", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -2642,7 +2642,7 @@ _codecs_mbcs_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("mbcs_encode", 1, "str", args[0]); + _PyArg_BadArgument("mbcs_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2667,7 +2667,7 @@ _codecs_mbcs_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("mbcs_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("mbcs_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2703,7 +2703,7 @@ _codecs_oem_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("oem_encode", 1, "str", args[0]); + _PyArg_BadArgument("oem_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2728,7 +2728,7 @@ _codecs_oem_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("oem_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("oem_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2775,7 +2775,7 @@ _codecs_code_page_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("code_page_encode", 2, "str", args[1]); + _PyArg_BadArgument("code_page_encode", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -2800,7 +2800,7 @@ _codecs_code_page_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("code_page_encode", 3, "str or None", args[2]); + _PyArg_BadArgument("code_page_encode", "argument 3", "str or None", args[2]); goto exit; } skip_optional: @@ -2840,7 +2840,7 @@ _codecs_register_error(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("register_error", 1, "str", args[0]); + _PyArg_BadArgument("register_error", "argument 1", "str", args[0]); goto exit; } Py_ssize_t errors_length; @@ -2881,7 +2881,7 @@ _codecs_lookup_error(PyObject *module, PyObject *arg) const char *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("lookup_error", 0, "str", arg); + _PyArg_BadArgument("lookup_error", "argument", "str", arg); goto exit; } Py_ssize_t name_length; @@ -2922,4 +2922,4 @@ _codecs_lookup_error(PyObject *module, PyObject *arg) #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=da3c47709a55a05e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=59726a305e4ec24a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_cryptmodule.c.h b/Modules/clinic/_cryptmodule.c.h index 2fcb0c1bf12c..ea91d7c130b8 100644 --- a/Modules/clinic/_cryptmodule.c.h +++ b/Modules/clinic/_cryptmodule.c.h @@ -30,7 +30,7 @@ crypt_crypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("crypt", 1, "str", args[0]); + _PyArg_BadArgument("crypt", "argument 1", "str", args[0]); goto exit; } Py_ssize_t word_length; @@ -43,7 +43,7 @@ crypt_crypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("crypt", 2, "str", args[1]); + _PyArg_BadArgument("crypt", "argument 2", "str", args[1]); goto exit; } Py_ssize_t salt_length; @@ -60,4 +60,4 @@ crypt_crypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=3f75d4d4be4dddbb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=549de0d43b030126 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_curses_panel.c.h b/Modules/clinic/_curses_panel.c.h index 0df442056ea9..9840ed86e791 100644 --- a/Modules/clinic/_curses_panel.c.h +++ b/Modules/clinic/_curses_panel.c.h @@ -214,7 +214,7 @@ _curses_panel_panel_replace(PyCursesPanelObject *self, PyObject *arg) PyCursesWindowObject *win; if (!PyObject_TypeCheck(arg, &PyCursesWindow_Type)) { - _PyArg_BadArgument("replace", 0, (&PyCursesWindow_Type)->tp_name, arg); + _PyArg_BadArgument("replace", "argument", (&PyCursesWindow_Type)->tp_name, arg); goto exit; } win = (PyCursesWindowObject *)arg; @@ -288,7 +288,7 @@ _curses_panel_new_panel(PyObject *module, PyObject *arg) PyCursesWindowObject *win; if (!PyObject_TypeCheck(arg, &PyCursesWindow_Type)) { - _PyArg_BadArgument("new_panel", 0, (&PyCursesWindow_Type)->tp_name, arg); + _PyArg_BadArgument("new_panel", "argument", (&PyCursesWindow_Type)->tp_name, arg); goto exit; } win = (PyCursesWindowObject *)arg; @@ -335,4 +335,4 @@ _curses_panel_update_panels(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _curses_panel_update_panels_impl(module); } -/*[clinic end generated code: output=3cc16062281b7e07 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d96dc1fd68e898d9 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index 6837eac39096..ad93e6a0ca02 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -2521,7 +2521,7 @@ _curses_ungetmouse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyLong_Check(args[4])) { - _PyArg_BadArgument("ungetmouse", 5, "int", args[4]); + _PyArg_BadArgument("ungetmouse", "argument 5", "int", args[4]); goto exit; } bstate = PyLong_AsUnsignedLongMask(args[4]); @@ -3017,7 +3017,7 @@ _curses_setupterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO } } else { - _PyArg_BadArgument("setupterm", 1, "str or None", args[0]); + _PyArg_BadArgument("setupterm", "argument 'term'", "str or None", args[0]); goto exit; } if (!--noptargs) { @@ -3326,7 +3326,7 @@ _curses_mousemask(PyObject *module, PyObject *arg) unsigned long newmask; if (!PyLong_Check(arg)) { - _PyArg_BadArgument("mousemask", 0, "int", arg); + _PyArg_BadArgument("mousemask", "argument", "int", arg); goto exit; } newmask = PyLong_AsUnsignedLongMask(arg); @@ -4201,7 +4201,7 @@ _curses_tigetflag(PyObject *module, PyObject *arg) const char *capname; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("tigetflag", 0, "str", arg); + _PyArg_BadArgument("tigetflag", "argument", "str", arg); goto exit; } Py_ssize_t capname_length; @@ -4244,7 +4244,7 @@ _curses_tigetnum(PyObject *module, PyObject *arg) const char *capname; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("tigetnum", 0, "str", arg); + _PyArg_BadArgument("tigetnum", "argument", "str", arg); goto exit; } Py_ssize_t capname_length; @@ -4287,7 +4287,7 @@ _curses_tigetstr(PyObject *module, PyObject *arg) const char *capname; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("tigetstr", 0, "str", arg); + _PyArg_BadArgument("tigetstr", "argument", "str", arg); goto exit; } Py_ssize_t capname_length; @@ -4569,4 +4569,4 @@ _curses_use_default_colors(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF #define _CURSES_USE_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=1350eeb0c1e06af6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e5b3502f1d38dff0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h index e54c69cf7082..a7d735085068 100644 --- a/Modules/clinic/_dbmmodule.c.h +++ b/Modules/clinic/_dbmmodule.c.h @@ -136,7 +136,7 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("open", 1, "str", args[0]); + _PyArg_BadArgument("open", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -147,7 +147,7 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("open", 2, "str", args[1]); + _PyArg_BadArgument("open", "argument 2", "str", args[1]); goto exit; } Py_ssize_t flags_length; @@ -177,4 +177,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=7f5d30ef5d820b8a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7ced103488cbca7a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h index 0f55480140b3..324e549d486a 100644 --- a/Modules/clinic/_elementtree.c.h +++ b/Modules/clinic/_elementtree.c.h @@ -20,7 +20,7 @@ _elementtree_Element_append(ElementObject *self, PyObject *arg) PyObject *subelement; if (!PyObject_TypeCheck(arg, &Element_Type)) { - _PyArg_BadArgument("append", 0, (&Element_Type)->tp_name, arg); + _PyArg_BadArgument("append", "argument", (&Element_Type)->tp_name, arg); goto exit; } subelement = arg; @@ -82,7 +82,7 @@ _elementtree_Element___deepcopy__(ElementObject *self, PyObject *arg) PyObject *memo; if (!PyDict_Check(arg)) { - _PyArg_BadArgument("__deepcopy__", 0, "dict", arg); + _PyArg_BadArgument("__deepcopy__", "argument", "dict", arg); goto exit; } memo = arg; @@ -501,7 +501,7 @@ _elementtree_Element_insert(ElementObject *self, PyObject *const *args, Py_ssize index = ival; } if (!PyObject_TypeCheck(args[1], &Element_Type)) { - _PyArg_BadArgument("insert", 2, (&Element_Type)->tp_name, args[1]); + _PyArg_BadArgument("insert", "argument 2", (&Element_Type)->tp_name, args[1]); goto exit; } subelement = args[1]; @@ -593,7 +593,7 @@ _elementtree_Element_remove(ElementObject *self, PyObject *arg) PyObject *subelement; if (!PyObject_TypeCheck(arg, &Element_Type)) { - _PyArg_BadArgument("remove", 0, (&Element_Type)->tp_name, arg); + _PyArg_BadArgument("remove", "argument", (&Element_Type)->tp_name, arg); goto exit; } subelement = arg; @@ -892,7 +892,7 @@ _elementtree_XMLParser___init__(PyObject *self, PyObject *args, PyObject *kwargs } } else { - _PyArg_BadArgument("XMLParser", 2, "str or None", fastargs[1]); + _PyArg_BadArgument("XMLParser", "argument 'encoding'", "str or None", fastargs[1]); goto exit; } skip_optional_kwonly: @@ -969,4 +969,4 @@ _elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=386a68425d072b5c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=50e0b1954c5f9e0f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h index 15f47dc70dc6..aa37a24d3b21 100644 --- a/Modules/clinic/_gdbmmodule.c.h +++ b/Modules/clinic/_gdbmmodule.c.h @@ -257,7 +257,7 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("open", 1, "str", args[0]); + _PyArg_BadArgument("open", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -268,7 +268,7 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("open", 2, "str", args[1]); + _PyArg_BadArgument("open", "argument 2", "str", args[1]); goto exit; } Py_ssize_t flags_length; @@ -298,4 +298,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=0a72598e5a3acd60 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2766471b2fa1a816 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h index 5596f13e508f..6377e18ece7a 100644 --- a/Modules/clinic/_hashopenssl.c.h +++ b/Modules/clinic/_hashopenssl.c.h @@ -145,7 +145,7 @@ pbkdf2_hmac(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("pbkdf2_hmac", 1, "str", args[0]); + _PyArg_BadArgument("pbkdf2_hmac", "argument 'hash_name'", "str", args[0]); goto exit; } Py_ssize_t hash_name_length; @@ -161,14 +161,14 @@ pbkdf2_hmac(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyBuffer_IsContiguous(&password, 'C')) { - _PyArg_BadArgument("pbkdf2_hmac", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("pbkdf2_hmac", "argument 'password'", "contiguous buffer", args[1]); goto exit; } if (PyObject_GetBuffer(args[2], &salt, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("pbkdf2_hmac", 3, "contiguous buffer", args[2]); + _PyArg_BadArgument("pbkdf2_hmac", "argument 'salt'", "contiguous buffer", args[2]); goto exit; } if (PyFloat_Check(args[3])) { @@ -243,7 +243,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyBuffer_IsContiguous(&password, 'C')) { - _PyArg_BadArgument("scrypt", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("scrypt", "argument 'password'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -254,7 +254,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("scrypt", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("scrypt", "argument 'salt'", "contiguous buffer", args[1]); goto exit; } if (!--noptargs) { @@ -263,7 +263,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } if (args[2]) { if (!PyLong_Check(args[2])) { - _PyArg_BadArgument("scrypt", 3, "int", args[2]); + _PyArg_BadArgument("scrypt", "argument 'n'", "int", args[2]); goto exit; } n_obj = args[2]; @@ -273,7 +273,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } if (args[3]) { if (!PyLong_Check(args[3])) { - _PyArg_BadArgument("scrypt", 4, "int", args[3]); + _PyArg_BadArgument("scrypt", "argument 'r'", "int", args[3]); goto exit; } r_obj = args[3]; @@ -283,7 +283,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } if (args[4]) { if (!PyLong_Check(args[4])) { - _PyArg_BadArgument("scrypt", 5, "int", args[4]); + _PyArg_BadArgument("scrypt", "argument 'p'", "int", args[4]); goto exit; } p_obj = args[4]; @@ -364,18 +364,18 @@ _hashlib_hmac_digest(PyObject *module, PyObject *const *args, Py_ssize_t nargs, goto exit; } if (!PyBuffer_IsContiguous(&key, 'C')) { - _PyArg_BadArgument("hmac_digest", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("hmac_digest", "argument 'key'", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &msg, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&msg, 'C')) { - _PyArg_BadArgument("hmac_digest", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("hmac_digest", "argument 'msg'", "contiguous buffer", args[1]); goto exit; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("hmac_digest", 3, "str", args[2]); + _PyArg_BadArgument("hmac_digest", "argument 'digest'", "str", args[2]); goto exit; } Py_ssize_t digest_length; @@ -409,4 +409,4 @@ _hashlib_hmac_digest(PyObject *module, PyObject *const *args, Py_ssize_t nargs, #ifndef _HASHLIB_SCRYPT_METHODDEF #define _HASHLIB_SCRYPT_METHODDEF #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ -/*[clinic end generated code: output=5955ec791260045a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=565dcbe3452e71f4 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_lzmamodule.c.h b/Modules/clinic/_lzmamodule.c.h index 68aa770d41f8..82ef4d517d83 100644 --- a/Modules/clinic/_lzmamodule.c.h +++ b/Modules/clinic/_lzmamodule.c.h @@ -29,7 +29,7 @@ _lzma_LZMACompressor_compress(Compressor *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", 0, "contiguous buffer", arg); + _PyArg_BadArgument("compress", "argument", "contiguous buffer", arg); goto exit; } return_value = _lzma_LZMACompressor_compress_impl(self, &data); @@ -110,7 +110,7 @@ _lzma_LZMADecompressor_decompress(Decompressor *self, PyObject *const *args, Py_ goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decompress", "argument 'data'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -321,7 +321,7 @@ _lzma__decode_filter_properties(PyObject *module, PyObject *const *args, Py_ssiz goto exit; } if (!PyBuffer_IsContiguous(&encoded_props, 'C')) { - _PyArg_BadArgument("_decode_filter_properties", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("_decode_filter_properties", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = _lzma__decode_filter_properties_impl(module, filter_id, &encoded_props); @@ -334,4 +334,4 @@ _lzma__decode_filter_properties(PyObject *module, PyObject *const *args, Py_ssiz return return_value; } -/*[clinic end generated code: output=1a290aa478603107 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f7477a10e86a717d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_pickle.c.h b/Modules/clinic/_pickle.c.h index 8ac723fd43a6..b92daa72105a 100644 --- a/Modules/clinic/_pickle.c.h +++ b/Modules/clinic/_pickle.c.h @@ -356,7 +356,7 @@ _pickle_Unpickler___init__(PyObject *self, PyObject *args, PyObject *kwargs) } if (fastargs[2]) { if (!PyUnicode_Check(fastargs[2])) { - _PyArg_BadArgument("Unpickler", 3, "str", fastargs[2]); + _PyArg_BadArgument("Unpickler", "argument 'encoding'", "str", fastargs[2]); goto exit; } Py_ssize_t encoding_length; @@ -374,7 +374,7 @@ _pickle_Unpickler___init__(PyObject *self, PyObject *args, PyObject *kwargs) } if (fastargs[3]) { if (!PyUnicode_Check(fastargs[3])) { - _PyArg_BadArgument("Unpickler", 4, "str", fastargs[3]); + _PyArg_BadArgument("Unpickler", "argument 'errors'", "str", fastargs[3]); goto exit; } Py_ssize_t errors_length; @@ -691,7 +691,7 @@ _pickle_load(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject } if (args[2]) { if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("load", 3, "str", args[2]); + _PyArg_BadArgument("load", "argument 'encoding'", "str", args[2]); goto exit; } Py_ssize_t encoding_length; @@ -709,7 +709,7 @@ _pickle_load(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject } if (args[3]) { if (!PyUnicode_Check(args[3])) { - _PyArg_BadArgument("load", 4, "str", args[3]); + _PyArg_BadArgument("load", "argument 'errors'", "str", args[3]); goto exit; } Py_ssize_t errors_length; @@ -794,7 +794,7 @@ _pickle_loads(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec } if (args[2]) { if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("loads", 3, "str", args[2]); + _PyArg_BadArgument("loads", "argument 'encoding'", "str", args[2]); goto exit; } Py_ssize_t encoding_length; @@ -812,7 +812,7 @@ _pickle_loads(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec } if (args[3]) { if (!PyUnicode_Check(args[3])) { - _PyArg_BadArgument("loads", 4, "str", args[3]); + _PyArg_BadArgument("loads", "argument 'errors'", "str", args[3]); goto exit; } Py_ssize_t errors_length; @@ -835,4 +835,4 @@ _pickle_loads(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=8dc0e862f96c4afe input=a9049054013a1b77]*/ +/*[clinic end generated code: output=17f6a76ebd94325d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_sre.c.h b/Modules/clinic/_sre.c.h index 9c08dec4541a..d398a8504ba4 100644 --- a/Modules/clinic/_sre.c.h +++ b/Modules/clinic/_sre.c.h @@ -894,7 +894,7 @@ _sre_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyList_Check(args[2])) { - _PyArg_BadArgument("compile", 3, "list", args[2]); + _PyArg_BadArgument("compile", "argument 'code'", "list", args[2]); goto exit; } code = args[2]; @@ -916,12 +916,12 @@ _sre_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject groups = ival; } if (!PyDict_Check(args[4])) { - _PyArg_BadArgument("compile", 5, "dict", args[4]); + _PyArg_BadArgument("compile", "argument 'groupindex'", "dict", args[4]); goto exit; } groupindex = args[4]; if (!PyTuple_Check(args[5])) { - _PyArg_BadArgument("compile", 6, "tuple", args[5]); + _PyArg_BadArgument("compile", "argument 'indexgroup'", "tuple", args[5]); goto exit; } indexgroup = args[5]; @@ -1207,4 +1207,4 @@ _sre_SRE_Scanner_search(ScannerObject *self, PyObject *Py_UNUSED(ignored)) { return _sre_SRE_Scanner_search_impl(self); } -/*[clinic end generated code: output=67b702da5bdc9cac input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1adeddce58ae284c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index adef7dbf90ce..25769a225af9 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -222,7 +222,7 @@ _ssl__SSLSocket_write(PySSLSocket *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", 0, "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); goto exit; } return_value = _ssl__SSLSocket_write_impl(self, &b); @@ -353,7 +353,7 @@ _ssl__SSLSocket_get_channel_binding(PySSLSocket *self, PyObject *const *args, Py goto skip_optional_pos; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("get_channel_binding", 1, "str", args[0]); + _PyArg_BadArgument("get_channel_binding", "argument 'cb_type'", "str", args[0]); goto exit; } Py_ssize_t cb_type_length; @@ -439,7 +439,7 @@ _ssl__SSLContext_set_ciphers(PySSLContext *self, PyObject *arg) const char *cipherlist; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("set_ciphers", 0, "str", arg); + _PyArg_BadArgument("set_ciphers", "argument", "str", arg); goto exit; } Py_ssize_t cipherlist_length; @@ -500,7 +500,7 @@ _ssl__SSLContext__set_npn_protocols(PySSLContext *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&protos, 'C')) { - _PyArg_BadArgument("_set_npn_protocols", 0, "contiguous buffer", arg); + _PyArg_BadArgument("_set_npn_protocols", "argument", "contiguous buffer", arg); goto exit; } return_value = _ssl__SSLContext__set_npn_protocols_impl(self, &protos); @@ -536,7 +536,7 @@ _ssl__SSLContext__set_alpn_protocols(PySSLContext *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&protos, 'C')) { - _PyArg_BadArgument("_set_alpn_protocols", 0, "contiguous buffer", arg); + _PyArg_BadArgument("_set_alpn_protocols", "argument", "contiguous buffer", arg); goto exit; } return_value = _ssl__SSLContext__set_alpn_protocols_impl(self, &protos); @@ -690,7 +690,7 @@ _ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *const *args, Py_ssiz goto exit; } if (!PyObject_TypeCheck(args[0], PySocketModule.Sock_Type)) { - _PyArg_BadArgument("_wrap_socket", 1, (PySocketModule.Sock_Type)->tp_name, args[0]); + _PyArg_BadArgument("_wrap_socket", "argument 'sock'", (PySocketModule.Sock_Type)->tp_name, args[0]); goto exit; } sock = args[0]; @@ -765,12 +765,12 @@ _ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *const *args, Py_ssize_t goto exit; } if (!PyObject_TypeCheck(args[0], &PySSLMemoryBIO_Type)) { - _PyArg_BadArgument("_wrap_bio", 1, (&PySSLMemoryBIO_Type)->tp_name, args[0]); + _PyArg_BadArgument("_wrap_bio", "argument 'incoming'", (&PySSLMemoryBIO_Type)->tp_name, args[0]); goto exit; } incoming = (PySSLMemoryBIO *)args[0]; if (!PyObject_TypeCheck(args[1], &PySSLMemoryBIO_Type)) { - _PyArg_BadArgument("_wrap_bio", 2, (&PySSLMemoryBIO_Type)->tp_name, args[1]); + _PyArg_BadArgument("_wrap_bio", "argument 'outgoing'", (&PySSLMemoryBIO_Type)->tp_name, args[1]); goto exit; } outgoing = (PySSLMemoryBIO *)args[1]; @@ -1017,7 +1017,7 @@ _ssl_MemoryBIO_write(PySSLMemoryBIO *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", 0, "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); goto exit; } return_value = _ssl_MemoryBIO_write_impl(self, &b); @@ -1089,7 +1089,7 @@ _ssl_RAND_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&view, 'C')) { - _PyArg_BadArgument("RAND_add", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("RAND_add", "argument 1", "contiguous buffer", args[0]); goto exit; } } @@ -1289,7 +1289,7 @@ _ssl_txt2obj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("txt2obj", 1, "str", args[0]); + _PyArg_BadArgument("txt2obj", "argument 'txt'", "str", args[0]); goto exit; } Py_ssize_t txt_length; @@ -1382,7 +1382,7 @@ _ssl_enum_certificates(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("enum_certificates", 1, "str", args[0]); + _PyArg_BadArgument("enum_certificates", "argument 'store_name'", "str", args[0]); goto exit; } Py_ssize_t store_name_length; @@ -1435,7 +1435,7 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("enum_crls", 1, "str", args[0]); + _PyArg_BadArgument("enum_crls", "argument 'store_name'", "str", args[0]); goto exit; } Py_ssize_t store_name_length; @@ -1482,4 +1482,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=5003112e167cd948 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=aa4947067c3fef2d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h index 908c44266c4e..36c4b4046cd7 100644 --- a/Modules/clinic/_struct.c.h +++ b/Modules/clinic/_struct.c.h @@ -65,7 +65,7 @@ Struct_unpack(PyStructObject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack", 0, "contiguous buffer", arg); + _PyArg_BadArgument("unpack", "argument", "contiguous buffer", arg); goto exit; } return_value = Struct_unpack_impl(self, &buffer); @@ -118,7 +118,7 @@ Struct_unpack_from(PyStructObject *self, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack_from", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("unpack_from", "argument 'buffer'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -253,7 +253,7 @@ unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("unpack", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = unpack_impl(module, s_object, &buffer); @@ -309,7 +309,7 @@ unpack_from(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack_from", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("unpack_from", "argument 'buffer'", "contiguous buffer", args[1]); goto exit; } if (!noptargs) { @@ -386,4 +386,4 @@ iter_unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=b642e1002d25ebdd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6a6228cfc4b7099c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_tkinter.c.h b/Modules/clinic/_tkinter.c.h index 0a3e7ff5fc96..4870e9b4aad7 100644 --- a/Modules/clinic/_tkinter.c.h +++ b/Modules/clinic/_tkinter.c.h @@ -20,7 +20,7 @@ _tkinter_tkapp_eval(TkappObject *self, PyObject *arg) const char *script; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("eval", 0, "str", arg); + _PyArg_BadArgument("eval", "argument", "str", arg); goto exit; } Py_ssize_t script_length; @@ -56,7 +56,7 @@ _tkinter_tkapp_evalfile(TkappObject *self, PyObject *arg) const char *fileName; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("evalfile", 0, "str", arg); + _PyArg_BadArgument("evalfile", "argument", "str", arg); goto exit; } Py_ssize_t fileName_length; @@ -92,7 +92,7 @@ _tkinter_tkapp_record(TkappObject *self, PyObject *arg) const char *script; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("record", 0, "str", arg); + _PyArg_BadArgument("record", "argument", "str", arg); goto exit; } Py_ssize_t script_length; @@ -128,7 +128,7 @@ _tkinter_tkapp_adderrorinfo(TkappObject *self, PyObject *arg) const char *msg; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("adderrorinfo", 0, "str", arg); + _PyArg_BadArgument("adderrorinfo", "argument", "str", arg); goto exit; } Py_ssize_t msg_length; @@ -188,7 +188,7 @@ _tkinter_tkapp_exprstring(TkappObject *self, PyObject *arg) const char *s; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("exprstring", 0, "str", arg); + _PyArg_BadArgument("exprstring", "argument", "str", arg); goto exit; } Py_ssize_t s_length; @@ -224,7 +224,7 @@ _tkinter_tkapp_exprlong(TkappObject *self, PyObject *arg) const char *s; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("exprlong", 0, "str", arg); + _PyArg_BadArgument("exprlong", "argument", "str", arg); goto exit; } Py_ssize_t s_length; @@ -260,7 +260,7 @@ _tkinter_tkapp_exprdouble(TkappObject *self, PyObject *arg) const char *s; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("exprdouble", 0, "str", arg); + _PyArg_BadArgument("exprdouble", "argument", "str", arg); goto exit; } Py_ssize_t s_length; @@ -296,7 +296,7 @@ _tkinter_tkapp_exprboolean(TkappObject *self, PyObject *arg) const char *s; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("exprboolean", 0, "str", arg); + _PyArg_BadArgument("exprboolean", "argument", "str", arg); goto exit; } Py_ssize_t s_length; @@ -353,7 +353,7 @@ _tkinter_tkapp_createcommand(TkappObject *self, PyObject *const *args, Py_ssize_ goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("createcommand", 1, "str", args[0]); + _PyArg_BadArgument("createcommand", "argument 1", "str", args[0]); goto exit; } Py_ssize_t name_length; @@ -390,7 +390,7 @@ _tkinter_tkapp_deletecommand(TkappObject *self, PyObject *arg) const char *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("deletecommand", 0, "str", arg); + _PyArg_BadArgument("deletecommand", "argument", "str", arg); goto exit; } Py_ssize_t name_length; @@ -731,14 +731,14 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("create", 1, "str or None", args[0]); + _PyArg_BadArgument("create", "argument 1", "str or None", args[0]); goto exit; } if (nargs < 2) { goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("create", 2, "str", args[1]); + _PyArg_BadArgument("create", "argument 2", "str", args[1]); goto exit; } Py_ssize_t baseName_length; @@ -754,7 +754,7 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("create", 3, "str", args[2]); + _PyArg_BadArgument("create", "argument 3", "str", args[2]); goto exit; } Py_ssize_t className_length; @@ -832,7 +832,7 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("create", 8, "str or None", args[7]); + _PyArg_BadArgument("create", "argument 8", "str or None", args[7]); goto exit; } skip_optional: @@ -912,4 +912,4 @@ _tkinter_getbusywaitinterval(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF #define _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF #endif /* !defined(_TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF) */ -/*[clinic end generated code: output=2cf95f0101f3dbca input=a9049054013a1b77]*/ +/*[clinic end generated code: output=da0115c470aac1c0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_weakref.c.h b/Modules/clinic/_weakref.c.h index aa0d77f7180e..c3a908fa6a13 100644 --- a/Modules/clinic/_weakref.c.h +++ b/Modules/clinic/_weakref.c.h @@ -54,7 +54,7 @@ _weakref__remove_dead_weakref(PyObject *module, PyObject *const *args, Py_ssize_ goto exit; } if (!PyDict_Check(args[0])) { - _PyArg_BadArgument("_remove_dead_weakref", 1, "dict", args[0]); + _PyArg_BadArgument("_remove_dead_weakref", "argument 1", "dict", args[0]); goto exit; } dct = args[0]; @@ -64,4 +64,4 @@ _weakref__remove_dead_weakref(PyObject *module, PyObject *const *args, Py_ssize_ exit: return return_value; } -/*[clinic end generated code: output=eae22e2d2e43120e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c543dc2cd6ece975 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h index 5f45b7cf6734..33f82d4da8b6 100644 --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -345,7 +345,7 @@ array_array_fromstring(arrayobject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("fromstring", 0, "contiguous buffer", arg); + _PyArg_BadArgument("fromstring", "argument", "contiguous buffer", arg); goto exit; } } @@ -382,7 +382,7 @@ array_array_frombytes(arrayobject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("frombytes", 0, "contiguous buffer", arg); + _PyArg_BadArgument("frombytes", "argument", "contiguous buffer", arg); goto exit; } return_value = array_array_frombytes_impl(self, &buffer); @@ -537,14 +537,14 @@ array__array_reconstructor(PyObject *module, PyObject *const *args, Py_ssize_t n } arraytype = (PyTypeObject *)args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("_array_reconstructor", 2, "a unicode character", args[1]); + _PyArg_BadArgument("_array_reconstructor", "argument 2", "a unicode character", args[1]); goto exit; } if (PyUnicode_READY(args[1])) { goto exit; } if (PyUnicode_GET_LENGTH(args[1]) != 1) { - _PyArg_BadArgument("_array_reconstructor", 2, "a unicode character", args[1]); + _PyArg_BadArgument("_array_reconstructor", "argument 2", "a unicode character", args[1]); goto exit; } typecode = PyUnicode_READ_CHAR(args[1], 0); @@ -599,4 +599,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__, #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=c9a40f11f1a866fb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6aa421571e2c0756 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/audioop.c.h b/Modules/clinic/audioop.c.h index aa176964b0f3..8745533eeb62 100644 --- a/Modules/clinic/audioop.c.h +++ b/Modules/clinic/audioop.c.h @@ -30,7 +30,7 @@ audioop_getsample(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("getsample", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("getsample", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -96,7 +96,7 @@ audioop_max(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("max", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("max", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -145,7 +145,7 @@ audioop_minmax(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("minmax", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("minmax", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -194,7 +194,7 @@ audioop_avg(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("avg", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("avg", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -243,7 +243,7 @@ audioop_rms(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("rms", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("rms", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -293,14 +293,14 @@ audioop_findfit(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("findfit", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("findfit", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &reference, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&reference, 'C')) { - _PyArg_BadArgument("findfit", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("findfit", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = audioop_findfit_impl(module, &fragment, &reference); @@ -345,14 +345,14 @@ audioop_findfactor(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("findfactor", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("findfactor", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &reference, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&reference, 'C')) { - _PyArg_BadArgument("findfactor", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("findfactor", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = audioop_findfactor_impl(module, &fragment, &reference); @@ -397,7 +397,7 @@ audioop_findmax(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("findmax", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("findmax", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -454,7 +454,7 @@ audioop_avgpp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("avgpp", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("avgpp", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -503,7 +503,7 @@ audioop_maxpp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("maxpp", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("maxpp", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -552,7 +552,7 @@ audioop_cross(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("cross", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("cross", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -603,7 +603,7 @@ audioop_mul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("mul", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("mul", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -665,7 +665,7 @@ audioop_tomono(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("tomono", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("tomono", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -737,7 +737,7 @@ audioop_tostereo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("tostereo", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("tostereo", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -808,14 +808,14 @@ audioop_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment1, 'C')) { - _PyArg_BadArgument("add", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("add", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &fragment2, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&fragment2, 'C')) { - _PyArg_BadArgument("add", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("add", "argument 2", "contiguous buffer", args[1]); goto exit; } if (PyFloat_Check(args[2])) { @@ -869,7 +869,7 @@ audioop_bias(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("bias", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("bias", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -927,7 +927,7 @@ audioop_reverse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("reverse", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("reverse", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -976,7 +976,7 @@ audioop_byteswap(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("byteswap", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("byteswap", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1027,7 +1027,7 @@ audioop_lin2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("lin2lin", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("lin2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1094,7 +1094,7 @@ audioop_ratecv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("ratecv", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("ratecv", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1196,7 +1196,7 @@ audioop_lin2ulaw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("lin2ulaw", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("lin2ulaw", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1245,7 +1245,7 @@ audioop_ulaw2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("ulaw2lin", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("ulaw2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1294,7 +1294,7 @@ audioop_lin2alaw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("lin2alaw", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("lin2alaw", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1343,7 +1343,7 @@ audioop_alaw2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("alaw2lin", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("alaw2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1394,7 +1394,7 @@ audioop_lin2adpcm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("lin2adpcm", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("lin2adpcm", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1446,7 +1446,7 @@ audioop_adpcm2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("adpcm2lin", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("adpcm2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1469,4 +1469,4 @@ audioop_adpcm2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=af32f4bce9c934fa input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6b4f2c597f295abc input=a9049054013a1b77]*/ diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index d48504856902..e18d407ba9e8 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -64,7 +64,7 @@ binascii_b2a_uu(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_uu", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("b2a_uu", "argument 1", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -153,7 +153,7 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_base64", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("b2a_base64", "argument 1", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -233,7 +233,7 @@ binascii_rlecode_hqx(PyObject *module, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("rlecode_hqx", 0, "contiguous buffer", arg); + _PyArg_BadArgument("rlecode_hqx", "argument", "contiguous buffer", arg); goto exit; } return_value = binascii_rlecode_hqx_impl(module, &data); @@ -269,7 +269,7 @@ binascii_b2a_hqx(PyObject *module, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_hqx", 0, "contiguous buffer", arg); + _PyArg_BadArgument("b2a_hqx", "argument", "contiguous buffer", arg); goto exit; } return_value = binascii_b2a_hqx_impl(module, &data); @@ -305,7 +305,7 @@ binascii_rledecode_hqx(PyObject *module, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("rledecode_hqx", 0, "contiguous buffer", arg); + _PyArg_BadArgument("rledecode_hqx", "argument", "contiguous buffer", arg); goto exit; } return_value = binascii_rledecode_hqx_impl(module, &data); @@ -346,7 +346,7 @@ binascii_crc_hqx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("crc_hqx", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("crc_hqx", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -400,7 +400,7 @@ binascii_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("crc32", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("crc32", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -481,7 +481,7 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_hex", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("b2a_hex", "argument 'data'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -556,7 +556,7 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("hexlify", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("hexlify", "argument 'data'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -747,7 +747,7 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_qp", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("b2a_qp", "argument 'data'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -801,4 +801,4 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj return return_value; } -/*[clinic end generated code: output=f7b8049edb130c63 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e13bd02ac40496f0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/grpmodule.c.h b/Modules/clinic/grpmodule.c.h index ae99c50955f6..2e2690ad8d3f 100644 --- a/Modules/clinic/grpmodule.c.h +++ b/Modules/clinic/grpmodule.c.h @@ -64,7 +64,7 @@ grp_getgrnam(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("getgrnam", 1, "str", args[0]); + _PyArg_BadArgument("getgrnam", "argument 'name'", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -97,4 +97,4 @@ grp_getgrall(PyObject *module, PyObject *Py_UNUSED(ignored)) { return grp_getgrall_impl(module); } -/*[clinic end generated code: output=2aa6c60873d41ee8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9b3f26779e4e1a52 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index b43ce64af0dc..20594b0fed4c 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -66,7 +66,7 @@ itertools__grouper(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), &groupby_type)) { - _PyArg_BadArgument("_grouper", 1, (&groupby_type)->tp_name, PyTuple_GET_ITEM(args, 0)); + _PyArg_BadArgument("_grouper", "argument 1", (&groupby_type)->tp_name, PyTuple_GET_ITEM(args, 0)); goto exit; } parent = PyTuple_GET_ITEM(args, 0); @@ -104,7 +104,7 @@ itertools_teedataobject(PyTypeObject *type, PyObject *args, PyObject *kwargs) } it = PyTuple_GET_ITEM(args, 0); if (!PyList_Check(PyTuple_GET_ITEM(args, 1))) { - _PyArg_BadArgument("teedataobject", 2, "list", PyTuple_GET_ITEM(args, 1)); + _PyArg_BadArgument("teedataobject", "argument 2", "list", PyTuple_GET_ITEM(args, 1)); goto exit; } values = PyTuple_GET_ITEM(args, 1); @@ -642,4 +642,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=04c49debcae96003 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=392c9706e79f6710 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index c4ebe3996aa7..cb4ef5978dbf 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -616,7 +616,7 @@ os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * goto exit; } if (!PyLong_Check(args[1])) { - _PyArg_BadArgument("chflags", 2, "int", args[1]); + _PyArg_BadArgument("chflags", "argument 'flags'", "int", args[1]); goto exit; } flags = PyLong_AsUnsignedLongMask(args[1]); @@ -674,7 +674,7 @@ os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyLong_Check(args[1])) { - _PyArg_BadArgument("lchflags", 2, "int", args[1]); + _PyArg_BadArgument("lchflags", "argument 'flags'", "int", args[1]); goto exit; } flags = PyLong_AsUnsignedLongMask(args[1]); @@ -4956,7 +4956,7 @@ os_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("write", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("write", "argument 2", "contiguous buffer", args[1]); goto exit; } _return_value = os_write_impl(module, fd, &data); @@ -5279,7 +5279,7 @@ os_pwrite(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("pwrite", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("pwrite", "argument 2", "contiguous buffer", args[1]); goto exit; } if (!Py_off_t_converter(args[2], &offset)) { @@ -6012,7 +6012,7 @@ os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("putenv", 1, "str", args[0]); + _PyArg_BadArgument("putenv", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -6020,7 +6020,7 @@ os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } name = args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("putenv", 2, "str", args[1]); + _PyArg_BadArgument("putenv", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -7216,7 +7216,7 @@ os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyBuffer_IsContiguous(&value, 'C')) { - _PyArg_BadArgument("setxattr", 3, "contiguous buffer", args[2]); + _PyArg_BadArgument("setxattr", "argument 'value'", "contiguous buffer", args[2]); goto exit; } if (!noptargs) { @@ -8724,4 +8724,4 @@ os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF #define OS__REMOVE_DLL_DIRECTORY_METHODDEF #endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */ -/*[clinic end generated code: output=b71eff00b91f5e43 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3c5cb675b0d09145 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pwdmodule.c.h b/Modules/clinic/pwdmodule.c.h index cf84ec959d58..cb83062495dc 100644 --- a/Modules/clinic/pwdmodule.c.h +++ b/Modules/clinic/pwdmodule.c.h @@ -34,7 +34,7 @@ pwd_getpwnam(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("getpwnam", 0, "str", arg); + _PyArg_BadArgument("getpwnam", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -74,4 +74,4 @@ pwd_getpwall(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef PWD_GETPWALL_METHODDEF #define PWD_GETPWALL_METHODDEF #endif /* !defined(PWD_GETPWALL_METHODDEF) */ -/*[clinic end generated code: output=f9412bdedc69706c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7fceab7f1a85da36 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h index dfb27d5f1114..41ab536bce23 100644 --- a/Modules/clinic/pyexpat.c.h +++ b/Modules/clinic/pyexpat.c.h @@ -75,7 +75,7 @@ pyexpat_xmlparser_SetBase(xmlparseobject *self, PyObject *arg) const char *base; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("SetBase", 0, "str", arg); + _PyArg_BadArgument("SetBase", "argument", "str", arg); goto exit; } Py_ssize_t base_length; @@ -171,14 +171,14 @@ pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyObject *con } } else { - _PyArg_BadArgument("ExternalEntityParserCreate", 1, "str or None", args[0]); + _PyArg_BadArgument("ExternalEntityParserCreate", "argument 1", "str or None", args[0]); goto exit; } if (nargs < 2) { goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("ExternalEntityParserCreate", 2, "str", args[1]); + _PyArg_BadArgument("ExternalEntityParserCreate", "argument 2", "str", args[1]); goto exit; } Py_ssize_t encoding_length; @@ -327,7 +327,7 @@ pyexpat_ParserCreate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } } else { - _PyArg_BadArgument("ParserCreate", 1, "str or None", args[0]); + _PyArg_BadArgument("ParserCreate", "argument 'encoding'", "str or None", args[0]); goto exit; } if (!--noptargs) { @@ -350,7 +350,7 @@ pyexpat_ParserCreate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } } else { - _PyArg_BadArgument("ParserCreate", 2, "str or None", args[1]); + _PyArg_BadArgument("ParserCreate", "argument 'namespace_separator'", "str or None", args[1]); goto exit; } if (!--noptargs) { @@ -401,4 +401,4 @@ pyexpat_ErrorString(PyObject *module, PyObject *arg) #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=e48f37d326956bdd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=133a4105d508ebec input=a9049054013a1b77]*/ diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index bc46515cb436..3cb1db14878c 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -590,7 +590,7 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyLong_Check(args[0])) { - _PyArg_BadArgument("pthread_kill", 1, "int", args[0]); + _PyArg_BadArgument("pthread_kill", "argument 1", "int", args[0]); goto exit; } thread_id = PyLong_AsUnsignedLongMask(args[0]); @@ -658,4 +658,4 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #ifndef SIGNAL_PTHREAD_KILL_METHODDEF #define SIGNAL_PTHREAD_KILL_METHODDEF #endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */ -/*[clinic end generated code: output=f0d3a5703581da76 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3320b8f73c20ba60 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/spwdmodule.c.h b/Modules/clinic/spwdmodule.c.h index e051e6eb6589..411d2344e18f 100644 --- a/Modules/clinic/spwdmodule.c.h +++ b/Modules/clinic/spwdmodule.c.h @@ -25,7 +25,7 @@ spwd_getspnam(PyObject *module, PyObject *arg_) PyObject *arg; if (!PyUnicode_Check(arg_)) { - _PyArg_BadArgument("getspnam", 0, "str", arg_); + _PyArg_BadArgument("getspnam", "argument", "str", arg_); goto exit; } if (PyUnicode_READY(arg_) == -1) { @@ -71,4 +71,4 @@ spwd_getspall(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SPWD_GETSPALL_METHODDEF #define SPWD_GETSPALL_METHODDEF #endif /* !defined(SPWD_GETSPALL_METHODDEF) */ -/*[clinic end generated code: output=2bbaa6bab1d9116e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=eec8d0bedcd312e5 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/symtablemodule.c.h b/Modules/clinic/symtablemodule.c.h index 7d8b0ad300c2..4a17f130ac97 100644 --- a/Modules/clinic/symtablemodule.c.h +++ b/Modules/clinic/symtablemodule.c.h @@ -31,7 +31,7 @@ _symtable_symtable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("symtable", 3, "str", args[2]); + _PyArg_BadArgument("symtable", "argument 3", "str", args[2]); goto exit; } Py_ssize_t startstr_length; @@ -48,4 +48,4 @@ _symtable_symtable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=de655625eee705f4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a12f75cdbdf4e52a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/unicodedata.c.h b/Modules/clinic/unicodedata.c.h index 8ca0881efcf8..77e4f22593b0 100644 --- a/Modules/clinic/unicodedata.c.h +++ b/Modules/clinic/unicodedata.c.h @@ -30,14 +30,14 @@ unicodedata_UCD_decimal(PyObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("decimal", 1, "a unicode character", args[0]); + _PyArg_BadArgument("decimal", "argument 1", "a unicode character", args[0]); goto exit; } if (PyUnicode_READY(args[0])) { goto exit; } if (PyUnicode_GET_LENGTH(args[0]) != 1) { - _PyArg_BadArgument("decimal", 1, "a unicode character", args[0]); + _PyArg_BadArgument("decimal", "argument 1", "a unicode character", args[0]); goto exit; } chr = PyUnicode_READ_CHAR(args[0], 0); @@ -79,14 +79,14 @@ unicodedata_UCD_digit(PyObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("digit", 1, "a unicode character", args[0]); + _PyArg_BadArgument("digit", "argument 1", "a unicode character", args[0]); goto exit; } if (PyUnicode_READY(args[0])) { goto exit; } if (PyUnicode_GET_LENGTH(args[0]) != 1) { - _PyArg_BadArgument("digit", 1, "a unicode character", args[0]); + _PyArg_BadArgument("digit", "argument 1", "a unicode character", args[0]); goto exit; } chr = PyUnicode_READ_CHAR(args[0], 0); @@ -129,14 +129,14 @@ unicodedata_UCD_numeric(PyObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("numeric", 1, "a unicode character", args[0]); + _PyArg_BadArgument("numeric", "argument 1", "a unicode character", args[0]); goto exit; } if (PyUnicode_READY(args[0])) { goto exit; } if (PyUnicode_GET_LENGTH(args[0]) != 1) { - _PyArg_BadArgument("numeric", 1, "a unicode character", args[0]); + _PyArg_BadArgument("numeric", "argument 1", "a unicode character", args[0]); goto exit; } chr = PyUnicode_READ_CHAR(args[0], 0); @@ -170,14 +170,14 @@ unicodedata_UCD_category(PyObject *self, PyObject *arg) int chr; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("category", 0, "a unicode character", arg); + _PyArg_BadArgument("category", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("category", 0, "a unicode character", arg); + _PyArg_BadArgument("category", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -208,14 +208,14 @@ unicodedata_UCD_bidirectional(PyObject *self, PyObject *arg) int chr; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("bidirectional", 0, "a unicode character", arg); + _PyArg_BadArgument("bidirectional", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("bidirectional", 0, "a unicode character", arg); + _PyArg_BadArgument("bidirectional", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -247,14 +247,14 @@ unicodedata_UCD_combining(PyObject *self, PyObject *arg) int _return_value; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("combining", 0, "a unicode character", arg); + _PyArg_BadArgument("combining", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("combining", 0, "a unicode character", arg); + _PyArg_BadArgument("combining", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -291,14 +291,14 @@ unicodedata_UCD_mirrored(PyObject *self, PyObject *arg) int _return_value; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("mirrored", 0, "a unicode character", arg); + _PyArg_BadArgument("mirrored", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("mirrored", 0, "a unicode character", arg); + _PyArg_BadArgument("mirrored", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -331,14 +331,14 @@ unicodedata_UCD_east_asian_width(PyObject *self, PyObject *arg) int chr; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("east_asian_width", 0, "a unicode character", arg); + _PyArg_BadArgument("east_asian_width", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("east_asian_width", 0, "a unicode character", arg); + _PyArg_BadArgument("east_asian_width", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -369,14 +369,14 @@ unicodedata_UCD_decomposition(PyObject *self, PyObject *arg) int chr; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("decomposition", 0, "a unicode character", arg); + _PyArg_BadArgument("decomposition", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("decomposition", 0, "a unicode character", arg); + _PyArg_BadArgument("decomposition", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -412,7 +412,7 @@ unicodedata_UCD_is_normalized(PyObject *self, PyObject *const *args, Py_ssize_t goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("is_normalized", 1, "str", args[0]); + _PyArg_BadArgument("is_normalized", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -420,7 +420,7 @@ unicodedata_UCD_is_normalized(PyObject *self, PyObject *const *args, Py_ssize_t } form = args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("is_normalized", 2, "str", args[1]); + _PyArg_BadArgument("is_normalized", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -459,7 +459,7 @@ unicodedata_UCD_normalize(PyObject *self, PyObject *const *args, Py_ssize_t narg goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("normalize", 1, "str", args[0]); + _PyArg_BadArgument("normalize", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -467,7 +467,7 @@ unicodedata_UCD_normalize(PyObject *self, PyObject *const *args, Py_ssize_t narg } form = args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("normalize", 2, "str", args[1]); + _PyArg_BadArgument("normalize", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -506,14 +506,14 @@ unicodedata_UCD_name(PyObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("name", 1, "a unicode character", args[0]); + _PyArg_BadArgument("name", "argument 1", "a unicode character", args[0]); goto exit; } if (PyUnicode_READY(args[0])) { goto exit; } if (PyUnicode_GET_LENGTH(args[0]) != 1) { - _PyArg_BadArgument("name", 1, "a unicode character", args[0]); + _PyArg_BadArgument("name", "argument 1", "a unicode character", args[0]); goto exit; } chr = PyUnicode_READ_CHAR(args[0], 0); @@ -559,4 +559,4 @@ unicodedata_UCD_lookup(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=0fc850fe5b6b312c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3238f76814fb48d1 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h index aa579209108d..77ea04a353bf 100644 --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -38,7 +38,7 @@ zlib_compress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("compress", "argument 1", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -105,7 +105,7 @@ zlib_decompress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decompress", "argument 1", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -273,7 +273,7 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto exit; } if (!PyBuffer_IsContiguous(&zdict, 'C')) { - _PyArg_BadArgument("compressobj", 6, "contiguous buffer", args[5]); + _PyArg_BadArgument("compressobj", "argument 'zdict'", "contiguous buffer", args[5]); goto exit; } skip_optional_pos: @@ -375,7 +375,7 @@ zlib_Compress_compress(compobject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", 0, "contiguous buffer", arg); + _PyArg_BadArgument("compress", "argument", "contiguous buffer", arg); goto exit; } return_value = zlib_Compress_compress_impl(self, &data); @@ -432,7 +432,7 @@ zlib_Decompress_decompress(compobject *self, PyObject *const *args, Py_ssize_t n goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decompress", "argument 1", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -677,7 +677,7 @@ zlib_adler32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("adler32", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("adler32", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -735,7 +735,7 @@ zlib_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("crc32", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("crc32", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -785,4 +785,4 @@ zlib_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #ifndef ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF #define ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF #endif /* !defined(ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF) */ -/*[clinic end generated code: output=feb079cebbbaacd6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=faae38ef96b88b16 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index 08c6eb53f587..ad8ed7eba7e8 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -115,14 +115,14 @@ bytearray_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&frm, 'C')) { - _PyArg_BadArgument("maketrans", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("maketrans", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &to, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&to, 'C')) { - _PyArg_BadArgument("maketrans", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("maketrans", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = bytearray_maketrans_impl(&frm, &to); @@ -175,14 +175,14 @@ bytearray_replace(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&old, 'C')) { - _PyArg_BadArgument("replace", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("replace", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&new, 'C')) { - _PyArg_BadArgument("replace", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("replace", "argument 2", "contiguous buffer", args[1]); goto exit; } if (nargs < 3) { @@ -735,7 +735,7 @@ bytearray_decode(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t narg } if (args[0]) { if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("decode", 1, "str", args[0]); + _PyArg_BadArgument("decode", "argument 'encoding'", "str", args[0]); goto exit; } Py_ssize_t encoding_length; @@ -752,7 +752,7 @@ bytearray_decode(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t narg } } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("decode", 2, "str", args[1]); + _PyArg_BadArgument("decode", "argument 'errors'", "str", args[1]); goto exit; } Py_ssize_t errors_length; @@ -854,7 +854,7 @@ bytearray_fromhex(PyTypeObject *type, PyObject *arg) PyObject *string; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("fromhex", 0, "str", arg); + _PyArg_BadArgument("fromhex", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -1011,4 +1011,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=7848247e5469ba1b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=09df354d3374dfb2 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 69c35063c6cf..7e2ce1af285c 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -99,7 +99,7 @@ bytes_partition(PyBytesObject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&sep, 'C')) { - _PyArg_BadArgument("partition", 0, "contiguous buffer", arg); + _PyArg_BadArgument("partition", "argument", "contiguous buffer", arg); goto exit; } return_value = bytes_partition_impl(self, &sep); @@ -142,7 +142,7 @@ bytes_rpartition(PyBytesObject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&sep, 'C')) { - _PyArg_BadArgument("rpartition", 0, "contiguous buffer", arg); + _PyArg_BadArgument("rpartition", "argument", "contiguous buffer", arg); goto exit; } return_value = bytes_rpartition_impl(self, &sep); @@ -420,14 +420,14 @@ bytes_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&frm, 'C')) { - _PyArg_BadArgument("maketrans", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("maketrans", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &to, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&to, 'C')) { - _PyArg_BadArgument("maketrans", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("maketrans", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = bytes_maketrans_impl(&frm, &to); @@ -480,14 +480,14 @@ bytes_replace(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&old, 'C')) { - _PyArg_BadArgument("replace", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("replace", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&new, 'C')) { - _PyArg_BadArgument("replace", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("replace", "argument 2", "contiguous buffer", args[1]); goto exit; } if (nargs < 3) { @@ -568,7 +568,7 @@ bytes_decode(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObj } if (args[0]) { if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("decode", 1, "str", args[0]); + _PyArg_BadArgument("decode", "argument 'encoding'", "str", args[0]); goto exit; } Py_ssize_t encoding_length; @@ -585,7 +585,7 @@ bytes_decode(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObj } } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("decode", 2, "str", args[1]); + _PyArg_BadArgument("decode", "argument 'errors'", "str", args[1]); goto exit; } Py_ssize_t errors_length; @@ -674,7 +674,7 @@ bytes_fromhex(PyTypeObject *type, PyObject *arg) PyObject *string; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("fromhex", 0, "str", arg); + _PyArg_BadArgument("fromhex", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -755,4 +755,4 @@ bytes_hex(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject exit: return return_value; } -/*[clinic end generated code: output=2d0a3733e13e753a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dbed3c3ff6faa382 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/codeobject.c.h b/Objects/clinic/codeobject.c.h index ec127ce17189..6596de051cac 100644 --- a/Objects/clinic/codeobject.c.h +++ b/Objects/clinic/codeobject.c.h @@ -158,7 +158,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[7]) { if (!PyBytes_Check(args[7])) { - _PyArg_BadArgument("replace", 8, "bytes", args[7]); + _PyArg_BadArgument("replace", "argument 'co_code'", "bytes", args[7]); goto exit; } co_code = (PyBytesObject *)args[7]; @@ -168,7 +168,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[8]) { if (!PyTuple_Check(args[8])) { - _PyArg_BadArgument("replace", 9, "tuple", args[8]); + _PyArg_BadArgument("replace", "argument 'co_consts'", "tuple", args[8]); goto exit; } co_consts = args[8]; @@ -178,7 +178,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[9]) { if (!PyTuple_Check(args[9])) { - _PyArg_BadArgument("replace", 10, "tuple", args[9]); + _PyArg_BadArgument("replace", "argument 'co_names'", "tuple", args[9]); goto exit; } co_names = args[9]; @@ -188,7 +188,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[10]) { if (!PyTuple_Check(args[10])) { - _PyArg_BadArgument("replace", 11, "tuple", args[10]); + _PyArg_BadArgument("replace", "argument 'co_varnames'", "tuple", args[10]); goto exit; } co_varnames = args[10]; @@ -198,7 +198,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[11]) { if (!PyTuple_Check(args[11])) { - _PyArg_BadArgument("replace", 12, "tuple", args[11]); + _PyArg_BadArgument("replace", "argument 'co_freevars'", "tuple", args[11]); goto exit; } co_freevars = args[11]; @@ -208,7 +208,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[12]) { if (!PyTuple_Check(args[12])) { - _PyArg_BadArgument("replace", 13, "tuple", args[12]); + _PyArg_BadArgument("replace", "argument 'co_cellvars'", "tuple", args[12]); goto exit; } co_cellvars = args[12]; @@ -218,7 +218,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[13]) { if (!PyUnicode_Check(args[13])) { - _PyArg_BadArgument("replace", 14, "str", args[13]); + _PyArg_BadArgument("replace", "argument 'co_filename'", "str", args[13]); goto exit; } if (PyUnicode_READY(args[13]) == -1) { @@ -231,7 +231,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[14]) { if (!PyUnicode_Check(args[14])) { - _PyArg_BadArgument("replace", 15, "str", args[14]); + _PyArg_BadArgument("replace", "argument 'co_name'", "str", args[14]); goto exit; } if (PyUnicode_READY(args[14]) == -1) { @@ -243,7 +243,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (!PyBytes_Check(args[15])) { - _PyArg_BadArgument("replace", 16, "bytes", args[15]); + _PyArg_BadArgument("replace", "argument 'co_lnotab'", "bytes", args[15]); goto exit; } co_lnotab = (PyBytesObject *)args[15]; @@ -253,4 +253,4 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje exit: return return_value; } -/*[clinic end generated code: output=624ab6f2ea8f0ea4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fade581d6313a0c2 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h index 4251d63c247b..6515d118e506 100644 --- a/Objects/clinic/floatobject.c.h +++ b/Objects/clinic/floatobject.c.h @@ -235,7 +235,7 @@ float___getformat__(PyTypeObject *type, PyObject *arg) const char *typestr; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("__getformat__", 0, "str", arg); + _PyArg_BadArgument("__getformat__", "argument", "str", arg); goto exit; } Py_ssize_t typestr_length; @@ -289,7 +289,7 @@ float___set_format__(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("__set_format__", 1, "str", args[0]); + _PyArg_BadArgument("__set_format__", "argument 1", "str", args[0]); goto exit; } Py_ssize_t typestr_length; @@ -302,7 +302,7 @@ float___set_format__(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("__set_format__", 2, "str", args[1]); + _PyArg_BadArgument("__set_format__", "argument 2", "str", args[1]); goto exit; } Py_ssize_t fmt_length; @@ -339,7 +339,7 @@ float___format__(PyObject *self, PyObject *arg) PyObject *format_spec; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("__format__", 0, "str", arg); + _PyArg_BadArgument("__format__", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -351,4 +351,4 @@ float___format__(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=c183029d87dd41fa input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cc8098eb73f1a64c input=a9049054013a1b77]*/ diff --git a/Objects/clinic/funcobject.c.h b/Objects/clinic/funcobject.c.h index 929797bfb02d..17fb13fe085a 100644 --- a/Objects/clinic/funcobject.c.h +++ b/Objects/clinic/funcobject.c.h @@ -44,12 +44,12 @@ func_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyObject_TypeCheck(fastargs[0], &PyCode_Type)) { - _PyArg_BadArgument("function", 1, (&PyCode_Type)->tp_name, fastargs[0]); + _PyArg_BadArgument("function", "argument 'code'", (&PyCode_Type)->tp_name, fastargs[0]); goto exit; } code = (PyCodeObject *)fastargs[0]; if (!PyDict_Check(fastargs[1])) { - _PyArg_BadArgument("function", 2, "dict", fastargs[1]); + _PyArg_BadArgument("function", "argument 'globals'", "dict", fastargs[1]); goto exit; } globals = fastargs[1]; @@ -75,4 +75,4 @@ func_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=1d01072cd5620d7e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3d96afa3396e5c82 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/longobject.c.h b/Objects/clinic/longobject.c.h index 453edba481df..27e8dfe935b6 100644 --- a/Objects/clinic/longobject.c.h +++ b/Objects/clinic/longobject.c.h @@ -74,7 +74,7 @@ int___format__(PyObject *self, PyObject *arg) PyObject *format_spec; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("__format__", 0, "str", arg); + _PyArg_BadArgument("__format__", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -227,7 +227,7 @@ int_to_bytes(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject * length = ival; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("to_bytes", 2, "str", args[1]); + _PyArg_BadArgument("to_bytes", "argument 'byteorder'", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -293,7 +293,7 @@ int_from_bytes(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyOb } bytes_obj = args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("from_bytes", 2, "str", args[1]); + _PyArg_BadArgument("from_bytes", "argument 'byteorder'", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -313,4 +313,4 @@ int_from_bytes(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyOb exit: return return_value; } -/*[clinic end generated code: output=709503897c55bca1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=77bc3b2615822cb8 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/moduleobject.c.h b/Objects/clinic/moduleobject.c.h index 512edee72fea..c1534eaee258 100644 --- a/Objects/clinic/moduleobject.c.h +++ b/Objects/clinic/moduleobject.c.h @@ -31,7 +31,7 @@ module___init__(PyObject *self, PyObject *args, PyObject *kwargs) goto exit; } if (!PyUnicode_Check(fastargs[0])) { - _PyArg_BadArgument("module", 1, "str", fastargs[0]); + _PyArg_BadArgument("module", "argument 'name'", "str", fastargs[0]); goto exit; } if (PyUnicode_READY(fastargs[0]) == -1) { @@ -48,4 +48,4 @@ module___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=d7b7ca1237597b08 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=680276bc3a496d7a input=a9049054013a1b77]*/ diff --git a/Objects/clinic/typeobject.c.h b/Objects/clinic/typeobject.c.h index fbe1261fb5a0..357eb44b12b8 100644 --- a/Objects/clinic/typeobject.c.h +++ b/Objects/clinic/typeobject.c.h @@ -200,7 +200,7 @@ object___format__(PyObject *self, PyObject *arg) PyObject *format_spec; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("__format__", 0, "str", arg); + _PyArg_BadArgument("__format__", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -248,4 +248,4 @@ object___dir__(PyObject *self, PyObject *Py_UNUSED(ignored)) { return object___dir___impl(self); } -/*[clinic end generated code: output=ea5734413064fa7e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7a6d272d282308f3 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h index 647507dea61a..cb350874dad1 100644 --- a/Objects/clinic/unicodeobject.c.h +++ b/Objects/clinic/unicodeobject.c.h @@ -157,7 +157,7 @@ unicode_encode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject } if (args[0]) { if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("encode", 1, "str", args[0]); + _PyArg_BadArgument("encode", "argument 'encoding'", "str", args[0]); goto exit; } Py_ssize_t encoding_length; @@ -174,7 +174,7 @@ unicode_encode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject } } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("encode", 2, "str", args[1]); + _PyArg_BadArgument("encode", "argument 'errors'", "str", args[1]); goto exit; } Py_ssize_t errors_length; @@ -712,7 +712,7 @@ unicode_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("replace", 1, "str", args[0]); + _PyArg_BadArgument("replace", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -720,7 +720,7 @@ unicode_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } old = args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("replace", 2, "str", args[1]); + _PyArg_BadArgument("replace", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -1080,7 +1080,7 @@ unicode_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("maketrans", 2, "str", args[1]); + _PyArg_BadArgument("maketrans", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -1091,7 +1091,7 @@ unicode_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("maketrans", 3, "str", args[2]); + _PyArg_BadArgument("maketrans", "argument 3", "str", args[2]); goto exit; } if (PyUnicode_READY(args[2]) == -1) { @@ -1202,7 +1202,7 @@ unicode___format__(PyObject *self, PyObject *arg) PyObject *format_spec; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("__format__", 0, "str", arg); + _PyArg_BadArgument("__format__", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -1232,4 +1232,4 @@ unicode_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored)) { return unicode_sizeof_impl(self); } -/*[clinic end generated code: output=d1541724cb4a0070 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d9a6ee45ddd0ccfd input=a9049054013a1b77]*/ diff --git a/Objects/stringlib/clinic/transmogrify.h.h b/Objects/stringlib/clinic/transmogrify.h.h index 0c53a75b1bf8..8a3a060f12bc 100644 --- a/Objects/stringlib/clinic/transmogrify.h.h +++ b/Objects/stringlib/clinic/transmogrify.h.h @@ -100,7 +100,7 @@ stringlib_ljust(PyObject *self, PyObject *const *args, Py_ssize_t nargs) fillchar = PyByteArray_AS_STRING(args[1])[0]; } else { - _PyArg_BadArgument("ljust", 2, "a byte string of length 1", args[1]); + _PyArg_BadArgument("ljust", "argument 2", "a byte string of length 1", args[1]); goto exit; } skip_optional: @@ -161,7 +161,7 @@ stringlib_rjust(PyObject *self, PyObject *const *args, Py_ssize_t nargs) fillchar = PyByteArray_AS_STRING(args[1])[0]; } else { - _PyArg_BadArgument("rjust", 2, "a byte string of length 1", args[1]); + _PyArg_BadArgument("rjust", "argument 2", "a byte string of length 1", args[1]); goto exit; } skip_optional: @@ -222,7 +222,7 @@ stringlib_center(PyObject *self, PyObject *const *args, Py_ssize_t nargs) fillchar = PyByteArray_AS_STRING(args[1])[0]; } else { - _PyArg_BadArgument("center", 2, "a byte string of length 1", args[1]); + _PyArg_BadArgument("center", "argument 2", "a byte string of length 1", args[1]); goto exit; } skip_optional: @@ -274,4 +274,4 @@ stringlib_zfill(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=96cbb19b238d0e84 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=15be047aef999b4e input=a9049054013a1b77]*/ diff --git a/PC/clinic/_testconsole.c.h b/PC/clinic/_testconsole.c.h index a37d1235a02a..cf5e4ee09063 100644 --- a/PC/clinic/_testconsole.c.h +++ b/PC/clinic/_testconsole.c.h @@ -33,7 +33,7 @@ _testconsole_write_input(PyObject *module, PyObject *const *args, Py_ssize_t nar } file = args[0]; if (!PyBytes_Check(args[1])) { - _PyArg_BadArgument("write_input", 2, "bytes", args[1]); + _PyArg_BadArgument("write_input", "argument 's'", "bytes", args[1]); goto exit; } s = (PyBytesObject *)args[1]; @@ -88,4 +88,4 @@ _testconsole_read_output(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef _TESTCONSOLE_READ_OUTPUT_METHODDEF #define _TESTCONSOLE_READ_OUTPUT_METHODDEF #endif /* !defined(_TESTCONSOLE_READ_OUTPUT_METHODDEF) */ -/*[clinic end generated code: output=ef452d5fb9287fc2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dd8b093a91b62753 input=a9049054013a1b77]*/ diff --git a/PC/clinic/msvcrtmodule.c.h b/PC/clinic/msvcrtmodule.c.h index d8e77d5f328d..180c3e5fc54a 100644 --- a/PC/clinic/msvcrtmodule.c.h +++ b/PC/clinic/msvcrtmodule.c.h @@ -375,7 +375,7 @@ msvcrt_putch(PyObject *module, PyObject *arg) char_value = PyByteArray_AS_STRING(arg)[0]; } else { - _PyArg_BadArgument("putch", 0, "a byte string of length 1", arg); + _PyArg_BadArgument("putch", "argument", "a byte string of length 1", arg); goto exit; } return_value = msvcrt_putch_impl(module, char_value); @@ -403,14 +403,14 @@ msvcrt_putwch(PyObject *module, PyObject *arg) int unicode_char; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("putwch", 0, "a unicode character", arg); + _PyArg_BadArgument("putwch", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("putwch", 0, "a unicode character", arg); + _PyArg_BadArgument("putwch", "argument", "a unicode character", arg); goto exit; } unicode_char = PyUnicode_READ_CHAR(arg, 0); @@ -449,7 +449,7 @@ msvcrt_ungetch(PyObject *module, PyObject *arg) char_value = PyByteArray_AS_STRING(arg)[0]; } else { - _PyArg_BadArgument("ungetch", 0, "a byte string of length 1", arg); + _PyArg_BadArgument("ungetch", "argument", "a byte string of length 1", arg); goto exit; } return_value = msvcrt_ungetch_impl(module, char_value); @@ -477,14 +477,14 @@ msvcrt_ungetwch(PyObject *module, PyObject *arg) int unicode_char; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("ungetwch", 0, "a unicode character", arg); + _PyArg_BadArgument("ungetwch", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("ungetwch", 0, "a unicode character", arg); + _PyArg_BadArgument("ungetwch", "argument", "a unicode character", arg); goto exit; } unicode_char = PyUnicode_READ_CHAR(arg, 0); @@ -679,4 +679,4 @@ msvcrt_SetErrorMode(PyObject *module, PyObject *arg) #ifndef MSVCRT_SET_ERROR_MODE_METHODDEF #define MSVCRT_SET_ERROR_MODE_METHODDEF #endif /* !defined(MSVCRT_SET_ERROR_MODE_METHODDEF) */ -/*[clinic end generated code: output=816bc4f993893cea input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7cc6ffaf64f268f7 input=a9049054013a1b77]*/ diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h index abed6cc3e174..49608ccf3df9 100644 --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -102,7 +102,7 @@ builtin_format(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("format", 2, "str", args[1]); + _PyArg_BadArgument("format", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -200,7 +200,7 @@ builtin_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("compile", 3, "str", args[2]); + _PyArg_BadArgument("compile", "argument 'mode'", "str", args[2]); goto exit; } Py_ssize_t mode_length; @@ -849,4 +849,4 @@ builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=e173df340a9e4516 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1927f3c9abd00c35 input=a9049054013a1b77]*/ diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h index 05e3106bb39a..743d00222914 100644 --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -92,12 +92,12 @@ _imp__fix_co_filename(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyObject_TypeCheck(args[0], &PyCode_Type)) { - _PyArg_BadArgument("_fix_co_filename", 1, (&PyCode_Type)->tp_name, args[0]); + _PyArg_BadArgument("_fix_co_filename", "argument 1", (&PyCode_Type)->tp_name, args[0]); goto exit; } code = (PyCodeObject *)args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("_fix_co_filename", 2, "str", args[1]); + _PyArg_BadArgument("_fix_co_filename", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -156,7 +156,7 @@ _imp_init_frozen(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("init_frozen", 0, "str", arg); + _PyArg_BadArgument("init_frozen", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -188,7 +188,7 @@ _imp_get_frozen_object(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("get_frozen_object", 0, "str", arg); + _PyArg_BadArgument("get_frozen_object", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -220,7 +220,7 @@ _imp_is_frozen_package(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("is_frozen_package", 0, "str", arg); + _PyArg_BadArgument("is_frozen_package", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -252,7 +252,7 @@ _imp_is_builtin(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("is_builtin", 0, "str", arg); + _PyArg_BadArgument("is_builtin", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -284,7 +284,7 @@ _imp_is_frozen(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("is_frozen", 0, "str", arg); + _PyArg_BadArgument("is_frozen", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -433,7 +433,7 @@ _imp_source_hash(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto exit; } if (!PyBuffer_IsContiguous(&source, 'C')) { - _PyArg_BadArgument("source_hash", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("source_hash", "argument 'source'", "contiguous buffer", args[1]); goto exit; } return_value = _imp_source_hash_impl(module, key, &source); @@ -454,4 +454,4 @@ _imp_source_hash(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=b51244770fdcf4b8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ff06f7cf4b73eb76 input=a9049054013a1b77]*/ diff --git a/Python/clinic/marshal.c.h b/Python/clinic/marshal.c.h index ab4575340e25..05d4830c4ab3 100644 --- a/Python/clinic/marshal.c.h +++ b/Python/clinic/marshal.c.h @@ -152,7 +152,7 @@ marshal_loads(PyObject *module, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&bytes, 'C')) { - _PyArg_BadArgument("loads", 0, "contiguous buffer", arg); + _PyArg_BadArgument("loads", "argument", "contiguous buffer", arg); goto exit; } return_value = marshal_loads_impl(module, &bytes); @@ -165,4 +165,4 @@ marshal_loads(PyObject *module, PyObject *arg) return return_value; } -/*[clinic end generated code: output=ae2bca1aa239e095 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a859dabe8b0afeb6 input=a9049054013a1b77]*/ diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 2f3bd146e288..f9ab28dd055c 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -228,7 +228,7 @@ sys_intern(PyObject *module, PyObject *arg) PyObject *s; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("intern", 0, "str", arg); + _PyArg_BadArgument("intern", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -875,7 +875,7 @@ sys_call_tracing(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } func = args[0]; if (!PyTuple_Check(args[1])) { - _PyArg_BadArgument("call_tracing", 2, "tuple", args[1]); + _PyArg_BadArgument("call_tracing", "argument 2", "tuple", args[1]); goto exit; } funcargs = args[1]; @@ -995,4 +995,4 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=b26faa0abdd700da input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8b250245a1265eef input=a9049054013a1b77]*/ diff --git a/Python/clinic/traceback.c.h b/Python/clinic/traceback.c.h index 2815f65d3dd1..04daf2a37669 100644 --- a/Python/clinic/traceback.c.h +++ b/Python/clinic/traceback.c.h @@ -32,7 +32,7 @@ tb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } tb_next = fastargs[0]; if (!PyObject_TypeCheck(fastargs[1], &PyFrame_Type)) { - _PyArg_BadArgument("TracebackType", 2, (&PyFrame_Type)->tp_name, fastargs[1]); + _PyArg_BadArgument("TracebackType", "argument 'tb_frame'", (&PyFrame_Type)->tp_name, fastargs[1]); goto exit; } tb_frame = (PyFrameObject *)fastargs[1]; @@ -59,4 +59,4 @@ tb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=7e4c0e252d0973b0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3def6c06248feed8 input=a9049054013a1b77]*/ diff --git a/Python/getargs.c b/Python/getargs.c index fe6474c18112..02a0366ece46 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -610,24 +610,18 @@ convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, -/* Format an error message generated by convertsimple(). */ +/* Format an error message generated by convertsimple(). + displayname must be UTF-8 encoded. +*/ void -_PyArg_BadArgument(const char *fname, int iarg, +_PyArg_BadArgument(const char *fname, const char *displayname, const char *expected, PyObject *arg) { - if (iarg) { - PyErr_Format(PyExc_TypeError, - "%.200s() argument %d must be %.50s, not %.50s", - fname, iarg, expected, - arg == Py_None ? "None" : arg->ob_type->tp_name); - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s() argument must be %.50s, not %.50s", - fname, expected, - arg == Py_None ? "None" : arg->ob_type->tp_name); - } + PyErr_Format(PyExc_TypeError, + "%.200s() %.200s must be %.50s, not %.50s", + fname, displayname, expected, + arg == Py_None ? "None" : arg->ob_type->tp_name); } static const char * diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index d5863a3effe9..cec7c5392db3 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -806,7 +806,8 @@ def parser_body(prototype, *fields, declarations=''): {c_basename}({self_type}{self_name}, PyObject *%s) """ % argname) - parsearg = converters[0].parse_arg(argname, 0) + displayname = parameters[0].get_displayname(0) + parsearg = converters[0].parse_arg(argname, displayname) if parsearg is None: parsearg = """ if (!PyArg_Parse(%s, "{format_units}:{name}", {parse_arguments})) {{ @@ -851,7 +852,8 @@ def parser_body(prototype, *fields, declarations=''): """ % (nargs, min_pos, max_pos), indent=4)] has_optional = False for i, p in enumerate(parameters): - parsearg = p.converter.parse_arg(argname_fmt % i, i + 1) + displayname = p.get_displayname(i+1) + parsearg = p.converter.parse_arg(argname_fmt % i, displayname) if parsearg is None: #print('Cannot convert %s %r for %s' % (p.converter.__class__.__name__, p.converter.format_unit, p.converter.name), file=sys.stderr) parser_code = None @@ -927,7 +929,8 @@ def parser_body(prototype, *fields, declarations=''): add_label = None for i, p in enumerate(parameters): - parsearg = p.converter.parse_arg(argname_fmt % i, i + 1) + displayname = p.get_displayname(i+1) + parsearg = p.converter.parse_arg(argname_fmt % i, displayname) if parsearg is None: #print('Cannot convert %s %r for %s' % (p.converter.__class__.__name__, p.converter.format_unit, p.converter.name), file=sys.stderr) parser_code = None @@ -2287,6 +2290,13 @@ def copy(self, **overrides): kwargs['converter'] = converter return Parameter(**kwargs) + def get_displayname(self, i): + if i == 0: + return '"argument"' + if not self.is_positional_only(): + return '''"argument '{}'"'''.format(self.name) + else: + return '"argument {}"'.format(i) class LandMine: @@ -2634,7 +2644,7 @@ def pre_render(self): """ pass - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'O&': return """ if (!{converter}({argname}, &{paramname})) {{{{ @@ -2648,21 +2658,22 @@ def parse_arg(self, argname, argnum): typecheck, typename = type_checks[self.subclass_of] return """ if (!{typecheck}({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "{typename}", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "{typename}", {argname}); goto exit; }}}} {paramname} = {cast}{argname}; """.format(argname=argname, paramname=self.name, - argnum=argnum, - typecheck=typecheck, typename=typename, cast=cast) + displayname=displayname, typecheck=typecheck, + typename=typename, cast=cast) return """ if (!PyObject_TypeCheck({argname}, {subclass_of})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, ({subclass_of})->tp_name, {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, ({subclass_of})->tp_name, {argname}); goto exit; }}}} {paramname} = {cast}{argname}; - """.format(argname=argname, paramname=self.name, argnum=argnum, - subclass_of=self.subclass_of, cast=cast) + """.format(argname=argname, paramname=self.name, + subclass_of=self.subclass_of, cast=cast, + displayname=displayname) if self.format_unit == 'O': cast = '(%s)' % self.type if self.type != 'PyObject *' else '' return """ @@ -2698,7 +2709,7 @@ def converter_init(self, *, accept={object}): self.default = bool(self.default) self.c_default = str(int(self.default)) - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'i': # XXX PyFloat_Check can be removed after the end of the # deprecation in _PyLong_FromNbIndexOrNbInt. @@ -2720,7 +2731,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class char_converter(CConverter): type = 'char' @@ -2737,7 +2748,7 @@ def converter_init(self): if self.c_default == '"\'"': self.c_default = r"'\''" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'c': return """ if (PyBytes_Check({argname}) && PyBytes_GET_SIZE({argname}) == 1) {{{{ @@ -2747,11 +2758,12 @@ def parse_arg(self, argname, argnum): {paramname} = PyByteArray_AS_STRING({argname})[0]; }}}} else {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "a byte string of length 1", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "a byte string of length 1", {argname}); goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) @add_legacy_c_converter('B', bitwise=True) @@ -2765,7 +2777,7 @@ def converter_init(self, *, bitwise=False): if bitwise: self.format_unit = 'B' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'b': return """ if (PyFloat_Check({argname})) {{{{ @@ -2810,7 +2822,7 @@ def parse_arg(self, argname, argnum): }}}} }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class byte_converter(unsigned_char_converter): pass @@ -2820,7 +2832,7 @@ class short_converter(CConverter): format_unit = 'h' c_ignored_default = "0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'h': return """ if (PyFloat_Check({argname})) {{{{ @@ -2848,7 +2860,7 @@ def parse_arg(self, argname, argnum): }}}} }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class unsigned_short_converter(CConverter): type = 'unsigned short' @@ -2861,7 +2873,7 @@ def converter_init(self, *, bitwise=False): else: self.converter = '_PyLong_UnsignedShort_Converter' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'H': return """ if (PyFloat_Check({argname})) {{{{ @@ -2874,7 +2886,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) @add_legacy_c_converter('C', accept={str}) class int_converter(CConverter): @@ -2891,7 +2903,7 @@ def converter_init(self, *, accept={int}, type=None): if type != None: self.type = type - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'i': return """ if (PyFloat_Check({argname})) {{{{ @@ -2907,19 +2919,20 @@ def parse_arg(self, argname, argnum): elif self.format_unit == 'C': return """ if (!PyUnicode_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "a unicode character", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "a unicode character", {argname}); goto exit; }}}} if (PyUnicode_READY({argname})) {{{{ goto exit; }}}} if (PyUnicode_GET_LENGTH({argname}) != 1) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "a unicode character", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "a unicode character", {argname}); goto exit; }}}} {paramname} = PyUnicode_READ_CHAR({argname}, 0); - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) class unsigned_int_converter(CConverter): type = 'unsigned int' @@ -2932,7 +2945,7 @@ def converter_init(self, *, bitwise=False): else: self.converter = '_PyLong_UnsignedInt_Converter' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'I': return """ if (PyFloat_Check({argname})) {{{{ @@ -2945,7 +2958,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class long_converter(CConverter): type = 'long' @@ -2953,7 +2966,7 @@ class long_converter(CConverter): format_unit = 'l' c_ignored_default = "0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'l': return """ if (PyFloat_Check({argname})) {{{{ @@ -2966,7 +2979,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class unsigned_long_converter(CConverter): type = 'unsigned long' @@ -2979,16 +2992,17 @@ def converter_init(self, *, bitwise=False): else: self.converter = '_PyLong_UnsignedLong_Converter' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'k': return """ if (!PyLong_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "int", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "int", {argname}); goto exit; }}}} {paramname} = PyLong_AsUnsignedLongMask({argname}); - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) class long_long_converter(CConverter): type = 'long long' @@ -2996,7 +3010,7 @@ class long_long_converter(CConverter): format_unit = 'L' c_ignored_default = "0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'L': return """ if (PyFloat_Check({argname})) {{{{ @@ -3009,7 +3023,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class unsigned_long_long_converter(CConverter): type = 'unsigned long long' @@ -3022,16 +3036,17 @@ def converter_init(self, *, bitwise=False): else: self.converter = '_PyLong_UnsignedLongLong_Converter' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'K': return """ if (!PyLong_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "int", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "int", {argname}); goto exit; }}}} {paramname} = PyLong_AsUnsignedLongLongMask({argname}); - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) class Py_ssize_t_converter(CConverter): type = 'Py_ssize_t' @@ -3046,7 +3061,7 @@ def converter_init(self, *, accept={int}): else: fail("Py_ssize_t_converter: illegal 'accept' argument " + repr(accept)) - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'n': return """ if (PyFloat_Check({argname})) {{{{ @@ -3067,7 +3082,7 @@ def parse_arg(self, argname, argnum): {paramname} = ival; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class slice_index_converter(CConverter): @@ -3086,7 +3101,7 @@ class size_t_converter(CConverter): converter = '_PyLong_Size_t_Converter' c_ignored_default = "0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'n': return """ {paramname} = PyNumber_AsSsize_t({argname}, PyExc_OverflowError); @@ -3094,7 +3109,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class float_converter(CConverter): @@ -3103,7 +3118,7 @@ class float_converter(CConverter): format_unit = 'f' c_ignored_default = "0.0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'f': return """ if (PyFloat_CheckExact({argname})) {{{{ @@ -3117,7 +3132,7 @@ def parse_arg(self, argname, argnum): }}}} }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class double_converter(CConverter): type = 'double' @@ -3125,7 +3140,7 @@ class double_converter(CConverter): format_unit = 'd' c_ignored_default = "0.0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'd': return """ if (PyFloat_CheckExact({argname})) {{{{ @@ -3139,7 +3154,7 @@ def parse_arg(self, argname, argnum): }}}} }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class Py_complex_converter(CConverter): @@ -3148,7 +3163,7 @@ class Py_complex_converter(CConverter): format_unit = 'D' c_ignored_default = "{0.0, 0.0}" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'D': return """ {paramname} = PyComplex_AsCComplex({argname}); @@ -3156,7 +3171,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class object_converter(CConverter): @@ -3222,11 +3237,11 @@ def cleanup(self): name = self.name return "".join(["if (", name, ") {\n PyMem_FREE(", name, ");\n}\n"]) - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 's': return """ if (!PyUnicode_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "str", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "str", {argname}); goto exit; }}}} Py_ssize_t {paramname}_length; @@ -3238,7 +3253,8 @@ def parse_arg(self, argname, argnum): PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) if self.format_unit == 'z': return """ if ({argname} == Py_None) {{{{ @@ -3256,11 +3272,12 @@ def parse_arg(self, argname, argnum): }}}} }}}} else {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "str or None", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "str or None", {argname}); goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) # # This is the fourth or fifth rewrite of registering all the @@ -3315,53 +3332,54 @@ class PyBytesObject_converter(CConverter): format_unit = 'S' # accept = {bytes} - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'S': return """ if (!PyBytes_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "bytes", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "bytes", {argname}); goto exit; }}}} {paramname} = ({type}){argname}; - """.format(argname=argname, paramname=self.name, argnum=argnum, - type=self.type) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + type=self.type, displayname=displayname) + return super().parse_arg(argname, displayname) class PyByteArrayObject_converter(CConverter): type = 'PyByteArrayObject *' format_unit = 'Y' # accept = {bytearray} - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'Y': return """ if (!PyByteArray_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "bytearray", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "bytearray", {argname}); goto exit; }}}} {paramname} = ({type}){argname}; - """.format(argname=argname, paramname=self.name, argnum=argnum, - type=self.type) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + type=self.type, displayname=displayname) + return super().parse_arg(argname, displayname) class unicode_converter(CConverter): type = 'PyObject *' default_type = (str, Null, NoneType) format_unit = 'U' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'U': return """ if (!PyUnicode_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "str", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "str", {argname}); goto exit; }}}} if (PyUnicode_READY({argname}) == -1) {{{{ goto exit; }}}} {paramname} = {argname}; - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) @add_legacy_c_converter('u#', zeroes=True) @add_legacy_c_converter('Z', accept={str, NoneType}) @@ -3410,17 +3428,18 @@ def cleanup(self): name = self.name return "".join(["if (", name, ".obj) {\n PyBuffer_Release(&", name, ");\n}\n"]) - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'y*': return """ if (PyObject_GetBuffer({argname}, &{paramname}, PyBUF_SIMPLE) != 0) {{{{ goto exit; }}}} if (!PyBuffer_IsContiguous(&{paramname}, 'C')) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "contiguous buffer", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname}); goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) elif self.format_unit == 's*': return """ if (PyUnicode_Check({argname})) {{{{ @@ -3436,24 +3455,26 @@ def parse_arg(self, argname, argnum): goto exit; }}}} if (!PyBuffer_IsContiguous(&{paramname}, 'C')) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "contiguous buffer", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname}); goto exit; }}}} }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) elif self.format_unit == 'w*': return """ if (PyObject_GetBuffer({argname}, &{paramname}, PyBUF_WRITABLE) < 0) {{{{ PyErr_Clear(); - _PyArg_BadArgument("{{name}}", {argnum}, "read-write bytes-like object", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "read-write bytes-like object", {argname}); goto exit; }}}} if (!PyBuffer_IsContiguous(&{paramname}, 'C')) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "contiguous buffer", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname}); goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) def correct_name_for_self(f): From webhook-mailer at python.org Thu Aug 29 10:54:09 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 14:54:09 -0000 Subject: [Python-checkins] bpo-37979: Add alternative to fromisoformat in documentation (GH-15596) Message-ID: https://github.com/python/cpython/commit/8ba8cc51a9899594f7fe66fe790973d83fd3d657 commit: 8ba8cc51a9899594f7fe66fe790973d83fd3d657 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-29T07:54:04-07:00 summary: bpo-37979: Add alternative to fromisoformat in documentation (GH-15596) Adds a link to `dateutil.parser.isoparse` in the documentation. It would be nice to set up intersphinx for things like this, but I think we can leave that for a separate PR. CC: @pitrou [bpo-37979](https://bugs.python.org/issue37979) https://bugs.python.org/issue37979 Automerge-Triggered-By: @pitrou (cherry picked from commit 59725f3badb3028636c8906ecac4ceb0a37f3982) Co-authored-by: Paul Ganssle files: A Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index c725b75b98c1..342dc2b8cfbd 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -850,7 +850,9 @@ Other constructors, all class methods: .. caution:: This does not support parsing arbitrary ISO 8601 strings - it is only intended - as the inverse operation of :meth:`datetime.isoformat`. + as the inverse operation of :meth:`datetime.isoformat`. A more full-featured + ISO 8601 parser, ``dateutil.parser.isoparse`` is available in the third-party package + `dateutil `_. .. versionadded:: 3.7 diff --git a/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst b/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst new file mode 100644 index 000000000000..d8d70d613706 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst @@ -0,0 +1,2 @@ +Added a link to dateutil.parser.isoparse in the datetime.fromisoformat +documentation. Patch by Paul Ganssle From webhook-mailer at python.org Thu Aug 29 10:54:41 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 29 Aug 2019 14:54:41 -0000 Subject: [Python-checkins] bpo-37979: Add alternative to fromisoformat in documentation (GH-15596) Message-ID: https://github.com/python/cpython/commit/9db66a2b5ab6a302bc46421712f13b0afd94654b commit: 9db66a2b5ab6a302bc46421712f13b0afd94654b branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-29T07:54:37-07:00 summary: bpo-37979: Add alternative to fromisoformat in documentation (GH-15596) Adds a link to `dateutil.parser.isoparse` in the documentation. It would be nice to set up intersphinx for things like this, but I think we can leave that for a separate PR. CC: @pitrou [bpo-37979](https://bugs.python.org/issue37979) https://bugs.python.org/issue37979 Automerge-Triggered-By: @pitrou (cherry picked from commit 59725f3badb3028636c8906ecac4ceb0a37f3982) Co-authored-by: Paul Ganssle files: A Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 0135fa4b0218..50f1b9e74949 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -857,7 +857,9 @@ Other constructors, all class methods: .. caution:: This does not support parsing arbitrary ISO 8601 strings - it is only intended - as the inverse operation of :meth:`datetime.isoformat`. + as the inverse operation of :meth:`datetime.isoformat`. A more full-featured + ISO 8601 parser, ``dateutil.parser.isoparse`` is available in the third-party package + `dateutil `_. .. versionadded:: 3.7 diff --git a/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst b/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst new file mode 100644 index 000000000000..d8d70d613706 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst @@ -0,0 +1,2 @@ +Added a link to dateutil.parser.isoparse in the datetime.fromisoformat +documentation. Patch by Paul Ganssle From webhook-mailer at python.org Thu Aug 29 11:30:04 2019 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 29 Aug 2019 15:30:04 -0000 Subject: [Python-checkins] [3.8] bpo-37034: Display argument name on errors with keyword arguments with Argument Clinic. (GH-13593). (GH-15599) Message-ID: https://github.com/python/cpython/commit/96631dcb11c2786f470d4586bf23ecca14361506 commit: 96631dcb11c2786f470d4586bf23ecca14361506 branch: 3.8 author: Serhiy Storchaka committer: GitHub date: 2019-08-29T18:29:59+03:00 summary: [3.8] bpo-37034: Display argument name on errors with keyword arguments with Argument Clinic. (GH-13593). (GH-15599) (cherry picked from commit 4901fe274bc82b95dc89bcb3de8802a3dfedab32) Co-authored-by: R?mi Lapeyre files: A Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst M Include/modsupport.h M Lib/test/clinic.test M Lib/test/test_pyexpat.py M Modules/_blake2/clinic/blake2b_impl.c.h M Modules/_blake2/clinic/blake2s_impl.c.h M Modules/_io/clinic/_iomodule.c.h M Modules/_io/clinic/bufferedio.c.h M Modules/_io/clinic/bytesio.c.h M Modules/_io/clinic/fileio.c.h M Modules/_io/clinic/textio.c.h M Modules/_io/clinic/winconsoleio.c.h M Modules/_multiprocessing/clinic/posixshmem.c.h M Modules/cjkcodecs/clinic/multibytecodec.c.h M Modules/clinic/_bz2module.c.h M Modules/clinic/_codecsmodule.c.h M Modules/clinic/_cryptmodule.c.h M Modules/clinic/_curses_panel.c.h M Modules/clinic/_cursesmodule.c.h M Modules/clinic/_dbmmodule.c.h M Modules/clinic/_elementtree.c.h M Modules/clinic/_gdbmmodule.c.h M Modules/clinic/_hashopenssl.c.h M Modules/clinic/_lzmamodule.c.h M Modules/clinic/_pickle.c.h M Modules/clinic/_sre.c.h M Modules/clinic/_ssl.c.h M Modules/clinic/_struct.c.h M Modules/clinic/_tkinter.c.h M Modules/clinic/_weakref.c.h M Modules/clinic/arraymodule.c.h M Modules/clinic/audioop.c.h M Modules/clinic/binascii.c.h M Modules/clinic/grpmodule.c.h M Modules/clinic/itertoolsmodule.c.h M Modules/clinic/posixmodule.c.h M Modules/clinic/pwdmodule.c.h M Modules/clinic/pyexpat.c.h M Modules/clinic/signalmodule.c.h M Modules/clinic/spwdmodule.c.h M Modules/clinic/symtablemodule.c.h M Modules/clinic/unicodedata.c.h M Modules/clinic/zlibmodule.c.h M Objects/clinic/bytearrayobject.c.h M Objects/clinic/bytesobject.c.h M Objects/clinic/codeobject.c.h M Objects/clinic/floatobject.c.h M Objects/clinic/funcobject.c.h M Objects/clinic/longobject.c.h M Objects/clinic/moduleobject.c.h M Objects/clinic/typeobject.c.h M Objects/clinic/unicodeobject.c.h M Objects/stringlib/clinic/transmogrify.h.h M PC/clinic/_testconsole.c.h M PC/clinic/msvcrtmodule.c.h M Python/clinic/bltinmodule.c.h M Python/clinic/import.c.h M Python/clinic/marshal.c.h M Python/clinic/sysmodule.c.h M Python/clinic/traceback.c.h M Python/getargs.c M Tools/clinic/clinic.py diff --git a/Include/modsupport.h b/Include/modsupport.h index 66a5ec839e2a..f90ede4831e3 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -66,7 +66,7 @@ PyAPI_FUNC(int) _PyArg_NoPositional(const char *funcname, PyObject *args); #define _PyArg_NoPositional(funcname, args) \ ((args) == NULL || _PyArg_NoPositional((funcname), (args))) -PyAPI_FUNC(void) _PyArg_BadArgument(const char *, int, const char *, PyObject *); +PyAPI_FUNC(void) _PyArg_BadArgument(const char *, const char *, const char *, PyObject *); PyAPI_FUNC(int) _PyArg_CheckPositional(const char *, Py_ssize_t, Py_ssize_t, Py_ssize_t); #define _PyArg_CheckPositional(funcname, nargs, min, max) \ diff --git a/Lib/test/clinic.test b/Lib/test/clinic.test index ac6f419c0d3a..f9c55e2a577f 100644 --- a/Lib/test/clinic.test +++ b/Lib/test/clinic.test @@ -44,7 +44,7 @@ test_object_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("test_object_converter", 3, "str", args[2]); + _PyArg_BadArgument("test_object_converter", "argument 3", "str", args[2]); goto exit; } c = args[2]; @@ -58,7 +58,7 @@ exit: static PyObject * test_object_converter_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, PyUnicode_Object *d) -/*[clinic end generated code: output=f2c26174b3d46e94 input=005e6a8a711a869b]*/ +/*[clinic end generated code: output=a78312d933df9ea1 input=005e6a8a711a869b]*/ /*[clinic input] @@ -180,52 +180,52 @@ test_object_converter_subclass_of(PyObject *module, PyObject *const *args, Py_ss goto exit; } if (!PyLong_Check(args[0])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 1, "int", args[0]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 1", "int", args[0]); goto exit; } a = args[0]; if (!PyTuple_Check(args[1])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 2, "tuple", args[1]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 2", "tuple", args[1]); goto exit; } b = args[1]; if (!PyList_Check(args[2])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 3, "list", args[2]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 3", "list", args[2]); goto exit; } c = args[2]; if (!PySet_Check(args[3])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 4, "set", args[3]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 4", "set", args[3]); goto exit; } d = args[3]; if (!PyFrozenSet_Check(args[4])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 5, "frozenset", args[4]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 5", "frozenset", args[4]); goto exit; } e = args[4]; if (!PyDict_Check(args[5])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 6, "dict", args[5]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 6", "dict", args[5]); goto exit; } f = args[5]; if (!PyUnicode_Check(args[6])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 7, "str", args[6]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 7", "str", args[6]); goto exit; } g = args[6]; if (!PyBytes_Check(args[7])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 8, "bytes", args[7]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 8", "bytes", args[7]); goto exit; } h = args[7]; if (!PyByteArray_Check(args[8])) { - _PyArg_BadArgument("test_object_converter_subclass_of", 9, "bytearray", args[8]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 9", "bytearray", args[8]); goto exit; } i = args[8]; if (!PyObject_TypeCheck(args[9], &MyType)) { - _PyArg_BadArgument("test_object_converter_subclass_of", 10, (&MyType)->tp_name, args[9]); + _PyArg_BadArgument("test_object_converter_subclass_of", "argument 10", (&MyType)->tp_name, args[9]); goto exit; } j = args[9]; @@ -240,7 +240,7 @@ test_object_converter_subclass_of_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c, PyObject *d, PyObject *e, PyObject *f, PyObject *g, PyObject *h, PyObject *i, PyObject *j) -/*[clinic end generated code: output=99691bda8eeda6d6 input=31b06b772d5f983e]*/ +/*[clinic end generated code: output=dcf7772bf0c876dd input=31b06b772d5f983e]*/ /*[clinic input] @@ -269,7 +269,7 @@ test_PyBytesObject_converter(PyObject *module, PyObject *arg) PyBytesObject *a; if (!PyBytes_Check(arg)) { - _PyArg_BadArgument("test_PyBytesObject_converter", 0, "bytes", arg); + _PyArg_BadArgument("test_PyBytesObject_converter", "argument", "bytes", arg); goto exit; } a = (PyBytesObject *)arg; @@ -281,7 +281,7 @@ exit: static PyObject * test_PyBytesObject_converter_impl(PyObject *module, PyBytesObject *a) -/*[clinic end generated code: output=5d9a301c1df24eb5 input=12b10c7cb5750400]*/ +/*[clinic end generated code: output=7539d628e6fceace input=12b10c7cb5750400]*/ /*[clinic input] @@ -310,7 +310,7 @@ test_PyByteArrayObject_converter(PyObject *module, PyObject *arg) PyByteArrayObject *a; if (!PyByteArray_Check(arg)) { - _PyArg_BadArgument("test_PyByteArrayObject_converter", 0, "bytearray", arg); + _PyArg_BadArgument("test_PyByteArrayObject_converter", "argument", "bytearray", arg); goto exit; } a = (PyByteArrayObject *)arg; @@ -322,7 +322,7 @@ exit: static PyObject * test_PyByteArrayObject_converter_impl(PyObject *module, PyByteArrayObject *a) -/*[clinic end generated code: output=9455d06f4f09637b input=5a657da535d194ae]*/ +/*[clinic end generated code: output=1245af9f5b3e355e input=5a657da535d194ae]*/ /*[clinic input] @@ -351,7 +351,7 @@ test_unicode_converter(PyObject *module, PyObject *arg) PyObject *a; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("test_unicode_converter", 0, "str", arg); + _PyArg_BadArgument("test_unicode_converter", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -366,7 +366,7 @@ exit: static PyObject * test_unicode_converter_impl(PyObject *module, PyObject *a) -/*[clinic end generated code: output=9275c04fe204f4c5 input=aa33612df92aa9c5]*/ +/*[clinic end generated code: output=18f1e3880c862611 input=aa33612df92aa9c5]*/ /*[clinic input] @@ -507,7 +507,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) a = PyByteArray_AS_STRING(args[0])[0]; } else { - _PyArg_BadArgument("test_char_converter", 1, "a byte string of length 1", args[0]); + _PyArg_BadArgument("test_char_converter", "argument 1", "a byte string of length 1", args[0]); goto exit; } if (nargs < 2) { @@ -520,7 +520,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) b = PyByteArray_AS_STRING(args[1])[0]; } else { - _PyArg_BadArgument("test_char_converter", 2, "a byte string of length 1", args[1]); + _PyArg_BadArgument("test_char_converter", "argument 2", "a byte string of length 1", args[1]); goto exit; } if (nargs < 3) { @@ -533,7 +533,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) c = PyByteArray_AS_STRING(args[2])[0]; } else { - _PyArg_BadArgument("test_char_converter", 3, "a byte string of length 1", args[2]); + _PyArg_BadArgument("test_char_converter", "argument 3", "a byte string of length 1", args[2]); goto exit; } if (nargs < 4) { @@ -546,7 +546,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) d = PyByteArray_AS_STRING(args[3])[0]; } else { - _PyArg_BadArgument("test_char_converter", 4, "a byte string of length 1", args[3]); + _PyArg_BadArgument("test_char_converter", "argument 4", "a byte string of length 1", args[3]); goto exit; } if (nargs < 5) { @@ -559,7 +559,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) e = PyByteArray_AS_STRING(args[4])[0]; } else { - _PyArg_BadArgument("test_char_converter", 5, "a byte string of length 1", args[4]); + _PyArg_BadArgument("test_char_converter", "argument 5", "a byte string of length 1", args[4]); goto exit; } if (nargs < 6) { @@ -572,7 +572,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) f = PyByteArray_AS_STRING(args[5])[0]; } else { - _PyArg_BadArgument("test_char_converter", 6, "a byte string of length 1", args[5]); + _PyArg_BadArgument("test_char_converter", "argument 6", "a byte string of length 1", args[5]); goto exit; } if (nargs < 7) { @@ -585,7 +585,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) g = PyByteArray_AS_STRING(args[6])[0]; } else { - _PyArg_BadArgument("test_char_converter", 7, "a byte string of length 1", args[6]); + _PyArg_BadArgument("test_char_converter", "argument 7", "a byte string of length 1", args[6]); goto exit; } if (nargs < 8) { @@ -598,7 +598,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) h = PyByteArray_AS_STRING(args[7])[0]; } else { - _PyArg_BadArgument("test_char_converter", 8, "a byte string of length 1", args[7]); + _PyArg_BadArgument("test_char_converter", "argument 8", "a byte string of length 1", args[7]); goto exit; } if (nargs < 9) { @@ -611,7 +611,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) i = PyByteArray_AS_STRING(args[8])[0]; } else { - _PyArg_BadArgument("test_char_converter", 9, "a byte string of length 1", args[8]); + _PyArg_BadArgument("test_char_converter", "argument 9", "a byte string of length 1", args[8]); goto exit; } if (nargs < 10) { @@ -624,7 +624,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) j = PyByteArray_AS_STRING(args[9])[0]; } else { - _PyArg_BadArgument("test_char_converter", 10, "a byte string of length 1", args[9]); + _PyArg_BadArgument("test_char_converter", "argument 10", "a byte string of length 1", args[9]); goto exit; } if (nargs < 11) { @@ -637,7 +637,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) k = PyByteArray_AS_STRING(args[10])[0]; } else { - _PyArg_BadArgument("test_char_converter", 11, "a byte string of length 1", args[10]); + _PyArg_BadArgument("test_char_converter", "argument 11", "a byte string of length 1", args[10]); goto exit; } if (nargs < 12) { @@ -650,7 +650,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) l = PyByteArray_AS_STRING(args[11])[0]; } else { - _PyArg_BadArgument("test_char_converter", 12, "a byte string of length 1", args[11]); + _PyArg_BadArgument("test_char_converter", "argument 12", "a byte string of length 1", args[11]); goto exit; } if (nargs < 13) { @@ -663,7 +663,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) m = PyByteArray_AS_STRING(args[12])[0]; } else { - _PyArg_BadArgument("test_char_converter", 13, "a byte string of length 1", args[12]); + _PyArg_BadArgument("test_char_converter", "argument 13", "a byte string of length 1", args[12]); goto exit; } if (nargs < 14) { @@ -676,7 +676,7 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) n = PyByteArray_AS_STRING(args[13])[0]; } else { - _PyArg_BadArgument("test_char_converter", 14, "a byte string of length 1", args[13]); + _PyArg_BadArgument("test_char_converter", "argument 14", "a byte string of length 1", args[13]); goto exit; } skip_optional: @@ -690,7 +690,7 @@ static PyObject * test_char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, char f, char g, char h, char i, char j, char k, char l, char m, char n) -/*[clinic end generated code: output=e041d687555e0a5d input=e42330417a44feac]*/ +/*[clinic end generated code: output=9d3aaf5d6857ec9e input=e42330417a44feac]*/ /*[clinic input] @@ -1009,14 +1009,14 @@ test_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("test_int_converter", 3, "a unicode character", args[2]); + _PyArg_BadArgument("test_int_converter", "argument 3", "a unicode character", args[2]); goto exit; } if (PyUnicode_READY(args[2])) { goto exit; } if (PyUnicode_GET_LENGTH(args[2]) != 1) { - _PyArg_BadArgument("test_int_converter", 3, "a unicode character", args[2]); + _PyArg_BadArgument("test_int_converter", "argument 3", "a unicode character", args[2]); goto exit; } c = PyUnicode_READ_CHAR(args[2], 0); @@ -1041,7 +1041,7 @@ exit: static PyObject * test_int_converter_impl(PyObject *module, int a, int b, int c, myenum d) -/*[clinic end generated code: output=de74e24e85a669a5 input=d20541fc1ca0553e]*/ +/*[clinic end generated code: output=10a2e48a34af5d7a input=d20541fc1ca0553e]*/ /*[clinic input] @@ -1215,7 +1215,7 @@ test_unsigned_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t goto skip_optional; } if (!PyLong_Check(args[2])) { - _PyArg_BadArgument("test_unsigned_long_converter", 3, "int", args[2]); + _PyArg_BadArgument("test_unsigned_long_converter", "argument 3", "int", args[2]); goto exit; } c = PyLong_AsUnsignedLongMask(args[2]); @@ -1229,7 +1229,7 @@ exit: static PyObject * test_unsigned_long_converter_impl(PyObject *module, unsigned long a, unsigned long b, unsigned long c) -/*[clinic end generated code: output=1c05c871c0309e08 input=f450d94cae1ef73b]*/ +/*[clinic end generated code: output=87c6b29fa217026e input=f450d94cae1ef73b]*/ /*[clinic input] @@ -1335,7 +1335,7 @@ test_unsigned_long_long_converter(PyObject *module, PyObject *const *args, Py_ss goto skip_optional; } if (!PyLong_Check(args[2])) { - _PyArg_BadArgument("test_unsigned_long_long_converter", 3, "int", args[2]); + _PyArg_BadArgument("test_unsigned_long_long_converter", "argument 3", "int", args[2]); goto exit; } c = PyLong_AsUnsignedLongLongMask(args[2]); @@ -1351,7 +1351,7 @@ test_unsigned_long_long_converter_impl(PyObject *module, unsigned long long a, unsigned long long b, unsigned long long c) -/*[clinic end generated code: output=0a9b17fb824e28eb input=a15115dc41866ff4]*/ +/*[clinic end generated code: output=aad2c7b43db2f190 input=a15115dc41866ff4]*/ /*[clinic input] @@ -3207,3 +3207,56 @@ test_posonly_opt_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *d, PyObject *e, PyObject *f) /*[clinic end generated code: output=719e4f6c224402d4 input=9914857713c5bbf8]*/ + +/*[clinic input] +test_keyword_only_parameter + + + * + co_lnotab: PyBytesObject(c_default="(PyBytesObject *)self->co_lnotab") = None + +[clinic start generated code]*/ + +PyDoc_STRVAR(test_keyword_only_parameter__doc__, +"test_keyword_only_parameter($module, /, *, co_lnotab=None)\n" +"--\n" +"\n"); + +#define TEST_KEYWORD_ONLY_PARAMETER_METHODDEF \ + {"test_keyword_only_parameter", (PyCFunction)(void(*)(void))test_keyword_only_parameter, METH_FASTCALL|METH_KEYWORDS, test_keyword_only_parameter__doc__}, + +static PyObject * +test_keyword_only_parameter_impl(PyObject *module, PyBytesObject *co_lnotab); + +static PyObject * +test_keyword_only_parameter(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"co_lnotab", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "test_keyword_only_parameter", 0}; + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyBytesObject *co_lnotab = (PyBytesObject *)self->co_lnotab; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (!PyBytes_Check(args[0])) { + _PyArg_BadArgument("test_keyword_only_parameter", "argument 'co_lnotab'", "bytes", args[0]); + goto exit; + } + co_lnotab = (PyBytesObject *)args[0]; +skip_optional_kwonly: + return_value = test_keyword_only_parameter_impl(module, co_lnotab); + +exit: + return return_value; +} + +static PyObject * +test_keyword_only_parameter_impl(PyObject *module, PyBytesObject *co_lnotab) +/*[clinic end generated code: output=f25914b402039493 input=303df5046c7e37a3]*/ diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index 92fffc45f30a..2b6c2d20e746 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -285,7 +285,7 @@ def test_illegal(self): self.fail() except TypeError as e: self.assertEqual(str(e), - 'ParserCreate() argument 2 must be str or None, not int') + "ParserCreate() argument 'namespace_separator' must be str or None, not int") try: expat.ParserCreate(namespace_separator='too long') diff --git a/Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst b/Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst new file mode 100644 index 000000000000..3457789635b4 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst @@ -0,0 +1,2 @@ +Argument Clinic now uses the argument name on errors with keyword-only +argument instead of their position. Patch contributed by R?mi Lapeyre. diff --git a/Modules/_blake2/clinic/blake2b_impl.c.h b/Modules/_blake2/clinic/blake2b_impl.c.h index 09fe00457f35..cd329c07c999 100644 --- a/Modules/_blake2/clinic/blake2b_impl.c.h +++ b/Modules/_blake2/clinic/blake2b_impl.c.h @@ -72,7 +72,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&key, 'C')) { - _PyArg_BadArgument("blake2b", 3, "contiguous buffer", fastargs[2]); + _PyArg_BadArgument("blake2b", "argument 'key'", "contiguous buffer", fastargs[2]); goto exit; } if (!--noptargs) { @@ -84,7 +84,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("blake2b", 4, "contiguous buffer", fastargs[3]); + _PyArg_BadArgument("blake2b", "argument 'salt'", "contiguous buffer", fastargs[3]); goto exit; } if (!--noptargs) { @@ -96,7 +96,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&person, 'C')) { - _PyArg_BadArgument("blake2b", 5, "contiguous buffer", fastargs[4]); + _PyArg_BadArgument("blake2b", "argument 'person'", "contiguous buffer", fastargs[4]); goto exit; } if (!--noptargs) { @@ -261,4 +261,4 @@ _blake2_blake2b_hexdigest(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2_blake2b_hexdigest_impl(self); } -/*[clinic end generated code: output=a91d182ce1109f34 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cbb625d7f60c288c input=a9049054013a1b77]*/ diff --git a/Modules/_blake2/clinic/blake2s_impl.c.h b/Modules/_blake2/clinic/blake2s_impl.c.h index 92739a1feb32..560bd68160b0 100644 --- a/Modules/_blake2/clinic/blake2s_impl.c.h +++ b/Modules/_blake2/clinic/blake2s_impl.c.h @@ -72,7 +72,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&key, 'C')) { - _PyArg_BadArgument("blake2s", 3, "contiguous buffer", fastargs[2]); + _PyArg_BadArgument("blake2s", "argument 'key'", "contiguous buffer", fastargs[2]); goto exit; } if (!--noptargs) { @@ -84,7 +84,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("blake2s", 4, "contiguous buffer", fastargs[3]); + _PyArg_BadArgument("blake2s", "argument 'salt'", "contiguous buffer", fastargs[3]); goto exit; } if (!--noptargs) { @@ -96,7 +96,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyBuffer_IsContiguous(&person, 'C')) { - _PyArg_BadArgument("blake2s", 5, "contiguous buffer", fastargs[4]); + _PyArg_BadArgument("blake2s", "argument 'person'", "contiguous buffer", fastargs[4]); goto exit; } if (!--noptargs) { @@ -261,4 +261,4 @@ _blake2_blake2s_hexdigest(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2_blake2s_hexdigest_impl(self); } -/*[clinic end generated code: output=ae8e9b7301d092b4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=39af5a74c8805b36 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/_iomodule.c.h b/Modules/_io/clinic/_iomodule.c.h index 00ad616b41fe..1a9651d34081 100644 --- a/Modules/_io/clinic/_iomodule.c.h +++ b/Modules/_io/clinic/_iomodule.c.h @@ -161,7 +161,7 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } if (args[1]) { if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("open", 2, "str", args[1]); + _PyArg_BadArgument("open", "argument 'mode'", "str", args[1]); goto exit; } Py_ssize_t mode_length; @@ -207,7 +207,7 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } } else { - _PyArg_BadArgument("open", 4, "str or None", args[3]); + _PyArg_BadArgument("open", "argument 'encoding'", "str or None", args[3]); goto exit; } if (!--noptargs) { @@ -230,7 +230,7 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } } else { - _PyArg_BadArgument("open", 5, "str or None", args[4]); + _PyArg_BadArgument("open", "argument 'errors'", "str or None", args[4]); goto exit; } if (!--noptargs) { @@ -253,7 +253,7 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } } else { - _PyArg_BadArgument("open", 6, "str or None", args[5]); + _PyArg_BadArgument("open", "argument 'newline'", "str or None", args[5]); goto exit; } if (!--noptargs) { @@ -311,7 +311,7 @@ _io_open_code(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("open_code", 1, "str", args[0]); + _PyArg_BadArgument("open_code", "argument 'path'", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -323,4 +323,4 @@ _io_open_code(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=d479285078750d68 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3df6bc6d91697545 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h index d5e8c8a74813..72841fcb6779 100644 --- a/Modules/_io/clinic/bufferedio.c.h +++ b/Modules/_io/clinic/bufferedio.c.h @@ -21,11 +21,11 @@ _io__BufferedIOBase_readinto(PyObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__BufferedIOBase_readinto_impl(self, &buffer); @@ -58,11 +58,11 @@ _io__BufferedIOBase_readinto1(PyObject *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto1", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto1", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto1", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto1", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__BufferedIOBase_readinto1_impl(self, &buffer); @@ -243,11 +243,11 @@ _io__Buffered_readinto(buffered *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__Buffered_readinto_impl(self, &buffer); @@ -280,11 +280,11 @@ _io__Buffered_readinto1(buffered *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto1", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto1", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto1", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto1", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__Buffered_readinto1_impl(self, &buffer); @@ -538,7 +538,7 @@ _io_BufferedWriter_write(buffered *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("write", 0, "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); goto exit; } return_value = _io_BufferedWriter_write_impl(self, &buffer); @@ -672,4 +672,4 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=b22b4aedd53c340a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7246104f6c7d3167 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bytesio.c.h b/Modules/_io/clinic/bytesio.c.h index 8dd68f56137f..83cd490dc598 100644 --- a/Modules/_io/clinic/bytesio.c.h +++ b/Modules/_io/clinic/bytesio.c.h @@ -319,11 +319,11 @@ _io_BytesIO_readinto(bytesio *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); goto exit; } return_value = _io_BytesIO_readinto_impl(self, &buffer); @@ -515,4 +515,4 @@ _io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=22e8fb54874b6ee5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4ec2506def9c8eb9 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/fileio.c.h b/Modules/_io/clinic/fileio.c.h index 8016e9888624..64addde57f3e 100644 --- a/Modules/_io/clinic/fileio.c.h +++ b/Modules/_io/clinic/fileio.c.h @@ -70,7 +70,7 @@ _io_FileIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) } if (fastargs[1]) { if (!PyUnicode_Check(fastargs[1])) { - _PyArg_BadArgument("FileIO", 2, "str", fastargs[1]); + _PyArg_BadArgument("FileIO", "argument 'mode'", "str", fastargs[1]); goto exit; } Py_ssize_t mode_length; @@ -200,11 +200,11 @@ _io_FileIO_readinto(fileio *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); goto exit; } return_value = _io_FileIO_readinto_impl(self, &buffer); @@ -303,7 +303,7 @@ _io_FileIO_write(fileio *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", 0, "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); goto exit; } return_value = _io_FileIO_write_impl(self, &b); @@ -447,4 +447,4 @@ _io_FileIO_isatty(fileio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO_FILEIO_TRUNCATE_METHODDEF #define _IO_FILEIO_TRUNCATE_METHODDEF #endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */ -/*[clinic end generated code: output=7ee4f3ae584fc6d2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a7e9cca3613660fb input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h index cec9defea025..b8b507543ea8 100644 --- a/Modules/_io/clinic/textio.c.h +++ b/Modules/_io/clinic/textio.c.h @@ -229,7 +229,7 @@ _io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs) } } else { - _PyArg_BadArgument("TextIOWrapper", 2, "str or None", fastargs[1]); + _PyArg_BadArgument("TextIOWrapper", "argument 'encoding'", "str or None", fastargs[1]); goto exit; } if (!--noptargs) { @@ -258,7 +258,7 @@ _io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs) } } else { - _PyArg_BadArgument("TextIOWrapper", 4, "str or None", fastargs[3]); + _PyArg_BadArgument("TextIOWrapper", "argument 'newline'", "str or None", fastargs[3]); goto exit; } if (!--noptargs) { @@ -401,7 +401,7 @@ _io_TextIOWrapper_write(textio *self, PyObject *arg) PyObject *text; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("write", 0, "str", arg); + _PyArg_BadArgument("write", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -701,4 +701,4 @@ _io_TextIOWrapper_close(textio *self, PyObject *Py_UNUSED(ignored)) { return _io_TextIOWrapper_close_impl(self); } -/*[clinic end generated code: output=b651e056e3000f88 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b1bae4f4cdf6019e input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/winconsoleio.c.h b/Modules/_io/clinic/winconsoleio.c.h index bb0cdc4558dd..3e501a585371 100644 --- a/Modules/_io/clinic/winconsoleio.c.h +++ b/Modules/_io/clinic/winconsoleio.c.h @@ -69,7 +69,7 @@ _io__WindowsConsoleIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) } if (fastargs[1]) { if (!PyUnicode_Check(fastargs[1])) { - _PyArg_BadArgument("_WindowsConsoleIO", 2, "str", fastargs[1]); + _PyArg_BadArgument("_WindowsConsoleIO", "argument 'mode'", "str", fastargs[1]); goto exit; } Py_ssize_t mode_length; @@ -200,11 +200,11 @@ _io__WindowsConsoleIO_readinto(winconsoleio *self, PyObject *arg) if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", 0, "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", 0, "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__WindowsConsoleIO_readinto_impl(self, &buffer); @@ -313,7 +313,7 @@ _io__WindowsConsoleIO_write(winconsoleio *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", 0, "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); goto exit; } return_value = _io__WindowsConsoleIO_write_impl(self, &b); @@ -386,4 +386,4 @@ _io__WindowsConsoleIO_isatty(winconsoleio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #define _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #endif /* !defined(_IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF) */ -/*[clinic end generated code: output=57bf2c09a42bd330 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f5b8860a658a001a input=a9049054013a1b77]*/ diff --git a/Modules/_multiprocessing/clinic/posixshmem.c.h b/Modules/_multiprocessing/clinic/posixshmem.c.h index 0ebfa2fe3789..a99f0d2aae1d 100644 --- a/Modules/_multiprocessing/clinic/posixshmem.c.h +++ b/Modules/_multiprocessing/clinic/posixshmem.c.h @@ -35,7 +35,7 @@ _posixshmem_shm_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("shm_open", 1, "str", args[0]); + _PyArg_BadArgument("shm_open", "argument 'path'", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -108,7 +108,7 @@ _posixshmem_shm_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("shm_unlink", 1, "str", args[0]); + _PyArg_BadArgument("shm_unlink", "argument 'path'", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -130,4 +130,4 @@ _posixshmem_shm_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs #ifndef _POSIXSHMEM_SHM_UNLINK_METHODDEF #define _POSIXSHMEM_SHM_UNLINK_METHODDEF #endif /* !defined(_POSIXSHMEM_SHM_UNLINK_METHODDEF) */ -/*[clinic end generated code: output=be42e23c18677c0f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9132861c61d8c2d8 input=a9049054013a1b77]*/ diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h index 84774f007600..5ddbbe221b98 100644 --- a/Modules/cjkcodecs/clinic/multibytecodec.c.h +++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h @@ -55,7 +55,7 @@ _multibytecodec_MultibyteCodec_encode(MultibyteCodecObject *self, PyObject *cons } } else { - _PyArg_BadArgument("encode", 2, "str or None", args[1]); + _PyArg_BadArgument("encode", "argument 'errors'", "str or None", args[1]); goto exit; } skip_optional_pos: @@ -103,7 +103,7 @@ _multibytecodec_MultibyteCodec_decode(MultibyteCodecObject *self, PyObject *cons goto exit; } if (!PyBuffer_IsContiguous(&input, 'C')) { - _PyArg_BadArgument("decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decode", "argument 'input'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -124,7 +124,7 @@ _multibytecodec_MultibyteCodec_decode(MultibyteCodecObject *self, PyObject *cons } } else { - _PyArg_BadArgument("decode", 2, "str or None", args[1]); + _PyArg_BadArgument("decode", "argument 'errors'", "str or None", args[1]); goto exit; } skip_optional_pos: @@ -223,7 +223,7 @@ _multibytecodec_MultibyteIncrementalEncoder_setstate(MultibyteIncrementalEncoder PyLongObject *statelong; if (!PyLong_Check(arg)) { - _PyArg_BadArgument("setstate", 0, "int", arg); + _PyArg_BadArgument("setstate", "argument", "int", arg); goto exit; } statelong = (PyLongObject *)arg; @@ -282,7 +282,7 @@ _multibytecodec_MultibyteIncrementalDecoder_decode(MultibyteIncrementalDecoderOb goto exit; } if (!PyBuffer_IsContiguous(&input, 'C')) { - _PyArg_BadArgument("decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decode", "argument 'input'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -345,7 +345,7 @@ _multibytecodec_MultibyteIncrementalDecoder_setstate(MultibyteIncrementalDecoder PyObject *state; if (!PyTuple_Check(arg)) { - _PyArg_BadArgument("setstate", 0, "tuple", arg); + _PyArg_BadArgument("setstate", "argument", "tuple", arg); goto exit; } state = arg; @@ -525,4 +525,4 @@ PyDoc_STRVAR(_multibytecodec___create_codec__doc__, #define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \ {"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__}, -/*[clinic end generated code: output=eb95a408c4ddbfff input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5ce6fd4ca1f95620 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_bz2module.c.h b/Modules/clinic/_bz2module.c.h index cc16d8bb228f..ac826bd9b598 100644 --- a/Modules/clinic/_bz2module.c.h +++ b/Modules/clinic/_bz2module.c.h @@ -29,7 +29,7 @@ _bz2_BZ2Compressor_compress(BZ2Compressor *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", 0, "contiguous buffer", arg); + _PyArg_BadArgument("compress", "argument", "contiguous buffer", arg); goto exit; } return_value = _bz2_BZ2Compressor_compress_impl(self, &data); @@ -156,7 +156,7 @@ _bz2_BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject *const *args, Py goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decompress", "argument 'data'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -220,4 +220,4 @@ _bz2_BZ2Decompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=8e123f4eec497655 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ec3d1b3652c98823 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h index 65e24832fff6..be1d2f70cf1b 100644 --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -34,7 +34,7 @@ _codecs_lookup(PyObject *module, PyObject *arg) const char *encoding; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("lookup", 0, "str", arg); + _PyArg_BadArgument("lookup", "argument", "str", arg); goto exit; } Py_ssize_t encoding_length; @@ -93,7 +93,7 @@ _codecs_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[1]) { if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("encode", 2, "str", args[1]); + _PyArg_BadArgument("encode", "argument 'encoding'", "str", args[1]); goto exit; } Py_ssize_t encoding_length; @@ -110,7 +110,7 @@ _codecs_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("encode", 3, "str", args[2]); + _PyArg_BadArgument("encode", "argument 'errors'", "str", args[2]); goto exit; } Py_ssize_t errors_length; @@ -170,7 +170,7 @@ _codecs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[1]) { if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("decode", 2, "str", args[1]); + _PyArg_BadArgument("decode", "argument 'encoding'", "str", args[1]); goto exit; } Py_ssize_t encoding_length; @@ -187,7 +187,7 @@ _codecs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("decode", 3, "str", args[2]); + _PyArg_BadArgument("decode", "argument 'errors'", "str", args[2]); goto exit; } Py_ssize_t errors_length; @@ -225,7 +225,7 @@ _codecs__forget_codec(PyObject *module, PyObject *arg) const char *encoding; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("_forget_codec", 0, "str", arg); + _PyArg_BadArgument("_forget_codec", "argument", "str", arg); goto exit; } Py_ssize_t encoding_length; @@ -278,7 +278,7 @@ _codecs_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("escape_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("escape_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } } @@ -300,7 +300,7 @@ _codecs_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("escape_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("escape_decode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -338,7 +338,7 @@ _codecs_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBytes_Check(args[0])) { - _PyArg_BadArgument("escape_encode", 1, "bytes", args[0]); + _PyArg_BadArgument("escape_encode", "argument 1", "bytes", args[0]); goto exit; } data = args[0]; @@ -360,7 +360,7 @@ _codecs_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("escape_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("escape_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -397,7 +397,7 @@ _codecs_utf_7_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_7_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_7_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -418,7 +418,7 @@ _codecs_utf_7_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_7_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_7_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -472,7 +472,7 @@ _codecs_utf_8_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_8_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_8_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -493,7 +493,7 @@ _codecs_utf_8_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_8_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_8_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -547,7 +547,7 @@ _codecs_utf_16_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_16_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -568,7 +568,7 @@ _codecs_utf_16_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_16_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -622,7 +622,7 @@ _codecs_utf_16_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_le_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_16_le_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -643,7 +643,7 @@ _codecs_utf_16_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_16_le_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_le_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -697,7 +697,7 @@ _codecs_utf_16_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_be_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_16_be_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -718,7 +718,7 @@ _codecs_utf_16_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_16_be_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_be_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -774,7 +774,7 @@ _codecs_utf_16_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_16_ex_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_16_ex_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -795,7 +795,7 @@ _codecs_utf_16_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_16_ex_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_ex_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -861,7 +861,7 @@ _codecs_utf_32_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_32_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -882,7 +882,7 @@ _codecs_utf_32_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_32_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -936,7 +936,7 @@ _codecs_utf_32_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_le_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_32_le_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -957,7 +957,7 @@ _codecs_utf_32_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_32_le_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_le_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1011,7 +1011,7 @@ _codecs_utf_32_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_be_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_32_be_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1032,7 +1032,7 @@ _codecs_utf_32_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_32_be_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_be_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1088,7 +1088,7 @@ _codecs_utf_32_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("utf_32_ex_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("utf_32_ex_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1109,7 +1109,7 @@ _codecs_utf_32_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_32_ex_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_ex_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1183,7 +1183,7 @@ _codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_ goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("unicode_escape_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("unicode_escape_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } } @@ -1205,7 +1205,7 @@ _codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_ } } else { - _PyArg_BadArgument("unicode_escape_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("unicode_escape_decode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1255,7 +1255,7 @@ _codecs_raw_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ss goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("raw_unicode_escape_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("raw_unicode_escape_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } } @@ -1277,7 +1277,7 @@ _codecs_raw_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ss } } else { - _PyArg_BadArgument("raw_unicode_escape_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("raw_unicode_escape_decode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1318,7 +1318,7 @@ _codecs_latin_1_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("latin_1_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("latin_1_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1339,7 +1339,7 @@ _codecs_latin_1_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs } } else { - _PyArg_BadArgument("latin_1_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("latin_1_decode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1380,7 +1380,7 @@ _codecs_ascii_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("ascii_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("ascii_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1401,7 +1401,7 @@ _codecs_ascii_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("ascii_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("ascii_decode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1443,7 +1443,7 @@ _codecs_charmap_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("charmap_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("charmap_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1464,7 +1464,7 @@ _codecs_charmap_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs } } else { - _PyArg_BadArgument("charmap_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("charmap_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1512,7 +1512,7 @@ _codecs_mbcs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("mbcs_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("mbcs_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1533,7 +1533,7 @@ _codecs_mbcs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("mbcs_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("mbcs_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1591,7 +1591,7 @@ _codecs_oem_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("oem_decode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("oem_decode", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -1612,7 +1612,7 @@ _codecs_oem_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("oem_decode", 2, "str or None", args[1]); + _PyArg_BadArgument("oem_decode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -1680,7 +1680,7 @@ _codecs_code_page_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("code_page_decode", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("code_page_decode", "argument 2", "contiguous buffer", args[1]); goto exit; } if (nargs < 3) { @@ -1701,7 +1701,7 @@ _codecs_code_page_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("code_page_decode", 3, "str or None", args[2]); + _PyArg_BadArgument("code_page_decode", "argument 3", "str or None", args[2]); goto exit; } if (nargs < 4) { @@ -1765,7 +1765,7 @@ _codecs_readbuffer_encode(PyObject *module, PyObject *const *args, Py_ssize_t na goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("readbuffer_encode", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("readbuffer_encode", "argument 1", "contiguous buffer", args[0]); goto exit; } } @@ -1787,7 +1787,7 @@ _codecs_readbuffer_encode(PyObject *module, PyObject *const *args, Py_ssize_t na } } else { - _PyArg_BadArgument("readbuffer_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("readbuffer_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1825,7 +1825,7 @@ _codecs_utf_7_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_7_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_7_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -1850,7 +1850,7 @@ _codecs_utf_7_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_7_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_7_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1883,7 +1883,7 @@ _codecs_utf_8_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_8_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_8_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -1908,7 +1908,7 @@ _codecs_utf_8_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_8_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_8_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -1942,7 +1942,7 @@ _codecs_utf_16_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_16_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_16_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -1967,7 +1967,7 @@ _codecs_utf_16_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_16_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_encode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -2012,7 +2012,7 @@ _codecs_utf_16_le_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_16_le_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_16_le_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2037,7 +2037,7 @@ _codecs_utf_16_le_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_16_le_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_le_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2070,7 +2070,7 @@ _codecs_utf_16_be_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_16_be_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_16_be_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2095,7 +2095,7 @@ _codecs_utf_16_be_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_16_be_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_16_be_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2129,7 +2129,7 @@ _codecs_utf_32_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_32_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_32_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2154,7 +2154,7 @@ _codecs_utf_32_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("utf_32_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_encode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -2199,7 +2199,7 @@ _codecs_utf_32_le_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_32_le_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_32_le_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2224,7 +2224,7 @@ _codecs_utf_32_le_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_32_le_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_le_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2257,7 +2257,7 @@ _codecs_utf_32_be_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("utf_32_be_encode", 1, "str", args[0]); + _PyArg_BadArgument("utf_32_be_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2282,7 +2282,7 @@ _codecs_utf_32_be_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("utf_32_be_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("utf_32_be_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2315,7 +2315,7 @@ _codecs_unicode_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_ goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("unicode_escape_encode", 1, "str", args[0]); + _PyArg_BadArgument("unicode_escape_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2340,7 +2340,7 @@ _codecs_unicode_escape_encode(PyObject *module, PyObject *const *args, Py_ssize_ } } else { - _PyArg_BadArgument("unicode_escape_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("unicode_escape_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2373,7 +2373,7 @@ _codecs_raw_unicode_escape_encode(PyObject *module, PyObject *const *args, Py_ss goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("raw_unicode_escape_encode", 1, "str", args[0]); + _PyArg_BadArgument("raw_unicode_escape_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2398,7 +2398,7 @@ _codecs_raw_unicode_escape_encode(PyObject *module, PyObject *const *args, Py_ss } } else { - _PyArg_BadArgument("raw_unicode_escape_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("raw_unicode_escape_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2431,7 +2431,7 @@ _codecs_latin_1_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("latin_1_encode", 1, "str", args[0]); + _PyArg_BadArgument("latin_1_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2456,7 +2456,7 @@ _codecs_latin_1_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs } } else { - _PyArg_BadArgument("latin_1_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("latin_1_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2489,7 +2489,7 @@ _codecs_ascii_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("ascii_encode", 1, "str", args[0]); + _PyArg_BadArgument("ascii_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2514,7 +2514,7 @@ _codecs_ascii_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("ascii_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("ascii_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2548,7 +2548,7 @@ _codecs_charmap_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("charmap_encode", 1, "str", args[0]); + _PyArg_BadArgument("charmap_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2573,7 +2573,7 @@ _codecs_charmap_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs } } else { - _PyArg_BadArgument("charmap_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("charmap_encode", "argument 2", "str or None", args[1]); goto exit; } if (nargs < 3) { @@ -2605,7 +2605,7 @@ _codecs_charmap_build(PyObject *module, PyObject *arg) PyObject *map; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("charmap_build", 0, "str", arg); + _PyArg_BadArgument("charmap_build", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -2642,7 +2642,7 @@ _codecs_mbcs_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("mbcs_encode", 1, "str", args[0]); + _PyArg_BadArgument("mbcs_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2667,7 +2667,7 @@ _codecs_mbcs_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("mbcs_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("mbcs_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2703,7 +2703,7 @@ _codecs_oem_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("oem_encode", 1, "str", args[0]); + _PyArg_BadArgument("oem_encode", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -2728,7 +2728,7 @@ _codecs_oem_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("oem_encode", 2, "str or None", args[1]); + _PyArg_BadArgument("oem_encode", "argument 2", "str or None", args[1]); goto exit; } skip_optional: @@ -2775,7 +2775,7 @@ _codecs_code_page_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("code_page_encode", 2, "str", args[1]); + _PyArg_BadArgument("code_page_encode", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -2800,7 +2800,7 @@ _codecs_code_page_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar } } else { - _PyArg_BadArgument("code_page_encode", 3, "str or None", args[2]); + _PyArg_BadArgument("code_page_encode", "argument 3", "str or None", args[2]); goto exit; } skip_optional: @@ -2840,7 +2840,7 @@ _codecs_register_error(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("register_error", 1, "str", args[0]); + _PyArg_BadArgument("register_error", "argument 1", "str", args[0]); goto exit; } Py_ssize_t errors_length; @@ -2881,7 +2881,7 @@ _codecs_lookup_error(PyObject *module, PyObject *arg) const char *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("lookup_error", 0, "str", arg); + _PyArg_BadArgument("lookup_error", "argument", "str", arg); goto exit; } Py_ssize_t name_length; @@ -2922,4 +2922,4 @@ _codecs_lookup_error(PyObject *module, PyObject *arg) #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=da3c47709a55a05e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=59726a305e4ec24a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_cryptmodule.c.h b/Modules/clinic/_cryptmodule.c.h index 2fcb0c1bf12c..ea91d7c130b8 100644 --- a/Modules/clinic/_cryptmodule.c.h +++ b/Modules/clinic/_cryptmodule.c.h @@ -30,7 +30,7 @@ crypt_crypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("crypt", 1, "str", args[0]); + _PyArg_BadArgument("crypt", "argument 1", "str", args[0]); goto exit; } Py_ssize_t word_length; @@ -43,7 +43,7 @@ crypt_crypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("crypt", 2, "str", args[1]); + _PyArg_BadArgument("crypt", "argument 2", "str", args[1]); goto exit; } Py_ssize_t salt_length; @@ -60,4 +60,4 @@ crypt_crypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=3f75d4d4be4dddbb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=549de0d43b030126 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_curses_panel.c.h b/Modules/clinic/_curses_panel.c.h index 0df442056ea9..9840ed86e791 100644 --- a/Modules/clinic/_curses_panel.c.h +++ b/Modules/clinic/_curses_panel.c.h @@ -214,7 +214,7 @@ _curses_panel_panel_replace(PyCursesPanelObject *self, PyObject *arg) PyCursesWindowObject *win; if (!PyObject_TypeCheck(arg, &PyCursesWindow_Type)) { - _PyArg_BadArgument("replace", 0, (&PyCursesWindow_Type)->tp_name, arg); + _PyArg_BadArgument("replace", "argument", (&PyCursesWindow_Type)->tp_name, arg); goto exit; } win = (PyCursesWindowObject *)arg; @@ -288,7 +288,7 @@ _curses_panel_new_panel(PyObject *module, PyObject *arg) PyCursesWindowObject *win; if (!PyObject_TypeCheck(arg, &PyCursesWindow_Type)) { - _PyArg_BadArgument("new_panel", 0, (&PyCursesWindow_Type)->tp_name, arg); + _PyArg_BadArgument("new_panel", "argument", (&PyCursesWindow_Type)->tp_name, arg); goto exit; } win = (PyCursesWindowObject *)arg; @@ -335,4 +335,4 @@ _curses_panel_update_panels(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _curses_panel_update_panels_impl(module); } -/*[clinic end generated code: output=3cc16062281b7e07 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d96dc1fd68e898d9 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index 6837eac39096..ad93e6a0ca02 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -2521,7 +2521,7 @@ _curses_ungetmouse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyLong_Check(args[4])) { - _PyArg_BadArgument("ungetmouse", 5, "int", args[4]); + _PyArg_BadArgument("ungetmouse", "argument 5", "int", args[4]); goto exit; } bstate = PyLong_AsUnsignedLongMask(args[4]); @@ -3017,7 +3017,7 @@ _curses_setupterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO } } else { - _PyArg_BadArgument("setupterm", 1, "str or None", args[0]); + _PyArg_BadArgument("setupterm", "argument 'term'", "str or None", args[0]); goto exit; } if (!--noptargs) { @@ -3326,7 +3326,7 @@ _curses_mousemask(PyObject *module, PyObject *arg) unsigned long newmask; if (!PyLong_Check(arg)) { - _PyArg_BadArgument("mousemask", 0, "int", arg); + _PyArg_BadArgument("mousemask", "argument", "int", arg); goto exit; } newmask = PyLong_AsUnsignedLongMask(arg); @@ -4201,7 +4201,7 @@ _curses_tigetflag(PyObject *module, PyObject *arg) const char *capname; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("tigetflag", 0, "str", arg); + _PyArg_BadArgument("tigetflag", "argument", "str", arg); goto exit; } Py_ssize_t capname_length; @@ -4244,7 +4244,7 @@ _curses_tigetnum(PyObject *module, PyObject *arg) const char *capname; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("tigetnum", 0, "str", arg); + _PyArg_BadArgument("tigetnum", "argument", "str", arg); goto exit; } Py_ssize_t capname_length; @@ -4287,7 +4287,7 @@ _curses_tigetstr(PyObject *module, PyObject *arg) const char *capname; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("tigetstr", 0, "str", arg); + _PyArg_BadArgument("tigetstr", "argument", "str", arg); goto exit; } Py_ssize_t capname_length; @@ -4569,4 +4569,4 @@ _curses_use_default_colors(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF #define _CURSES_USE_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=1350eeb0c1e06af6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e5b3502f1d38dff0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h index e54c69cf7082..a7d735085068 100644 --- a/Modules/clinic/_dbmmodule.c.h +++ b/Modules/clinic/_dbmmodule.c.h @@ -136,7 +136,7 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("open", 1, "str", args[0]); + _PyArg_BadArgument("open", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -147,7 +147,7 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("open", 2, "str", args[1]); + _PyArg_BadArgument("open", "argument 2", "str", args[1]); goto exit; } Py_ssize_t flags_length; @@ -177,4 +177,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=7f5d30ef5d820b8a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7ced103488cbca7a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h index 0f55480140b3..324e549d486a 100644 --- a/Modules/clinic/_elementtree.c.h +++ b/Modules/clinic/_elementtree.c.h @@ -20,7 +20,7 @@ _elementtree_Element_append(ElementObject *self, PyObject *arg) PyObject *subelement; if (!PyObject_TypeCheck(arg, &Element_Type)) { - _PyArg_BadArgument("append", 0, (&Element_Type)->tp_name, arg); + _PyArg_BadArgument("append", "argument", (&Element_Type)->tp_name, arg); goto exit; } subelement = arg; @@ -82,7 +82,7 @@ _elementtree_Element___deepcopy__(ElementObject *self, PyObject *arg) PyObject *memo; if (!PyDict_Check(arg)) { - _PyArg_BadArgument("__deepcopy__", 0, "dict", arg); + _PyArg_BadArgument("__deepcopy__", "argument", "dict", arg); goto exit; } memo = arg; @@ -501,7 +501,7 @@ _elementtree_Element_insert(ElementObject *self, PyObject *const *args, Py_ssize index = ival; } if (!PyObject_TypeCheck(args[1], &Element_Type)) { - _PyArg_BadArgument("insert", 2, (&Element_Type)->tp_name, args[1]); + _PyArg_BadArgument("insert", "argument 2", (&Element_Type)->tp_name, args[1]); goto exit; } subelement = args[1]; @@ -593,7 +593,7 @@ _elementtree_Element_remove(ElementObject *self, PyObject *arg) PyObject *subelement; if (!PyObject_TypeCheck(arg, &Element_Type)) { - _PyArg_BadArgument("remove", 0, (&Element_Type)->tp_name, arg); + _PyArg_BadArgument("remove", "argument", (&Element_Type)->tp_name, arg); goto exit; } subelement = arg; @@ -892,7 +892,7 @@ _elementtree_XMLParser___init__(PyObject *self, PyObject *args, PyObject *kwargs } } else { - _PyArg_BadArgument("XMLParser", 2, "str or None", fastargs[1]); + _PyArg_BadArgument("XMLParser", "argument 'encoding'", "str or None", fastargs[1]); goto exit; } skip_optional_kwonly: @@ -969,4 +969,4 @@ _elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=386a68425d072b5c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=50e0b1954c5f9e0f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h index 15f47dc70dc6..aa37a24d3b21 100644 --- a/Modules/clinic/_gdbmmodule.c.h +++ b/Modules/clinic/_gdbmmodule.c.h @@ -257,7 +257,7 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("open", 1, "str", args[0]); + _PyArg_BadArgument("open", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -268,7 +268,7 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("open", 2, "str", args[1]); + _PyArg_BadArgument("open", "argument 2", "str", args[1]); goto exit; } Py_ssize_t flags_length; @@ -298,4 +298,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=0a72598e5a3acd60 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2766471b2fa1a816 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h index 5596f13e508f..6377e18ece7a 100644 --- a/Modules/clinic/_hashopenssl.c.h +++ b/Modules/clinic/_hashopenssl.c.h @@ -145,7 +145,7 @@ pbkdf2_hmac(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("pbkdf2_hmac", 1, "str", args[0]); + _PyArg_BadArgument("pbkdf2_hmac", "argument 'hash_name'", "str", args[0]); goto exit; } Py_ssize_t hash_name_length; @@ -161,14 +161,14 @@ pbkdf2_hmac(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyBuffer_IsContiguous(&password, 'C')) { - _PyArg_BadArgument("pbkdf2_hmac", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("pbkdf2_hmac", "argument 'password'", "contiguous buffer", args[1]); goto exit; } if (PyObject_GetBuffer(args[2], &salt, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("pbkdf2_hmac", 3, "contiguous buffer", args[2]); + _PyArg_BadArgument("pbkdf2_hmac", "argument 'salt'", "contiguous buffer", args[2]); goto exit; } if (PyFloat_Check(args[3])) { @@ -243,7 +243,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyBuffer_IsContiguous(&password, 'C')) { - _PyArg_BadArgument("scrypt", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("scrypt", "argument 'password'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -254,7 +254,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyBuffer_IsContiguous(&salt, 'C')) { - _PyArg_BadArgument("scrypt", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("scrypt", "argument 'salt'", "contiguous buffer", args[1]); goto exit; } if (!--noptargs) { @@ -263,7 +263,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } if (args[2]) { if (!PyLong_Check(args[2])) { - _PyArg_BadArgument("scrypt", 3, "int", args[2]); + _PyArg_BadArgument("scrypt", "argument 'n'", "int", args[2]); goto exit; } n_obj = args[2]; @@ -273,7 +273,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } if (args[3]) { if (!PyLong_Check(args[3])) { - _PyArg_BadArgument("scrypt", 4, "int", args[3]); + _PyArg_BadArgument("scrypt", "argument 'r'", "int", args[3]); goto exit; } r_obj = args[3]; @@ -283,7 +283,7 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } if (args[4]) { if (!PyLong_Check(args[4])) { - _PyArg_BadArgument("scrypt", 5, "int", args[4]); + _PyArg_BadArgument("scrypt", "argument 'p'", "int", args[4]); goto exit; } p_obj = args[4]; @@ -364,18 +364,18 @@ _hashlib_hmac_digest(PyObject *module, PyObject *const *args, Py_ssize_t nargs, goto exit; } if (!PyBuffer_IsContiguous(&key, 'C')) { - _PyArg_BadArgument("hmac_digest", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("hmac_digest", "argument 'key'", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &msg, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&msg, 'C')) { - _PyArg_BadArgument("hmac_digest", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("hmac_digest", "argument 'msg'", "contiguous buffer", args[1]); goto exit; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("hmac_digest", 3, "str", args[2]); + _PyArg_BadArgument("hmac_digest", "argument 'digest'", "str", args[2]); goto exit; } Py_ssize_t digest_length; @@ -409,4 +409,4 @@ _hashlib_hmac_digest(PyObject *module, PyObject *const *args, Py_ssize_t nargs, #ifndef _HASHLIB_SCRYPT_METHODDEF #define _HASHLIB_SCRYPT_METHODDEF #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ -/*[clinic end generated code: output=5955ec791260045a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=565dcbe3452e71f4 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_lzmamodule.c.h b/Modules/clinic/_lzmamodule.c.h index 68aa770d41f8..82ef4d517d83 100644 --- a/Modules/clinic/_lzmamodule.c.h +++ b/Modules/clinic/_lzmamodule.c.h @@ -29,7 +29,7 @@ _lzma_LZMACompressor_compress(Compressor *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", 0, "contiguous buffer", arg); + _PyArg_BadArgument("compress", "argument", "contiguous buffer", arg); goto exit; } return_value = _lzma_LZMACompressor_compress_impl(self, &data); @@ -110,7 +110,7 @@ _lzma_LZMADecompressor_decompress(Decompressor *self, PyObject *const *args, Py_ goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decompress", "argument 'data'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -321,7 +321,7 @@ _lzma__decode_filter_properties(PyObject *module, PyObject *const *args, Py_ssiz goto exit; } if (!PyBuffer_IsContiguous(&encoded_props, 'C')) { - _PyArg_BadArgument("_decode_filter_properties", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("_decode_filter_properties", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = _lzma__decode_filter_properties_impl(module, filter_id, &encoded_props); @@ -334,4 +334,4 @@ _lzma__decode_filter_properties(PyObject *module, PyObject *const *args, Py_ssiz return return_value; } -/*[clinic end generated code: output=1a290aa478603107 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f7477a10e86a717d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_pickle.c.h b/Modules/clinic/_pickle.c.h index 8ac723fd43a6..b92daa72105a 100644 --- a/Modules/clinic/_pickle.c.h +++ b/Modules/clinic/_pickle.c.h @@ -356,7 +356,7 @@ _pickle_Unpickler___init__(PyObject *self, PyObject *args, PyObject *kwargs) } if (fastargs[2]) { if (!PyUnicode_Check(fastargs[2])) { - _PyArg_BadArgument("Unpickler", 3, "str", fastargs[2]); + _PyArg_BadArgument("Unpickler", "argument 'encoding'", "str", fastargs[2]); goto exit; } Py_ssize_t encoding_length; @@ -374,7 +374,7 @@ _pickle_Unpickler___init__(PyObject *self, PyObject *args, PyObject *kwargs) } if (fastargs[3]) { if (!PyUnicode_Check(fastargs[3])) { - _PyArg_BadArgument("Unpickler", 4, "str", fastargs[3]); + _PyArg_BadArgument("Unpickler", "argument 'errors'", "str", fastargs[3]); goto exit; } Py_ssize_t errors_length; @@ -691,7 +691,7 @@ _pickle_load(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject } if (args[2]) { if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("load", 3, "str", args[2]); + _PyArg_BadArgument("load", "argument 'encoding'", "str", args[2]); goto exit; } Py_ssize_t encoding_length; @@ -709,7 +709,7 @@ _pickle_load(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject } if (args[3]) { if (!PyUnicode_Check(args[3])) { - _PyArg_BadArgument("load", 4, "str", args[3]); + _PyArg_BadArgument("load", "argument 'errors'", "str", args[3]); goto exit; } Py_ssize_t errors_length; @@ -794,7 +794,7 @@ _pickle_loads(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec } if (args[2]) { if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("loads", 3, "str", args[2]); + _PyArg_BadArgument("loads", "argument 'encoding'", "str", args[2]); goto exit; } Py_ssize_t encoding_length; @@ -812,7 +812,7 @@ _pickle_loads(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec } if (args[3]) { if (!PyUnicode_Check(args[3])) { - _PyArg_BadArgument("loads", 4, "str", args[3]); + _PyArg_BadArgument("loads", "argument 'errors'", "str", args[3]); goto exit; } Py_ssize_t errors_length; @@ -835,4 +835,4 @@ _pickle_loads(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=8dc0e862f96c4afe input=a9049054013a1b77]*/ +/*[clinic end generated code: output=17f6a76ebd94325d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_sre.c.h b/Modules/clinic/_sre.c.h index 9c08dec4541a..d398a8504ba4 100644 --- a/Modules/clinic/_sre.c.h +++ b/Modules/clinic/_sre.c.h @@ -894,7 +894,7 @@ _sre_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyList_Check(args[2])) { - _PyArg_BadArgument("compile", 3, "list", args[2]); + _PyArg_BadArgument("compile", "argument 'code'", "list", args[2]); goto exit; } code = args[2]; @@ -916,12 +916,12 @@ _sre_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject groups = ival; } if (!PyDict_Check(args[4])) { - _PyArg_BadArgument("compile", 5, "dict", args[4]); + _PyArg_BadArgument("compile", "argument 'groupindex'", "dict", args[4]); goto exit; } groupindex = args[4]; if (!PyTuple_Check(args[5])) { - _PyArg_BadArgument("compile", 6, "tuple", args[5]); + _PyArg_BadArgument("compile", "argument 'indexgroup'", "tuple", args[5]); goto exit; } indexgroup = args[5]; @@ -1207,4 +1207,4 @@ _sre_SRE_Scanner_search(ScannerObject *self, PyObject *Py_UNUSED(ignored)) { return _sre_SRE_Scanner_search_impl(self); } -/*[clinic end generated code: output=67b702da5bdc9cac input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1adeddce58ae284c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index adef7dbf90ce..25769a225af9 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -222,7 +222,7 @@ _ssl__SSLSocket_write(PySSLSocket *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", 0, "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); goto exit; } return_value = _ssl__SSLSocket_write_impl(self, &b); @@ -353,7 +353,7 @@ _ssl__SSLSocket_get_channel_binding(PySSLSocket *self, PyObject *const *args, Py goto skip_optional_pos; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("get_channel_binding", 1, "str", args[0]); + _PyArg_BadArgument("get_channel_binding", "argument 'cb_type'", "str", args[0]); goto exit; } Py_ssize_t cb_type_length; @@ -439,7 +439,7 @@ _ssl__SSLContext_set_ciphers(PySSLContext *self, PyObject *arg) const char *cipherlist; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("set_ciphers", 0, "str", arg); + _PyArg_BadArgument("set_ciphers", "argument", "str", arg); goto exit; } Py_ssize_t cipherlist_length; @@ -500,7 +500,7 @@ _ssl__SSLContext__set_npn_protocols(PySSLContext *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&protos, 'C')) { - _PyArg_BadArgument("_set_npn_protocols", 0, "contiguous buffer", arg); + _PyArg_BadArgument("_set_npn_protocols", "argument", "contiguous buffer", arg); goto exit; } return_value = _ssl__SSLContext__set_npn_protocols_impl(self, &protos); @@ -536,7 +536,7 @@ _ssl__SSLContext__set_alpn_protocols(PySSLContext *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&protos, 'C')) { - _PyArg_BadArgument("_set_alpn_protocols", 0, "contiguous buffer", arg); + _PyArg_BadArgument("_set_alpn_protocols", "argument", "contiguous buffer", arg); goto exit; } return_value = _ssl__SSLContext__set_alpn_protocols_impl(self, &protos); @@ -690,7 +690,7 @@ _ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *const *args, Py_ssiz goto exit; } if (!PyObject_TypeCheck(args[0], PySocketModule.Sock_Type)) { - _PyArg_BadArgument("_wrap_socket", 1, (PySocketModule.Sock_Type)->tp_name, args[0]); + _PyArg_BadArgument("_wrap_socket", "argument 'sock'", (PySocketModule.Sock_Type)->tp_name, args[0]); goto exit; } sock = args[0]; @@ -765,12 +765,12 @@ _ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *const *args, Py_ssize_t goto exit; } if (!PyObject_TypeCheck(args[0], &PySSLMemoryBIO_Type)) { - _PyArg_BadArgument("_wrap_bio", 1, (&PySSLMemoryBIO_Type)->tp_name, args[0]); + _PyArg_BadArgument("_wrap_bio", "argument 'incoming'", (&PySSLMemoryBIO_Type)->tp_name, args[0]); goto exit; } incoming = (PySSLMemoryBIO *)args[0]; if (!PyObject_TypeCheck(args[1], &PySSLMemoryBIO_Type)) { - _PyArg_BadArgument("_wrap_bio", 2, (&PySSLMemoryBIO_Type)->tp_name, args[1]); + _PyArg_BadArgument("_wrap_bio", "argument 'outgoing'", (&PySSLMemoryBIO_Type)->tp_name, args[1]); goto exit; } outgoing = (PySSLMemoryBIO *)args[1]; @@ -1017,7 +1017,7 @@ _ssl_MemoryBIO_write(PySSLMemoryBIO *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", 0, "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); goto exit; } return_value = _ssl_MemoryBIO_write_impl(self, &b); @@ -1089,7 +1089,7 @@ _ssl_RAND_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&view, 'C')) { - _PyArg_BadArgument("RAND_add", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("RAND_add", "argument 1", "contiguous buffer", args[0]); goto exit; } } @@ -1289,7 +1289,7 @@ _ssl_txt2obj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("txt2obj", 1, "str", args[0]); + _PyArg_BadArgument("txt2obj", "argument 'txt'", "str", args[0]); goto exit; } Py_ssize_t txt_length; @@ -1382,7 +1382,7 @@ _ssl_enum_certificates(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("enum_certificates", 1, "str", args[0]); + _PyArg_BadArgument("enum_certificates", "argument 'store_name'", "str", args[0]); goto exit; } Py_ssize_t store_name_length; @@ -1435,7 +1435,7 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("enum_crls", 1, "str", args[0]); + _PyArg_BadArgument("enum_crls", "argument 'store_name'", "str", args[0]); goto exit; } Py_ssize_t store_name_length; @@ -1482,4 +1482,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=5003112e167cd948 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=aa4947067c3fef2d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h index 908c44266c4e..36c4b4046cd7 100644 --- a/Modules/clinic/_struct.c.h +++ b/Modules/clinic/_struct.c.h @@ -65,7 +65,7 @@ Struct_unpack(PyStructObject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack", 0, "contiguous buffer", arg); + _PyArg_BadArgument("unpack", "argument", "contiguous buffer", arg); goto exit; } return_value = Struct_unpack_impl(self, &buffer); @@ -118,7 +118,7 @@ Struct_unpack_from(PyStructObject *self, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack_from", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("unpack_from", "argument 'buffer'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -253,7 +253,7 @@ unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("unpack", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = unpack_impl(module, s_object, &buffer); @@ -309,7 +309,7 @@ unpack_from(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("unpack_from", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("unpack_from", "argument 'buffer'", "contiguous buffer", args[1]); goto exit; } if (!noptargs) { @@ -386,4 +386,4 @@ iter_unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=b642e1002d25ebdd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6a6228cfc4b7099c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_tkinter.c.h b/Modules/clinic/_tkinter.c.h index 0a3e7ff5fc96..4870e9b4aad7 100644 --- a/Modules/clinic/_tkinter.c.h +++ b/Modules/clinic/_tkinter.c.h @@ -20,7 +20,7 @@ _tkinter_tkapp_eval(TkappObject *self, PyObject *arg) const char *script; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("eval", 0, "str", arg); + _PyArg_BadArgument("eval", "argument", "str", arg); goto exit; } Py_ssize_t script_length; @@ -56,7 +56,7 @@ _tkinter_tkapp_evalfile(TkappObject *self, PyObject *arg) const char *fileName; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("evalfile", 0, "str", arg); + _PyArg_BadArgument("evalfile", "argument", "str", arg); goto exit; } Py_ssize_t fileName_length; @@ -92,7 +92,7 @@ _tkinter_tkapp_record(TkappObject *self, PyObject *arg) const char *script; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("record", 0, "str", arg); + _PyArg_BadArgument("record", "argument", "str", arg); goto exit; } Py_ssize_t script_length; @@ -128,7 +128,7 @@ _tkinter_tkapp_adderrorinfo(TkappObject *self, PyObject *arg) const char *msg; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("adderrorinfo", 0, "str", arg); + _PyArg_BadArgument("adderrorinfo", "argument", "str", arg); goto exit; } Py_ssize_t msg_length; @@ -188,7 +188,7 @@ _tkinter_tkapp_exprstring(TkappObject *self, PyObject *arg) const char *s; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("exprstring", 0, "str", arg); + _PyArg_BadArgument("exprstring", "argument", "str", arg); goto exit; } Py_ssize_t s_length; @@ -224,7 +224,7 @@ _tkinter_tkapp_exprlong(TkappObject *self, PyObject *arg) const char *s; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("exprlong", 0, "str", arg); + _PyArg_BadArgument("exprlong", "argument", "str", arg); goto exit; } Py_ssize_t s_length; @@ -260,7 +260,7 @@ _tkinter_tkapp_exprdouble(TkappObject *self, PyObject *arg) const char *s; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("exprdouble", 0, "str", arg); + _PyArg_BadArgument("exprdouble", "argument", "str", arg); goto exit; } Py_ssize_t s_length; @@ -296,7 +296,7 @@ _tkinter_tkapp_exprboolean(TkappObject *self, PyObject *arg) const char *s; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("exprboolean", 0, "str", arg); + _PyArg_BadArgument("exprboolean", "argument", "str", arg); goto exit; } Py_ssize_t s_length; @@ -353,7 +353,7 @@ _tkinter_tkapp_createcommand(TkappObject *self, PyObject *const *args, Py_ssize_ goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("createcommand", 1, "str", args[0]); + _PyArg_BadArgument("createcommand", "argument 1", "str", args[0]); goto exit; } Py_ssize_t name_length; @@ -390,7 +390,7 @@ _tkinter_tkapp_deletecommand(TkappObject *self, PyObject *arg) const char *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("deletecommand", 0, "str", arg); + _PyArg_BadArgument("deletecommand", "argument", "str", arg); goto exit; } Py_ssize_t name_length; @@ -731,14 +731,14 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("create", 1, "str or None", args[0]); + _PyArg_BadArgument("create", "argument 1", "str or None", args[0]); goto exit; } if (nargs < 2) { goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("create", 2, "str", args[1]); + _PyArg_BadArgument("create", "argument 2", "str", args[1]); goto exit; } Py_ssize_t baseName_length; @@ -754,7 +754,7 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("create", 3, "str", args[2]); + _PyArg_BadArgument("create", "argument 3", "str", args[2]); goto exit; } Py_ssize_t className_length; @@ -832,7 +832,7 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } } else { - _PyArg_BadArgument("create", 8, "str or None", args[7]); + _PyArg_BadArgument("create", "argument 8", "str or None", args[7]); goto exit; } skip_optional: @@ -912,4 +912,4 @@ _tkinter_getbusywaitinterval(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF #define _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF #endif /* !defined(_TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF) */ -/*[clinic end generated code: output=2cf95f0101f3dbca input=a9049054013a1b77]*/ +/*[clinic end generated code: output=da0115c470aac1c0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_weakref.c.h b/Modules/clinic/_weakref.c.h index aa0d77f7180e..c3a908fa6a13 100644 --- a/Modules/clinic/_weakref.c.h +++ b/Modules/clinic/_weakref.c.h @@ -54,7 +54,7 @@ _weakref__remove_dead_weakref(PyObject *module, PyObject *const *args, Py_ssize_ goto exit; } if (!PyDict_Check(args[0])) { - _PyArg_BadArgument("_remove_dead_weakref", 1, "dict", args[0]); + _PyArg_BadArgument("_remove_dead_weakref", "argument 1", "dict", args[0]); goto exit; } dct = args[0]; @@ -64,4 +64,4 @@ _weakref__remove_dead_weakref(PyObject *module, PyObject *const *args, Py_ssize_ exit: return return_value; } -/*[clinic end generated code: output=eae22e2d2e43120e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c543dc2cd6ece975 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h index 5f45b7cf6734..33f82d4da8b6 100644 --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -345,7 +345,7 @@ array_array_fromstring(arrayobject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("fromstring", 0, "contiguous buffer", arg); + _PyArg_BadArgument("fromstring", "argument", "contiguous buffer", arg); goto exit; } } @@ -382,7 +382,7 @@ array_array_frombytes(arrayobject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("frombytes", 0, "contiguous buffer", arg); + _PyArg_BadArgument("frombytes", "argument", "contiguous buffer", arg); goto exit; } return_value = array_array_frombytes_impl(self, &buffer); @@ -537,14 +537,14 @@ array__array_reconstructor(PyObject *module, PyObject *const *args, Py_ssize_t n } arraytype = (PyTypeObject *)args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("_array_reconstructor", 2, "a unicode character", args[1]); + _PyArg_BadArgument("_array_reconstructor", "argument 2", "a unicode character", args[1]); goto exit; } if (PyUnicode_READY(args[1])) { goto exit; } if (PyUnicode_GET_LENGTH(args[1]) != 1) { - _PyArg_BadArgument("_array_reconstructor", 2, "a unicode character", args[1]); + _PyArg_BadArgument("_array_reconstructor", "argument 2", "a unicode character", args[1]); goto exit; } typecode = PyUnicode_READ_CHAR(args[1], 0); @@ -599,4 +599,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__, #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=c9a40f11f1a866fb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6aa421571e2c0756 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/audioop.c.h b/Modules/clinic/audioop.c.h index aa176964b0f3..8745533eeb62 100644 --- a/Modules/clinic/audioop.c.h +++ b/Modules/clinic/audioop.c.h @@ -30,7 +30,7 @@ audioop_getsample(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("getsample", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("getsample", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -96,7 +96,7 @@ audioop_max(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("max", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("max", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -145,7 +145,7 @@ audioop_minmax(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("minmax", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("minmax", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -194,7 +194,7 @@ audioop_avg(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("avg", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("avg", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -243,7 +243,7 @@ audioop_rms(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("rms", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("rms", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -293,14 +293,14 @@ audioop_findfit(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("findfit", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("findfit", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &reference, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&reference, 'C')) { - _PyArg_BadArgument("findfit", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("findfit", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = audioop_findfit_impl(module, &fragment, &reference); @@ -345,14 +345,14 @@ audioop_findfactor(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("findfactor", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("findfactor", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &reference, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&reference, 'C')) { - _PyArg_BadArgument("findfactor", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("findfactor", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = audioop_findfactor_impl(module, &fragment, &reference); @@ -397,7 +397,7 @@ audioop_findmax(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("findmax", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("findmax", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -454,7 +454,7 @@ audioop_avgpp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("avgpp", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("avgpp", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -503,7 +503,7 @@ audioop_maxpp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("maxpp", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("maxpp", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -552,7 +552,7 @@ audioop_cross(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("cross", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("cross", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -603,7 +603,7 @@ audioop_mul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("mul", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("mul", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -665,7 +665,7 @@ audioop_tomono(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("tomono", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("tomono", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -737,7 +737,7 @@ audioop_tostereo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("tostereo", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("tostereo", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -808,14 +808,14 @@ audioop_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment1, 'C')) { - _PyArg_BadArgument("add", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("add", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &fragment2, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&fragment2, 'C')) { - _PyArg_BadArgument("add", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("add", "argument 2", "contiguous buffer", args[1]); goto exit; } if (PyFloat_Check(args[2])) { @@ -869,7 +869,7 @@ audioop_bias(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("bias", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("bias", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -927,7 +927,7 @@ audioop_reverse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("reverse", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("reverse", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -976,7 +976,7 @@ audioop_byteswap(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("byteswap", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("byteswap", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1027,7 +1027,7 @@ audioop_lin2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("lin2lin", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("lin2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1094,7 +1094,7 @@ audioop_ratecv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("ratecv", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("ratecv", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1196,7 +1196,7 @@ audioop_lin2ulaw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("lin2ulaw", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("lin2ulaw", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1245,7 +1245,7 @@ audioop_ulaw2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("ulaw2lin", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("ulaw2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1294,7 +1294,7 @@ audioop_lin2alaw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("lin2alaw", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("lin2alaw", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1343,7 +1343,7 @@ audioop_alaw2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("alaw2lin", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("alaw2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1394,7 +1394,7 @@ audioop_lin2adpcm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("lin2adpcm", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("lin2adpcm", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1446,7 +1446,7 @@ audioop_adpcm2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&fragment, 'C')) { - _PyArg_BadArgument("adpcm2lin", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("adpcm2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -1469,4 +1469,4 @@ audioop_adpcm2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=af32f4bce9c934fa input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6b4f2c597f295abc input=a9049054013a1b77]*/ diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index d48504856902..e18d407ba9e8 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -64,7 +64,7 @@ binascii_b2a_uu(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_uu", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("b2a_uu", "argument 1", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -153,7 +153,7 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_base64", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("b2a_base64", "argument 1", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -233,7 +233,7 @@ binascii_rlecode_hqx(PyObject *module, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("rlecode_hqx", 0, "contiguous buffer", arg); + _PyArg_BadArgument("rlecode_hqx", "argument", "contiguous buffer", arg); goto exit; } return_value = binascii_rlecode_hqx_impl(module, &data); @@ -269,7 +269,7 @@ binascii_b2a_hqx(PyObject *module, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_hqx", 0, "contiguous buffer", arg); + _PyArg_BadArgument("b2a_hqx", "argument", "contiguous buffer", arg); goto exit; } return_value = binascii_b2a_hqx_impl(module, &data); @@ -305,7 +305,7 @@ binascii_rledecode_hqx(PyObject *module, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("rledecode_hqx", 0, "contiguous buffer", arg); + _PyArg_BadArgument("rledecode_hqx", "argument", "contiguous buffer", arg); goto exit; } return_value = binascii_rledecode_hqx_impl(module, &data); @@ -346,7 +346,7 @@ binascii_crc_hqx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("crc_hqx", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("crc_hqx", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyFloat_Check(args[1])) { @@ -400,7 +400,7 @@ binascii_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("crc32", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("crc32", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -481,7 +481,7 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_hex", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("b2a_hex", "argument 'data'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -556,7 +556,7 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("hexlify", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("hexlify", "argument 'data'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -747,7 +747,7 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("b2a_qp", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("b2a_qp", "argument 'data'", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -801,4 +801,4 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj return return_value; } -/*[clinic end generated code: output=f7b8049edb130c63 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e13bd02ac40496f0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/grpmodule.c.h b/Modules/clinic/grpmodule.c.h index ae99c50955f6..2e2690ad8d3f 100644 --- a/Modules/clinic/grpmodule.c.h +++ b/Modules/clinic/grpmodule.c.h @@ -64,7 +64,7 @@ grp_getgrnam(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("getgrnam", 1, "str", args[0]); + _PyArg_BadArgument("getgrnam", "argument 'name'", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -97,4 +97,4 @@ grp_getgrall(PyObject *module, PyObject *Py_UNUSED(ignored)) { return grp_getgrall_impl(module); } -/*[clinic end generated code: output=2aa6c60873d41ee8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9b3f26779e4e1a52 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index b43ce64af0dc..20594b0fed4c 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -66,7 +66,7 @@ itertools__grouper(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), &groupby_type)) { - _PyArg_BadArgument("_grouper", 1, (&groupby_type)->tp_name, PyTuple_GET_ITEM(args, 0)); + _PyArg_BadArgument("_grouper", "argument 1", (&groupby_type)->tp_name, PyTuple_GET_ITEM(args, 0)); goto exit; } parent = PyTuple_GET_ITEM(args, 0); @@ -104,7 +104,7 @@ itertools_teedataobject(PyTypeObject *type, PyObject *args, PyObject *kwargs) } it = PyTuple_GET_ITEM(args, 0); if (!PyList_Check(PyTuple_GET_ITEM(args, 1))) { - _PyArg_BadArgument("teedataobject", 2, "list", PyTuple_GET_ITEM(args, 1)); + _PyArg_BadArgument("teedataobject", "argument 2", "list", PyTuple_GET_ITEM(args, 1)); goto exit; } values = PyTuple_GET_ITEM(args, 1); @@ -642,4 +642,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=04c49debcae96003 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=392c9706e79f6710 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 5c674db3c3a5..1a5b03cb5be1 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -616,7 +616,7 @@ os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * goto exit; } if (!PyLong_Check(args[1])) { - _PyArg_BadArgument("chflags", 2, "int", args[1]); + _PyArg_BadArgument("chflags", "argument 'flags'", "int", args[1]); goto exit; } flags = PyLong_AsUnsignedLongMask(args[1]); @@ -674,7 +674,7 @@ os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyLong_Check(args[1])) { - _PyArg_BadArgument("lchflags", 2, "int", args[1]); + _PyArg_BadArgument("lchflags", "argument 'flags'", "int", args[1]); goto exit; } flags = PyLong_AsUnsignedLongMask(args[1]); @@ -4956,7 +4956,7 @@ os_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("write", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("write", "argument 2", "contiguous buffer", args[1]); goto exit; } _return_value = os_write_impl(module, fd, &data); @@ -5279,7 +5279,7 @@ os_pwrite(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("pwrite", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("pwrite", "argument 2", "contiguous buffer", args[1]); goto exit; } if (!Py_off_t_converter(args[2], &offset)) { @@ -6012,7 +6012,7 @@ os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("putenv", 1, "str", args[0]); + _PyArg_BadArgument("putenv", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -6020,7 +6020,7 @@ os_putenv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } name = args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("putenv", 2, "str", args[1]); + _PyArg_BadArgument("putenv", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -7216,7 +7216,7 @@ os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } if (!PyBuffer_IsContiguous(&value, 'C')) { - _PyArg_BadArgument("setxattr", 3, "contiguous buffer", args[2]); + _PyArg_BadArgument("setxattr", "argument 'value'", "contiguous buffer", args[2]); goto exit; } if (!noptargs) { @@ -8724,4 +8724,4 @@ os__remove_dll_directory(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF #define OS__REMOVE_DLL_DIRECTORY_METHODDEF #endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */ -/*[clinic end generated code: output=366a1de4c9c61a30 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ba6bac1702f55dbb input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pwdmodule.c.h b/Modules/clinic/pwdmodule.c.h index cf84ec959d58..cb83062495dc 100644 --- a/Modules/clinic/pwdmodule.c.h +++ b/Modules/clinic/pwdmodule.c.h @@ -34,7 +34,7 @@ pwd_getpwnam(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("getpwnam", 0, "str", arg); + _PyArg_BadArgument("getpwnam", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -74,4 +74,4 @@ pwd_getpwall(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef PWD_GETPWALL_METHODDEF #define PWD_GETPWALL_METHODDEF #endif /* !defined(PWD_GETPWALL_METHODDEF) */ -/*[clinic end generated code: output=f9412bdedc69706c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7fceab7f1a85da36 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h index dfb27d5f1114..41ab536bce23 100644 --- a/Modules/clinic/pyexpat.c.h +++ b/Modules/clinic/pyexpat.c.h @@ -75,7 +75,7 @@ pyexpat_xmlparser_SetBase(xmlparseobject *self, PyObject *arg) const char *base; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("SetBase", 0, "str", arg); + _PyArg_BadArgument("SetBase", "argument", "str", arg); goto exit; } Py_ssize_t base_length; @@ -171,14 +171,14 @@ pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyObject *con } } else { - _PyArg_BadArgument("ExternalEntityParserCreate", 1, "str or None", args[0]); + _PyArg_BadArgument("ExternalEntityParserCreate", "argument 1", "str or None", args[0]); goto exit; } if (nargs < 2) { goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("ExternalEntityParserCreate", 2, "str", args[1]); + _PyArg_BadArgument("ExternalEntityParserCreate", "argument 2", "str", args[1]); goto exit; } Py_ssize_t encoding_length; @@ -327,7 +327,7 @@ pyexpat_ParserCreate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } } else { - _PyArg_BadArgument("ParserCreate", 1, "str or None", args[0]); + _PyArg_BadArgument("ParserCreate", "argument 'encoding'", "str or None", args[0]); goto exit; } if (!--noptargs) { @@ -350,7 +350,7 @@ pyexpat_ParserCreate(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } } else { - _PyArg_BadArgument("ParserCreate", 2, "str or None", args[1]); + _PyArg_BadArgument("ParserCreate", "argument 'namespace_separator'", "str or None", args[1]); goto exit; } if (!--noptargs) { @@ -401,4 +401,4 @@ pyexpat_ErrorString(PyObject *module, PyObject *arg) #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=e48f37d326956bdd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=133a4105d508ebec input=a9049054013a1b77]*/ diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index bc46515cb436..3cb1db14878c 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -590,7 +590,7 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyLong_Check(args[0])) { - _PyArg_BadArgument("pthread_kill", 1, "int", args[0]); + _PyArg_BadArgument("pthread_kill", "argument 1", "int", args[0]); goto exit; } thread_id = PyLong_AsUnsignedLongMask(args[0]); @@ -658,4 +658,4 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #ifndef SIGNAL_PTHREAD_KILL_METHODDEF #define SIGNAL_PTHREAD_KILL_METHODDEF #endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */ -/*[clinic end generated code: output=f0d3a5703581da76 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3320b8f73c20ba60 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/spwdmodule.c.h b/Modules/clinic/spwdmodule.c.h index e051e6eb6589..411d2344e18f 100644 --- a/Modules/clinic/spwdmodule.c.h +++ b/Modules/clinic/spwdmodule.c.h @@ -25,7 +25,7 @@ spwd_getspnam(PyObject *module, PyObject *arg_) PyObject *arg; if (!PyUnicode_Check(arg_)) { - _PyArg_BadArgument("getspnam", 0, "str", arg_); + _PyArg_BadArgument("getspnam", "argument", "str", arg_); goto exit; } if (PyUnicode_READY(arg_) == -1) { @@ -71,4 +71,4 @@ spwd_getspall(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SPWD_GETSPALL_METHODDEF #define SPWD_GETSPALL_METHODDEF #endif /* !defined(SPWD_GETSPALL_METHODDEF) */ -/*[clinic end generated code: output=2bbaa6bab1d9116e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=eec8d0bedcd312e5 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/symtablemodule.c.h b/Modules/clinic/symtablemodule.c.h index 7d8b0ad300c2..4a17f130ac97 100644 --- a/Modules/clinic/symtablemodule.c.h +++ b/Modules/clinic/symtablemodule.c.h @@ -31,7 +31,7 @@ _symtable_symtable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("symtable", 3, "str", args[2]); + _PyArg_BadArgument("symtable", "argument 3", "str", args[2]); goto exit; } Py_ssize_t startstr_length; @@ -48,4 +48,4 @@ _symtable_symtable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=de655625eee705f4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a12f75cdbdf4e52a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/unicodedata.c.h b/Modules/clinic/unicodedata.c.h index 8ca0881efcf8..77e4f22593b0 100644 --- a/Modules/clinic/unicodedata.c.h +++ b/Modules/clinic/unicodedata.c.h @@ -30,14 +30,14 @@ unicodedata_UCD_decimal(PyObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("decimal", 1, "a unicode character", args[0]); + _PyArg_BadArgument("decimal", "argument 1", "a unicode character", args[0]); goto exit; } if (PyUnicode_READY(args[0])) { goto exit; } if (PyUnicode_GET_LENGTH(args[0]) != 1) { - _PyArg_BadArgument("decimal", 1, "a unicode character", args[0]); + _PyArg_BadArgument("decimal", "argument 1", "a unicode character", args[0]); goto exit; } chr = PyUnicode_READ_CHAR(args[0], 0); @@ -79,14 +79,14 @@ unicodedata_UCD_digit(PyObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("digit", 1, "a unicode character", args[0]); + _PyArg_BadArgument("digit", "argument 1", "a unicode character", args[0]); goto exit; } if (PyUnicode_READY(args[0])) { goto exit; } if (PyUnicode_GET_LENGTH(args[0]) != 1) { - _PyArg_BadArgument("digit", 1, "a unicode character", args[0]); + _PyArg_BadArgument("digit", "argument 1", "a unicode character", args[0]); goto exit; } chr = PyUnicode_READ_CHAR(args[0], 0); @@ -129,14 +129,14 @@ unicodedata_UCD_numeric(PyObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("numeric", 1, "a unicode character", args[0]); + _PyArg_BadArgument("numeric", "argument 1", "a unicode character", args[0]); goto exit; } if (PyUnicode_READY(args[0])) { goto exit; } if (PyUnicode_GET_LENGTH(args[0]) != 1) { - _PyArg_BadArgument("numeric", 1, "a unicode character", args[0]); + _PyArg_BadArgument("numeric", "argument 1", "a unicode character", args[0]); goto exit; } chr = PyUnicode_READ_CHAR(args[0], 0); @@ -170,14 +170,14 @@ unicodedata_UCD_category(PyObject *self, PyObject *arg) int chr; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("category", 0, "a unicode character", arg); + _PyArg_BadArgument("category", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("category", 0, "a unicode character", arg); + _PyArg_BadArgument("category", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -208,14 +208,14 @@ unicodedata_UCD_bidirectional(PyObject *self, PyObject *arg) int chr; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("bidirectional", 0, "a unicode character", arg); + _PyArg_BadArgument("bidirectional", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("bidirectional", 0, "a unicode character", arg); + _PyArg_BadArgument("bidirectional", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -247,14 +247,14 @@ unicodedata_UCD_combining(PyObject *self, PyObject *arg) int _return_value; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("combining", 0, "a unicode character", arg); + _PyArg_BadArgument("combining", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("combining", 0, "a unicode character", arg); + _PyArg_BadArgument("combining", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -291,14 +291,14 @@ unicodedata_UCD_mirrored(PyObject *self, PyObject *arg) int _return_value; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("mirrored", 0, "a unicode character", arg); + _PyArg_BadArgument("mirrored", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("mirrored", 0, "a unicode character", arg); + _PyArg_BadArgument("mirrored", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -331,14 +331,14 @@ unicodedata_UCD_east_asian_width(PyObject *self, PyObject *arg) int chr; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("east_asian_width", 0, "a unicode character", arg); + _PyArg_BadArgument("east_asian_width", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("east_asian_width", 0, "a unicode character", arg); + _PyArg_BadArgument("east_asian_width", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -369,14 +369,14 @@ unicodedata_UCD_decomposition(PyObject *self, PyObject *arg) int chr; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("decomposition", 0, "a unicode character", arg); + _PyArg_BadArgument("decomposition", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("decomposition", 0, "a unicode character", arg); + _PyArg_BadArgument("decomposition", "argument", "a unicode character", arg); goto exit; } chr = PyUnicode_READ_CHAR(arg, 0); @@ -412,7 +412,7 @@ unicodedata_UCD_is_normalized(PyObject *self, PyObject *const *args, Py_ssize_t goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("is_normalized", 1, "str", args[0]); + _PyArg_BadArgument("is_normalized", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -420,7 +420,7 @@ unicodedata_UCD_is_normalized(PyObject *self, PyObject *const *args, Py_ssize_t } form = args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("is_normalized", 2, "str", args[1]); + _PyArg_BadArgument("is_normalized", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -459,7 +459,7 @@ unicodedata_UCD_normalize(PyObject *self, PyObject *const *args, Py_ssize_t narg goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("normalize", 1, "str", args[0]); + _PyArg_BadArgument("normalize", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -467,7 +467,7 @@ unicodedata_UCD_normalize(PyObject *self, PyObject *const *args, Py_ssize_t narg } form = args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("normalize", 2, "str", args[1]); + _PyArg_BadArgument("normalize", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -506,14 +506,14 @@ unicodedata_UCD_name(PyObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("name", 1, "a unicode character", args[0]); + _PyArg_BadArgument("name", "argument 1", "a unicode character", args[0]); goto exit; } if (PyUnicode_READY(args[0])) { goto exit; } if (PyUnicode_GET_LENGTH(args[0]) != 1) { - _PyArg_BadArgument("name", 1, "a unicode character", args[0]); + _PyArg_BadArgument("name", "argument 1", "a unicode character", args[0]); goto exit; } chr = PyUnicode_READ_CHAR(args[0], 0); @@ -559,4 +559,4 @@ unicodedata_UCD_lookup(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=0fc850fe5b6b312c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3238f76814fb48d1 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h index aa579209108d..77ea04a353bf 100644 --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -38,7 +38,7 @@ zlib_compress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("compress", "argument 1", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -105,7 +105,7 @@ zlib_decompress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decompress", "argument 1", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -273,7 +273,7 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto exit; } if (!PyBuffer_IsContiguous(&zdict, 'C')) { - _PyArg_BadArgument("compressobj", 6, "contiguous buffer", args[5]); + _PyArg_BadArgument("compressobj", "argument 'zdict'", "contiguous buffer", args[5]); goto exit; } skip_optional_pos: @@ -375,7 +375,7 @@ zlib_Compress_compress(compobject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", 0, "contiguous buffer", arg); + _PyArg_BadArgument("compress", "argument", "contiguous buffer", arg); goto exit; } return_value = zlib_Compress_compress_impl(self, &data); @@ -432,7 +432,7 @@ zlib_Decompress_decompress(compobject *self, PyObject *const *args, Py_ssize_t n goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("decompress", "argument 1", "contiguous buffer", args[0]); goto exit; } if (!noptargs) { @@ -677,7 +677,7 @@ zlib_adler32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("adler32", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("adler32", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -735,7 +735,7 @@ zlib_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("crc32", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("crc32", "argument 1", "contiguous buffer", args[0]); goto exit; } if (nargs < 2) { @@ -785,4 +785,4 @@ zlib_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #ifndef ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF #define ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF #endif /* !defined(ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF) */ -/*[clinic end generated code: output=feb079cebbbaacd6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=faae38ef96b88b16 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index 08c6eb53f587..ad8ed7eba7e8 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -115,14 +115,14 @@ bytearray_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&frm, 'C')) { - _PyArg_BadArgument("maketrans", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("maketrans", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &to, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&to, 'C')) { - _PyArg_BadArgument("maketrans", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("maketrans", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = bytearray_maketrans_impl(&frm, &to); @@ -175,14 +175,14 @@ bytearray_replace(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nar goto exit; } if (!PyBuffer_IsContiguous(&old, 'C')) { - _PyArg_BadArgument("replace", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("replace", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&new, 'C')) { - _PyArg_BadArgument("replace", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("replace", "argument 2", "contiguous buffer", args[1]); goto exit; } if (nargs < 3) { @@ -735,7 +735,7 @@ bytearray_decode(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t narg } if (args[0]) { if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("decode", 1, "str", args[0]); + _PyArg_BadArgument("decode", "argument 'encoding'", "str", args[0]); goto exit; } Py_ssize_t encoding_length; @@ -752,7 +752,7 @@ bytearray_decode(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t narg } } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("decode", 2, "str", args[1]); + _PyArg_BadArgument("decode", "argument 'errors'", "str", args[1]); goto exit; } Py_ssize_t errors_length; @@ -854,7 +854,7 @@ bytearray_fromhex(PyTypeObject *type, PyObject *arg) PyObject *string; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("fromhex", 0, "str", arg); + _PyArg_BadArgument("fromhex", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -1011,4 +1011,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=7848247e5469ba1b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=09df354d3374dfb2 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 69c35063c6cf..7e2ce1af285c 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -99,7 +99,7 @@ bytes_partition(PyBytesObject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&sep, 'C')) { - _PyArg_BadArgument("partition", 0, "contiguous buffer", arg); + _PyArg_BadArgument("partition", "argument", "contiguous buffer", arg); goto exit; } return_value = bytes_partition_impl(self, &sep); @@ -142,7 +142,7 @@ bytes_rpartition(PyBytesObject *self, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&sep, 'C')) { - _PyArg_BadArgument("rpartition", 0, "contiguous buffer", arg); + _PyArg_BadArgument("rpartition", "argument", "contiguous buffer", arg); goto exit; } return_value = bytes_rpartition_impl(self, &sep); @@ -420,14 +420,14 @@ bytes_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&frm, 'C')) { - _PyArg_BadArgument("maketrans", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("maketrans", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &to, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&to, 'C')) { - _PyArg_BadArgument("maketrans", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("maketrans", "argument 2", "contiguous buffer", args[1]); goto exit; } return_value = bytes_maketrans_impl(&frm, &to); @@ -480,14 +480,14 @@ bytes_replace(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyBuffer_IsContiguous(&old, 'C')) { - _PyArg_BadArgument("replace", 1, "contiguous buffer", args[0]); + _PyArg_BadArgument("replace", "argument 1", "contiguous buffer", args[0]); goto exit; } if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&new, 'C')) { - _PyArg_BadArgument("replace", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("replace", "argument 2", "contiguous buffer", args[1]); goto exit; } if (nargs < 3) { @@ -568,7 +568,7 @@ bytes_decode(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObj } if (args[0]) { if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("decode", 1, "str", args[0]); + _PyArg_BadArgument("decode", "argument 'encoding'", "str", args[0]); goto exit; } Py_ssize_t encoding_length; @@ -585,7 +585,7 @@ bytes_decode(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObj } } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("decode", 2, "str", args[1]); + _PyArg_BadArgument("decode", "argument 'errors'", "str", args[1]); goto exit; } Py_ssize_t errors_length; @@ -674,7 +674,7 @@ bytes_fromhex(PyTypeObject *type, PyObject *arg) PyObject *string; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("fromhex", 0, "str", arg); + _PyArg_BadArgument("fromhex", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -755,4 +755,4 @@ bytes_hex(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject exit: return return_value; } -/*[clinic end generated code: output=2d0a3733e13e753a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dbed3c3ff6faa382 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/codeobject.c.h b/Objects/clinic/codeobject.c.h index ec127ce17189..6596de051cac 100644 --- a/Objects/clinic/codeobject.c.h +++ b/Objects/clinic/codeobject.c.h @@ -158,7 +158,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[7]) { if (!PyBytes_Check(args[7])) { - _PyArg_BadArgument("replace", 8, "bytes", args[7]); + _PyArg_BadArgument("replace", "argument 'co_code'", "bytes", args[7]); goto exit; } co_code = (PyBytesObject *)args[7]; @@ -168,7 +168,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[8]) { if (!PyTuple_Check(args[8])) { - _PyArg_BadArgument("replace", 9, "tuple", args[8]); + _PyArg_BadArgument("replace", "argument 'co_consts'", "tuple", args[8]); goto exit; } co_consts = args[8]; @@ -178,7 +178,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[9]) { if (!PyTuple_Check(args[9])) { - _PyArg_BadArgument("replace", 10, "tuple", args[9]); + _PyArg_BadArgument("replace", "argument 'co_names'", "tuple", args[9]); goto exit; } co_names = args[9]; @@ -188,7 +188,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[10]) { if (!PyTuple_Check(args[10])) { - _PyArg_BadArgument("replace", 11, "tuple", args[10]); + _PyArg_BadArgument("replace", "argument 'co_varnames'", "tuple", args[10]); goto exit; } co_varnames = args[10]; @@ -198,7 +198,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[11]) { if (!PyTuple_Check(args[11])) { - _PyArg_BadArgument("replace", 12, "tuple", args[11]); + _PyArg_BadArgument("replace", "argument 'co_freevars'", "tuple", args[11]); goto exit; } co_freevars = args[11]; @@ -208,7 +208,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[12]) { if (!PyTuple_Check(args[12])) { - _PyArg_BadArgument("replace", 13, "tuple", args[12]); + _PyArg_BadArgument("replace", "argument 'co_cellvars'", "tuple", args[12]); goto exit; } co_cellvars = args[12]; @@ -218,7 +218,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[13]) { if (!PyUnicode_Check(args[13])) { - _PyArg_BadArgument("replace", 14, "str", args[13]); + _PyArg_BadArgument("replace", "argument 'co_filename'", "str", args[13]); goto exit; } if (PyUnicode_READY(args[13]) == -1) { @@ -231,7 +231,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } if (args[14]) { if (!PyUnicode_Check(args[14])) { - _PyArg_BadArgument("replace", 15, "str", args[14]); + _PyArg_BadArgument("replace", "argument 'co_name'", "str", args[14]); goto exit; } if (PyUnicode_READY(args[14]) == -1) { @@ -243,7 +243,7 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (!PyBytes_Check(args[15])) { - _PyArg_BadArgument("replace", 16, "bytes", args[15]); + _PyArg_BadArgument("replace", "argument 'co_lnotab'", "bytes", args[15]); goto exit; } co_lnotab = (PyBytesObject *)args[15]; @@ -253,4 +253,4 @@ code_replace(PyCodeObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje exit: return return_value; } -/*[clinic end generated code: output=624ab6f2ea8f0ea4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fade581d6313a0c2 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h index 4251d63c247b..6515d118e506 100644 --- a/Objects/clinic/floatobject.c.h +++ b/Objects/clinic/floatobject.c.h @@ -235,7 +235,7 @@ float___getformat__(PyTypeObject *type, PyObject *arg) const char *typestr; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("__getformat__", 0, "str", arg); + _PyArg_BadArgument("__getformat__", "argument", "str", arg); goto exit; } Py_ssize_t typestr_length; @@ -289,7 +289,7 @@ float___set_format__(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("__set_format__", 1, "str", args[0]); + _PyArg_BadArgument("__set_format__", "argument 1", "str", args[0]); goto exit; } Py_ssize_t typestr_length; @@ -302,7 +302,7 @@ float___set_format__(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs goto exit; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("__set_format__", 2, "str", args[1]); + _PyArg_BadArgument("__set_format__", "argument 2", "str", args[1]); goto exit; } Py_ssize_t fmt_length; @@ -339,7 +339,7 @@ float___format__(PyObject *self, PyObject *arg) PyObject *format_spec; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("__format__", 0, "str", arg); + _PyArg_BadArgument("__format__", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -351,4 +351,4 @@ float___format__(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=c183029d87dd41fa input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cc8098eb73f1a64c input=a9049054013a1b77]*/ diff --git a/Objects/clinic/funcobject.c.h b/Objects/clinic/funcobject.c.h index 929797bfb02d..17fb13fe085a 100644 --- a/Objects/clinic/funcobject.c.h +++ b/Objects/clinic/funcobject.c.h @@ -44,12 +44,12 @@ func_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } if (!PyObject_TypeCheck(fastargs[0], &PyCode_Type)) { - _PyArg_BadArgument("function", 1, (&PyCode_Type)->tp_name, fastargs[0]); + _PyArg_BadArgument("function", "argument 'code'", (&PyCode_Type)->tp_name, fastargs[0]); goto exit; } code = (PyCodeObject *)fastargs[0]; if (!PyDict_Check(fastargs[1])) { - _PyArg_BadArgument("function", 2, "dict", fastargs[1]); + _PyArg_BadArgument("function", "argument 'globals'", "dict", fastargs[1]); goto exit; } globals = fastargs[1]; @@ -75,4 +75,4 @@ func_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=1d01072cd5620d7e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3d96afa3396e5c82 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/longobject.c.h b/Objects/clinic/longobject.c.h index 453edba481df..27e8dfe935b6 100644 --- a/Objects/clinic/longobject.c.h +++ b/Objects/clinic/longobject.c.h @@ -74,7 +74,7 @@ int___format__(PyObject *self, PyObject *arg) PyObject *format_spec; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("__format__", 0, "str", arg); + _PyArg_BadArgument("__format__", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -227,7 +227,7 @@ int_to_bytes(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject * length = ival; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("to_bytes", 2, "str", args[1]); + _PyArg_BadArgument("to_bytes", "argument 'byteorder'", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -293,7 +293,7 @@ int_from_bytes(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyOb } bytes_obj = args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("from_bytes", 2, "str", args[1]); + _PyArg_BadArgument("from_bytes", "argument 'byteorder'", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -313,4 +313,4 @@ int_from_bytes(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyOb exit: return return_value; } -/*[clinic end generated code: output=709503897c55bca1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=77bc3b2615822cb8 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/moduleobject.c.h b/Objects/clinic/moduleobject.c.h index 512edee72fea..c1534eaee258 100644 --- a/Objects/clinic/moduleobject.c.h +++ b/Objects/clinic/moduleobject.c.h @@ -31,7 +31,7 @@ module___init__(PyObject *self, PyObject *args, PyObject *kwargs) goto exit; } if (!PyUnicode_Check(fastargs[0])) { - _PyArg_BadArgument("module", 1, "str", fastargs[0]); + _PyArg_BadArgument("module", "argument 'name'", "str", fastargs[0]); goto exit; } if (PyUnicode_READY(fastargs[0]) == -1) { @@ -48,4 +48,4 @@ module___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=d7b7ca1237597b08 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=680276bc3a496d7a input=a9049054013a1b77]*/ diff --git a/Objects/clinic/typeobject.c.h b/Objects/clinic/typeobject.c.h index fbe1261fb5a0..357eb44b12b8 100644 --- a/Objects/clinic/typeobject.c.h +++ b/Objects/clinic/typeobject.c.h @@ -200,7 +200,7 @@ object___format__(PyObject *self, PyObject *arg) PyObject *format_spec; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("__format__", 0, "str", arg); + _PyArg_BadArgument("__format__", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -248,4 +248,4 @@ object___dir__(PyObject *self, PyObject *Py_UNUSED(ignored)) { return object___dir___impl(self); } -/*[clinic end generated code: output=ea5734413064fa7e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7a6d272d282308f3 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h index 647507dea61a..cb350874dad1 100644 --- a/Objects/clinic/unicodeobject.c.h +++ b/Objects/clinic/unicodeobject.c.h @@ -157,7 +157,7 @@ unicode_encode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject } if (args[0]) { if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("encode", 1, "str", args[0]); + _PyArg_BadArgument("encode", "argument 'encoding'", "str", args[0]); goto exit; } Py_ssize_t encoding_length; @@ -174,7 +174,7 @@ unicode_encode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject } } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("encode", 2, "str", args[1]); + _PyArg_BadArgument("encode", "argument 'errors'", "str", args[1]); goto exit; } Py_ssize_t errors_length; @@ -712,7 +712,7 @@ unicode_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyUnicode_Check(args[0])) { - _PyArg_BadArgument("replace", 1, "str", args[0]); + _PyArg_BadArgument("replace", "argument 1", "str", args[0]); goto exit; } if (PyUnicode_READY(args[0]) == -1) { @@ -720,7 +720,7 @@ unicode_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } old = args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("replace", 2, "str", args[1]); + _PyArg_BadArgument("replace", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -1080,7 +1080,7 @@ unicode_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("maketrans", 2, "str", args[1]); + _PyArg_BadArgument("maketrans", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -1091,7 +1091,7 @@ unicode_maketrans(void *null, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("maketrans", 3, "str", args[2]); + _PyArg_BadArgument("maketrans", "argument 3", "str", args[2]); goto exit; } if (PyUnicode_READY(args[2]) == -1) { @@ -1202,7 +1202,7 @@ unicode___format__(PyObject *self, PyObject *arg) PyObject *format_spec; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("__format__", 0, "str", arg); + _PyArg_BadArgument("__format__", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -1232,4 +1232,4 @@ unicode_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored)) { return unicode_sizeof_impl(self); } -/*[clinic end generated code: output=d1541724cb4a0070 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d9a6ee45ddd0ccfd input=a9049054013a1b77]*/ diff --git a/Objects/stringlib/clinic/transmogrify.h.h b/Objects/stringlib/clinic/transmogrify.h.h index 0c53a75b1bf8..8a3a060f12bc 100644 --- a/Objects/stringlib/clinic/transmogrify.h.h +++ b/Objects/stringlib/clinic/transmogrify.h.h @@ -100,7 +100,7 @@ stringlib_ljust(PyObject *self, PyObject *const *args, Py_ssize_t nargs) fillchar = PyByteArray_AS_STRING(args[1])[0]; } else { - _PyArg_BadArgument("ljust", 2, "a byte string of length 1", args[1]); + _PyArg_BadArgument("ljust", "argument 2", "a byte string of length 1", args[1]); goto exit; } skip_optional: @@ -161,7 +161,7 @@ stringlib_rjust(PyObject *self, PyObject *const *args, Py_ssize_t nargs) fillchar = PyByteArray_AS_STRING(args[1])[0]; } else { - _PyArg_BadArgument("rjust", 2, "a byte string of length 1", args[1]); + _PyArg_BadArgument("rjust", "argument 2", "a byte string of length 1", args[1]); goto exit; } skip_optional: @@ -222,7 +222,7 @@ stringlib_center(PyObject *self, PyObject *const *args, Py_ssize_t nargs) fillchar = PyByteArray_AS_STRING(args[1])[0]; } else { - _PyArg_BadArgument("center", 2, "a byte string of length 1", args[1]); + _PyArg_BadArgument("center", "argument 2", "a byte string of length 1", args[1]); goto exit; } skip_optional: @@ -274,4 +274,4 @@ stringlib_zfill(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=96cbb19b238d0e84 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=15be047aef999b4e input=a9049054013a1b77]*/ diff --git a/PC/clinic/_testconsole.c.h b/PC/clinic/_testconsole.c.h index a37d1235a02a..cf5e4ee09063 100644 --- a/PC/clinic/_testconsole.c.h +++ b/PC/clinic/_testconsole.c.h @@ -33,7 +33,7 @@ _testconsole_write_input(PyObject *module, PyObject *const *args, Py_ssize_t nar } file = args[0]; if (!PyBytes_Check(args[1])) { - _PyArg_BadArgument("write_input", 2, "bytes", args[1]); + _PyArg_BadArgument("write_input", "argument 's'", "bytes", args[1]); goto exit; } s = (PyBytesObject *)args[1]; @@ -88,4 +88,4 @@ _testconsole_read_output(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef _TESTCONSOLE_READ_OUTPUT_METHODDEF #define _TESTCONSOLE_READ_OUTPUT_METHODDEF #endif /* !defined(_TESTCONSOLE_READ_OUTPUT_METHODDEF) */ -/*[clinic end generated code: output=ef452d5fb9287fc2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dd8b093a91b62753 input=a9049054013a1b77]*/ diff --git a/PC/clinic/msvcrtmodule.c.h b/PC/clinic/msvcrtmodule.c.h index d8e77d5f328d..180c3e5fc54a 100644 --- a/PC/clinic/msvcrtmodule.c.h +++ b/PC/clinic/msvcrtmodule.c.h @@ -375,7 +375,7 @@ msvcrt_putch(PyObject *module, PyObject *arg) char_value = PyByteArray_AS_STRING(arg)[0]; } else { - _PyArg_BadArgument("putch", 0, "a byte string of length 1", arg); + _PyArg_BadArgument("putch", "argument", "a byte string of length 1", arg); goto exit; } return_value = msvcrt_putch_impl(module, char_value); @@ -403,14 +403,14 @@ msvcrt_putwch(PyObject *module, PyObject *arg) int unicode_char; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("putwch", 0, "a unicode character", arg); + _PyArg_BadArgument("putwch", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("putwch", 0, "a unicode character", arg); + _PyArg_BadArgument("putwch", "argument", "a unicode character", arg); goto exit; } unicode_char = PyUnicode_READ_CHAR(arg, 0); @@ -449,7 +449,7 @@ msvcrt_ungetch(PyObject *module, PyObject *arg) char_value = PyByteArray_AS_STRING(arg)[0]; } else { - _PyArg_BadArgument("ungetch", 0, "a byte string of length 1", arg); + _PyArg_BadArgument("ungetch", "argument", "a byte string of length 1", arg); goto exit; } return_value = msvcrt_ungetch_impl(module, char_value); @@ -477,14 +477,14 @@ msvcrt_ungetwch(PyObject *module, PyObject *arg) int unicode_char; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("ungetwch", 0, "a unicode character", arg); + _PyArg_BadArgument("ungetwch", "argument", "a unicode character", arg); goto exit; } if (PyUnicode_READY(arg)) { goto exit; } if (PyUnicode_GET_LENGTH(arg) != 1) { - _PyArg_BadArgument("ungetwch", 0, "a unicode character", arg); + _PyArg_BadArgument("ungetwch", "argument", "a unicode character", arg); goto exit; } unicode_char = PyUnicode_READ_CHAR(arg, 0); @@ -679,4 +679,4 @@ msvcrt_SetErrorMode(PyObject *module, PyObject *arg) #ifndef MSVCRT_SET_ERROR_MODE_METHODDEF #define MSVCRT_SET_ERROR_MODE_METHODDEF #endif /* !defined(MSVCRT_SET_ERROR_MODE_METHODDEF) */ -/*[clinic end generated code: output=816bc4f993893cea input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7cc6ffaf64f268f7 input=a9049054013a1b77]*/ diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h index abed6cc3e174..49608ccf3df9 100644 --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -102,7 +102,7 @@ builtin_format(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto skip_optional; } if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("format", 2, "str", args[1]); + _PyArg_BadArgument("format", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -200,7 +200,7 @@ builtin_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto exit; } if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("compile", 3, "str", args[2]); + _PyArg_BadArgument("compile", "argument 'mode'", "str", args[2]); goto exit; } Py_ssize_t mode_length; @@ -849,4 +849,4 @@ builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=e173df340a9e4516 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1927f3c9abd00c35 input=a9049054013a1b77]*/ diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h index 05e3106bb39a..743d00222914 100644 --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -92,12 +92,12 @@ _imp__fix_co_filename(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } if (!PyObject_TypeCheck(args[0], &PyCode_Type)) { - _PyArg_BadArgument("_fix_co_filename", 1, (&PyCode_Type)->tp_name, args[0]); + _PyArg_BadArgument("_fix_co_filename", "argument 1", (&PyCode_Type)->tp_name, args[0]); goto exit; } code = (PyCodeObject *)args[0]; if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("_fix_co_filename", 2, "str", args[1]); + _PyArg_BadArgument("_fix_co_filename", "argument 2", "str", args[1]); goto exit; } if (PyUnicode_READY(args[1]) == -1) { @@ -156,7 +156,7 @@ _imp_init_frozen(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("init_frozen", 0, "str", arg); + _PyArg_BadArgument("init_frozen", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -188,7 +188,7 @@ _imp_get_frozen_object(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("get_frozen_object", 0, "str", arg); + _PyArg_BadArgument("get_frozen_object", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -220,7 +220,7 @@ _imp_is_frozen_package(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("is_frozen_package", 0, "str", arg); + _PyArg_BadArgument("is_frozen_package", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -252,7 +252,7 @@ _imp_is_builtin(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("is_builtin", 0, "str", arg); + _PyArg_BadArgument("is_builtin", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -284,7 +284,7 @@ _imp_is_frozen(PyObject *module, PyObject *arg) PyObject *name; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("is_frozen", 0, "str", arg); + _PyArg_BadArgument("is_frozen", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -433,7 +433,7 @@ _imp_source_hash(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto exit; } if (!PyBuffer_IsContiguous(&source, 'C')) { - _PyArg_BadArgument("source_hash", 2, "contiguous buffer", args[1]); + _PyArg_BadArgument("source_hash", "argument 'source'", "contiguous buffer", args[1]); goto exit; } return_value = _imp_source_hash_impl(module, key, &source); @@ -454,4 +454,4 @@ _imp_source_hash(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=b51244770fdcf4b8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ff06f7cf4b73eb76 input=a9049054013a1b77]*/ diff --git a/Python/clinic/marshal.c.h b/Python/clinic/marshal.c.h index ab4575340e25..05d4830c4ab3 100644 --- a/Python/clinic/marshal.c.h +++ b/Python/clinic/marshal.c.h @@ -152,7 +152,7 @@ marshal_loads(PyObject *module, PyObject *arg) goto exit; } if (!PyBuffer_IsContiguous(&bytes, 'C')) { - _PyArg_BadArgument("loads", 0, "contiguous buffer", arg); + _PyArg_BadArgument("loads", "argument", "contiguous buffer", arg); goto exit; } return_value = marshal_loads_impl(module, &bytes); @@ -165,4 +165,4 @@ marshal_loads(PyObject *module, PyObject *arg) return return_value; } -/*[clinic end generated code: output=ae2bca1aa239e095 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a859dabe8b0afeb6 input=a9049054013a1b77]*/ diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 563332eeb5c6..93bc3320e337 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -228,7 +228,7 @@ sys_intern(PyObject *module, PyObject *arg) PyObject *s; if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("intern", 0, "str", arg); + _PyArg_BadArgument("intern", "argument", "str", arg); goto exit; } if (PyUnicode_READY(arg) == -1) { @@ -931,7 +931,7 @@ sys_call_tracing(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } func = args[0]; if (!PyTuple_Check(args[1])) { - _PyArg_BadArgument("call_tracing", 2, "tuple", args[1]); + _PyArg_BadArgument("call_tracing", "argument 2", "tuple", args[1]); goto exit; } funcargs = args[1]; @@ -1088,4 +1088,4 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=1a67b37c4486d65f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=092edc868de055a6 input=a9049054013a1b77]*/ diff --git a/Python/clinic/traceback.c.h b/Python/clinic/traceback.c.h index 2815f65d3dd1..04daf2a37669 100644 --- a/Python/clinic/traceback.c.h +++ b/Python/clinic/traceback.c.h @@ -32,7 +32,7 @@ tb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } tb_next = fastargs[0]; if (!PyObject_TypeCheck(fastargs[1], &PyFrame_Type)) { - _PyArg_BadArgument("TracebackType", 2, (&PyFrame_Type)->tp_name, fastargs[1]); + _PyArg_BadArgument("TracebackType", "argument 'tb_frame'", (&PyFrame_Type)->tp_name, fastargs[1]); goto exit; } tb_frame = (PyFrameObject *)fastargs[1]; @@ -59,4 +59,4 @@ tb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=7e4c0e252d0973b0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3def6c06248feed8 input=a9049054013a1b77]*/ diff --git a/Python/getargs.c b/Python/getargs.c index 051ebc78a0f8..c65530d859c3 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -610,24 +610,18 @@ convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, -/* Format an error message generated by convertsimple(). */ +/* Format an error message generated by convertsimple(). + displayname must be UTF-8 encoded. +*/ void -_PyArg_BadArgument(const char *fname, int iarg, +_PyArg_BadArgument(const char *fname, const char *displayname, const char *expected, PyObject *arg) { - if (iarg) { - PyErr_Format(PyExc_TypeError, - "%.200s() argument %d must be %.50s, not %.50s", - fname, iarg, expected, - arg == Py_None ? "None" : arg->ob_type->tp_name); - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s() argument must be %.50s, not %.50s", - fname, expected, - arg == Py_None ? "None" : arg->ob_type->tp_name); - } + PyErr_Format(PyExc_TypeError, + "%.200s() %.200s must be %.50s, not %.50s", + fname, displayname, expected, + arg == Py_None ? "None" : arg->ob_type->tp_name); } static const char * diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index d5863a3effe9..cec7c5392db3 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -806,7 +806,8 @@ def parser_body(prototype, *fields, declarations=''): {c_basename}({self_type}{self_name}, PyObject *%s) """ % argname) - parsearg = converters[0].parse_arg(argname, 0) + displayname = parameters[0].get_displayname(0) + parsearg = converters[0].parse_arg(argname, displayname) if parsearg is None: parsearg = """ if (!PyArg_Parse(%s, "{format_units}:{name}", {parse_arguments})) {{ @@ -851,7 +852,8 @@ def parser_body(prototype, *fields, declarations=''): """ % (nargs, min_pos, max_pos), indent=4)] has_optional = False for i, p in enumerate(parameters): - parsearg = p.converter.parse_arg(argname_fmt % i, i + 1) + displayname = p.get_displayname(i+1) + parsearg = p.converter.parse_arg(argname_fmt % i, displayname) if parsearg is None: #print('Cannot convert %s %r for %s' % (p.converter.__class__.__name__, p.converter.format_unit, p.converter.name), file=sys.stderr) parser_code = None @@ -927,7 +929,8 @@ def parser_body(prototype, *fields, declarations=''): add_label = None for i, p in enumerate(parameters): - parsearg = p.converter.parse_arg(argname_fmt % i, i + 1) + displayname = p.get_displayname(i+1) + parsearg = p.converter.parse_arg(argname_fmt % i, displayname) if parsearg is None: #print('Cannot convert %s %r for %s' % (p.converter.__class__.__name__, p.converter.format_unit, p.converter.name), file=sys.stderr) parser_code = None @@ -2287,6 +2290,13 @@ def copy(self, **overrides): kwargs['converter'] = converter return Parameter(**kwargs) + def get_displayname(self, i): + if i == 0: + return '"argument"' + if not self.is_positional_only(): + return '''"argument '{}'"'''.format(self.name) + else: + return '"argument {}"'.format(i) class LandMine: @@ -2634,7 +2644,7 @@ def pre_render(self): """ pass - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'O&': return """ if (!{converter}({argname}, &{paramname})) {{{{ @@ -2648,21 +2658,22 @@ def parse_arg(self, argname, argnum): typecheck, typename = type_checks[self.subclass_of] return """ if (!{typecheck}({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "{typename}", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "{typename}", {argname}); goto exit; }}}} {paramname} = {cast}{argname}; """.format(argname=argname, paramname=self.name, - argnum=argnum, - typecheck=typecheck, typename=typename, cast=cast) + displayname=displayname, typecheck=typecheck, + typename=typename, cast=cast) return """ if (!PyObject_TypeCheck({argname}, {subclass_of})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, ({subclass_of})->tp_name, {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, ({subclass_of})->tp_name, {argname}); goto exit; }}}} {paramname} = {cast}{argname}; - """.format(argname=argname, paramname=self.name, argnum=argnum, - subclass_of=self.subclass_of, cast=cast) + """.format(argname=argname, paramname=self.name, + subclass_of=self.subclass_of, cast=cast, + displayname=displayname) if self.format_unit == 'O': cast = '(%s)' % self.type if self.type != 'PyObject *' else '' return """ @@ -2698,7 +2709,7 @@ def converter_init(self, *, accept={object}): self.default = bool(self.default) self.c_default = str(int(self.default)) - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'i': # XXX PyFloat_Check can be removed after the end of the # deprecation in _PyLong_FromNbIndexOrNbInt. @@ -2720,7 +2731,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class char_converter(CConverter): type = 'char' @@ -2737,7 +2748,7 @@ def converter_init(self): if self.c_default == '"\'"': self.c_default = r"'\''" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'c': return """ if (PyBytes_Check({argname}) && PyBytes_GET_SIZE({argname}) == 1) {{{{ @@ -2747,11 +2758,12 @@ def parse_arg(self, argname, argnum): {paramname} = PyByteArray_AS_STRING({argname})[0]; }}}} else {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "a byte string of length 1", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "a byte string of length 1", {argname}); goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) @add_legacy_c_converter('B', bitwise=True) @@ -2765,7 +2777,7 @@ def converter_init(self, *, bitwise=False): if bitwise: self.format_unit = 'B' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'b': return """ if (PyFloat_Check({argname})) {{{{ @@ -2810,7 +2822,7 @@ def parse_arg(self, argname, argnum): }}}} }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class byte_converter(unsigned_char_converter): pass @@ -2820,7 +2832,7 @@ class short_converter(CConverter): format_unit = 'h' c_ignored_default = "0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'h': return """ if (PyFloat_Check({argname})) {{{{ @@ -2848,7 +2860,7 @@ def parse_arg(self, argname, argnum): }}}} }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class unsigned_short_converter(CConverter): type = 'unsigned short' @@ -2861,7 +2873,7 @@ def converter_init(self, *, bitwise=False): else: self.converter = '_PyLong_UnsignedShort_Converter' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'H': return """ if (PyFloat_Check({argname})) {{{{ @@ -2874,7 +2886,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) @add_legacy_c_converter('C', accept={str}) class int_converter(CConverter): @@ -2891,7 +2903,7 @@ def converter_init(self, *, accept={int}, type=None): if type != None: self.type = type - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'i': return """ if (PyFloat_Check({argname})) {{{{ @@ -2907,19 +2919,20 @@ def parse_arg(self, argname, argnum): elif self.format_unit == 'C': return """ if (!PyUnicode_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "a unicode character", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "a unicode character", {argname}); goto exit; }}}} if (PyUnicode_READY({argname})) {{{{ goto exit; }}}} if (PyUnicode_GET_LENGTH({argname}) != 1) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "a unicode character", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "a unicode character", {argname}); goto exit; }}}} {paramname} = PyUnicode_READ_CHAR({argname}, 0); - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) class unsigned_int_converter(CConverter): type = 'unsigned int' @@ -2932,7 +2945,7 @@ def converter_init(self, *, bitwise=False): else: self.converter = '_PyLong_UnsignedInt_Converter' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'I': return """ if (PyFloat_Check({argname})) {{{{ @@ -2945,7 +2958,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class long_converter(CConverter): type = 'long' @@ -2953,7 +2966,7 @@ class long_converter(CConverter): format_unit = 'l' c_ignored_default = "0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'l': return """ if (PyFloat_Check({argname})) {{{{ @@ -2966,7 +2979,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class unsigned_long_converter(CConverter): type = 'unsigned long' @@ -2979,16 +2992,17 @@ def converter_init(self, *, bitwise=False): else: self.converter = '_PyLong_UnsignedLong_Converter' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'k': return """ if (!PyLong_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "int", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "int", {argname}); goto exit; }}}} {paramname} = PyLong_AsUnsignedLongMask({argname}); - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) class long_long_converter(CConverter): type = 'long long' @@ -2996,7 +3010,7 @@ class long_long_converter(CConverter): format_unit = 'L' c_ignored_default = "0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'L': return """ if (PyFloat_Check({argname})) {{{{ @@ -3009,7 +3023,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class unsigned_long_long_converter(CConverter): type = 'unsigned long long' @@ -3022,16 +3036,17 @@ def converter_init(self, *, bitwise=False): else: self.converter = '_PyLong_UnsignedLongLong_Converter' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'K': return """ if (!PyLong_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "int", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "int", {argname}); goto exit; }}}} {paramname} = PyLong_AsUnsignedLongLongMask({argname}); - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) class Py_ssize_t_converter(CConverter): type = 'Py_ssize_t' @@ -3046,7 +3061,7 @@ def converter_init(self, *, accept={int}): else: fail("Py_ssize_t_converter: illegal 'accept' argument " + repr(accept)) - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'n': return """ if (PyFloat_Check({argname})) {{{{ @@ -3067,7 +3082,7 @@ def parse_arg(self, argname, argnum): {paramname} = ival; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class slice_index_converter(CConverter): @@ -3086,7 +3101,7 @@ class size_t_converter(CConverter): converter = '_PyLong_Size_t_Converter' c_ignored_default = "0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'n': return """ {paramname} = PyNumber_AsSsize_t({argname}, PyExc_OverflowError); @@ -3094,7 +3109,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class float_converter(CConverter): @@ -3103,7 +3118,7 @@ class float_converter(CConverter): format_unit = 'f' c_ignored_default = "0.0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'f': return """ if (PyFloat_CheckExact({argname})) {{{{ @@ -3117,7 +3132,7 @@ def parse_arg(self, argname, argnum): }}}} }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class double_converter(CConverter): type = 'double' @@ -3125,7 +3140,7 @@ class double_converter(CConverter): format_unit = 'd' c_ignored_default = "0.0" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'd': return """ if (PyFloat_CheckExact({argname})) {{{{ @@ -3139,7 +3154,7 @@ def parse_arg(self, argname, argnum): }}}} }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class Py_complex_converter(CConverter): @@ -3148,7 +3163,7 @@ class Py_complex_converter(CConverter): format_unit = 'D' c_ignored_default = "{0.0, 0.0}" - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'D': return """ {paramname} = PyComplex_AsCComplex({argname}); @@ -3156,7 +3171,7 @@ def parse_arg(self, argname, argnum): goto exit; }}}} """.format(argname=argname, paramname=self.name) - return super().parse_arg(argname, argnum) + return super().parse_arg(argname, displayname) class object_converter(CConverter): @@ -3222,11 +3237,11 @@ def cleanup(self): name = self.name return "".join(["if (", name, ") {\n PyMem_FREE(", name, ");\n}\n"]) - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 's': return """ if (!PyUnicode_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "str", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "str", {argname}); goto exit; }}}} Py_ssize_t {paramname}_length; @@ -3238,7 +3253,8 @@ def parse_arg(self, argname, argnum): PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) if self.format_unit == 'z': return """ if ({argname} == Py_None) {{{{ @@ -3256,11 +3272,12 @@ def parse_arg(self, argname, argnum): }}}} }}}} else {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "str or None", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "str or None", {argname}); goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) # # This is the fourth or fifth rewrite of registering all the @@ -3315,53 +3332,54 @@ class PyBytesObject_converter(CConverter): format_unit = 'S' # accept = {bytes} - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'S': return """ if (!PyBytes_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "bytes", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "bytes", {argname}); goto exit; }}}} {paramname} = ({type}){argname}; - """.format(argname=argname, paramname=self.name, argnum=argnum, - type=self.type) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + type=self.type, displayname=displayname) + return super().parse_arg(argname, displayname) class PyByteArrayObject_converter(CConverter): type = 'PyByteArrayObject *' format_unit = 'Y' # accept = {bytearray} - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'Y': return """ if (!PyByteArray_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "bytearray", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "bytearray", {argname}); goto exit; }}}} {paramname} = ({type}){argname}; - """.format(argname=argname, paramname=self.name, argnum=argnum, - type=self.type) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + type=self.type, displayname=displayname) + return super().parse_arg(argname, displayname) class unicode_converter(CConverter): type = 'PyObject *' default_type = (str, Null, NoneType) format_unit = 'U' - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'U': return """ if (!PyUnicode_Check({argname})) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "str", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "str", {argname}); goto exit; }}}} if (PyUnicode_READY({argname}) == -1) {{{{ goto exit; }}}} {paramname} = {argname}; - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) @add_legacy_c_converter('u#', zeroes=True) @add_legacy_c_converter('Z', accept={str, NoneType}) @@ -3410,17 +3428,18 @@ def cleanup(self): name = self.name return "".join(["if (", name, ".obj) {\n PyBuffer_Release(&", name, ");\n}\n"]) - def parse_arg(self, argname, argnum): + def parse_arg(self, argname, displayname): if self.format_unit == 'y*': return """ if (PyObject_GetBuffer({argname}, &{paramname}, PyBUF_SIMPLE) != 0) {{{{ goto exit; }}}} if (!PyBuffer_IsContiguous(&{paramname}, 'C')) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "contiguous buffer", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname}); goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) elif self.format_unit == 's*': return """ if (PyUnicode_Check({argname})) {{{{ @@ -3436,24 +3455,26 @@ def parse_arg(self, argname, argnum): goto exit; }}}} if (!PyBuffer_IsContiguous(&{paramname}, 'C')) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "contiguous buffer", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname}); goto exit; }}}} }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) elif self.format_unit == 'w*': return """ if (PyObject_GetBuffer({argname}, &{paramname}, PyBUF_WRITABLE) < 0) {{{{ PyErr_Clear(); - _PyArg_BadArgument("{{name}}", {argnum}, "read-write bytes-like object", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "read-write bytes-like object", {argname}); goto exit; }}}} if (!PyBuffer_IsContiguous(&{paramname}, 'C')) {{{{ - _PyArg_BadArgument("{{name}}", {argnum}, "contiguous buffer", {argname}); + _PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname}); goto exit; }}}} - """.format(argname=argname, paramname=self.name, argnum=argnum) - return super().parse_arg(argname, argnum) + """.format(argname=argname, paramname=self.name, + displayname=displayname) + return super().parse_arg(argname, displayname) def correct_name_for_self(f): From webhook-mailer at python.org Thu Aug 29 12:03:05 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Thu, 29 Aug 2019 16:03:05 -0000 Subject: [Python-checkins] bpo-8425: Fast path for set inplace difference when the second set is large (GH-15590) Message-ID: https://github.com/python/cpython/commit/88ea166dadb8aeb34541a0a464662dea222629e5 commit: 88ea166dadb8aeb34541a0a464662dea222629e5 branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-29T09:02:58-07:00 summary: bpo-8425: Fast path for set inplace difference when the second set is large (GH-15590) files: A Misc/NEWS.d/next/Core and Builtins/2019-08-29-01-55-38.bpo-8425.FTq4A8.rst M Objects/setobject.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-29-01-55-38.bpo-8425.FTq4A8.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-29-01-55-38.bpo-8425.FTq4A8.rst new file mode 100644 index 000000000000..8e5ec0bfe874 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-29-01-55-38.bpo-8425.FTq4A8.rst @@ -0,0 +1,3 @@ +Optimize set difference_update for the case when the other set is much +larger than the base set. (Suggested by Evgeny Kapun with code contributed +by Michele Orr?). diff --git a/Objects/setobject.c b/Objects/setobject.c index 56858dbccfe1..fafc2fa9e46d 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1463,9 +1463,25 @@ set_difference_update_internal(PySetObject *so, PyObject *other) setentry *entry; Py_ssize_t pos = 0; + /* Optimization: When the other set is more than 8 times + larger than the base set, replace the other set with + interesection of the two sets. + */ + if ((PySet_GET_SIZE(other) >> 3) > PySet_GET_SIZE(so)) { + other = set_intersection(so, other); + if (other == NULL) + return -1; + } else { + Py_INCREF(other); + } + while (set_next((PySetObject *)other, &pos, &entry)) - if (set_discard_entry(so, entry->key, entry->hash) < 0) + if (set_discard_entry(so, entry->key, entry->hash) < 0) { + Py_DECREF(other); return -1; + } + + Py_DECREF(other); } else { PyObject *key, *it; it = PyObject_GetIter(other); From webhook-mailer at python.org Thu Aug 29 12:30:08 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 29 Aug 2019 16:30:08 -0000 Subject: [Python-checkins] bpo-37933: Fix faulthandler.cancel_dump_traceback_later() (GH-15440) Message-ID: https://github.com/python/cpython/commit/e278335a6eb049e6028db9a8dcb8baac6cb365ee commit: e278335a6eb049e6028db9a8dcb8baac6cb365ee branch: master author: Thomas A Caswell committer: Victor Stinner date: 2019-08-29T18:30:04+02:00 summary: bpo-37933: Fix faulthandler.cancel_dump_traceback_later() (GH-15440) Fix faulthandler.cancel_dump_traceback_later() call if cancel_dump_traceback_later() was not called previously. files: M Lib/test/test_faulthandler.py M Modules/faulthandler.c diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 1cf20db1c7ff..b1aa8c32284b 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -817,6 +817,17 @@ def test_disable_windows_exc_handler(self): self.assertEqual(output, []) self.assertEqual(exitcode, 0xC0000005) + def test_cancel_later_without_dump_traceback_later(self): + # bpo-37933: Calling cancel_dump_traceback_later() + # without dump_traceback_later() must not segfault. + code = dedent(""" + import faulthandler + faulthandler.cancel_dump_traceback_later() + """) + output, exitcode = self.get_output(code) + self.assertEqual(output, []) + self.assertEqual(exitcode, 0) + if __name__ == "__main__": unittest.main() diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 35e7b34c29cc..011ab5fa28f2 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -631,6 +631,11 @@ faulthandler_thread(void *unused) static void cancel_dump_traceback_later(void) { + /* If not scheduled, nothing to cancel */ + if (!thread.cancel_event) { + return; + } + /* Notify cancellation */ PyThread_release_lock(thread.cancel_event); From webhook-mailer at python.org Fri Aug 30 00:04:43 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 30 Aug 2019 04:04:43 -0000 Subject: [Python-checkins] Steven Bethard designated a new maintainer for argparse (GH-15605) Message-ID: https://github.com/python/cpython/commit/496058f59937da478eb172c864502b5dcf67705b commit: 496058f59937da478eb172c864502b5dcf67705b branch: master author: Raymond Hettinger committer: GitHub date: 2019-08-29T21:04:37-07:00 summary: Steven Bethard designated a new maintainer for argparse (GH-15605) files: M Lib/argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index d29f161b666a..ddfd772c1126 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1,4 +1,5 @@ # Author: Steven J. Bethard . +# New maintainer as of 29 August 2019: Raymond Hettinger """Command-line parsing library From webhook-mailer at python.org Fri Aug 30 00:25:52 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 30 Aug 2019 04:25:52 -0000 Subject: [Python-checkins] bpo-37976: Prevent shadowing of TypeError in zip() (GH-15592) Message-ID: https://github.com/python/cpython/commit/6a650aaf7735e30636db2721247f317064c2cfd4 commit: 6a650aaf7735e30636db2721247f317064c2cfd4 branch: master author: Sergey Fedoseev committer: Raymond Hettinger date: 2019-08-29T21:25:48-07:00 summary: bpo-37976: Prevent shadowing of TypeError in zip() (GH-15592) files: M Lib/test/test_builtin.py M Lib/test/test_itertools.py M Modules/itertoolsmodule.c M Python/bltinmodule.c diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 61155799c44a..1100c49e9b88 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1477,6 +1477,18 @@ def test_zip_pickle(self): z1 = zip(a, b) self.check_iter_pickle(z1, t, proto) + def test_zip_bad_iterable(self): + exception = TypeError() + + class BadIterable: + def __iter__(self): + raise exception + + with self.assertRaises(TypeError) as cm: + zip(BadIterable()) + + self.assertIs(cm.exception, exception) + def test_format(self): # Test the basic machinery of the format() builtin. Don't test # the specifics of the various formatters diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index 573739fde14c..98b8c8373189 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -971,6 +971,18 @@ def test_zip_longest_pickling(self): self.pickletest(proto, zip_longest("abc", "defgh", fillvalue=1)) self.pickletest(proto, zip_longest("", "defgh")) + def test_zip_longest_bad_iterable(self): + exception = TypeError() + + class BadIterable: + def __iter__(self): + raise exception + + with self.assertRaises(TypeError) as cm: + zip_longest(BadIterable()) + + self.assertIs(cm.exception, exception) + def test_bug_7244(self): class Repeater: diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 101addcfd3a9..ab473e29fbd5 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -4442,10 +4442,6 @@ zip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *item = PyTuple_GET_ITEM(args, i); PyObject *it = PyObject_GetIter(item); if (it == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, - "zip_longest argument #%zd must support iteration", - i+1); Py_DECREF(ittuple); return NULL; } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 7f187eacd169..63e58128651a 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2548,10 +2548,6 @@ zip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *item = PyTuple_GET_ITEM(args, i); PyObject *it = PyObject_GetIter(item); if (it == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, - "zip argument #%zd must support iteration", - i+1); Py_DECREF(ittuple); return NULL; } From webhook-mailer at python.org Fri Aug 30 00:27:37 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 30 Aug 2019 04:27:37 -0000 Subject: [Python-checkins] Steven Bethard designated a new maintainer for argparse (GH-15605) (GH-15606) Message-ID: https://github.com/python/cpython/commit/c19d6bca5577547b3f4624d99b5f5f1db3e5e695 commit: c19d6bca5577547b3f4624d99b5f5f1db3e5e695 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-29T21:27:33-07:00 summary: Steven Bethard designated a new maintainer for argparse (GH-15605) (GH-15606) (cherry picked from commit 496058f59937da478eb172c864502b5dcf67705b) Co-authored-by: Raymond Hettinger files: M Lib/argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index 6f0b37c1c5ea..a6ab3b3b898d 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1,4 +1,5 @@ # Author: Steven J. Bethard . +# New maintainer as of 29 August 2019: Raymond Hettinger """Command-line parsing library From webhook-mailer at python.org Fri Aug 30 02:23:29 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 30 Aug 2019 06:23:29 -0000 Subject: [Python-checkins] bpo-37976: Prevent shadowing of TypeError in zip() (GH-15592) (GH-15608) Message-ID: https://github.com/python/cpython/commit/27f418640cf39c035114f29cc2d628775b43c0f9 commit: 27f418640cf39c035114f29cc2d628775b43c0f9 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-29T23:23:17-07:00 summary: bpo-37976: Prevent shadowing of TypeError in zip() (GH-15592) (GH-15608) (cherry picked from commit 6a650aaf7735e30636db2721247f317064c2cfd4) Co-authored-by: Sergey Fedoseev files: M Lib/test/test_builtin.py M Lib/test/test_itertools.py M Modules/itertoolsmodule.c M Python/bltinmodule.c diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 61155799c44a..1100c49e9b88 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1477,6 +1477,18 @@ def test_zip_pickle(self): z1 = zip(a, b) self.check_iter_pickle(z1, t, proto) + def test_zip_bad_iterable(self): + exception = TypeError() + + class BadIterable: + def __iter__(self): + raise exception + + with self.assertRaises(TypeError) as cm: + zip(BadIterable()) + + self.assertIs(cm.exception, exception) + def test_format(self): # Test the basic machinery of the format() builtin. Don't test # the specifics of the various formatters diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index 573739fde14c..98b8c8373189 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -971,6 +971,18 @@ def test_zip_longest_pickling(self): self.pickletest(proto, zip_longest("abc", "defgh", fillvalue=1)) self.pickletest(proto, zip_longest("", "defgh")) + def test_zip_longest_bad_iterable(self): + exception = TypeError() + + class BadIterable: + def __iter__(self): + raise exception + + with self.assertRaises(TypeError) as cm: + zip_longest(BadIterable()) + + self.assertIs(cm.exception, exception) + def test_bug_7244(self): class Repeater: diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 00e3cbb31b53..22c04f29353e 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -4434,10 +4434,6 @@ zip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *item = PyTuple_GET_ITEM(args, i); PyObject *it = PyObject_GetIter(item); if (it == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, - "zip_longest argument #%zd must support iteration", - i+1); Py_DECREF(ittuple); return NULL; } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 62502218ef4c..b85bfb2b91e3 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2549,10 +2549,6 @@ zip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *item = PyTuple_GET_ITEM(args, i); PyObject *it = PyObject_GetIter(item); if (it == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, - "zip argument #%zd must support iteration", - i+1); Py_DECREF(ittuple); return NULL; } From webhook-mailer at python.org Fri Aug 30 08:30:41 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 30 Aug 2019 12:30:41 -0000 Subject: [Python-checkins] bpo-37140: Fix StructUnionType_paramfunc() (GH-15612) Message-ID: https://github.com/python/cpython/commit/96b4087ce784ee7434dffdf69c475f5b40543982 commit: 96b4087ce784ee7434dffdf69c475f5b40543982 branch: master author: Victor Stinner committer: GitHub date: 2019-08-30T14:30:33+02:00 summary: bpo-37140: Fix StructUnionType_paramfunc() (GH-15612) Fix a ctypes regression of Python 3.8. When a ctypes.Structure is passed by copy to a function, ctypes internals created a temporary object which had the side effect of calling the structure finalizer (__del__) twice. The Python semantics requires a finalizer to be called exactly once. Fix ctypes internals to no longer call the finalizer twice. Create a new internal StructParam_Type which is only used by _ctypes_callproc() to call PyMem_Free(ptr) on Py_DECREF(argument). StructUnionType_paramfunc() creates such object. files: A Misc/NEWS.d/next/Library/2019-08-30-11-21-10.bpo-37140.cFAX-a.rst M Lib/ctypes/test/test_structures.py M Modules/_ctypes/_ctypes.c diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py index d1ea43bc7e3b..fda104563d29 100644 --- a/Lib/ctypes/test/test_structures.py +++ b/Lib/ctypes/test/test_structures.py @@ -3,7 +3,7 @@ from ctypes.test import need_symbol from struct import calcsize import _ctypes_test -import test.support +from test import support class SubclassesTest(unittest.TestCase): def test_subclass(self): @@ -202,7 +202,7 @@ class X(Structure): "_pack_": -1} self.assertRaises(ValueError, type(Structure), "X", (Structure,), d) - @test.support.cpython_only + @support.cpython_only def test_packed_c_limits(self): # Issue 15989 import _testcapi @@ -396,27 +396,66 @@ class Z(Y): self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7)) def test_pass_by_value(self): - # This should mirror the structure in Modules/_ctypes/_ctypes_test.c - class X(Structure): + # This should mirror the Test structure + # in Modules/_ctypes/_ctypes_test.c + class Test(Structure): _fields_ = [ ('first', c_ulong), ('second', c_ulong), ('third', c_ulong), ] - s = X() + s = Test() s.first = 0xdeadbeef s.second = 0xcafebabe s.third = 0x0bad1dea dll = CDLL(_ctypes_test.__file__) func = dll._testfunc_large_struct_update_value - func.argtypes = (X,) + func.argtypes = (Test,) func.restype = None func(s) self.assertEqual(s.first, 0xdeadbeef) self.assertEqual(s.second, 0xcafebabe) self.assertEqual(s.third, 0x0bad1dea) + def test_pass_by_value_finalizer(self): + # bpo-37140: Similar to test_pass_by_value(), but the Python structure + # has a finalizer (__del__() method): the finalizer must only be called + # once. + + finalizer_calls = [] + + class Test(Structure): + _fields_ = [ + ('first', c_ulong), + ('second', c_ulong), + ('third', c_ulong), + ] + def __del__(self): + finalizer_calls.append("called") + + s = Test(1, 2, 3) + # Test the StructUnionType_paramfunc() code path which copies the + # structure: if the stucture is larger than sizeof(void*). + self.assertGreater(sizeof(s), sizeof(c_void_p)) + + dll = CDLL(_ctypes_test.__file__) + func = dll._testfunc_large_struct_update_value + func.argtypes = (Test,) + func.restype = None + func(s) + # bpo-37140: Passing the structure by refrence must not call + # its finalizer! + self.assertEqual(finalizer_calls, []) + self.assertEqual(s.first, 1) + self.assertEqual(s.second, 2) + self.assertEqual(s.third, 3) + + # The finalizer must be called exactly once + s = None + support.gc_collect() + self.assertEqual(finalizer_calls, ["called"]) + def test_pass_by_value_in_register(self): class X(Structure): _fields_ = [ diff --git a/Misc/NEWS.d/next/Library/2019-08-30-11-21-10.bpo-37140.cFAX-a.rst b/Misc/NEWS.d/next/Library/2019-08-30-11-21-10.bpo-37140.cFAX-a.rst new file mode 100644 index 000000000000..4eaa226147f9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-30-11-21-10.bpo-37140.cFAX-a.rst @@ -0,0 +1,5 @@ +Fix a ctypes regression of Python 3.8. When a ctypes.Structure is passed by +copy to a function, ctypes internals created a temporary object which had +the side effect of calling the structure finalizer (__del__) twice. The +Python semantics requires a finalizer to be called exactly once. Fix ctypes +internals to no longer call the finalizer twice. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index c1941c16400e..95bfe9d6348e 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -392,6 +392,35 @@ _ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape, return result; } +/* StructParamObject and StructParam_Type are used in _ctypes_callproc() + for argument.keep to call PyMem_Free(ptr) on Py_DECREF(argument). + + StructUnionType_paramfunc() creates such object when a ctypes Structure is + passed by copy to a C function. */ +typedef struct { + PyObject_HEAD + void *ptr; +} StructParamObject; + + +static void +StructParam_dealloc(PyObject *myself) +{ + StructParamObject *self = (StructParamObject *)myself; + PyMem_Free(self->ptr); + Py_TYPE(self)->tp_free(myself); +} + + +static PyTypeObject StructParam_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_ctypes.StructParam_Type", + .tp_basicsize = sizeof(StructParamObject), + .tp_dealloc = StructParam_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + + /* PyCStructType_Type - a meta type/class. Creating a new class using this one as __metaclass__ will call the constructor StructUnionType_new. It replaces the @@ -403,35 +432,47 @@ static PyCArgObject * StructUnionType_paramfunc(CDataObject *self) { PyCArgObject *parg; - CDataObject *copied_self; + PyObject *obj; StgDictObject *stgdict; + void *ptr; if ((size_t)self->b_size > sizeof(void*)) { - void *new_ptr = PyMem_Malloc(self->b_size); - if (new_ptr == NULL) + ptr = PyMem_Malloc(self->b_size); + if (ptr == NULL) { return NULL; - memcpy(new_ptr, self->b_ptr, self->b_size); - copied_self = (CDataObject *)PyCData_AtAddress( - (PyObject *)Py_TYPE(self), new_ptr); - copied_self->b_needsfree = 1; + } + memcpy(ptr, self->b_ptr, self->b_size); + + /* Create a Python object which calls PyMem_Free(ptr) in + its deallocator. The object will be destroyed + at _ctypes_callproc() cleanup. */ + obj = (&StructParam_Type)->tp_alloc(&StructParam_Type, 0); + if (obj == NULL) { + PyMem_Free(ptr); + return NULL; + } + + StructParamObject *struct_param = (StructParamObject *)obj; + struct_param->ptr = ptr; } else { - copied_self = self; - Py_INCREF(copied_self); + ptr = self->b_ptr; + obj = (PyObject *)self; + Py_INCREF(obj); } parg = PyCArgObject_new(); if (parg == NULL) { - Py_DECREF(copied_self); + Py_DECREF(obj); return NULL; } parg->tag = 'V'; - stgdict = PyObject_stgdict((PyObject *)copied_self); + stgdict = PyObject_stgdict((PyObject *)self); assert(stgdict); /* Cannot be NULL for structure/union instances */ parg->pffi_type = &stgdict->ffi_type_pointer; - parg->value.p = copied_self->b_ptr; - parg->size = copied_self->b_size; - parg->obj = (PyObject *)copied_self; + parg->value.p = ptr; + parg->size = self->b_size; + parg->obj = obj; return parg; } @@ -5700,6 +5741,10 @@ PyInit__ctypes(void) if (PyType_Ready(&DictRemover_Type) < 0) return NULL; + if (PyType_Ready(&StructParam_Type) < 0) { + return NULL; + } + #ifdef MS_WIN32 if (create_comerror() < 0) return NULL; From webhook-mailer at python.org Fri Aug 30 08:50:48 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 30 Aug 2019 12:50:48 -0000 Subject: [Python-checkins] bpo-37140: Fix StructUnionType_paramfunc() (GH-15612) Message-ID: https://github.com/python/cpython/commit/17f61ed25a856ed673ad6f2e9782c3d5e556f151 commit: 17f61ed25a856ed673ad6f2e9782c3d5e556f151 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-30T05:50:44-07:00 summary: bpo-37140: Fix StructUnionType_paramfunc() (GH-15612) Fix a ctypes regression of Python 3.8. When a ctypes.Structure is passed by copy to a function, ctypes internals created a temporary object which had the side effect of calling the structure finalizer (__del__) twice. The Python semantics requires a finalizer to be called exactly once. Fix ctypes internals to no longer call the finalizer twice. Create a new internal StructParam_Type which is only used by _ctypes_callproc() to call PyMem_Free(ptr) on Py_DECREF(argument). StructUnionType_paramfunc() creates such object. (cherry picked from commit 96b4087ce784ee7434dffdf69c475f5b40543982) Co-authored-by: Victor Stinner files: A Misc/NEWS.d/next/Library/2019-08-30-11-21-10.bpo-37140.cFAX-a.rst M Lib/ctypes/test/test_structures.py M Modules/_ctypes/_ctypes.c diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py index d1ea43bc7e3b..fda104563d29 100644 --- a/Lib/ctypes/test/test_structures.py +++ b/Lib/ctypes/test/test_structures.py @@ -3,7 +3,7 @@ from ctypes.test import need_symbol from struct import calcsize import _ctypes_test -import test.support +from test import support class SubclassesTest(unittest.TestCase): def test_subclass(self): @@ -202,7 +202,7 @@ class X(Structure): "_pack_": -1} self.assertRaises(ValueError, type(Structure), "X", (Structure,), d) - @test.support.cpython_only + @support.cpython_only def test_packed_c_limits(self): # Issue 15989 import _testcapi @@ -396,27 +396,66 @@ class Z(Y): self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7)) def test_pass_by_value(self): - # This should mirror the structure in Modules/_ctypes/_ctypes_test.c - class X(Structure): + # This should mirror the Test structure + # in Modules/_ctypes/_ctypes_test.c + class Test(Structure): _fields_ = [ ('first', c_ulong), ('second', c_ulong), ('third', c_ulong), ] - s = X() + s = Test() s.first = 0xdeadbeef s.second = 0xcafebabe s.third = 0x0bad1dea dll = CDLL(_ctypes_test.__file__) func = dll._testfunc_large_struct_update_value - func.argtypes = (X,) + func.argtypes = (Test,) func.restype = None func(s) self.assertEqual(s.first, 0xdeadbeef) self.assertEqual(s.second, 0xcafebabe) self.assertEqual(s.third, 0x0bad1dea) + def test_pass_by_value_finalizer(self): + # bpo-37140: Similar to test_pass_by_value(), but the Python structure + # has a finalizer (__del__() method): the finalizer must only be called + # once. + + finalizer_calls = [] + + class Test(Structure): + _fields_ = [ + ('first', c_ulong), + ('second', c_ulong), + ('third', c_ulong), + ] + def __del__(self): + finalizer_calls.append("called") + + s = Test(1, 2, 3) + # Test the StructUnionType_paramfunc() code path which copies the + # structure: if the stucture is larger than sizeof(void*). + self.assertGreater(sizeof(s), sizeof(c_void_p)) + + dll = CDLL(_ctypes_test.__file__) + func = dll._testfunc_large_struct_update_value + func.argtypes = (Test,) + func.restype = None + func(s) + # bpo-37140: Passing the structure by refrence must not call + # its finalizer! + self.assertEqual(finalizer_calls, []) + self.assertEqual(s.first, 1) + self.assertEqual(s.second, 2) + self.assertEqual(s.third, 3) + + # The finalizer must be called exactly once + s = None + support.gc_collect() + self.assertEqual(finalizer_calls, ["called"]) + def test_pass_by_value_in_register(self): class X(Structure): _fields_ = [ diff --git a/Misc/NEWS.d/next/Library/2019-08-30-11-21-10.bpo-37140.cFAX-a.rst b/Misc/NEWS.d/next/Library/2019-08-30-11-21-10.bpo-37140.cFAX-a.rst new file mode 100644 index 000000000000..4eaa226147f9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-30-11-21-10.bpo-37140.cFAX-a.rst @@ -0,0 +1,5 @@ +Fix a ctypes regression of Python 3.8. When a ctypes.Structure is passed by +copy to a function, ctypes internals created a temporary object which had +the side effect of calling the structure finalizer (__del__) twice. The +Python semantics requires a finalizer to be called exactly once. Fix ctypes +internals to no longer call the finalizer twice. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 2201c4520ad0..47288740063e 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -392,6 +392,35 @@ _ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape, return result; } +/* StructParamObject and StructParam_Type are used in _ctypes_callproc() + for argument.keep to call PyMem_Free(ptr) on Py_DECREF(argument). + + StructUnionType_paramfunc() creates such object when a ctypes Structure is + passed by copy to a C function. */ +typedef struct { + PyObject_HEAD + void *ptr; +} StructParamObject; + + +static void +StructParam_dealloc(PyObject *myself) +{ + StructParamObject *self = (StructParamObject *)myself; + PyMem_Free(self->ptr); + Py_TYPE(self)->tp_free(myself); +} + + +static PyTypeObject StructParam_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "_ctypes.StructParam_Type", + .tp_basicsize = sizeof(StructParamObject), + .tp_dealloc = StructParam_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + + /* PyCStructType_Type - a meta type/class. Creating a new class using this one as __metaclass__ will call the constructor StructUnionType_new. It replaces the @@ -403,35 +432,47 @@ static PyCArgObject * StructUnionType_paramfunc(CDataObject *self) { PyCArgObject *parg; - CDataObject *copied_self; + PyObject *obj; StgDictObject *stgdict; + void *ptr; if ((size_t)self->b_size > sizeof(void*)) { - void *new_ptr = PyMem_Malloc(self->b_size); - if (new_ptr == NULL) + ptr = PyMem_Malloc(self->b_size); + if (ptr == NULL) { return NULL; - memcpy(new_ptr, self->b_ptr, self->b_size); - copied_self = (CDataObject *)PyCData_AtAddress( - (PyObject *)Py_TYPE(self), new_ptr); - copied_self->b_needsfree = 1; + } + memcpy(ptr, self->b_ptr, self->b_size); + + /* Create a Python object which calls PyMem_Free(ptr) in + its deallocator. The object will be destroyed + at _ctypes_callproc() cleanup. */ + obj = (&StructParam_Type)->tp_alloc(&StructParam_Type, 0); + if (obj == NULL) { + PyMem_Free(ptr); + return NULL; + } + + StructParamObject *struct_param = (StructParamObject *)obj; + struct_param->ptr = ptr; } else { - copied_self = self; - Py_INCREF(copied_self); + ptr = self->b_ptr; + obj = (PyObject *)self; + Py_INCREF(obj); } parg = PyCArgObject_new(); if (parg == NULL) { - Py_DECREF(copied_self); + Py_DECREF(obj); return NULL; } parg->tag = 'V'; - stgdict = PyObject_stgdict((PyObject *)copied_self); + stgdict = PyObject_stgdict((PyObject *)self); assert(stgdict); /* Cannot be NULL for structure/union instances */ parg->pffi_type = &stgdict->ffi_type_pointer; - parg->value.p = copied_self->b_ptr; - parg->size = copied_self->b_size; - parg->obj = (PyObject *)copied_self; + parg->value.p = ptr; + parg->size = self->b_size; + parg->obj = obj; return parg; } @@ -5700,6 +5741,10 @@ PyInit__ctypes(void) if (PyType_Ready(&DictRemover_Type) < 0) return NULL; + if (PyType_Ready(&StructParam_Type) < 0) { + return NULL; + } + #ifdef MS_WIN32 if (create_comerror() < 0) return NULL; From webhook-mailer at python.org Fri Aug 30 16:16:43 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Fri, 30 Aug 2019 20:16:43 -0000 Subject: [Python-checkins] IDLE: Fix 2 typos found by Min ho Kim. (GH-15617) Message-ID: https://github.com/python/cpython/commit/15119bc2a7e902ae1c6988556c3bef3de87fa789 commit: 15119bc2a7e902ae1c6988556c3bef3de87fa789 branch: master author: Terry Jan Reedy committer: GitHub date: 2019-08-30T16:16:37-04:00 summary: IDLE: Fix 2 typos found by Min ho Kim. (GH-15617) files: M Lib/idlelib/README.txt M Lib/idlelib/browser.py diff --git a/Lib/idlelib/README.txt b/Lib/idlelib/README.txt index 42c3506699ba..48a1f4a425c9 100644 --- a/Lib/idlelib/README.txt +++ b/Lib/idlelib/README.txt @@ -115,7 +115,7 @@ tooltip.py # unused IDLE MENUS Top level items and most submenu items are defined in mainmenu. -Extenstions add submenu items when active. The names given are +Extensions add submenu items when active. The names given are found, quoted, in one of these modules, paired with a '<>'. Each pseudoevent is bound to an event handler. Some event handlers call another function that does the actual work. The annotations below diff --git a/Lib/idlelib/browser.py b/Lib/idlelib/browser.py index e5b0bc53c662..3c3a53a6599a 100644 --- a/Lib/idlelib/browser.py +++ b/Lib/idlelib/browser.py @@ -29,7 +29,7 @@ def transform_children(child_dict, modname=None): The dictionary maps names to pyclbr information objects. Filter out imported objects. Augment class names with bases. - The insertion order of the dictonary is assumed to have been in line + The insertion order of the dictionary is assumed to have been in line number order, so sorting is not necessary. The current tree only calls this once per child_dict as it saves From webhook-mailer at python.org Fri Aug 30 16:21:23 2019 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Fri, 30 Aug 2019 20:21:23 -0000 Subject: [Python-checkins] Fix typos mostly in comments, docs and test names (GH-15209) Message-ID: https://github.com/python/cpython/commit/39d87b54715197ca9dcb6902bb43461c0ed701a2 commit: 39d87b54715197ca9dcb6902bb43461c0ed701a2 branch: master author: Min ho Kim committer: Terry Jan Reedy date: 2019-08-30T16:21:19-04:00 summary: Fix typos mostly in comments, docs and test names (GH-15209) files: M Doc/c-api/init_config.rst M Doc/library/importlib.rst M Include/pyhash.h M Lib/asyncio/streams.py M Lib/bdb.py M Lib/multiprocessing/util.py M Lib/test/lock_tests.py M Lib/test/test_cmd_line_script.py M Lib/test/test_collections.py M Lib/test/test_descr.py M Lib/test/test_format.py M Lib/test/test_gc.py M Lib/test/test_hmac.py M Lib/test/test_importlib/source/test_file_loader.py M Lib/test/test_importlib/test_main.py M Lib/test/test_importlib/util.py M Lib/test/test_statistics.py M Lib/test/test_tracemalloc.py M Lib/test/test_warnings/__init__.py M Lib/test/test_winreg.py M Lib/test/test_wsgiref.py M Lib/tkinter/filedialog.py M Lib/unittest/test/testmock/testpatch.py M Lib/uuid.py M Misc/HISTORY M Misc/NEWS.d/3.5.0a1.rst M Misc/NEWS.d/3.5.4rc1.rst M Misc/NEWS.d/3.6.0b1.rst M Misc/NEWS.d/3.6.0rc1.rst M Misc/NEWS.d/3.6.1rc1.rst M Misc/NEWS.d/3.7.0a1.rst M Misc/NEWS.d/3.8.0a1.rst M Misc/NEWS.d/3.8.0a4.rst M Misc/NEWS.d/3.8.0b1.rst M Modules/_ctypes/callproc.c M Modules/_ctypes/stgdict.c M Modules/_io/bytesio.c M Modules/_io/stringio.c M Modules/_testcapimodule.c M Modules/expat/loadlibrary.c M Modules/expat/xmlparse.c M Modules/termios.c M Objects/listsort.txt M Objects/typeobject.c M Python/ast.c M Python/pystate.c diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 72bd8c37b435..c198df3fb1d0 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -876,7 +876,7 @@ Path Configuration If at least one "output field" is not set, Python computes the path configuration to fill unset fields. If :c:member:`~PyConfig.module_search_paths_set` is equal to 0, -:c:member:`~PyConfig.module_search_paths` is overriden and +:c:member:`~PyConfig.module_search_paths` is overridden and :c:member:`~PyConfig.module_search_paths_set` is set to 1. It is possible to completely ignore the function computing the default diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 8be6172d4c76..0976360c6965 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -1379,8 +1379,8 @@ an :term:`importer`. bytecode file. An empty string represents no optimization, so ``/foo/bar/baz.py`` with an *optimization* of ``''`` will result in a bytecode path of ``/foo/bar/__pycache__/baz.cpython-32.pyc``. ``None`` causes - the interpter's optimization level to be used. Any other value's string - representation being used, so ``/foo/bar/baz.py`` with an *optimization* of + the interpreter's optimization level to be used. Any other value's string + representation is used, so ``/foo/bar/baz.py`` with an *optimization* of ``2`` will lead to the bytecode path of ``/foo/bar/__pycache__/baz.cpython-32.opt-2.pyc``. The string representation of *optimization* can only be alphanumeric, else :exc:`ValueError` is raised. diff --git a/Include/pyhash.h b/Include/pyhash.h index 9cfd071ea17b..dbcc9744be35 100644 --- a/Include/pyhash.h +++ b/Include/pyhash.h @@ -119,7 +119,7 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); * configure script. * * - FNV is available on all platforms and architectures. - * - SIPHASH24 only works on plaforms that don't require aligned memory for integers. + * - SIPHASH24 only works on platforms that don't require aligned memory for integers. * - With EXTERNAL embedders can provide an alternative implementation with:: * * PyHash_FuncDef PyHash_Func = {...}; diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index e56e2efe5cf1..33b2fa55673e 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -71,7 +71,7 @@ def connect(host=None, port=None, *, ssl_handshake_timeout=None, happy_eyeballs_delay=None, interleave=None): # Design note: - # Don't use decorator approach but exilicit non-async + # Don't use decorator approach but explicit non-async # function to fail fast and explicitly # if passed arguments don't match the function signature return _ContextManagerHelper(_connect(host, port, limit, @@ -442,7 +442,7 @@ def connect_unix(path=None, *, ssl_handshake_timeout=None): """Similar to `connect()` but works with UNIX Domain Sockets.""" # Design note: - # Don't use decorator approach but exilicit non-async + # Don't use decorator approach but explicit non-async # function to fail fast and explicitly # if passed arguments don't match the function signature return _ContextManagerHelper(_connect_unix(path, diff --git a/Lib/bdb.py b/Lib/bdb.py index fd34976a4d0b..7b19ba369036 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -38,7 +38,7 @@ def canonic(self, filename): """Return canonical form of filename. For real filenames, the canonical form is a case-normalized (on - case insenstive filesystems) absolute path. 'Filenames' with + case insensitive filesystems) absolute path. 'Filenames' with angle brackets, such as "", generated in interactive mode, are returned unchanged. """ diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py index 19380917b6f5..32b51b04373f 100644 --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -238,7 +238,7 @@ def __repr__(self): if self._kwargs: x += ', kwargs=' + str(self._kwargs) if self._key[0] is not None: - x += ', exitprority=' + str(self._key[0]) + x += ', exitpriority=' + str(self._key[0]) return x + '>' diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py index 888586840f2c..d12a86e7e934 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -467,7 +467,7 @@ def _check_notify(self, cond): # of the workers. # Secondly, this test assumes that condition variables are not subject # to spurious wakeups. The absence of spurious wakeups is an implementation - # detail of Condition Cariables in current CPython, but in general, not + # detail of Condition Variables in current CPython, but in general, not # a guaranteed property of condition variables as a programming # construct. In particular, it is possible that this can no longer # be conveniently guaranteed should their implementation ever change. diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index c8bf8af964f8..60723078efc6 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -474,7 +474,7 @@ def test_dash_m_errors(self): ('os.path', br'loader.*cannot handle'), ('importlib', br'No module named.*' br'is a package and cannot be directly executed'), - ('importlib.nonexistant', br'No module named'), + ('importlib.nonexistent', br'No module named'), ('.unittest', br'Relative module names not supported'), ) for name, regex in tests: diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 7f01de6f433d..a2a66a757220 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1927,7 +1927,7 @@ def test_order_preservation(self): 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l']) # Math operations order first by the order encountered in the left - # operand and then by the order encounted in the right operand. + # operand and then by the order encountered in the right operand. ps = 'aaabbcdddeefggghhijjjkkl' qs = 'abbcccdeefffhkkllllmmnno' order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))} diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 770e0c496e28..4368bb585f31 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -3025,7 +3025,7 @@ def test_str_subclass_as_dict_key(self): # Testing a str subclass used as dict key .. class cistr(str): - """Sublcass of str that computes __eq__ case-insensitively. + """Subclass of str that computes __eq__ case-insensitively. Also computes a hash code of the string in canonical form. """ diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py index 83804cbb00ab..4559cd5623ef 100644 --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -48,7 +48,7 @@ def testformat(formatstr, args, output=None, limit=None, overflowok=False): def testcommon(formatstr, args, output=None, limit=None, overflowok=False): # if formatstr is a str, test str, bytes, and bytearray; - # otherwise, test bytes and bytearry + # otherwise, test bytes and bytearray if isinstance(formatstr, str): testformat(formatstr, args, output, limit, overflowok) b_format = formatstr.encode('ascii') diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index 2dab53004452..311143da91d0 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -912,7 +912,7 @@ def test_collect_generation(self): def test_collect_garbage(self): self.preclean() # Each of these cause four objects to be garbage: Two - # Uncolectables and their instance dicts. + # Uncollectables and their instance dicts. Uncollectable() Uncollectable() C1055820(666) diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index 896bbe9ab798..f2eb6d716d52 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -445,7 +445,7 @@ def test_compare_digest(self): a, b = bytearray(b"foobar"), bytearray(b"foobar") self.assertTrue(hmac.compare_digest(a, b)) - # Testing bytearrays of diffeent lengths + # Testing bytearrays of different lengths a, b = bytearray(b"foobar"), bytearray(b"foo") self.assertFalse(hmac.compare_digest(a, b)) @@ -458,7 +458,7 @@ def test_compare_digest(self): self.assertTrue(hmac.compare_digest(a, b)) self.assertTrue(hmac.compare_digest(b, a)) - # Testing byte bytearray of diffeent lengths + # Testing byte bytearray of different lengths a, b = bytearray(b"foobar"), b"foo" self.assertFalse(hmac.compare_digest(a, b)) self.assertFalse(hmac.compare_digest(b, a)) @@ -472,7 +472,7 @@ def test_compare_digest(self): a, b = "foobar", "foobar" self.assertTrue(hmac.compare_digest(a, b)) - # Testing str of diffeent lengths + # Testing str of different lengths a, b = "foo", "foobar" self.assertFalse(hmac.compare_digest(a, b)) diff --git a/Lib/test/test_importlib/source/test_file_loader.py b/Lib/test/test_importlib/source/test_file_loader.py index 3ffb2aa1e60a..ab44722146e3 100644 --- a/Lib/test/test_importlib/source/test_file_loader.py +++ b/Lib/test/test_importlib/source/test_file_loader.py @@ -325,7 +325,7 @@ def test_unchecked_hash_based_pyc(self): ) @util.writes_bytecode_files - def test_overiden_unchecked_hash_based_pyc(self): + def test_overridden_unchecked_hash_based_pyc(self): with util.create_modules('_temp') as mapping, \ unittest.mock.patch('_imp.check_hash_based_pycs', 'always'): source = mapping['_temp'] diff --git a/Lib/test/test_importlib/test_main.py b/Lib/test/test_importlib/test_main.py index bc42b83ee291..3d7da819b343 100644 --- a/Lib/test/test_importlib/test_main.py +++ b/Lib/test/test_importlib/test_main.py @@ -32,7 +32,7 @@ def test_new_style_classes(self): class ImportTests(fixtures.DistInfoPkg, unittest.TestCase): def test_import_nonexistent_module(self): # Ensure that the MetadataPathFinder does not crash an import of a - # non-existant module. + # non-existent module. with self.assertRaises(ImportError): importlib.import_module('does_not_exist') diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index 913db4bb3b71..5aaf277e1f37 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -443,7 +443,7 @@ def contents(self): yield entry name = 'testingpackage' - # Unforunately importlib.util.module_from_spec() was not introduced until + # Unfortunately importlib.util.module_from_spec() was not introduced until # Python 3.5. module = types.ModuleType(name) loader = Reader() diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 23dd96e365a8..01b317c3281e 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -1810,13 +1810,13 @@ def test_bimodal_data(self): # Test mode with bimodal data. data = [1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 6, 6, 6, 7, 8, 9, 9] assert data.count(2) == data.count(6) == 4 - # mode() should return 2, the first encounted mode + # mode() should return 2, the first encountered mode self.assertEqual(self.func(data), 2) def test_unique_data(self): # Test mode when data points are all unique. data = list(range(10)) - # mode() should return 0, the first encounted mode + # mode() should return 0, the first encountered mode self.assertEqual(self.func(data), 0) def test_none_data(self): diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py index c3866483b8aa..4b9bf4ed5da1 100644 --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -885,7 +885,7 @@ def check_env_var_invalid(self, nframe): return if b'PYTHONTRACEMALLOC: invalid number of frames' in stderr: return - self.fail(f"unexpeced output: {stderr!a}") + self.fail(f"unexpected output: {stderr!a}") def test_env_var_invalid(self): @@ -914,7 +914,7 @@ def check_sys_xoptions_invalid(self, nframe): return if b'-X tracemalloc=NFRAME: invalid number of frames' in stderr: return - self.fail(f"unexpeced output: {stderr!a}") + self.fail(f"unexpected output: {stderr!a}") def test_sys_xoptions_invalid(self): for nframe in INVALID_NFRAME: diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index be848b2f9b6c..d1031829514b 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -714,7 +714,7 @@ def test_showwarning_not_callable(self): self.assertRaises(TypeError, self.module.warn, "Warning!") def test_show_warning_output(self): - # With showarning() missing, make sure that output is okay. + # With showwarning() missing, make sure that output is okay. text = 'test show_warning' with original_warnings.catch_warnings(module=self.module): self.module.filterwarnings("always", category=UserWarning) diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index dc2b46e42521..91a2bbc066b1 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -229,7 +229,7 @@ def test_connect_registry_to_local_machine_works(self): h.Close() self.assertEqual(h.handle, 0) - def test_inexistant_remote_registry(self): + def test_nonexistent_remote_registry(self): connect = lambda: ConnectRegistry("abcdefghijkl", HKEY_CURRENT_USER) self.assertRaises(OSError, connect) diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py index bce33291c566..6af45145a792 100644 --- a/Lib/test/test_wsgiref.py +++ b/Lib/test/test_wsgiref.py @@ -586,10 +586,10 @@ def testEnviron(self): expected.update({ # X doesn't exist in os_environ "X": "Y", - # HOME is overriden by TestHandler + # HOME is overridden by TestHandler 'HOME': "/override/home", - # overriden by setup_testing_defaults() + # overridden by setup_testing_defaults() "SCRIPT_NAME": "", "SERVER_NAME": "127.0.0.1", diff --git a/Lib/tkinter/filedialog.py b/Lib/tkinter/filedialog.py index dbb97dd5777e..3ed93eb8c163 100644 --- a/Lib/tkinter/filedialog.py +++ b/Lib/tkinter/filedialog.py @@ -469,7 +469,7 @@ def test(): except (ImportError, AttributeError): pass - # dialog for openening files + # dialog for opening files openfilename=askopenfilename(filetypes=[("all files", "*")]) try: diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index 27914a9d7178..0632d95e58fe 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -1651,7 +1651,7 @@ def test_patch_imports_lazily(self): p1.stop() self.assertEqual(squizz.squozz, 3) - def test_patch_propogrates_exc_on_exit(self): + def test_patch_propagates_exc_on_exit(self): class holder: exc_info = None, None, None @@ -1680,9 +1680,9 @@ def test(mock): self.assertIs(holder.exc_info[0], RuntimeError) self.assertIsNotNone(holder.exc_info[1], - 'exception value not propgated') + 'exception value not propagated') self.assertIsNotNone(holder.exc_info[2], - 'exception traceback not propgated') + 'exception traceback not propagated') def test_create_and_specs(self): diff --git a/Lib/uuid.py b/Lib/uuid.py index 7aa01bb5c355..188e16ba14e3 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -680,7 +680,7 @@ def _random_getnode(): return random.getrandbits(48) | (1 << 40) -# _OS_GETTERS, when known, are targetted for a specific OS or platform. +# _OS_GETTERS, when known, are targeted for a specific OS or platform. # The order is by 'common practice' on the specified platform. # Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method # which, when successful, means none of these "external" methods are called. diff --git a/Misc/HISTORY b/Misc/HISTORY index f49960c95ada..32b2a37866bc 100644 --- a/Misc/HISTORY +++ b/Misc/HISTORY @@ -1231,7 +1231,7 @@ Library - Issue #22448: Improve canceled timer handles cleanup to prevent unbound memory usage. Patch by Joshua Moore-Oliva. -- Issue #23009: Make sure selectors.EpollSelecrtor.select() works when no +- Issue #23009: Make sure selectors.EpollSelector.select() works when no FD is registered. IDLE @@ -16660,7 +16660,7 @@ Core and Builtins Exception (KeyboardInterrupt, and SystemExit) propagate instead of ignoring them. -- #3021 Exception reraising sematics have been significantly improved. However, +- #3021 Exception reraising semantics have been significantly improved. However, f_exc_type, f_exc_value, and f_exc_traceback cannot be accessed from Python code anymore. diff --git a/Misc/NEWS.d/3.5.0a1.rst b/Misc/NEWS.d/3.5.0a1.rst index 99f2d1d36dbf..56d0d33decc0 100644 --- a/Misc/NEWS.d/3.5.0a1.rst +++ b/Misc/NEWS.d/3.5.0a1.rst @@ -1255,7 +1255,7 @@ Support wrapped callables in doctest. Patch by Claudiu Popa. .. nonce: -sW7gk .. section: Library -Make sure selectors.EpollSelecrtor.select() works when no FD is registered. +Make sure selectors.EpollSelector.select() works when no FD is registered. .. diff --git a/Misc/NEWS.d/3.5.4rc1.rst b/Misc/NEWS.d/3.5.4rc1.rst index f261ddb3a2d3..04a035a41e74 100644 --- a/Misc/NEWS.d/3.5.4rc1.rst +++ b/Misc/NEWS.d/3.5.4rc1.rst @@ -913,7 +913,7 @@ Fixed infinite recursion in the repr of uninitialized ctypes.CDLL instances. Fixed race condition in C implementation of functools.lru_cache. KeyError could be raised when cached function with full cache was simultaneously -called from differen threads with the same uncached arguments. +called from different threads with the same uncached arguments. .. diff --git a/Misc/NEWS.d/3.6.0b1.rst b/Misc/NEWS.d/3.6.0b1.rst index bd0e0a7c58d1..3fbae5c6a4b3 100644 --- a/Misc/NEWS.d/3.6.0b1.rst +++ b/Misc/NEWS.d/3.6.0b1.rst @@ -1148,7 +1148,7 @@ dict constraint in ForwardRef._eval_type (upstream #252) .. nonce: hxh6_h .. section: Library -Make ``_normalize`` parameter to ``Fraction`` constuctor keyword-only, so +Make ``_normalize`` parameter to ``Fraction`` constructor keyword-only, so that ``Fraction(2, 3, 4)`` now raises ``TypeError``. .. diff --git a/Misc/NEWS.d/3.6.0rc1.rst b/Misc/NEWS.d/3.6.0rc1.rst index c44dec324d2f..15769f950db2 100644 --- a/Misc/NEWS.d/3.6.0rc1.rst +++ b/Misc/NEWS.d/3.6.0rc1.rst @@ -48,7 +48,7 @@ they still are deprecated and will be disabled in 3.7. .. section: Library Fix a regression introduced in warnings.catch_warnings(): call -warnings.showwarning() if it was overriden inside the context manager. +warnings.showwarning() if it was overridden inside the context manager. .. diff --git a/Misc/NEWS.d/3.6.1rc1.rst b/Misc/NEWS.d/3.6.1rc1.rst index 1f9fb13f6970..58fd1b0624b2 100644 --- a/Misc/NEWS.d/3.6.1rc1.rst +++ b/Misc/NEWS.d/3.6.1rc1.rst @@ -435,7 +435,7 @@ Fix an important omission by adding Deque to the typing module. Fixed race condition in C implementation of functools.lru_cache. KeyError could be raised when cached function with full cache was simultaneously -called from differen threads with the same uncached arguments. +called from different threads with the same uncached arguments. .. diff --git a/Misc/NEWS.d/3.7.0a1.rst b/Misc/NEWS.d/3.7.0a1.rst index bbd72d7f3ff8..244bb37e7c61 100644 --- a/Misc/NEWS.d/3.7.0a1.rst +++ b/Misc/NEWS.d/3.7.0a1.rst @@ -3651,7 +3651,7 @@ regular expression objects. Fixed race condition in C implementation of functools.lru_cache. KeyError could be raised when cached function with full cache was simultaneously -called from differen threads with the same uncached arguments. +called from different threads with the same uncached arguments. .. diff --git a/Misc/NEWS.d/3.8.0a1.rst b/Misc/NEWS.d/3.8.0a1.rst index 68217d31193e..c5ab5f4489c9 100644 --- a/Misc/NEWS.d/3.8.0a1.rst +++ b/Misc/NEWS.d/3.8.0a1.rst @@ -2418,7 +2418,7 @@ over browsers in the ``BROWSER`` environment variable. .. nonce: eSLKBE .. section: Library -Avoid stripping trailing whitespace in doctest fancy diff. Orignial patch by +Avoid stripping trailing whitespace in doctest fancy diff. Original patch by R. David Murray & Jairo Trad. Enhanced by Sanyam Khurana. .. diff --git a/Misc/NEWS.d/3.8.0a4.rst b/Misc/NEWS.d/3.8.0a4.rst index 894ce0b5a341..fc952fa9dcc8 100644 --- a/Misc/NEWS.d/3.8.0a4.rst +++ b/Misc/NEWS.d/3.8.0a4.rst @@ -1110,7 +1110,7 @@ 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 +alignment 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/3.8.0b1.rst b/Misc/NEWS.d/3.8.0b1.rst index 609aa338e844..84b0350134fb 100644 --- a/Misc/NEWS.d/3.8.0b1.rst +++ b/Misc/NEWS.d/3.8.0b1.rst @@ -1262,7 +1262,7 @@ 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 +that depend upon one another as the lock acquisition order cannot be guaranteed. .. diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index bd67c6eeaeed..85fa79983ec1 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -110,7 +110,7 @@ static void pymem_destructor(PyObject *ptr) WinDLL(..., use_last_error=True) swap the system LastError value with the ctypes private copy. - The values are also swapped immeditately before and after ctypes callback + The values are also swapped immediately before and after ctypes callback functions are called, if the callbacks are constructed using the new optional use_errno parameter set to True: CFUNCTYPE(..., use_errno=TRUE) or WINFUNCTYPE(..., use_errno=True). diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 235a4d79ad2c..8709cc5404a2 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -352,7 +352,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct int big_endian; /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to - be a way to use the old, broken sematics: _fields_ are not extended + be a way to use the old, broken semantics: _fields_ are not extended but replaced in subclasses. XXX Remove this in ctypes 1.0! diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 793ce920004e..a5f4c47863df 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -841,7 +841,7 @@ bytesio_setstate(bytesio *self, PyObject *state) /* Set carefully the position value. Alternatively, we could use the seek method instead of modifying self->pos directly to better protect the - object internal state against errneous (or malicious) inputs. */ + object internal state against erroneous (or malicious) inputs. */ position_obj = PyTuple_GET_ITEM(state, 1); if (!PyLong_Check(position_obj)) { PyErr_Format(PyExc_TypeError, diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 810cad6d63ce..3f7afad56347 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -899,7 +899,7 @@ stringio_setstate(stringio *self, PyObject *state) /* Set carefully the position value. Alternatively, we could use the seek method instead of modifying self->pos directly to better protect the - object internal state against errneous (or malicious) inputs. */ + object internal state against erroneous (or malicious) inputs. */ position_obj = PyTuple_GET_ITEM(state, 2); if (!PyLong_Check(position_obj)) { PyErr_Format(PyExc_TypeError, diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index cc3b089a0d7d..640ec5914577 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4634,7 +4634,7 @@ check_pyobject_forbidden_bytes_is_freed(PyObject *self, PyObject *Py_UNUSED(args /* Initialize reference count to avoid early crash in ceval or GC */ Py_REFCNT(op) = 1; /* ob_type field is after the memory block: part of "forbidden bytes" - when using debug hooks on memory allocatrs! */ + when using debug hooks on memory allocators! */ return test_pyobject_is_freed("check_pyobject_forbidden_bytes_is_freed", op); } diff --git a/Modules/expat/loadlibrary.c b/Modules/expat/loadlibrary.c index 35fdf98bce6c..2f80b3a379fd 100644 --- a/Modules/expat/loadlibrary.c +++ b/Modules/expat/loadlibrary.c @@ -53,12 +53,12 @@ typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); /* See function definitions in winbase.h */ #ifdef UNICODE # ifdef _WIN32_WCE -# define LOADLIBARYEX L"LoadLibraryExW" +# define LOADLIBRARYEX L"LoadLibraryExW" # else -# define LOADLIBARYEX "LoadLibraryExW" +# define LOADLIBRARYEX "LoadLibraryExW" # endif #else -# define LOADLIBARYEX "LoadLibraryExA" +# define LOADLIBRARYEX "LoadLibraryExA" #endif @@ -88,7 +88,7 @@ HMODULE _Expat_LoadLibrary(LPCTSTR filename) /* Attempt to find LoadLibraryEx() which is only available on Windows 2000 and above */ - pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBARYEX); + pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBRARYEX); /* Detect if there's already a path in the filename and load the library if there is. Note: Both back slashes and forward slashes have been supported diff --git a/Modules/expat/xmlparse.c b/Modules/expat/xmlparse.c index 9c0987f4f6d8..311dbc4dfb9c 100644 --- a/Modules/expat/xmlparse.c +++ b/Modules/expat/xmlparse.c @@ -3399,7 +3399,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, * has to have passed through the hash table lookup once * already. That implies that an entry for it already * exists, so the lookup above will return a pointer to - * already allocated memory. There is no opportunaity for + * already allocated memory. There is no opportunity for * the allocator to fail, so the condition above cannot be * fulfilled. * diff --git a/Modules/termios.c b/Modules/termios.c index 7601b68afda3..aee7f12c57ca 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -18,7 +18,7 @@ #include /* HP-UX requires that this be included to pick up MDCD, MCTS, MDSR, - * MDTR, MRI, and MRTS (appearantly used internally by some things + * MDTR, MRI, and MRTS (apparently used internally by some things * defined as macros; these are not used here directly). */ #ifdef HAVE_SYS_MODEM_H diff --git a/Objects/listsort.txt b/Objects/listsort.txt index 8c877515c72e..43fe1574c323 100644 --- a/Objects/listsort.txt +++ b/Objects/listsort.txt @@ -328,7 +328,7 @@ found is still high in the memory hierarchy. We also can't delay merging unmerged, and the stack has a fixed size. What turned out to be a good compromise maintains two invariants on the -stack entries, where A, B and C are the lengths of the three righmost not-yet +stack entries, where A, B and C are the lengths of the three rightmost not-yet merged slices: 1. A > B+C diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 0ca7dcb695bb..c816c3b6df23 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -117,7 +117,7 @@ find_signature(const char *name, const char *doc) #define SIGNATURE_END_MARKER ")\n--\n\n" #define SIGNATURE_END_MARKER_LENGTH 6 /* - * skips past the end of the docstring's instrospection signature. + * skips past the end of the docstring's introspection signature. * (assumes doc starts with a valid signature prefix.) */ static const char * diff --git a/Python/ast.c b/Python/ast.c index 8b3dbead2fdc..11524029ae26 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -5356,7 +5356,7 @@ typedef struct { doubling the number allocated each time. Note that the f-string f'{0}a{1}' contains 3 expr_ty's: 2 FormattedValue's, and one Constant for the literal 'a'. So you add expr_ty's about twice as - fast as you add exressions in an f-string. */ + fast as you add expressions in an f-string. */ Py_ssize_t allocated; /* Number we've allocated. */ Py_ssize_t size; /* Number we've used. */ diff --git a/Python/pystate.c b/Python/pystate.c index 3b2adf54be45..dc5240048ba0 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -729,7 +729,7 @@ PyState_RemoveModule(struct PyModuleDef* def) return -1; } if (state->modules_by_index == NULL) { - Py_FatalError("PyState_RemoveModule: Interpreters module-list not acessible."); + Py_FatalError("PyState_RemoveModule: Interpreters module-list not accessible."); return -1; } if (index > PyList_GET_SIZE(state->modules_by_index)) { @@ -888,7 +888,7 @@ PyThreadState_DeleteCurrent() * Note that, if there is a current thread state, it *must* be the one * passed as argument. Also, this won't touch any other interpreters * than the current one, since we don't know which thread state should - * be kept in those other interpreteres. + * be kept in those other interpreters. */ void _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate) From webhook-mailer at python.org Fri Aug 30 16:34:53 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 30 Aug 2019 20:34:53 -0000 Subject: [Python-checkins] IDLE: Fix 2 typos found by Min ho Kim. (GH-15617) Message-ID: https://github.com/python/cpython/commit/9a28400aace26597b35950ac561d49c102b6daf4 commit: 9a28400aace26597b35950ac561d49c102b6daf4 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-30T13:34:48-07:00 summary: IDLE: Fix 2 typos found by Min ho Kim. (GH-15617) (cherry picked from commit 15119bc2a7e902ae1c6988556c3bef3de87fa789) Co-authored-by: Terry Jan Reedy files: M Lib/idlelib/README.txt M Lib/idlelib/browser.py diff --git a/Lib/idlelib/README.txt b/Lib/idlelib/README.txt index 42c3506699ba..48a1f4a425c9 100644 --- a/Lib/idlelib/README.txt +++ b/Lib/idlelib/README.txt @@ -115,7 +115,7 @@ tooltip.py # unused IDLE MENUS Top level items and most submenu items are defined in mainmenu. -Extenstions add submenu items when active. The names given are +Extensions add submenu items when active. The names given are found, quoted, in one of these modules, paired with a '<>'. Each pseudoevent is bound to an event handler. Some event handlers call another function that does the actual work. The annotations below diff --git a/Lib/idlelib/browser.py b/Lib/idlelib/browser.py index e5b0bc53c662..3c3a53a6599a 100644 --- a/Lib/idlelib/browser.py +++ b/Lib/idlelib/browser.py @@ -29,7 +29,7 @@ def transform_children(child_dict, modname=None): The dictionary maps names to pyclbr information objects. Filter out imported objects. Augment class names with bases. - The insertion order of the dictonary is assumed to have been in line + The insertion order of the dictionary is assumed to have been in line number order, so sorting is not necessary. The current tree only calls this once per child_dict as it saves From webhook-mailer at python.org Fri Aug 30 16:36:10 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 30 Aug 2019 20:36:10 -0000 Subject: [Python-checkins] IDLE: Fix 2 typos found by Min ho Kim. (GH-15617) Message-ID: https://github.com/python/cpython/commit/3d75857dfa0e50dd6e5439e8bd92c07c5d5e9839 commit: 3d75857dfa0e50dd6e5439e8bd92c07c5d5e9839 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-30T13:36:06-07:00 summary: IDLE: Fix 2 typos found by Min ho Kim. (GH-15617) (cherry picked from commit 15119bc2a7e902ae1c6988556c3bef3de87fa789) Co-authored-by: Terry Jan Reedy files: M Lib/idlelib/README.txt M Lib/idlelib/browser.py diff --git a/Lib/idlelib/README.txt b/Lib/idlelib/README.txt index 42c3506699ba..48a1f4a425c9 100644 --- a/Lib/idlelib/README.txt +++ b/Lib/idlelib/README.txt @@ -115,7 +115,7 @@ tooltip.py # unused IDLE MENUS Top level items and most submenu items are defined in mainmenu. -Extenstions add submenu items when active. The names given are +Extensions add submenu items when active. The names given are found, quoted, in one of these modules, paired with a '<>'. Each pseudoevent is bound to an event handler. Some event handlers call another function that does the actual work. The annotations below diff --git a/Lib/idlelib/browser.py b/Lib/idlelib/browser.py index e5b0bc53c662..3c3a53a6599a 100644 --- a/Lib/idlelib/browser.py +++ b/Lib/idlelib/browser.py @@ -29,7 +29,7 @@ def transform_children(child_dict, modname=None): The dictionary maps names to pyclbr information objects. Filter out imported objects. Augment class names with bases. - The insertion order of the dictonary is assumed to have been in line + The insertion order of the dictionary is assumed to have been in line number order, so sorting is not necessary. The current tree only calls this once per child_dict as it saves From webhook-mailer at python.org Fri Aug 30 16:42:58 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 30 Aug 2019 20:42:58 -0000 Subject: [Python-checkins] Fix typos mostly in comments, docs and test names (GH-15209) Message-ID: https://github.com/python/cpython/commit/4bd1d05ee247f200e52fab3958d875bd88073e5b commit: 4bd1d05ee247f200e52fab3958d875bd88073e5b branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-08-30T13:42:54-07:00 summary: Fix typos mostly in comments, docs and test names (GH-15209) (cherry picked from commit 39d87b54715197ca9dcb6902bb43461c0ed701a2) Co-authored-by: Min ho Kim files: M Doc/c-api/init_config.rst M Doc/library/importlib.rst M Include/pyhash.h M Lib/asyncio/streams.py M Lib/bdb.py M Lib/multiprocessing/util.py M Lib/test/lock_tests.py M Lib/test/test_cmd_line_script.py M Lib/test/test_collections.py M Lib/test/test_descr.py M Lib/test/test_format.py M Lib/test/test_gc.py M Lib/test/test_hmac.py M Lib/test/test_importlib/source/test_file_loader.py M Lib/test/test_importlib/test_main.py M Lib/test/test_importlib/util.py M Lib/test/test_statistics.py M Lib/test/test_tracemalloc.py M Lib/test/test_warnings/__init__.py M Lib/test/test_winreg.py M Lib/test/test_wsgiref.py M Lib/tkinter/filedialog.py M Lib/unittest/test/testmock/testpatch.py M Lib/uuid.py M Misc/HISTORY M Misc/NEWS.d/3.5.0a1.rst M Misc/NEWS.d/3.5.4rc1.rst M Misc/NEWS.d/3.6.0b1.rst M Misc/NEWS.d/3.6.0rc1.rst M Misc/NEWS.d/3.6.1rc1.rst M Misc/NEWS.d/3.7.0a1.rst M Misc/NEWS.d/3.8.0a1.rst M Misc/NEWS.d/3.8.0a4.rst M Misc/NEWS.d/3.8.0b1.rst M Modules/_ctypes/callproc.c M Modules/_ctypes/stgdict.c M Modules/_io/bytesio.c M Modules/_io/stringio.c M Modules/_testcapimodule.c M Modules/expat/loadlibrary.c M Modules/expat/xmlparse.c M Modules/termios.c M Objects/listsort.txt M Objects/typeobject.c M Python/ast.c M Python/pystate.c diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 72bd8c37b435..c198df3fb1d0 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -876,7 +876,7 @@ Path Configuration If at least one "output field" is not set, Python computes the path configuration to fill unset fields. If :c:member:`~PyConfig.module_search_paths_set` is equal to 0, -:c:member:`~PyConfig.module_search_paths` is overriden and +:c:member:`~PyConfig.module_search_paths` is overridden and :c:member:`~PyConfig.module_search_paths_set` is set to 1. It is possible to completely ignore the function computing the default diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 65a685022e92..cb8360caca5e 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -1379,8 +1379,8 @@ an :term:`importer`. bytecode file. An empty string represents no optimization, so ``/foo/bar/baz.py`` with an *optimization* of ``''`` will result in a bytecode path of ``/foo/bar/__pycache__/baz.cpython-32.pyc``. ``None`` causes - the interpter's optimization level to be used. Any other value's string - representation being used, so ``/foo/bar/baz.py`` with an *optimization* of + the interpreter's optimization level to be used. Any other value's string + representation is used, so ``/foo/bar/baz.py`` with an *optimization* of ``2`` will lead to the bytecode path of ``/foo/bar/__pycache__/baz.cpython-32.opt-2.pyc``. The string representation of *optimization* can only be alphanumeric, else :exc:`ValueError` is raised. diff --git a/Include/pyhash.h b/Include/pyhash.h index 9cfd071ea17b..dbcc9744be35 100644 --- a/Include/pyhash.h +++ b/Include/pyhash.h @@ -119,7 +119,7 @@ PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); * configure script. * * - FNV is available on all platforms and architectures. - * - SIPHASH24 only works on plaforms that don't require aligned memory for integers. + * - SIPHASH24 only works on platforms that don't require aligned memory for integers. * - With EXTERNAL embedders can provide an alternative implementation with:: * * PyHash_FuncDef PyHash_Func = {...}; diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 204eaf7394c5..1d3e487b1d93 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -71,7 +71,7 @@ def connect(host=None, port=None, *, ssl_handshake_timeout=None, happy_eyeballs_delay=None, interleave=None): # Design note: - # Don't use decorator approach but exilicit non-async + # Don't use decorator approach but explicit non-async # function to fail fast and explicitly # if passed arguments don't match the function signature return _ContextManagerHelper(_connect(host, port, limit, @@ -442,7 +442,7 @@ def connect_unix(path=None, *, ssl_handshake_timeout=None): """Similar to `connect()` but works with UNIX Domain Sockets.""" # Design note: - # Don't use decorator approach but exilicit non-async + # Don't use decorator approach but explicit non-async # function to fail fast and explicitly # if passed arguments don't match the function signature return _ContextManagerHelper(_connect_unix(path, diff --git a/Lib/bdb.py b/Lib/bdb.py index 96e7d18d718d..50d9eece89ad 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -38,7 +38,7 @@ def canonic(self, filename): """Return canonical form of filename. For real filenames, the canonical form is a case-normalized (on - case insenstive filesystems) absolute path. 'Filenames' with + case insensitive filesystems) absolute path. 'Filenames' with angle brackets, such as "", generated in interactive mode, are returned unchanged. """ diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py index 19380917b6f5..32b51b04373f 100644 --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -238,7 +238,7 @@ def __repr__(self): if self._kwargs: x += ', kwargs=' + str(self._kwargs) if self._key[0] is not None: - x += ', exitprority=' + str(self._key[0]) + x += ', exitpriority=' + str(self._key[0]) return x + '>' diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py index 23a02e0b4eb2..7b1ad8eb6de8 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -467,7 +467,7 @@ def _check_notify(self, cond): # of the workers. # Secondly, this test assumes that condition variables are not subject # to spurious wakeups. The absence of spurious wakeups is an implementation - # detail of Condition Cariables in current CPython, but in general, not + # detail of Condition Variables in current CPython, but in general, not # a guaranteed property of condition variables as a programming # construct. In particular, it is possible that this can no longer # be conveniently guaranteed should their implementation ever change. diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index b74eeba81e04..f0bd013e5536 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -462,7 +462,7 @@ def test_dash_m_errors(self): ('os.path', br'loader.*cannot handle'), ('importlib', br'No module named.*' br'is a package and cannot be directly executed'), - ('importlib.nonexistant', br'No module named'), + ('importlib.nonexistent', br'No module named'), ('.unittest', br'Relative module names not supported'), ) for name, regex in tests: diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index e532be6eeaf0..58f65f3e266c 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1930,7 +1930,7 @@ def test_order_preservation(self): 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l']) # Math operations order first by the order encountered in the left - # operand and then by the order encounted in the right operand. + # operand and then by the order encountered in the right operand. ps = 'aaabbcdddeefggghhijjjkkl' qs = 'abbcccdeefffhkkllllmmnno' order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))} diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 0d0c1dd1acbe..741cb6dce285 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -3025,7 +3025,7 @@ def test_str_subclass_as_dict_key(self): # Testing a str subclass used as dict key .. class cistr(str): - """Sublcass of str that computes __eq__ case-insensitively. + """Subclass of str that computes __eq__ case-insensitively. Also computes a hash code of the string in canonical form. """ diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py index 83804cbb00ab..4559cd5623ef 100644 --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -48,7 +48,7 @@ def testformat(formatstr, args, output=None, limit=None, overflowok=False): def testcommon(formatstr, args, output=None, limit=None, overflowok=False): # if formatstr is a str, test str, bytes, and bytearray; - # otherwise, test bytes and bytearry + # otherwise, test bytes and bytearray if isinstance(formatstr, str): testformat(formatstr, args, output, limit, overflowok) b_format = formatstr.encode('ascii') diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index 2dab53004452..311143da91d0 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -912,7 +912,7 @@ def test_collect_generation(self): def test_collect_garbage(self): self.preclean() # Each of these cause four objects to be garbage: Two - # Uncolectables and their instance dicts. + # Uncollectables and their instance dicts. Uncollectable() Uncollectable() C1055820(666) diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index 896bbe9ab798..f2eb6d716d52 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -445,7 +445,7 @@ def test_compare_digest(self): a, b = bytearray(b"foobar"), bytearray(b"foobar") self.assertTrue(hmac.compare_digest(a, b)) - # Testing bytearrays of diffeent lengths + # Testing bytearrays of different lengths a, b = bytearray(b"foobar"), bytearray(b"foo") self.assertFalse(hmac.compare_digest(a, b)) @@ -458,7 +458,7 @@ def test_compare_digest(self): self.assertTrue(hmac.compare_digest(a, b)) self.assertTrue(hmac.compare_digest(b, a)) - # Testing byte bytearray of diffeent lengths + # Testing byte bytearray of different lengths a, b = bytearray(b"foobar"), b"foo" self.assertFalse(hmac.compare_digest(a, b)) self.assertFalse(hmac.compare_digest(b, a)) @@ -472,7 +472,7 @@ def test_compare_digest(self): a, b = "foobar", "foobar" self.assertTrue(hmac.compare_digest(a, b)) - # Testing str of diffeent lengths + # Testing str of different lengths a, b = "foo", "foobar" self.assertFalse(hmac.compare_digest(a, b)) diff --git a/Lib/test/test_importlib/source/test_file_loader.py b/Lib/test/test_importlib/source/test_file_loader.py index 3ffb2aa1e60a..ab44722146e3 100644 --- a/Lib/test/test_importlib/source/test_file_loader.py +++ b/Lib/test/test_importlib/source/test_file_loader.py @@ -325,7 +325,7 @@ def test_unchecked_hash_based_pyc(self): ) @util.writes_bytecode_files - def test_overiden_unchecked_hash_based_pyc(self): + def test_overridden_unchecked_hash_based_pyc(self): with util.create_modules('_temp') as mapping, \ unittest.mock.patch('_imp.check_hash_based_pycs', 'always'): source = mapping['_temp'] diff --git a/Lib/test/test_importlib/test_main.py b/Lib/test/test_importlib/test_main.py index bc42b83ee291..3d7da819b343 100644 --- a/Lib/test/test_importlib/test_main.py +++ b/Lib/test/test_importlib/test_main.py @@ -32,7 +32,7 @@ def test_new_style_classes(self): class ImportTests(fixtures.DistInfoPkg, unittest.TestCase): def test_import_nonexistent_module(self): # Ensure that the MetadataPathFinder does not crash an import of a - # non-existant module. + # non-existent module. with self.assertRaises(ImportError): importlib.import_module('does_not_exist') diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index 196ea1c9d4dd..e016ea49119a 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -443,7 +443,7 @@ def contents(self): yield entry name = 'testingpackage' - # Unforunately importlib.util.module_from_spec() was not introduced until + # Unfortunately importlib.util.module_from_spec() was not introduced until # Python 3.5. module = types.ModuleType(name) loader = Reader() diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 23dd96e365a8..01b317c3281e 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -1810,13 +1810,13 @@ def test_bimodal_data(self): # Test mode with bimodal data. data = [1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 6, 6, 6, 7, 8, 9, 9] assert data.count(2) == data.count(6) == 4 - # mode() should return 2, the first encounted mode + # mode() should return 2, the first encountered mode self.assertEqual(self.func(data), 2) def test_unique_data(self): # Test mode when data points are all unique. data = list(range(10)) - # mode() should return 0, the first encounted mode + # mode() should return 0, the first encountered mode self.assertEqual(self.func(data), 0) def test_none_data(self): diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py index c3866483b8aa..4b9bf4ed5da1 100644 --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -885,7 +885,7 @@ def check_env_var_invalid(self, nframe): return if b'PYTHONTRACEMALLOC: invalid number of frames' in stderr: return - self.fail(f"unexpeced output: {stderr!a}") + self.fail(f"unexpected output: {stderr!a}") def test_env_var_invalid(self): @@ -914,7 +914,7 @@ def check_sys_xoptions_invalid(self, nframe): return if b'-X tracemalloc=NFRAME: invalid number of frames' in stderr: return - self.fail(f"unexpeced output: {stderr!a}") + self.fail(f"unexpected output: {stderr!a}") def test_sys_xoptions_invalid(self): for nframe in INVALID_NFRAME: diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 86c2f226ebcf..fc3f8f6fe7f0 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -714,7 +714,7 @@ def test_showwarning_not_callable(self): self.assertRaises(TypeError, self.module.warn, "Warning!") def test_show_warning_output(self): - # With showarning() missing, make sure that output is okay. + # With showwarning() missing, make sure that output is okay. text = 'test show_warning' with original_warnings.catch_warnings(module=self.module): self.module.filterwarnings("always", category=UserWarning) diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index dc2b46e42521..91a2bbc066b1 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -229,7 +229,7 @@ def test_connect_registry_to_local_machine_works(self): h.Close() self.assertEqual(h.handle, 0) - def test_inexistant_remote_registry(self): + def test_nonexistent_remote_registry(self): connect = lambda: ConnectRegistry("abcdefghijkl", HKEY_CURRENT_USER) self.assertRaises(OSError, connect) diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py index bce33291c566..6af45145a792 100644 --- a/Lib/test/test_wsgiref.py +++ b/Lib/test/test_wsgiref.py @@ -586,10 +586,10 @@ def testEnviron(self): expected.update({ # X doesn't exist in os_environ "X": "Y", - # HOME is overriden by TestHandler + # HOME is overridden by TestHandler 'HOME': "/override/home", - # overriden by setup_testing_defaults() + # overridden by setup_testing_defaults() "SCRIPT_NAME": "", "SERVER_NAME": "127.0.0.1", diff --git a/Lib/tkinter/filedialog.py b/Lib/tkinter/filedialog.py index d9d3436145c9..88d23476fde2 100644 --- a/Lib/tkinter/filedialog.py +++ b/Lib/tkinter/filedialog.py @@ -463,7 +463,7 @@ def test(): except (ImportError, AttributeError): pass - # dialog for openening files + # dialog for opening files openfilename=askopenfilename(filetypes=[("all files", "*")]) try: diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index 27914a9d7178..0632d95e58fe 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -1651,7 +1651,7 @@ def test_patch_imports_lazily(self): p1.stop() self.assertEqual(squizz.squozz, 3) - def test_patch_propogrates_exc_on_exit(self): + def test_patch_propagates_exc_on_exit(self): class holder: exc_info = None, None, None @@ -1680,9 +1680,9 @@ def test(mock): self.assertIs(holder.exc_info[0], RuntimeError) self.assertIsNotNone(holder.exc_info[1], - 'exception value not propgated') + 'exception value not propagated') self.assertIsNotNone(holder.exc_info[2], - 'exception traceback not propgated') + 'exception traceback not propagated') def test_create_and_specs(self): diff --git a/Lib/uuid.py b/Lib/uuid.py index 7aa01bb5c355..188e16ba14e3 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -680,7 +680,7 @@ def _random_getnode(): return random.getrandbits(48) | (1 << 40) -# _OS_GETTERS, when known, are targetted for a specific OS or platform. +# _OS_GETTERS, when known, are targeted for a specific OS or platform. # The order is by 'common practice' on the specified platform. # Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method # which, when successful, means none of these "external" methods are called. diff --git a/Misc/HISTORY b/Misc/HISTORY index f4b756cf0a46..fa5a05fd40fd 100644 --- a/Misc/HISTORY +++ b/Misc/HISTORY @@ -1231,7 +1231,7 @@ Library - Issue #22448: Improve canceled timer handles cleanup to prevent unbound memory usage. Patch by Joshua Moore-Oliva. -- Issue #23009: Make sure selectors.EpollSelecrtor.select() works when no +- Issue #23009: Make sure selectors.EpollSelector.select() works when no FD is registered. IDLE @@ -16660,7 +16660,7 @@ Core and Builtins Exception (KeyboardInterrupt, and SystemExit) propagate instead of ignoring them. -- #3021 Exception reraising sematics have been significantly improved. However, +- #3021 Exception reraising semantics have been significantly improved. However, f_exc_type, f_exc_value, and f_exc_traceback cannot be accessed from Python code anymore. diff --git a/Misc/NEWS.d/3.5.0a1.rst b/Misc/NEWS.d/3.5.0a1.rst index 62406e1aa008..376cb02ed4ba 100644 --- a/Misc/NEWS.d/3.5.0a1.rst +++ b/Misc/NEWS.d/3.5.0a1.rst @@ -1255,7 +1255,7 @@ Support wrapped callables in doctest. Patch by Claudiu Popa. .. nonce: -sW7gk .. section: Library -Make sure selectors.EpollSelecrtor.select() works when no FD is registered. +Make sure selectors.EpollSelector.select() works when no FD is registered. .. diff --git a/Misc/NEWS.d/3.5.4rc1.rst b/Misc/NEWS.d/3.5.4rc1.rst index f261ddb3a2d3..04a035a41e74 100644 --- a/Misc/NEWS.d/3.5.4rc1.rst +++ b/Misc/NEWS.d/3.5.4rc1.rst @@ -913,7 +913,7 @@ Fixed infinite recursion in the repr of uninitialized ctypes.CDLL instances. Fixed race condition in C implementation of functools.lru_cache. KeyError could be raised when cached function with full cache was simultaneously -called from differen threads with the same uncached arguments. +called from different threads with the same uncached arguments. .. diff --git a/Misc/NEWS.d/3.6.0b1.rst b/Misc/NEWS.d/3.6.0b1.rst index bd0e0a7c58d1..3fbae5c6a4b3 100644 --- a/Misc/NEWS.d/3.6.0b1.rst +++ b/Misc/NEWS.d/3.6.0b1.rst @@ -1148,7 +1148,7 @@ dict constraint in ForwardRef._eval_type (upstream #252) .. nonce: hxh6_h .. section: Library -Make ``_normalize`` parameter to ``Fraction`` constuctor keyword-only, so +Make ``_normalize`` parameter to ``Fraction`` constructor keyword-only, so that ``Fraction(2, 3, 4)`` now raises ``TypeError``. .. diff --git a/Misc/NEWS.d/3.6.0rc1.rst b/Misc/NEWS.d/3.6.0rc1.rst index c44dec324d2f..15769f950db2 100644 --- a/Misc/NEWS.d/3.6.0rc1.rst +++ b/Misc/NEWS.d/3.6.0rc1.rst @@ -48,7 +48,7 @@ they still are deprecated and will be disabled in 3.7. .. section: Library Fix a regression introduced in warnings.catch_warnings(): call -warnings.showwarning() if it was overriden inside the context manager. +warnings.showwarning() if it was overridden inside the context manager. .. diff --git a/Misc/NEWS.d/3.6.1rc1.rst b/Misc/NEWS.d/3.6.1rc1.rst index 1f9fb13f6970..58fd1b0624b2 100644 --- a/Misc/NEWS.d/3.6.1rc1.rst +++ b/Misc/NEWS.d/3.6.1rc1.rst @@ -435,7 +435,7 @@ Fix an important omission by adding Deque to the typing module. Fixed race condition in C implementation of functools.lru_cache. KeyError could be raised when cached function with full cache was simultaneously -called from differen threads with the same uncached arguments. +called from different threads with the same uncached arguments. .. diff --git a/Misc/NEWS.d/3.7.0a1.rst b/Misc/NEWS.d/3.7.0a1.rst index f9cd59c8d4bd..8a304e8755e6 100644 --- a/Misc/NEWS.d/3.7.0a1.rst +++ b/Misc/NEWS.d/3.7.0a1.rst @@ -3651,7 +3651,7 @@ regular expression objects. Fixed race condition in C implementation of functools.lru_cache. KeyError could be raised when cached function with full cache was simultaneously -called from differen threads with the same uncached arguments. +called from different threads with the same uncached arguments. .. diff --git a/Misc/NEWS.d/3.8.0a1.rst b/Misc/NEWS.d/3.8.0a1.rst index 3d376693d380..96208c88d32b 100644 --- a/Misc/NEWS.d/3.8.0a1.rst +++ b/Misc/NEWS.d/3.8.0a1.rst @@ -2418,7 +2418,7 @@ over browsers in the ``BROWSER`` environment variable. .. nonce: eSLKBE .. section: Library -Avoid stripping trailing whitespace in doctest fancy diff. Orignial patch by +Avoid stripping trailing whitespace in doctest fancy diff. Original patch by R. David Murray & Jairo Trad. Enhanced by Sanyam Khurana. .. diff --git a/Misc/NEWS.d/3.8.0a4.rst b/Misc/NEWS.d/3.8.0a4.rst index 80e01d97a043..995aa94a7405 100644 --- a/Misc/NEWS.d/3.8.0a4.rst +++ b/Misc/NEWS.d/3.8.0a4.rst @@ -1110,7 +1110,7 @@ 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 +alignment 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/3.8.0b1.rst b/Misc/NEWS.d/3.8.0b1.rst index 609aa338e844..84b0350134fb 100644 --- a/Misc/NEWS.d/3.8.0b1.rst +++ b/Misc/NEWS.d/3.8.0b1.rst @@ -1262,7 +1262,7 @@ 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 +that depend upon one another as the lock acquisition order cannot be guaranteed. .. diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 67665246414e..1de86e48d719 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -110,7 +110,7 @@ static void pymem_destructor(PyObject *ptr) WinDLL(..., use_last_error=True) swap the system LastError value with the ctypes private copy. - The values are also swapped immeditately before and after ctypes callback + The values are also swapped immediately before and after ctypes callback functions are called, if the callbacks are constructed using the new optional use_errno parameter set to True: CFUNCTYPE(..., use_errno=TRUE) or WINFUNCTYPE(..., use_errno=True). diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 235a4d79ad2c..8709cc5404a2 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -352,7 +352,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct int big_endian; /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to - be a way to use the old, broken sematics: _fields_ are not extended + be a way to use the old, broken semantics: _fields_ are not extended but replaced in subclasses. XXX Remove this in ctypes 1.0! diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 19e1ed8441e3..3cf6402e75f7 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -818,7 +818,7 @@ bytesio_setstate(bytesio *self, PyObject *state) /* Set carefully the position value. Alternatively, we could use the seek method instead of modifying self->pos directly to better protect the - object internal state against errneous (or malicious) inputs. */ + object internal state against erroneous (or malicious) inputs. */ position_obj = PyTuple_GET_ITEM(state, 1); if (!PyLong_Check(position_obj)) { PyErr_Format(PyExc_TypeError, diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 9e9724db2d33..8b5fa7a369f3 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -899,7 +899,7 @@ stringio_setstate(stringio *self, PyObject *state) /* Set carefully the position value. Alternatively, we could use the seek method instead of modifying self->pos directly to better protect the - object internal state against errneous (or malicious) inputs. */ + object internal state against erroneous (or malicious) inputs. */ position_obj = PyTuple_GET_ITEM(state, 2); if (!PyLong_Check(position_obj)) { PyErr_Format(PyExc_TypeError, diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 1042ea701923..15bfe26a044f 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4523,7 +4523,7 @@ check_pyobject_forbidden_bytes_is_freed(PyObject *self, PyObject *Py_UNUSED(args /* Initialize reference count to avoid early crash in ceval or GC */ Py_REFCNT(op) = 1; /* ob_type field is after the memory block: part of "forbidden bytes" - when using debug hooks on memory allocatrs! */ + when using debug hooks on memory allocators! */ return test_pyobject_is_freed("check_pyobject_forbidden_bytes_is_freed", op); } diff --git a/Modules/expat/loadlibrary.c b/Modules/expat/loadlibrary.c index 35fdf98bce6c..2f80b3a379fd 100644 --- a/Modules/expat/loadlibrary.c +++ b/Modules/expat/loadlibrary.c @@ -53,12 +53,12 @@ typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); /* See function definitions in winbase.h */ #ifdef UNICODE # ifdef _WIN32_WCE -# define LOADLIBARYEX L"LoadLibraryExW" +# define LOADLIBRARYEX L"LoadLibraryExW" # else -# define LOADLIBARYEX "LoadLibraryExW" +# define LOADLIBRARYEX "LoadLibraryExW" # endif #else -# define LOADLIBARYEX "LoadLibraryExA" +# define LOADLIBRARYEX "LoadLibraryExA" #endif @@ -88,7 +88,7 @@ HMODULE _Expat_LoadLibrary(LPCTSTR filename) /* Attempt to find LoadLibraryEx() which is only available on Windows 2000 and above */ - pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBARYEX); + pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBRARYEX); /* Detect if there's already a path in the filename and load the library if there is. Note: Both back slashes and forward slashes have been supported diff --git a/Modules/expat/xmlparse.c b/Modules/expat/xmlparse.c index 9c0987f4f6d8..311dbc4dfb9c 100644 --- a/Modules/expat/xmlparse.c +++ b/Modules/expat/xmlparse.c @@ -3399,7 +3399,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, * has to have passed through the hash table lookup once * already. That implies that an entry for it already * exists, so the lookup above will return a pointer to - * already allocated memory. There is no opportunaity for + * already allocated memory. There is no opportunity for * the allocator to fail, so the condition above cannot be * fulfilled. * diff --git a/Modules/termios.c b/Modules/termios.c index 7601b68afda3..aee7f12c57ca 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -18,7 +18,7 @@ #include /* HP-UX requires that this be included to pick up MDCD, MCTS, MDSR, - * MDTR, MRI, and MRTS (appearantly used internally by some things + * MDTR, MRI, and MRTS (apparently used internally by some things * defined as macros; these are not used here directly). */ #ifdef HAVE_SYS_MODEM_H diff --git a/Objects/listsort.txt b/Objects/listsort.txt index 8c877515c72e..43fe1574c323 100644 --- a/Objects/listsort.txt +++ b/Objects/listsort.txt @@ -328,7 +328,7 @@ found is still high in the memory hierarchy. We also can't delay merging unmerged, and the stack has a fixed size. What turned out to be a good compromise maintains two invariants on the -stack entries, where A, B and C are the lengths of the three righmost not-yet +stack entries, where A, B and C are the lengths of the three rightmost not-yet merged slices: 1. A > B+C diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 6d94bc998981..bf0c3e072919 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -117,7 +117,7 @@ find_signature(const char *name, const char *doc) #define SIGNATURE_END_MARKER ")\n--\n\n" #define SIGNATURE_END_MARKER_LENGTH 6 /* - * skips past the end of the docstring's instrospection signature. + * skips past the end of the docstring's introspection signature. * (assumes doc starts with a valid signature prefix.) */ static const char * diff --git a/Python/ast.c b/Python/ast.c index 9947824de744..79a29a6628ad 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -5359,7 +5359,7 @@ typedef struct { doubling the number allocated each time. Note that the f-string f'{0}a{1}' contains 3 expr_ty's: 2 FormattedValue's, and one Constant for the literal 'a'. So you add expr_ty's about twice as - fast as you add exressions in an f-string. */ + fast as you add expressions in an f-string. */ Py_ssize_t allocated; /* Number we've allocated. */ Py_ssize_t size; /* Number we've used. */ diff --git a/Python/pystate.c b/Python/pystate.c index 833e0fb30dcb..8f30c94096b0 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -730,7 +730,7 @@ PyState_RemoveModule(struct PyModuleDef* def) return -1; } if (state->modules_by_index == NULL) { - Py_FatalError("PyState_RemoveModule: Interpreters module-list not acessible."); + Py_FatalError("PyState_RemoveModule: Interpreters module-list not accessible."); return -1; } if (index > PyList_GET_SIZE(state->modules_by_index)) { @@ -885,7 +885,7 @@ PyThreadState_DeleteCurrent() * Note that, if there is a current thread state, it *must* be the one * passed as argument. Also, this won't touch any other interpreters * than the current one, since we don't know which thread state should - * be kept in those other interpreteres. + * be kept in those other interpreters. */ void _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate) From webhook-mailer at python.org Fri Aug 30 18:25:45 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Fri, 30 Aug 2019 22:25:45 -0000 Subject: [Python-checkins] [3.8] bpo-29553: Fix ArgumentParser.format_usage() for mutually exclusive groups (GH-14976) (GH-15494) (GH-15624) Message-ID: https://github.com/python/cpython/commit/bd8ca9aaccef0569c4b5c2e6dad0feb869ffd6c5 commit: bd8ca9aaccef0569c4b5c2e6dad0feb869ffd6c5 branch: 3.8 author: Raymond Hettinger committer: GitHub date: 2019-08-30T15:25:38-07:00 summary: [3.8] bpo-29553: Fix ArgumentParser.format_usage() for mutually exclusive groups (GH-14976) (GH-15494) (GH-15624) files: M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index a6ab3b3b898d..456ec8bb7fc8 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -405,13 +405,19 @@ def _format_actions_usage(self, actions, groups): inserts[start] += ' [' else: inserts[start] = '[' - inserts[end] = ']' + if end in inserts: + inserts[end] += ']' + else: + inserts[end] = ']' else: if start in inserts: inserts[start] += ' (' else: inserts[start] = '(' - inserts[end] = ')' + if end in inserts: + inserts[end] += ')' + else: + inserts[end] = ')' for i in range(start + 1, end): inserts[i] = '|' diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index d6d16090eb02..86ec6cca51ac 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2813,6 +2813,46 @@ def get_parser(self, required): -c c help ''' +class TestMutuallyExclusiveNested(MEMixin, TestCase): + + def get_parser(self, required): + parser = ErrorRaisingArgumentParser(prog='PROG') + group = parser.add_mutually_exclusive_group(required=required) + group.add_argument('-a') + group.add_argument('-b') + group2 = group.add_mutually_exclusive_group(required=required) + group2.add_argument('-c') + group2.add_argument('-d') + group3 = group2.add_mutually_exclusive_group(required=required) + group3.add_argument('-e') + group3.add_argument('-f') + return parser + + usage_when_not_required = '''\ + usage: PROG [-h] [-a A | -b B | [-c C | -d D | [-e E | -f F]]] + ''' + usage_when_required = '''\ + usage: PROG [-h] (-a A | -b B | (-c C | -d D | (-e E | -f F))) + ''' + + help = '''\ + + optional arguments: + -h, --help show this help message and exit + -a A + -b B + -c C + -d D + -e E + -f F + ''' + + # We are only interested in testing the behavior of format_usage(). + test_failures_when_not_required = None + test_failures_when_required = None + test_successes_when_not_required = None + test_successes_when_required = None + # ================================================= # Mutually exclusive group in parent parser tests # ================================================= From webhook-mailer at python.org Fri Aug 30 19:48:17 2019 From: webhook-mailer at python.org (Inada Naoki) Date: Fri, 30 Aug 2019 23:48:17 -0000 Subject: [Python-checkins] bpo-37781: use "z" for PY_FORMAT_SIZE_T (GH-15156) Message-ID: https://github.com/python/cpython/commit/d765d81b8fb5ab707bfe8b079348e5038c298aa3 commit: d765d81b8fb5ab707bfe8b079348e5038c298aa3 branch: master author: Inada Naoki committer: GitHub date: 2019-08-31T08:48:12+09:00 summary: bpo-37781: use "z" for PY_FORMAT_SIZE_T (GH-15156) MSVC 2015 supports %zd / %zu. "z" is portable enough nowadays. files: M Include/pyport.h diff --git a/Include/pyport.h b/Include/pyport.h index 32d98c59a7c1..19415001c5b0 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -133,8 +133,9 @@ typedef int Py_ssize_clean_t; /* PY_FORMAT_SIZE_T is a platform-specific modifier for use in a printf * format to convert an argument with the width of a size_t or Py_ssize_t. - * C99 introduced "z" for this purpose, but not all platforms support that; - * e.g., MS compilers use "I" instead. + * C99 introduced "z" for this purpose, but old MSVCs had not supported it. + * Since MSVC supports "z" since (at least) 2015, we can just use "z" + * for new code. * * These "high level" Python format functions interpret "z" correctly on * all platforms (Python interprets the format string itself, and does whatever @@ -152,19 +153,11 @@ typedef int Py_ssize_clean_t; * Py_ssize_t index; * fprintf(stderr, "index %" PY_FORMAT_SIZE_T "d sucks\n", index); * - * That will expand to %ld, or %Id, or to something else correct for a - * Py_ssize_t on the platform. + * That will expand to %zd or to something else correct for a Py_ssize_t on + * the platform. */ #ifndef PY_FORMAT_SIZE_T -# if SIZEOF_SIZE_T == SIZEOF_INT && !defined(__APPLE__) -# define PY_FORMAT_SIZE_T "" -# elif SIZEOF_SIZE_T == SIZEOF_LONG -# define PY_FORMAT_SIZE_T "l" -# elif defined(MS_WINDOWS) -# define PY_FORMAT_SIZE_T "I" -# else -# error "This platform's pyconfig.h needs to define PY_FORMAT_SIZE_T" -# endif +# define PY_FORMAT_SIZE_T "z" #endif /* Py_LOCAL can be used instead of static to get the fastest possible calling From webhook-mailer at python.org Fri Aug 30 20:13:46 2019 From: webhook-mailer at python.org (Inada Naoki) Date: Sat, 31 Aug 2019 00:13:46 -0000 Subject: [Python-checkins] bpo-37990: fix gc stats (GH-15626) Message-ID: https://github.com/python/cpython/commit/013e52fd340d9ef558013b546f25456f94ee1804 commit: 013e52fd340d9ef558013b546f25456f94ee1804 branch: master author: Inada Naoki committer: GitHub date: 2019-08-31T09:13:42+09:00 summary: bpo-37990: fix gc stats (GH-15626) files: M Modules/gcmodule.c diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 7586cd3e0515..134f6d168c96 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1115,8 +1115,9 @@ collect(struct _gc_runtime_state *state, int generation, } if (state->debug & DEBUG_STATS) { double d = _PyTime_AsSecondsDouble(_PyTime_GetMonotonicClock() - t1); - PySys_FormatStderr( - "gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n", + PySys_WriteStderr( + "gc: done, %" PY_FORMAT_SIZE_T "d unreachable, " + "%" PY_FORMAT_SIZE_T "d uncollectable, %.4fs elapsed\n", n+m, n, d); } From webhook-mailer at python.org Fri Aug 30 21:50:33 2019 From: webhook-mailer at python.org (Inada Naoki) Date: Sat, 31 Aug 2019 01:50:33 -0000 Subject: [Python-checkins] [3.8] bpo-37990: fix gc stats (GH-15626) Message-ID: https://github.com/python/cpython/commit/97a31c7b486c45ba9c21cab5fb96337859a60275 commit: 97a31c7b486c45ba9c21cab5fb96337859a60275 branch: 3.8 author: Inada Naoki committer: GitHub date: 2019-08-31T10:50:27+09:00 summary: [3.8] bpo-37990: fix gc stats (GH-15626) (cherry picked from commit 013e52f) files: A Misc/NEWS.d/next/Core and Builtins/2019-08-31-09-22-33.bpo-37990.WDY2f-.rst M Modules/gcmodule.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-31-09-22-33.bpo-37990.WDY2f-.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-31-09-22-33.bpo-37990.WDY2f-.rst new file mode 100644 index 000000000000..39edc595418e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-31-09-22-33.bpo-37990.WDY2f-.rst @@ -0,0 +1,2 @@ +Fix elapsed time in gc stats was not printed correctly. This bug was +a regression in 3.8b4. diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 21839d95bd8c..2741edc0a021 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1115,8 +1115,9 @@ collect(struct _gc_runtime_state *state, int generation, } if (state->debug & DEBUG_STATS) { double d = _PyTime_AsSecondsDouble(_PyTime_GetMonotonicClock() - t1); - PySys_FormatStderr( - "gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n", + PySys_WriteStderr( + "gc: done, %" PY_FORMAT_SIZE_T "d unreachable, " + "%" PY_FORMAT_SIZE_T "d uncollectable, %.4fs elapsed\n", n+m, n, d); } From webhook-mailer at python.org Sat Aug 31 01:51:37 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 31 Aug 2019 05:51:37 -0000 Subject: [Python-checkins] bpo-37977: Warn more strongly and clearly about pickle security (GH-15595) Message-ID: https://github.com/python/cpython/commit/daa82d019c52e95c3c57275307918078c1c0ac81 commit: daa82d019c52e95c3c57275307918078c1c0ac81 branch: master author: Daniel Pope committer: Raymond Hettinger date: 2019-08-30T22:51:33-07:00 summary: bpo-37977: Warn more strongly and clearly about pickle security (GH-15595) files: A Misc/NEWS.d/next/Documentation/2019-08-29-14-38-01.bpo-37977.pML-UI.rst M Doc/library/pickle.rst diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst index 09c9c86abbba..eb58178e0e92 100644 --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -30,9 +30,17 @@ avoid confusion, the terms used here are "pickling" and "unpickling". .. warning:: - The :mod:`pickle` module is not secure against erroneous or maliciously - constructed data. Never unpickle data received from an untrusted or - unauthenticated source. + The ``pickle`` module **is not secure**. Only unpickle data you trust. + + It is possible to construct malicious pickle data which will **execute + arbitrary code during unpickling**. Never unpickle data that could have come + from an untrusted source, or that could have been tampered with. + + Consider signing data with :mod:`hmac` if you need to ensure that it has not + been tampered with. + + Safer serialization formats such as :mod:`json` may be more appropriate if + you are processing untrusted data. See :ref:`comparison-with-json`. Relationship to other Python modules @@ -75,6 +83,9 @@ The :mod:`pickle` module differs from :mod:`marshal` in several significant ways pickling and unpickling code deals with Python 2 to Python 3 type differences if your data is crossing that unique breaking change language boundary. + +.. _comparison-with-json: + Comparison with ``json`` ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -94,7 +105,10 @@ There are fundamental differences between the pickle protocols and types, and no custom classes; pickle can represent an extremely large number of Python types (many of them automatically, by clever usage of Python's introspection facilities; complex cases can be tackled by - implementing :ref:`specific object APIs `). + implementing :ref:`specific object APIs `); + +* Unlike pickle, deserializing untrusted JSON does not in itself create an + arbitrary code execution vulnerability. .. seealso:: The :mod:`json` module: a standard library module allowing JSON diff --git a/Misc/NEWS.d/next/Documentation/2019-08-29-14-38-01.bpo-37977.pML-UI.rst b/Misc/NEWS.d/next/Documentation/2019-08-29-14-38-01.bpo-37977.pML-UI.rst new file mode 100644 index 000000000000..cd0fa3c0584a --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-08-29-14-38-01.bpo-37977.pML-UI.rst @@ -0,0 +1 @@ +Warn more strongly and clearly about pickle insecurity From webhook-mailer at python.org Sat Aug 31 02:02:19 2019 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 31 Aug 2019 06:02:19 -0000 Subject: [Python-checkins] bpo-37977: Warn more strongly and clearly about pickle security (GH-15595) (GH-15629) Message-ID: https://github.com/python/cpython/commit/6922b9e4fce635339cb94c2fdef6bba4e2a99621 commit: 6922b9e4fce635339cb94c2fdef6bba4e2a99621 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2019-08-30T23:02:15-07:00 summary: bpo-37977: Warn more strongly and clearly about pickle security (GH-15595) (GH-15629) (cherry picked from commit daa82d019c52e95c3c57275307918078c1c0ac81) Co-authored-by: Daniel Pope files: A Misc/NEWS.d/next/Documentation/2019-08-29-14-38-01.bpo-37977.pML-UI.rst M Doc/library/pickle.rst diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst index e6025aeaf476..9442efa2b667 100644 --- a/Doc/library/pickle.rst +++ b/Doc/library/pickle.rst @@ -30,9 +30,17 @@ avoid confusion, the terms used here are "pickling" and "unpickling". .. warning:: - The :mod:`pickle` module is not secure against erroneous or maliciously - constructed data. Never unpickle data received from an untrusted or - unauthenticated source. + The ``pickle`` module **is not secure**. Only unpickle data you trust. + + It is possible to construct malicious pickle data which will **execute + arbitrary code during unpickling**. Never unpickle data that could have come + from an untrusted source, or that could have been tampered with. + + Consider signing data with :mod:`hmac` if you need to ensure that it has not + been tampered with. + + Safer serialization formats such as :mod:`json` may be more appropriate if + you are processing untrusted data. See :ref:`comparison-with-json`. Relationship to other Python modules @@ -75,6 +83,9 @@ The :mod:`pickle` module differs from :mod:`marshal` in several significant ways pickling and unpickling code deals with Python 2 to Python 3 type differences if your data is crossing that unique breaking change language boundary. + +.. _comparison-with-json: + Comparison with ``json`` ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -94,7 +105,10 @@ There are fundamental differences between the pickle protocols and types, and no custom classes; pickle can represent an extremely large number of Python types (many of them automatically, by clever usage of Python's introspection facilities; complex cases can be tackled by - implementing :ref:`specific object APIs `). + implementing :ref:`specific object APIs `); + +* Unlike pickle, deserializing untrusted JSON does not in itself create an + arbitrary code execution vulnerability. .. seealso:: The :mod:`json` module: a standard library module allowing JSON diff --git a/Misc/NEWS.d/next/Documentation/2019-08-29-14-38-01.bpo-37977.pML-UI.rst b/Misc/NEWS.d/next/Documentation/2019-08-29-14-38-01.bpo-37977.pML-UI.rst new file mode 100644 index 000000000000..cd0fa3c0584a --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2019-08-29-14-38-01.bpo-37977.pML-UI.rst @@ -0,0 +1 @@ +Warn more strongly and clearly about pickle insecurity From webhook-mailer at python.org Sat Aug 31 11:25:39 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 31 Aug 2019 15:25:39 -0000 Subject: [Python-checkins] bpo-37764: Fix infinite loop when parsing unstructured email headers. (GH-15239) Message-ID: https://github.com/python/cpython/commit/c5b242f87f31286ad38991bc3868cf4cfbf2b681 commit: c5b242f87f31286ad38991bc3868cf4cfbf2b681 branch: master author: Ashwin Ramaswami committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> date: 2019-08-31T08:25:35-07:00 summary: bpo-37764: Fix infinite loop when parsing unstructured email headers. (GH-15239) Fixes a case in which email._header_value_parser.get_unstructured hangs the system for some invalid headers. This covers the cases in which the header contains either: - a case without trailing whitespace - an invalid encoded word https://bugs.python.org/issue37764 This fix should also be backported to 3.7 and 3.8 https://bugs.python.org/issue37764 files: A Misc/NEWS.d/next/Security/2019-08-27-01-13-05.bpo-37764.qv67PQ.rst M Lib/email/_header_value_parser.py M Lib/test/test_email/test__header_value_parser.py M Lib/test/test_email/test_email.py M Misc/ACKS diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index b5003943ab0d..16c19907d68d 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -935,6 +935,10 @@ def __str__(self): return '' +class _InvalidEwError(errors.HeaderParseError): + """Invalid encoded word found while parsing headers.""" + + # XXX these need to become classes and used as instances so # that a program can't change them in a parse tree and screw # up other parse trees. Maybe should have tests for that, too. @@ -1039,7 +1043,10 @@ def get_encoded_word(value): raise errors.HeaderParseError( "expected encoded word but found {}".format(value)) remstr = ''.join(remainder) - if len(remstr) > 1 and remstr[0] in hexdigits and remstr[1] in hexdigits: + if (len(remstr) > 1 and + remstr[0] in hexdigits and + remstr[1] in hexdigits and + tok.count('?') < 2): # The ? after the CTE was followed by an encoded word escape (=XX). rest, *remainder = remstr.split('?=', 1) tok = tok + '?=' + rest @@ -1051,7 +1058,7 @@ def get_encoded_word(value): try: text, charset, lang, defects = _ew.decode('=?' + tok + '?=') except ValueError: - raise errors.HeaderParseError( + raise _InvalidEwError( "encoded word format invalid: '{}'".format(ew.cte)) ew.charset = charset ew.lang = lang @@ -1101,9 +1108,12 @@ def get_unstructured(value): token, value = get_fws(value) unstructured.append(token) continue + valid_ew = True if value.startswith('=?'): try: token, value = get_encoded_word(value) + except _InvalidEwError: + valid_ew = False except errors.HeaderParseError: # XXX: Need to figure out how to register defects when # appropriate here. @@ -1125,7 +1135,10 @@ def get_unstructured(value): # Split in the middle of an atom if there is a rfc2047 encoded word # which does not have WSP on both sides. The defect will be registered # the next time through the loop. - if rfc2047_matcher.search(tok): + # This needs to only be performed when the encoded word is valid; + # otherwise, performing it on an invalid encoded word can cause + # the parser to go in an infinite loop. + if valid_ew and rfc2047_matcher.search(tok): tok, *remainder = value.partition('=?') vtext = ValueTerminal(tok, 'vtext') _validate_xtext(vtext) diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index b3e6b2661524..058d902459b6 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -383,6 +383,22 @@ def test_get_unstructured_ew_without_trailing_whitespace(self): [errors.InvalidHeaderDefect], '') + def test_get_unstructured_without_trailing_whitespace_hang_case(self): + self._test_get_x(self._get_unst, + '=?utf-8?q?somevalue?=aa', + 'somevalueaa', + 'somevalueaa', + [errors.InvalidHeaderDefect], + '') + + def test_get_unstructured_invalid_ew(self): + self._test_get_x(self._get_unst, + '=?utf-8?q?=somevalue?=', + '=?utf-8?q?=somevalue?=', + '=?utf-8?q?=somevalue?=', + [], + '') + # get_qp_ctext def test_get_qp_ctext_only(self): diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index ae9625845646..8ec39190ea8d 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -5381,6 +5381,27 @@ def test_rfc2231_unencoded_then_encoded_segments(self): eq(language, 'en-us') eq(s, 'My Document For You') + def test_should_not_hang_on_invalid_ew_messages(self): + messages = ["""From: user at host.com +To: user at host.com +Bad-Header: + =?us-ascii?Q?LCSwrV11+IB0rSbSker+M9vWR7wEDSuGqmHD89Gt=ea0nJFSaiz4vX3XMJPT4vrE?= + =?us-ascii?Q?xGUZeOnp0o22pLBB7CYLH74Js=wOlK6Tfru2U47qR?= + =?us-ascii?Q?72OfyEY2p2=2FrA9xNFyvH+fBTCmazxwzF8nGkK6D?= + +Hello! +""", """From: ??????????????? ???????????????????????? +To: "xxx" +Subject: ????????? ?????????????????????????????? ??????????????? ??????????????? ??? ??????????????????????????? ?????? ???????????? +MIME-Version: 1.0 +Content-Type: text/plain; charset="windows-1251"; +Content-Transfer-Encoding: 8bit + +?????? ??????????????? ??? ???????????? ?????????????????? ????????? ???????????????????????? +"""] + for m in messages: + with self.subTest(m=m): + msg = email.message_from_string(m) # Tests to ensure that signed parts of an email are completely preserved, as diff --git a/Misc/ACKS b/Misc/ACKS index e9ae0ed56b0d..ce8b144900eb 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1336,6 +1336,7 @@ Burton Radons Abhilash Raj Shorya Raj Dhushyanth Ramasamy +Ashwin Ramaswami Jeff Ramnani Bayard Randel Varpu Rantala diff --git a/Misc/NEWS.d/next/Security/2019-08-27-01-13-05.bpo-37764.qv67PQ.rst b/Misc/NEWS.d/next/Security/2019-08-27-01-13-05.bpo-37764.qv67PQ.rst new file mode 100644 index 000000000000..27fa8e192f0c --- /dev/null +++ b/Misc/NEWS.d/next/Security/2019-08-27-01-13-05.bpo-37764.qv67PQ.rst @@ -0,0 +1 @@ +Fixes email._header_value_parser.get_unstructured going into an infinite loop for a specific case in which the email header does not have trailing whitespace, and the case in which it contains an invalid encoded word. Patch by Ashwin Ramaswami. \ No newline at end of file From webhook-mailer at python.org Thu Aug 29 17:20:10 2019 From: webhook-mailer at python.org (=?utf-8?q?=C5=81ukasz?= Langa) Date: Thu, 29 Aug 2019 21:20:10 -0000 Subject: [Python-checkins] (no subject) Message-ID: To: python-checkins at python.org Subject: bpo-37834: Prevent shutil.rmtree exception (GH-15602) Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 https://github.com/python/cpython/commit/7fcc2088a50a4ecb80e5644cd195bee209c9= f979 commit: 7fcc2088a50a4ecb80e5644cd195bee209c9f979 branch: master author: Ned Deily committer: =C5=81ukasz Langa date: 2019-08-29T23:20:03+02:00 summary: bpo-37834: Prevent shutil.rmtree exception (GH-15602) when built on non-Windows system without fd system call support, like older versions of macOS. files: A Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rst M Lib/shutil.py diff --git a/Lib/shutil.py b/Lib/shutil.py index 39f793b5f3bd..561ad71508cc 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -544,7 +544,7 @@ def copytree(src, dst, symlinks=3DFalse, ignore=3DNone, c= opy_function=3Dcopy2, ignore_dangling_symlinks=3Dignore_dangling_symlinks, dirs_exist_ok=3Ddirs_exist_ok) =20 -if hasattr(stat, 'FILE_ATTRIBUTE_REPARSE_POINT'): +if hasattr(os.stat_result, 'st_file_attributes'): # Special handling for directory junctions to make them behave like # symlinks for shutil.rmtree, since in general they do not appear as # regular links. diff --git a/Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rs= t b/Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rst new file mode 100644 index 000000000000..afbbb3313a5b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rst @@ -0,0 +1,2 @@ +Prevent shutil.rmtree exception when built on non-Windows system without fd +system call support, like older versions of macOS. From webhook-mailer at python.org Thu Aug 29 17:51:24 2019 From: webhook-mailer at python.org (=?utf-8?q?=C5=81ukasz?= Langa) Date: Thu, 29 Aug 2019 21:51:24 -0000 Subject: [Python-checkins] (no subject) Message-ID: To: python-checkins at python.org Subject: [3.8] bpo-37834: Prevent shutil.rmtree exception (GH-15602) (#15603) Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 https://github.com/python/cpython/commit/25a044ee6ce50a9172478cc61d9146447784= 55f6 commit: 25a044ee6ce50a9172478cc61d914644778455f6 branch: 3.8 author: =C5=81ukasz Langa committer: GitHub date: 2019-08-29T23:51:19+02:00 summary: [3.8] bpo-37834: Prevent shutil.rmtree exception (GH-15602) (#15603) when built on non-Windows system without fd system call support, like older versions of macOS. (cherry picked from commit 7fcc2088a50a4ecb80e5644cd195bee209c9f979) Co-authored-by: Ned Deily files: A Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rst M Lib/shutil.py diff --git a/Lib/shutil.py b/Lib/shutil.py index 39f793b5f3bd..561ad71508cc 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -544,7 +544,7 @@ def copytree(src, dst, symlinks=3DFalse, ignore=3DNone, c= opy_function=3Dcopy2, ignore_dangling_symlinks=3Dignore_dangling_symlinks, dirs_exist_ok=3Ddirs_exist_ok) =20 -if hasattr(stat, 'FILE_ATTRIBUTE_REPARSE_POINT'): +if hasattr(os.stat_result, 'st_file_attributes'): # Special handling for directory junctions to make them behave like # symlinks for shutil.rmtree, since in general they do not appear as # regular links. diff --git a/Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rs= t b/Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rst new file mode 100644 index 000000000000..afbbb3313a5b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rst @@ -0,0 +1,2 @@ +Prevent shutil.rmtree exception when built on non-Windows system without fd +system call support, like older versions of macOS. From webhook-mailer at python.org Fri Aug 30 05:02:32 2019 From: webhook-mailer at python.org (=?utf-8?q?=C5=81ukasz?= Langa) Date: Fri, 30 Aug 2019 09:02:32 -0000 Subject: [Python-checkins] (no subject) Message-ID: To: python-checkins at python.org Subject: Python 3.8.0b4 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 https://github.com/python/cpython/commit/d93605de7232da5e6a182fd1d5c220639e90= 0159 commit: d93605de7232da5e6a182fd1d5c220639e900159 branch: 3.8 author: =C5=81ukasz Langa committer: =C5=81ukasz Langa date: 2019-08-29T23:59:20+02:00 summary: Python 3.8.0b4 files: A Misc/NEWS.d/3.8.0b4.rst D Misc/NEWS.d/next/Build/2019-07-29-11-36-16.bpo-37707.Sm-dGk.rst D Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst D Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst D Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr.rst D Misc/NEWS.d/next/Core and Builtins/2019-06-27-15-01-14.bpo-37433.amNGqr.rst D Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-.rst D Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757.lRv5HX.rst D Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912.UDwSMJ.rst D Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830.fNfMbz.rst D Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947.mzAQtB.rst D Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst D Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst D Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst D Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst D Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i.rst D Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst D Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst D Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst D Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst D Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst D Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst D Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst D Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst D Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst D Misc/NEWS.d/next/Library/2019-06-18-16-29-31.bpo-37085.GeYaD6.rst D Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst D Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst D Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst D Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst D Misc/NEWS.d/next/Library/2019-07-13-16-02-48.bpo-37587.fd-1aF.rst D Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst D Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst D Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst D Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst D Misc/NEWS.d/next/Library/2019-07-27-20-21-03.bpo-37695.QANdvg.rst D Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst D Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst D Misc/NEWS.d/next/Library/2019-07-31-16-49-01.bpo-37723.zq6tw8.rst D Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst D Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst D Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst D Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst D Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst D Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst D Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst D Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst D Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst D Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst D Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst D Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst D Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst D Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst D Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst D Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst D Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst D Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst D Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst D Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst D Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rst D Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst D Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst D Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst D Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst D Misc/NEWS.d/next/Windows/2019-05-05-05-23-34.bpo-28269.-MOHI7.rst D Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst D Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst D Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst D Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst D Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst D Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst D Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst D Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst D Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst M Include/patchlevel.h M Lib/pydoc_data/topics.py M README.rst diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 82181c586147..12f84b840d9f 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_BETA -#define PY_RELEASE_SERIAL 3 +#define PY_RELEASE_SERIAL 4 =20 /* Version as a string */ -#define PY_VERSION "3.8.0b3+" +#define PY_VERSION "3.8.0b4" /*--end constants--*/ =20 /* Version as a single 4-byte hex number, e.g. 0x010502B2 =3D=3D 1.5.2b2. diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index c3049b95207c..8992ea9b4ea7 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 Jul 29 15:22:27 2019 +# Autogenerated by Sphinx on Thu Aug 29 23:57:58 2019 topics =3D {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -808,21 +808,34 @@ 'whose name is\n' 'the key of the property in the owner class=E2=80=99 "_= _dict__".\n' '\n' - 'object.__get__(self, instance, owner)\n' + 'object.__get__(self, instance, owner=3DNone)\n' '\n' ' Called to get the attribute of the owner class (cla= ss ' 'attribute\n' ' access) or of an instance of that class (instance ' 'attribute\n' - ' access). *owner* is always the owner class, while ' - '*instance* is the\n' - ' instance that the attribute was accessed through, o= r ' - '"None" when\n' - ' the attribute is accessed through the *owner*. Thi= s ' - 'method should\n' - ' return the (computed) attribute value or raise an ' - '"AttributeError"\n' - ' exception.\n' + ' access). The optional *owner* argument is the owner= ' + 'class, while\n' + ' *instance* is the instance that the attribute was ' + 'accessed through,\n' + ' or "None" when the attribute is accessed through th= e ' + '*owner*.\n' + '\n' + ' This method should return the computed attribute ' + 'value or raise an\n' + ' "AttributeError" exception.\n' + '\n' + ' **PEP 252** specifies that "__get__()" is callable ' + 'with one or two\n' + ' arguments. Python=E2=80=99s own built-in descripto= rs support ' + 'this\n' + ' specification; however, it is likely that some ' + 'third-party tools\n' + ' have descriptors that require both arguments. ' + 'Python=E2=80=99s own\n' + ' "__getattribute__()" implementation always passes i= n ' + 'both arguments\n' + ' whether they are required or not.\n' '\n' 'object.__set__(self, instance, value)\n' '\n' @@ -830,6 +843,12 @@ 'of the owner\n' ' class to a new value, *value*.\n' '\n' + ' Note, adding "__set__()" or "__delete__()" changes ' + 'the kind of\n' + ' descriptor to a =E2=80=9Cdata descriptor=E2=80=9D. = See Invoking ' + 'Descriptors for\n' + ' more details.\n' + '\n' 'object.__delete__(self, instance)\n' '\n' ' Called to delete the attribute on an instance ' @@ -1829,6 +1848,12 @@ 'all false.\n' ' This behavior is compliant with IEEE 754.\n' '\n' + '* "None" and "NotImplemented" are singletons. **PEP 8** ' + 'advises\n' + ' that comparisons for singletons should always be done wit= h ' + '"is" or\n' + ' "is not", never the equality operators.\n' + '\n' '* Binary sequences (instances of "bytes" or "bytearray") ca= n ' 'be\n' ' compared within and across their types. They compare\n' @@ -1854,38 +1879,13 @@ ' these types raises "TypeError".\n' '\n' ' Sequences compare lexicographically using comparison of\n' - ' corresponding elements, whereby reflexivity of the elemen= ts ' - 'is\n' - ' enforced.\n' - '\n' - ' In enforcing reflexivity of elements, the comparison of ' - 'collections\n' - ' assumes that for a collection element "x", "x =3D=3D x" i= s ' - 'always true.\n' - ' Based on that assumption, element identity is compared ' - 'first, and\n' - ' element comparison is performed only for distinct ' - 'elements. This\n' - ' approach yields the same result as a strict element ' - 'comparison\n' - ' would, if the compared elements are reflexive. For ' - 'non-reflexive\n' - ' elements, the result is different than for strict element= \n' - ' comparison, and may be surprising: The non-reflexive ' - 'not-a-number\n' - ' values for example result in the following comparison ' - 'behavior when\n' - ' used in a list:\n' - '\n' - " >>> nan =3D float('NaN')\n" - ' >>> nan is nan\n' - ' True\n' - ' >>> nan =3D=3D nan\n' - ' False <-- the defined non-reflexive ' - 'behavior of NaN\n' - ' >>> [nan] =3D=3D [nan]\n' - ' True <-- list enforces reflexivity an= d ' - 'tests identity first\n' + ' corresponding elements. The built-in containers typicall= y ' + 'assume\n' + ' identical objects are equal to themselves. That lets the= m ' + 'bypass\n' + ' equality tests for identical objects to improve performan= ce ' + 'and to\n' + ' maintain their internal invariants.\n' '\n' ' Lexicographical comparison between built-in collections ' 'works as\n' @@ -3126,13 +3126,15 @@ 'returning\n' ' it.\n' '\n' - ' If "__new__()" returns an instance of *cls*, then the ' - 'new\n' - ' instance=E2=80=99s "__init__()" method will be invoked= like\n' - ' "__init__(self[, ...])", where *self* is the new ' - 'instance and the\n' - ' remaining arguments are the same as were passed to ' - '"__new__()".\n' + ' If "__new__()" is invoked during object construction a= nd ' + 'it returns\n' + ' an instance or subclass of *cls*, then the new ' + 'instance=E2=80=99s\n' + ' "__init__()" method will be invoked like ' + '"__init__(self[, ...])",\n' + ' where *self* is the new instance and the remaining ' + 'arguments are\n' + ' the same as were passed to the object constructor.\n' '\n' ' If "__new__()" does not return an instance of *cls*, ' 'then the new\n' @@ -3500,10 +3502,10 @@ ' hashable by an "isinstance(obj, ' 'collections.abc.Hashable)" call.\n' '\n' - ' Note: By default, the "__hash__()" values of str, byte= s ' - 'and\n' - ' datetime objects are =E2=80=9Csalted=E2=80=9D with a= n unpredictable ' - 'random value.\n' + ' Note: By default, the "__hash__()" values of str and ' + 'bytes\n' + ' objects are =E2=80=9Csalted=E2=80=9D with an unpredi= ctable random ' + 'value.\n' ' Although they remain constant within an individual ' 'Python\n' ' process, they are not predictable between repeated ' @@ -7841,13 +7843,15 @@ 'returning\n' ' it.\n' '\n' - ' If "__new__()" returns an instance of *cls*, then the ' - 'new\n' - ' instance=E2=80=99s "__init__()" method will be invoked = like\n' - ' "__init__(self[, ...])", where *self* is the new instan= ce ' - 'and the\n' - ' remaining arguments are the same as were passed to ' - '"__new__()".\n' + ' If "__new__()" is invoked during object construction an= d ' + 'it returns\n' + ' an instance or subclass of *cls*, then the new ' + 'instance=E2=80=99s\n' + ' "__init__()" method will be invoked like "__init__(self= [, ' + '...])",\n' + ' where *self* is the new instance and the remaining ' + 'arguments are\n' + ' the same as were passed to the object constructor.\n' '\n' ' If "__new__()" does not return an instance of *cls*, th= en ' 'the new\n' @@ -8212,10 +8216,10 @@ ' hashable by an "isinstance(obj, ' 'collections.abc.Hashable)" call.\n' '\n' - ' Note: By default, the "__hash__()" values of str, bytes= ' - 'and\n' - ' datetime objects are =E2=80=9Csalted=E2=80=9D with an= unpredictable ' - 'random value.\n' + ' Note: By default, the "__hash__()" values of str and ' + 'bytes\n' + ' objects are =E2=80=9Csalted=E2=80=9D with an unpredic= table random ' + 'value.\n' ' Although they remain constant within an individual ' 'Python\n' ' process, they are not predictable between repeated ' @@ -8440,21 +8444,34 @@ 'whose name is\n' 'the key of the property in the owner class=E2=80=99 "__dic= t__".\n' '\n' - 'object.__get__(self, instance, owner)\n' + 'object.__get__(self, instance, owner=3DNone)\n' '\n' ' Called to get the attribute of the owner class (class ' 'attribute\n' ' access) or of an instance of that class (instance ' 'attribute\n' - ' access). *owner* is always the owner class, while ' - '*instance* is the\n' - ' instance that the attribute was accessed through, or ' - '"None" when\n' - ' the attribute is accessed through the *owner*. This ' - 'method should\n' - ' return the (computed) attribute value or raise an ' - '"AttributeError"\n' - ' exception.\n' + ' access). The optional *owner* argument is the owner ' + 'class, while\n' + ' *instance* is the instance that the attribute was ' + 'accessed through,\n' + ' or "None" when the attribute is accessed through the ' + '*owner*.\n' + '\n' + ' This method should return the computed attribute value = or ' + 'raise an\n' + ' "AttributeError" exception.\n' + '\n' + ' **PEP 252** specifies that "__get__()" is callable with= ' + 'one or two\n' + ' arguments. Python=E2=80=99s own built-in descriptors s= upport ' + 'this\n' + ' specification; however, it is likely that some ' + 'third-party tools\n' + ' have descriptors that require both arguments. Python= =E2=80=99s ' + 'own\n' + ' "__getattribute__()" implementation always passes in bo= th ' + 'arguments\n' + ' whether they are required or not.\n' '\n' 'object.__set__(self, instance, value)\n' '\n' @@ -8462,6 +8479,12 @@ 'the owner\n' ' class to a new value, *value*.\n' '\n' + ' Note, adding "__set__()" or "__delete__()" changes the ' + 'kind of\n' + ' descriptor to a =E2=80=9Cdata descriptor=E2=80=9D. See= Invoking ' + 'Descriptors for\n' + ' more details.\n' + '\n' 'object.__delete__(self, instance)\n' '\n' ' Called to delete the attribute on an instance *instance= * ' @@ -10030,13 +10053,15 @@ '\n' ' Return true if there are only whitespace characters i= n ' 'the string\n' - ' and there is at least one character, false otherwise.= ' - 'Whitespace\n' - ' characters are those characters defined in the Unico= de ' - 'character\n' - ' database as =E2=80=9COther=E2=80=9D or =E2=80=9CSepar= ator=E2=80=9D and those with ' - 'bidirectional\n' - ' property being one of =E2=80=9CWS=E2=80=9D, =E2=80=9C= B=E2=80=9D, or =E2=80=9CS=E2=80=9D.\n' + ' and there is at least one character, false otherwise.= \n' + '\n' + ' A character is *whitespace* if in the Unicode charact= er ' + 'database\n' + ' (see "unicodedata"), either its general category is ' + '"Zs"\n' + ' (=E2=80=9CSeparator, space=E2=80=9D), or its bidirect= ional class is one ' + 'of "WS",\n' + ' "B", or "S".\n' '\n' 'str.istitle()\n' '\n' @@ -10725,13 +10750,9 @@ '\n' ' Changed in version 3.6: Unrecognized escape sequences produc= e ' 'a\n' - ' "DeprecationWarning".\n' - '\n' - ' Changed in version 3.8: Unrecognized escape sequences produc= e ' + ' "DeprecationWarning". In a future Python version they will = be ' 'a\n' - ' "SyntaxWarning". In some future version of Python they will= ' - 'be a\n' - ' "SyntaxError".\n' + ' "SyntaxWarning" and eventually a "SyntaxError".\n' '\n' 'Even in a raw literal, quotes can be escaped with a backslash, ' 'but the\n' diff --git a/Misc/NEWS.d/3.8.0b4.rst b/Misc/NEWS.d/3.8.0b4.rst new file mode 100644 index 000000000000..99c914815e52 --- /dev/null +++ b/Misc/NEWS.d/3.8.0b4.rst @@ -0,0 +1,733 @@ +.. bpo: 34155 +.. date: 2019-05-04-13-33-37 +.. nonce: MJll68 +.. release date: 2019-08-29 +.. section: Security + +Fix parsing of invalid email addresses with more than one ``@`` (e.g. +a at b@c.com.) to not return the part before 2nd ``@`` as valid email address. +Patch by maxking & jpic. + +.. + +.. bpo: 37947 +.. date: 2019-08-26-04-09-57 +.. nonce: mzAQtB +.. section: Core and Builtins + +Adjust correctly the recursion level in the symtable generation for named +expressions. Patch by Pablo Galindo. + +.. + +.. bpo: 37830 +.. date: 2019-08-17-18-41-59 +.. nonce: fNfMbz +.. section: Core and Builtins + +Fixed compilation of :keyword:`break` and :keyword:`continue` in the +:keyword:`finally` block when the corresponding :keyword:`try` block +contains :keyword:`return` with a non-constant value. + +.. + +.. bpo: 32912 +.. date: 2019-08-06-14-03-59 +.. nonce: UDwSMJ +.. section: Core and Builtins + +Reverted :issue:`32912`: emitting :exc:`SyntaxWarning` instead of +:exc:`DeprecationWarning` for invalid escape sequences in string and bytes +literals. + +.. + +.. bpo: 37757 +.. date: 2019-08-05-14-22-59 +.. nonce: lRv5HX +.. section: Core and Builtins + +:pep:`572`: As described in the PEP, assignment expressions now raise +:exc:`SyntaxError` when their interaction with comprehension scoping results +in an ambiguous target scope. + +The ``TargetScopeError`` subclass originally proposed by the PEP has been +removed in favour of just raising regular syntax errors for the disallowed +cases. + +.. + +.. bpo: 36311 +.. date: 2019-08-02-15-01-33 +.. nonce: uY5vt- +.. section: Core and Builtins + +Decoding bytes objects larger than 2GiB is faster and no longer fails when a +multibyte characters spans a chunk boundary. + +.. + +.. bpo: 37433 +.. date: 2019-06-27-15-01-14 +.. nonce: amNGqr +.. section: Core and Builtins + +Fix ``SyntaxError`` indicator printing too many spaces for multi-line +strings - by Anthony Sottile. + +.. + +.. bpo: 20523 +.. date: 2019-02-15-20-42-36 +.. nonce: rRLrvr +.. section: Core and Builtins + +``pdb.Pdb`` supports ~/.pdbrc in Windows 7. Patch by Tim Hopper and Dan +Lidral-Porter. + +.. + +.. bpo: 37834 +.. date: 2019-08-29-16-41-36 +.. nonce: FThnsh +.. section: Library + +Prevent shutil.rmtree exception when built on non-Windows system without fd +system call support, like older versions of macOS. + +.. + +.. bpo: 37965 +.. date: 2019-08-28-14-04-18 +.. nonce: 7xGE-C +.. section: Library + +Fix C compiler warning caused by distutils.ccompiler.CCompiler.has_function. + +.. + +.. bpo: 37960 +.. date: 2019-08-27-10-52-13 +.. nonce: CTY7Lw +.. section: Library + +``repr()`` of buffered and text streams now silences only expected +exceptions when get the value of "name" and "mode" attributes. + +.. + +.. bpo: 37951 +.. date: 2019-08-27-10-03-48 +.. nonce: MfRQgL +.. section: Library + +Most features of the subprocess module now work again in subinterpreters. +Only *preexec_fn* is restricted in subinterpreters. + +.. + +.. bpo: 36205 +.. date: 2019-08-27-03-53-26 +.. nonce: AfkGRl +.. section: Library + +Fix the rusage implementation of time.process_time() to correctly report the +sum of the system and user CPU time. + +.. + +.. bpo: 37950 +.. date: 2019-08-26-10-45-51 +.. nonce: -K1IKT +.. section: Library + +Fix :func:`ast.dump` when call with incompletely initialized node. + +.. + +.. bpo: 34679 +.. date: 2019-08-25-18-07-48 +.. nonce: HECzL7 +.. section: Library + +Restores instantiation of Windows IOCP event loops from the non-main thread. + +.. + +.. bpo: 36917 +.. date: 2019-08-25-14-56-42 +.. nonce: GBxdw2 +.. section: Library + +Add default implementation of the :meth:`ast.NodeVisitor.visit_Constant` +method which emits a deprecation warning and calls corresponding methody +``visit_Num()``, ``visit_Str()``, etc. + +.. + +.. bpo: 37798 +.. date: 2019-08-24-16-54-49 +.. nonce: 7mRQCk +.. section: Library + +Update test_statistics.py to verify that the statistics module works well +for both C and Python implementations. Patch by Dong-hee Na + +.. + +.. bpo: 26589 +.. date: 2019-08-23-00-55-19 +.. nonce: M1xyxG +.. section: Library + +Added a new status code to the http module: 451 +UNAVAILABLE_FOR_LEGAL_REASONS + +.. + +.. bpo: 37915 +.. date: 2019-08-22-16-13-27 +.. nonce: xyoZI5 +.. section: Library + +Fix a segmentation fault that appeared when comparing instances of +``datetime.timezone`` and ``datetime.tzinfo`` objects. Patch by Pablo +Galindo. + +.. + +.. bpo: 37868 +.. date: 2019-08-17-22-33-54 +.. nonce: hp64fi +.. section: Library + +Fix dataclasses.is_dataclass when given an instance that never raises +AttributeError in __getattr__. That is, an object that returns something +for __dataclass_fields__ even if it's not a dataclass. + +.. + +.. bpo: 37811 +.. date: 2019-08-14-21-41-07 +.. nonce: d1xYj7 +.. section: Library + +Fix ``socket`` module's ``socket.connect(address)`` function being unable to +establish connection in case of interrupted system call. The problem was +observed on all OSes which ``poll(2)`` system call can take only +non-negative integers and -1 as a timeout value. + +.. + +.. bpo: 21131 +.. date: 2019-08-14-15-34-23 +.. nonce: 0MMQRi +.. section: Library + +Fix ``faulthandler.register(chain=3DTrue)`` stack. faulthandler now allocates +a dedicated stack of ``SIGSTKSZ*2`` bytes, instead of just ``SIGSTKSZ`` +bytes. Calling the previous signal handler in faulthandler signal handler +uses more than ``SIGSTKSZ`` bytes of stack memory on some platforms. + +.. + +.. bpo: 37798 +.. date: 2019-08-14-13-51-24 +.. nonce: AmXrik +.. section: Library + +Add C fastpath for statistics.NormalDist.inv_cdf() Patch by Dong-hee Na + +.. + +.. bpo: 37819 +.. date: 2019-08-11-10-34-19 +.. nonce: LVJls- +.. section: Library + +Add Fraction.as_integer_ratio() to match the corresponding methods in bool, +int, float, and decimal. + +.. + +.. bpo: 37810 +.. date: 2019-08-10-12-33-27 +.. nonce: d4zbvB +.. section: Library + +Fix :mod:`difflib` ``?`` hint in diff output when dealing with tabs. Patch +by Anthony Sottile. + +.. + +.. bpo: 37772 +.. date: 2019-08-07-23-48-09 +.. nonce: hLCvdn +.. section: Library + +In ``zipfile.Path``, when adding implicit dirs, ensure that ancestral +directories are added and that duplicates are excluded. + +.. + +.. bpo: 28292 +.. date: 2019-08-04-11-47-58 +.. nonce: vkihH5 +.. section: Library + +Mark calendar.py helper functions as being private. The follows PEP 8 +guidance to maintain the style conventions in the module and it addresses a +known case of user confusion. + +.. + +.. bpo: 18049 +.. date: 2019-08-02-16-44-42 +.. nonce: OA4qBL +.. section: Library + +Add definition of THREAD_STACK_SIZE for AIX in Python/thread_pthread.h The +default thread stacksize caused crashes with the default recursion limit +Patch by M Felt + +.. + +.. bpo: 37738 +.. date: 2019-08-01-17-11-16 +.. nonce: A3WWcT +.. section: Library + +Fix the implementation of curses ``addch(str, color_pair)``: pass the color +pair to ``setcchar()``, instead of always passing 0 as the color pair. + +.. + +.. bpo: 37723 +.. date: 2019-07-31-16-49-01 +.. nonce: zq6tw8 +.. section: Library + +Fix performance regression on regular expression parsing with huge character +sets. Patch by Yann Vaginay. + +.. + +.. bpo: 32178 +.. date: 2019-07-30-22-41-05 +.. nonce: X-IFLe +.. section: Library + +Fix IndexError in :mod:`email` package when trying to parse invalid address +fields starting with ``:``. + +.. + +.. bpo: 37685 +.. date: 2019-07-28-22-25-25 +.. nonce: _3bN9f +.. section: Library + +Fixed comparisons of :class:`datetime.timedelta` and +:class:`datetime.timezone`. + +.. + +.. bpo: 37695 +.. date: 2019-07-27-20-21-03 +.. nonce: QANdvg +.. section: Library + +Correct :func:`curses.unget_wch` error message. Patch by Anthony Sottile. + +.. + +.. bpo: 37354 +.. date: 2019-07-25-10-28-40 +.. nonce: RT3_3H +.. section: Library + +Make Activate.ps1 Powershell script static to allow for signing it. + +.. + +.. bpo: 37664 +.. date: 2019-07-24-18-27-44 +.. nonce: o-GYZC +.. section: Library + +Update wheels bundled with ensurepip (pip 19.2.3 and setuptools 41.2.0) + +.. + +.. bpo: 37642 +.. date: 2019-07-21-20-59-31 +.. nonce: L61Bvy +.. section: Library + +Allowed the pure Python implementation of :class:`datetime.timezone` to +represent sub-minute offsets close to minimum and maximum boundaries, +specifically in the ranges (23:59, 24:00) and (-23:59, 24:00). Patch by +Ngalim Siregar + +.. + +.. bpo: 16970 +.. date: 2019-07-19-01-46-56 +.. nonce: GEASf5 +.. section: Library + +Adding a value error when an invalid value in passed to nargs Patch by +Robert Leenders + +.. + +.. bpo: 37587 +.. date: 2019-07-13-16-02-48 +.. nonce: fd-1aF +.. section: Library + +Make json.loads faster for long strings. (Patch by Marco Paolini) + +.. + +.. bpo: 18378 +.. date: 2019-07-13-13-40-12 +.. nonce: NHcojp +.. section: Library + +Recognize "UTF-8" as a valid value for LC_CTYPE in locale._parse_localename. + +.. + +.. bpo: 37531 +.. date: 2019-07-09-19-38-26 +.. nonce: GX7s8S +.. section: Library + +"python3 -m test -jN --timeout=3DTIMEOUT" now kills a worker process if it +runs longer than *TIMEOUT* seconds. + +.. + +.. bpo: 37482 +.. date: 2019-07-09-11-20-21 +.. nonce: auzvev +.. section: Library + +Fix serialization of display name in originator or destination address +fields with both encoded words and special chars. + +.. + +.. bpo: 37372 +.. date: 2019-06-22-12-30-00 +.. nonce: kIKqZ6 +.. section: Library + +Fix error unpickling datetime.time objects from Python 2 with seconds>=3D24. +Patch by Justin Blanchard. + +.. + +.. bpo: 37085 +.. date: 2019-06-18-16-29-31 +.. nonce: GeYaD6 +.. section: Library + +Add the optional Linux SocketCAN Broadcast Manager constants, used as flags +to configure the BCM behaviour, in the socket module. Patch by Karl Ding. + +.. + +.. bpo: 36871 +.. date: 2019-05-12-12-58-37 +.. nonce: 6xiEHZ +.. section: Library + +Ensure method signature is used instead of constructor signature of a class +while asserting mock object against method calls. Patch by Karthikeyan +Singaravelan. + +.. + +.. bpo: 36582 +.. date: 2019-05-07-17-42-36 +.. nonce: L_dxR6 +.. section: Library + +Fix ``UserString.encode()`` to correctly return ``bytes`` rather than a +``UserString`` instance. + +.. + +.. bpo: 34775 +.. date: 2018-09-23-03-18-52 +.. nonce: vHeuHk +.. section: Library + +Division handling of PurePath now returns NotImplemented instead of raising +a TypeError when passed something other than an instance of str or PurePath. +Patch by Roger Aiudi. + +.. + +.. bpo: 37979 +.. date: 2019-08-29-10-40-05 +.. nonce: TAUx_E +.. section: Documentation + +Added a link to dateutil.parser.isoparse in the datetime.fromisoformat +documentation. Patch by Paul Ganssle + +.. + +.. bpo: 37759 +.. date: 2019-08-04-19-20-58 +.. nonce: EHRF4i +.. section: Documentation + +Beginning edits to Whatsnew 3.8 + +.. + +.. bpo: 37726 +.. date: 2019-07-31-11-40-06 +.. nonce: h-3o9a +.. section: Documentation + +Stop recommending getopt in the tutorial for command line argument parsing +and promote argparse. + +.. + +.. bpo: 37256 +.. date: 2019-07-16-14-48-12 +.. nonce: qJTrBb +.. section: Documentation + +Fix wording of arguments for :class:`Request` in :mod:`urllib.request` + +.. + +.. bpo: 37004 +.. date: 2019-05-22-04-30-07 +.. nonce: BRgxrt +.. section: Documentation + +In the documentation for difflib, a note was added explicitly warning that +the results of SequenceMatcher's ratio method may depend on the order of the +input strings. + +.. + +.. bpo: 36487 +.. date: 2019-04-02-19-23-00 +.. nonce: Jg6-MG +.. section: Documentation + +Make C-API docs clear about what the "main" interpreter is. + +.. + +.. bpo: 37805 +.. date: 2019-08-25-19-51-46 +.. nonce: Kl1sti +.. section: Tests + +Add tests for json.dump(..., skipkeys=3DTrue). Patch by Dong-hee Na. + +.. + +.. bpo: 37707 +.. date: 2019-07-29-11-36-16 +.. nonce: Sm-dGk +.. section: Build + +Mark some individual tests to skip when --pgo is used. The tests marked +increase the PGO task time significantly and likely don't help improve +optimization of the final executable. + +.. + +.. bpo: 37549 +.. date: 2019-08-22-09-04-44 +.. nonce: TpKI3M +.. section: Windows + +:func:`os.dup` no longer fails for standard streams on Windows 7. + +.. + +.. bpo: 1311 +.. date: 2019-08-21-12-58-18 +.. nonce: BoW1wU +.. section: Windows + +The ``nul`` file on Windows now returns True from :func:`~os.path.exists` +and a valid result from :func:`os.stat` with ``S_IFCHR`` set. + +.. + +.. bpo: 9949 +.. date: 2019-08-14-13-40-15 +.. nonce: zW45Ks +.. section: Windows + +Enable support for following symlinks in :func:`os.realpath`. + +.. + +.. bpo: 37834 +.. date: 2019-08-12-12-00-24 +.. nonce: VB2QVj +.. section: Windows + +Treat all name surrogate reparse points on Windows in :func:`os.lstat` and +other reparse points as regular files in :func:`os.stat`. + +.. + +.. bpo: 36266 +.. date: 2019-08-08-18-05-27 +.. nonce: x4eZU3 +.. section: Windows + +Add the module name in the formatted error message when DLL load fail +happens during module import in ``_PyImport_FindSharedFuncptrWindows()``. +Patch by Srinivas Nyayapati. + +.. + +.. bpo: 25172 +.. date: 2019-08-06-18-09-18 +.. nonce: Akreij +.. section: Windows + +Trying to import the :mod:`crypt` module on Windows will result in an +:exc:`ImportError` with a message explaining that the module isn't supported +on Windows. On other platforms, if the underlying ``_crypt`` module is not +available, the ImportError will include a message explaining the problem. + +.. + +.. bpo: 37778 +.. date: 2019-08-06-13-54-12 +.. nonce: AY1XhH +.. section: Windows + +Fixes the icons used for file associations to the Microsoft Store package. + +.. + +.. bpo: 37734 +.. date: 2019-08-06-09-35-12 +.. nonce: EoJ9Nh +.. section: Windows + +Fix use of registry values to launch Python from Microsoft Store app. + +.. + +.. bpo: 28269 +.. date: 2019-05-05-05-23-34 +.. nonce: -MOHI7 +.. section: Windows + +Replace use of :c:func:`strcasecmp` for the system function +:c:func:`_stricmp`. Patch by Minmin Gong. + +.. + +.. bpo: 18049 +.. date: 2019-07-13-15-58-18 +.. nonce: MklhQQ +.. section: macOS + +Increase the default stack size of threads from 5MB to 16MB on macOS, to +match the stack size of the main thread. This avoids crashes on deep +recursion in threads. + +.. + +.. bpo: 37824 +.. date: 2019-08-26-00-41-53 +.. nonce: YY5jAI +.. section: IDLE + +Properly handle user input warnings in IDLE shell. Cease turning +SyntaxWarnings into SyntaxErrors. + +.. + +.. bpo: 37929 +.. date: 2019-08-24-22-00-33 +.. nonce: jb7523 +.. section: IDLE + +IDLE Settings dialog now closes properly when there is no shell window. + +.. + +.. bpo: 37849 +.. date: 2019-08-14-09-43-15 +.. nonce: -bcYF3 +.. section: IDLE + +Fixed completions list appearing too high or low when shown above the +current line. + +.. + +.. bpo: 36419 +.. date: 2019-08-04-17-10-01 +.. nonce: TJZqOc +.. section: IDLE + +Refactor IDLE autocomplete and improve testing. + +.. + +.. bpo: 37748 +.. date: 2019-08-04-15-27-50 +.. nonce: 0vf6pg +.. section: IDLE + +Reorder the Run menu. Put the most common choice, Run Module, at the top. + +.. + +.. bpo: 37942 +.. date: 2019-08-24-12-11-30 +.. nonce: 7H8N9a +.. section: Tools/Demos + +Improve ArgumentClinic converter for floats. + +.. + +.. bpo: 37034 +.. date: 2019-05-27-16-13-08 +.. nonce: zbTgy8 +.. section: Tools/Demos + +Argument Clinic now uses the argument name on errors with keyword-only +argument instead of their position. Patch contributed by R=C3=A9mi Lapeyre. + +.. + +.. bpo: 36763 +.. date: 2019-08-23-18-45-11 +.. nonce: q3Kh8Z +.. section: C API + +Options added by ``PySys_AddXOption()`` are now handled the same way than +``PyConfig.xoptions`` and command line ``-X`` options. + +.. + +.. bpo: 37926 +.. date: 2019-08-23-11-35-55 +.. nonce: hnI5IQ +.. section: C API + +Fix a crash in ``PySys_SetArgvEx(0, NULL, 0)``. diff --git a/Misc/NEWS.d/next/Build/2019-07-29-11-36-16.bpo-37707.Sm-dGk.rst = b/Misc/NEWS.d/next/Build/2019-07-29-11-36-16.bpo-37707.Sm-dGk.rst deleted file mode 100644 index c0d58ab747b2..000000000000 --- a/Misc/NEWS.d/next/Build/2019-07-29-11-36-16.bpo-37707.Sm-dGk.rst +++ /dev/null @@ -1,3 +0,0 @@ -Mark some individual tests to skip when --pgo is used. The tests marked -increase the PGO task time significantly and likely don't help improve -optimization of the final executable. diff --git a/Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst = b/Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst deleted file mode 100644 index 20185330a8f4..000000000000 --- a/Misc/NEWS.d/next/C API/2019-08-23-11-35-55.bpo-37926.hnI5IQ.rst=09 +++ /dev/null @@ -1 +0,0 @@ -Fix a crash in ``PySys_SetArgvEx(0, NULL, 0)``. diff --git a/Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst = b/Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst deleted file mode 100644 index 500cdbf34117..000000000000 --- a/Misc/NEWS.d/next/C API/2019-08-23-18-45-11.bpo-36763.q3Kh8Z.rst=09 +++ /dev/null @@ -1,2 +0,0 @@ -Options added by ``PySys_AddXOption()`` are now handled the same way than -``PyConfig.xoptions`` and command line ``-X`` options. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523= .rRLrvr.rst b/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-2052= 3.rRLrvr.rst deleted file mode 100644 index 91397c243b9f..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-02-15-20-42-36.bpo-20523.rRLrvr= .rst=09 +++ /dev/null @@ -1,2 +0,0 @@ -``pdb.Pdb`` supports ~/.pdbrc in Windows 7. Patch by Tim Hopper and Dan=20 -Lidral-Porter. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-06-27-15-01-14.bpo-37433= .amNGqr.rst b/Misc/NEWS.d/next/Core and Builtins/2019-06-27-15-01-14.bpo-3743= 3.amNGqr.rst deleted file mode 100644 index 794ddbbfec73..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-06-27-15-01-14.bpo-37433.amNGqr= .rst=09 +++ /dev/null @@ -1 +0,0 @@ -Fix ``SyntaxError`` indicator printing too many spaces for multi-line string= s - by Anthony Sottile. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311= .uY5vt-.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-3631= 1.uY5vt-.rst deleted file mode 100644 index c45f2224237b..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-08-02-15-01-33.bpo-36311.uY5vt-= .rst=09 +++ /dev/null @@ -1,2 +0,0 @@ -Decoding bytes objects larger than 2GiB is faster and no longer fails when a -multibyte characters spans a chunk boundary. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757= .lRv5HX.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-3775= 7.lRv5HX.rst deleted file mode 100644 index 258df0dc09bd..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-08-05-14-22-59.bpo-37757.lRv5HX= .rst=09 +++ /dev/null @@ -1,7 +0,0 @@ -:pep:`572`: As described in the PEP, assignment expressions now raise -:exc:`SyntaxError` when their interaction with comprehension scoping results -in an ambiguous target scope. - -The ``TargetScopeError`` subclass originally proposed by the PEP has been -removed in favour of just raising regular syntax errors for the disallowed -cases. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912= .UDwSMJ.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-3291= 2.UDwSMJ.rst deleted file mode 100644 index e18d8adfbee9..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-08-06-14-03-59.bpo-32912.UDwSMJ= .rst=09 +++ /dev/null @@ -1,3 +0,0 @@ -Reverted :issue:`32912`: emitting :exc:`SyntaxWarning` instead of -:exc:`DeprecationWarning` for invalid escape sequences in string and bytes -literals. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830= .fNfMbz.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-3783= 0.fNfMbz.rst deleted file mode 100644 index 76f4bf671d1c..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-08-17-18-41-59.bpo-37830.fNfMbz= .rst=09 +++ /dev/null @@ -1,3 +0,0 @@ -Fixed compilation of :keyword:`break` and :keyword:`continue` in the -:keyword:`finally` block when the corresponding :keyword:`try` block -contains :keyword:`return` with a non-constant value. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947= .mzAQtB.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-3794= 7.mzAQtB.rst deleted file mode 100644 index 2b3b72367030..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-08-26-04-09-57.bpo-37947.mzAQtB= .rst=09 +++ /dev/null @@ -1,2 +0,0 @@ -Adjust correctly the recursion level in the symtable generation for named -expressions. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6= -MG.rst b/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG= .rst deleted file mode 100755 index c8eb05b6c79c..000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-04-02-19-23-00.bpo-36487.Jg6-MG.rst +++ /dev/null @@ -1 +0,0 @@ -Make C-API docs clear about what the "main" interpreter is. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRg= xrt.rst b/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt= .rst deleted file mode 100644 index dfc8b7ed74ca..000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-05-22-04-30-07.bpo-37004.BRgxrt.rst +++ /dev/null @@ -1 +0,0 @@ -In the documentation for difflib, a note was added explicitly warning that t= he results of SequenceMatcher's ratio method may depend on the order of the i= nput strings. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJT= rBb.rst b/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb= .rst deleted file mode 100644 index 480d7c87ebc4..000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-07-16-14-48-12.bpo-37256.qJTrBb.rst +++ /dev/null @@ -1 +0,0 @@ -Fix wording of arguments for :class:`Request` in :mod:`urllib.request` diff --git a/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3= o9a.rst b/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a= .rst deleted file mode 100644 index 195e9755a43c..000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-07-31-11-40-06.bpo-37726.h-3o9a.rst +++ /dev/null @@ -1,2 +0,0 @@ -Stop recommending getopt in the tutorial for command line argument parsing -and promote argparse. diff --git a/Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHR= F4i.rst b/Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i= .rst deleted file mode 100644 index 90fb7213ebde..000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-08-04-19-20-58.bpo-37759.EHRF4i.rst +++ /dev/null @@ -1 +0,0 @@ -Beginning edits to Whatsnew 3.8 diff --git a/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAU= x_E.rst b/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E= .rst deleted file mode 100644 index d8d70d613706..000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-08-29-10-40-05.bpo-37979.TAUx_E.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added a link to dateutil.parser.isoparse in the datetime.fromisoformat -documentation. Patch by Paul Ganssle diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst b= /Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst deleted file mode 100644 index fc1d6b6bb357..000000000000 --- a/Misc/NEWS.d/next/IDLE/2019-08-04-15-27-50.bpo-37748.0vf6pg.rst +++ /dev/null @@ -1 +0,0 @@ -Reorder the Run menu. Put the most common choice, Run Module, at the top. diff --git a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst b= /Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst deleted file mode 100644 index 2a5b0bd0e90c..000000000000 --- a/Misc/NEWS.d/next/IDLE/2019-08-04-17-10-01.bpo-36419.TJZqOc.rst +++ /dev/null @@ -1 +0,0 @@ -Refactor IDLE autocomplete and improve testing. diff --git a/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst b= /Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst deleted file mode 100644 index 9f700d9031f1..000000000000 --- a/Misc/NEWS.d/next/IDLE/2019-08-14-09-43-15.bpo-37849.-bcYF3.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed completions list appearing too high or low when shown above -the current line. diff --git a/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst b= /Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst deleted file mode 100644 index d627b2de2a7c..000000000000 --- a/Misc/NEWS.d/next/IDLE/2019-08-24-22-00-33.bpo-37929.jb7523.rst +++ /dev/null @@ -1 +0,0 @@ -IDLE Settings dialog now closes properly when there is no shell window. diff --git a/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst b= /Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst deleted file mode 100644 index 1a1e8a59816a..000000000000 --- a/Misc/NEWS.d/next/IDLE/2019-08-26-00-41-53.bpo-37824.YY5jAI.rst +++ /dev/null @@ -1,2 +0,0 @@ -Properly handle user input warnings in IDLE shell. Cease turning -SyntaxWarnings into SyntaxErrors. diff --git a/Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rs= t b/Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst deleted file mode 100644 index f99bf5b39f95..000000000000 --- a/Misc/NEWS.d/next/Library/2018-09-23-03-18-52.bpo-34775.vHeuHk.rst +++ /dev/null @@ -1,3 +0,0 @@ -Division handling of PurePath now returns NotImplemented instead of raising -a TypeError when passed something other than an instance of str or PurePath. -Patch by Roger Aiudi. diff --git a/Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rs= t b/Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst deleted file mode 100644 index 34f16fcde879..000000000000 --- a/Misc/NEWS.d/next/Library/2019-05-07-17-42-36.bpo-36582.L_dxR6.rst +++ /dev/null @@ -1 +0,0 @@ -Fix ``UserString.encode()`` to correctly return ``bytes`` rather than a ``Us= erString`` instance. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rs= t b/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst deleted file mode 100644 index 218795f203be..000000000000 --- a/Misc/NEWS.d/next/Library/2019-05-12-12-58-37.bpo-36871.6xiEHZ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Ensure method signature is used instead of constructor signature of a class -while asserting mock object against method calls. Patch by Karthikeyan -Singaravelan. diff --git a/Misc/NEWS.d/next/Library/2019-06-18-16-29-31.bpo-37085.GeYaD6.rs= t b/Misc/NEWS.d/next/Library/2019-06-18-16-29-31.bpo-37085.GeYaD6.rst deleted file mode 100644 index e8db521d7aba..000000000000 --- a/Misc/NEWS.d/next/Library/2019-06-18-16-29-31.bpo-37085.GeYaD6.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add the optional Linux SocketCAN Broadcast Manager constants, used as flags -to configure the BCM behaviour, in the socket module. Patch by Karl Ding. diff --git a/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rs= t b/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst deleted file mode 100644 index b958d8fed40a..000000000000 --- a/Misc/NEWS.d/next/Library/2019-06-22-12-30-00.bpo-37372.kIKqZ6.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix error unpickling datetime.time objects from Python 2 with seconds>=3D24. -Patch by Justin Blanchard. diff --git a/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rs= t b/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst deleted file mode 100644 index e09ff63eedc4..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst +++ /dev/null @@ -1 +0,0 @@ -Fix serialization of display name in originator or destination address field= s with both encoded words and special chars. diff --git a/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rs= t b/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst deleted file mode 100644 index aaf1052bd3c1..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-09-19-38-26.bpo-37531.GX7s8S.rst +++ /dev/null @@ -1,2 +0,0 @@ -"python3 -m test -jN --timeout=3DTIMEOUT" now kills a worker process if it r= uns -longer than *TIMEOUT* seconds. diff --git a/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rs= t b/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst deleted file mode 100644 index 6dda8abf15d5..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-13-13-40-12.bpo-18378.NHcojp.rst +++ /dev/null @@ -1 +0,0 @@ -Recognize "UTF-8" as a valid value for LC_CTYPE in locale._parse_localename. diff --git a/Misc/NEWS.d/next/Library/2019-07-13-16-02-48.bpo-37587.fd-1aF.rs= t b/Misc/NEWS.d/next/Library/2019-07-13-16-02-48.bpo-37587.fd-1aF.rst deleted file mode 100644 index 80a89feab0ce..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-13-16-02-48.bpo-37587.fd-1aF.rst +++ /dev/null @@ -1 +0,0 @@ -Make json.loads faster for long strings. (Patch by Marco Paolini) diff --git a/Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rs= t b/Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst deleted file mode 100644 index 7285b8176032..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-19-01-46-56.bpo-16970.GEASf5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Adding a value error when an invalid value in passed to nargs -Patch by Robert Leenders diff --git a/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rs= t b/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst deleted file mode 100644 index 09ff257597e8..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-21-20-59-31.bpo-37642.L61Bvy.rst +++ /dev/null @@ -1,3 +0,0 @@ -Allowed the pure Python implementation of :class:`datetime.timezone` to repr= esent -sub-minute offsets close to minimum and maximum boundaries, specifically in = the -ranges (23:59, 24:00) and (-23:59, 24:00). Patch by Ngalim Siregar diff --git a/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rs= t b/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst deleted file mode 100644 index f12590540eb7..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-24-18-27-44.bpo-37664.o-GYZC.rst +++ /dev/null @@ -1 +0,0 @@ -Update wheels bundled with ensurepip (pip 19.2.3 and setuptools 41.2.0) diff --git a/Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rs= t b/Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst deleted file mode 100644 index a314bcc9bf90..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-25-10-28-40.bpo-37354.RT3_3H.rst +++ /dev/null @@ -1 +0,0 @@ -Make Activate.ps1 Powershell script static to allow for signing it. diff --git a/Misc/NEWS.d/next/Library/2019-07-27-20-21-03.bpo-37695.QANdvg.rs= t b/Misc/NEWS.d/next/Library/2019-07-27-20-21-03.bpo-37695.QANdvg.rst deleted file mode 100644 index ca6c11641ed6..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-27-20-21-03.bpo-37695.QANdvg.rst +++ /dev/null @@ -1 +0,0 @@ -Correct :func:`curses.unget_wch` error message. Patch by Anthony Sottile. diff --git a/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rs= t b/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst deleted file mode 100644 index ba60057e6fb6..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-28-22-25-25.bpo-37685._3bN9f.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed comparisons of :class:`datetime.timedelta` and -:class:`datetime.timezone`. diff --git a/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rs= t b/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst deleted file mode 100644 index 5e7a2e964d93..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-30-22-41-05.bpo-32178.X-IFLe.rst +++ /dev/null @@ -1 +0,0 @@ -Fix IndexError in :mod:`email` package when trying to parse invalid address = fields starting with ``:``. diff --git a/Misc/NEWS.d/next/Library/2019-07-31-16-49-01.bpo-37723.zq6tw8.rs= t b/Misc/NEWS.d/next/Library/2019-07-31-16-49-01.bpo-37723.zq6tw8.rst deleted file mode 100644 index 65507bd0dc91..000000000000 --- a/Misc/NEWS.d/next/Library/2019-07-31-16-49-01.bpo-37723.zq6tw8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix performance regression on regular expression parsing with huge -character sets. Patch by Yann Vaginay. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rs= t b/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst deleted file mode 100644 index 7e70a9c2231a..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-01-17-11-16.bpo-37738.A3WWcT.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix the implementation of curses ``addch(str, color_pair)``: pass the color -pair to ``setcchar()``, instead of always passing 0 as the color pair. diff --git a/Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rs= t b/Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst deleted file mode 100644 index 36a4de384cc0..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-02-16-44-42.bpo-18049.OA4qBL.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add definition of THREAD_STACK_SIZE for AIX in Python/thread_pthread.h -The default thread stacksize caused crashes with the default recursion limit -Patch by M Felt diff --git a/Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rs= t b/Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst deleted file mode 100644 index 478a1b03c195..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-04-11-47-58.bpo-28292.vkihH5.rst +++ /dev/null @@ -1,3 +0,0 @@ -Mark calendar.py helper functions as being private. The follows PEP 8 -guidance to maintain the style conventions in the module and it addresses a -known case of user confusion. diff --git a/Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rs= t b/Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst deleted file mode 100644 index f9ec6a33b07b..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-07-23-48-09.bpo-37772.hLCvdn.rst +++ /dev/null @@ -1 +0,0 @@ -In ``zipfile.Path``, when adding implicit dirs, ensure that ancestral direct= ories are added and that duplicates are excluded. diff --git a/Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rs= t b/Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst deleted file mode 100644 index 3e0b31775d07..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-10-12-33-27.bpo-37810.d4zbvB.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :mod:`difflib` ``?`` hint in diff output when dealing with tabs. Patch -by Anthony Sottile. diff --git a/Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rs= t b/Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst deleted file mode 100644 index cfc1f1afb4f7..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-11-10-34-19.bpo-37819.LVJls-.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add Fraction.as_integer_ratio() to match the corresponding methods in bool, -int, float, and decimal. diff --git a/Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rs= t b/Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst deleted file mode 100644 index 620f0ecdf41a..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-14-13-51-24.bpo-37798.AmXrik.rst +++ /dev/null @@ -1 +0,0 @@ -Add C fastpath for statistics.NormalDist.inv_cdf() Patch by Dong-hee Na diff --git a/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rs= t b/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst deleted file mode 100644 index d330aca1c17d..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-14-15-34-23.bpo-21131.0MMQRi.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix ``faulthandler.register(chain=3DTrue)`` stack. faulthandler now allocate= s a -dedicated stack of ``SIGSTKSZ*2`` bytes, instead of just ``SIGSTKSZ`` bytes. -Calling the previous signal handler in faulthandler signal handler uses more -than ``SIGSTKSZ`` bytes of stack memory on some platforms. diff --git a/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rs= t b/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst deleted file mode 100644 index 662e7dc41005..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-14-21-41-07.bpo-37811.d1xYj7.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix ``socket`` module's ``socket.connect(address)`` function being unable to -establish connection in case of interrupted system call. The problem was -observed on all OSes which ``poll(2)`` system call can take only -non-negative integers and -1 as a timeout value. diff --git a/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rs= t b/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst deleted file mode 100644 index 7f342e1ee354..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-17-22-33-54.bpo-37868.hp64fi.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix dataclasses.is_dataclass when given an instance that never raises -AttributeError in __getattr__. That is, an object that returns something -for __dataclass_fields__ even if it's not a dataclass. diff --git a/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rs= t b/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst deleted file mode 100644 index 1dc9ea4b8cf8..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-22-16-13-27.bpo-37915.xyoZI5.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a segmentation fault that appeared when comparing instances of -``datetime.timezone`` and ``datetime.tzinfo`` objects. Patch by Pablo -Galindo. diff --git a/Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rs= t b/Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst deleted file mode 100644 index ef132dcceb2c..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-23-00-55-19.bpo-26589.M1xyxG.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added a new status code to the http module: 451 -UNAVAILABLE_FOR_LEGAL_REASONS diff --git a/Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rs= t b/Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst deleted file mode 100644 index 25cfa0047886..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-24-16-54-49.bpo-37798.7mRQCk.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update test_statistics.py to verify that the statistics module works well -for both C and Python implementations. Patch by Dong-hee Na diff --git a/Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rs= t b/Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst deleted file mode 100644 index 3509a7530b89..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-25-14-56-42.bpo-36917.GBxdw2.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add default implementation of the :meth:`ast.NodeVisitor.visit_Constant` -method which emits a deprecation warning and calls corresponding methody -``visit_Num()``, ``visit_Str()``, etc. diff --git a/Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rs= t b/Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst deleted file mode 100644 index 785b06b6482c..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-25-18-07-48.bpo-34679.HECzL7.rst +++ /dev/null @@ -1 +0,0 @@ -Restores instantiation of Windows IOCP event loops from the non-main thread. diff --git a/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rs= t b/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst deleted file mode 100644 index ded80d3b00ef..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-26-10-45-51.bpo-37950.-K1IKT.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :func:`ast.dump` when call with incompletely initialized node. diff --git a/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rs= t b/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst deleted file mode 100644 index 50cda34fbbd3..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-27-03-53-26.bpo-36205.AfkGRl.rst +++ /dev/null @@ -1 +0,0 @@ -Fix the rusage implementation of time.process_time() to correctly report the= sum of the system and user CPU time. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rs= t b/Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst deleted file mode 100644 index 18e4c620bdea..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-27-10-03-48.bpo-37951.MfRQgL.rst +++ /dev/null @@ -1,2 +0,0 @@ -Most features of the subprocess module now work again in subinterpreters. -Only *preexec_fn* is restricted in subinterpreters. diff --git a/Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rs= t b/Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst deleted file mode 100644 index 421cfb9c38e1..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-27-10-52-13.bpo-37960.CTY7Lw.rst +++ /dev/null @@ -1,2 +0,0 @@ -``repr()`` of buffered and text streams now silences only expected -exceptions when get the value of "name" and "mode" attributes. diff --git a/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rs= t b/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst deleted file mode 100644 index 116a9e49dccc..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-28-14-04-18.bpo-37965.7xGE-C.rst +++ /dev/null @@ -1 +0,0 @@ -Fix C compiler warning caused by distutils.ccompiler.CCompiler.has_function. diff --git a/Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rs= t b/Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rst deleted file mode 100644 index afbbb3313a5b..000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-29-16-41-36.bpo-37834.FThnsh.rst +++ /dev/null @@ -1,2 +0,0 @@ -Prevent shutil.rmtree exception when built on non-Windows system without fd -system call support, like older versions of macOS. diff --git a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.r= st b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst deleted file mode 100644 index 50292e29ed1d..000000000000 --- a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst +++ /dev/null @@ -1 +0,0 @@ -Fix parsing of invalid email addresses with more than one ``@`` (e.g. a at b@c.= com.) to not return the part before 2nd ``@`` as valid email address. Patch b= y maxking & jpic. diff --git a/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst = b/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst deleted file mode 100644 index 478c38c3d4c5..000000000000 --- a/Misc/NEWS.d/next/Tests/2019-08-25-19-51-46.bpo-37805.Kl1sti.rst +++ /dev/null @@ -1 +0,0 @@ -Add tests for json.dump(..., skipkeys=3DTrue). Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy= 8.rst b/Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst deleted file mode 100644 index 3457789635b4..000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2019-05-27-16-13-08.bpo-37034.zbTgy8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Argument Clinic now uses the argument name on errors with keyword-only -argument instead of their position. Patch contributed by R=C3=A9mi Lapeyre. diff --git a/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9= a.rst b/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst deleted file mode 100644 index 6f6431409554..000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst +++ /dev/null @@ -1 +0,0 @@ -Improve ArgumentClinic converter for floats. diff --git a/Misc/NEWS.d/next/Windows/2019-05-05-05-23-34.bpo-28269.-MOHI7.rs= t b/Misc/NEWS.d/next/Windows/2019-05-05-05-23-34.bpo-28269.-MOHI7.rst deleted file mode 100644 index a531b98118a2..000000000000 --- a/Misc/NEWS.d/next/Windows/2019-05-05-05-23-34.bpo-28269.-MOHI7.rst +++ /dev/null @@ -1 +0,0 @@ -Replace use of :c:func:`strcasecmp` for the system function :c:func:`_stricm= p`. Patch by Minmin Gong. diff --git a/Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rs= t b/Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst deleted file mode 100644 index 51feecb076ba..000000000000 --- a/Misc/NEWS.d/next/Windows/2019-08-06-09-35-12.bpo-37734.EoJ9Nh.rst +++ /dev/null @@ -1 +0,0 @@ -Fix use of registry values to launch Python from Microsoft Store app. diff --git a/Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rs= t b/Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst deleted file mode 100644 index 14d81c05ee84..000000000000 --- a/Misc/NEWS.d/next/Windows/2019-08-06-13-54-12.bpo-37778.AY1XhH.rst +++ /dev/null @@ -1 +0,0 @@ -Fixes the icons used for file associations to the Microsoft Store package. diff --git a/Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rs= t b/Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst deleted file mode 100644 index 47106d887921..000000000000 --- a/Misc/NEWS.d/next/Windows/2019-08-06-18-09-18.bpo-25172.Akreij.rst +++ /dev/null @@ -1 +0,0 @@ -Trying to import the :mod:`crypt` module on Windows will result in an :exc:`= ImportError` with a message explaining that the module isn't supported on Win= dows. On other platforms, if the underlying ``_crypt`` module is not availabl= e, the ImportError will include a message explaining the problem. diff --git a/Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rs= t b/Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst deleted file mode 100644 index 86fdd6fe17f4..000000000000 --- a/Misc/NEWS.d/next/Windows/2019-08-08-18-05-27.bpo-36266.x4eZU3.rst +++ /dev/null @@ -1 +0,0 @@ -Add the module name in the formatted error message when DLL load fail happen= s during module import in ``_PyImport_FindSharedFuncptrWindows()``. Patch by = Srinivas Nyayapati. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rs= t b/Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst deleted file mode 100644 index f2a654cac911..000000000000 --- a/Misc/NEWS.d/next/Windows/2019-08-12-12-00-24.bpo-37834.VB2QVj.rst +++ /dev/null @@ -1,2 +0,0 @@ -Treat all name surrogate reparse points on Windows in :func:`os.lstat` and -other reparse points as regular files in :func:`os.stat`. diff --git a/Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst= b/Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst deleted file mode 100644 index e42169a927c7..000000000000 --- a/Misc/NEWS.d/next/Windows/2019-08-14-13-40-15.bpo-9949.zW45Ks.rst +++ /dev/null @@ -1 +0,0 @@ -Enable support for following symlinks in :func:`os.realpath`. diff --git a/Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst= b/Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst deleted file mode 100644 index 2ee98e450fae..000000000000 --- a/Misc/NEWS.d/next/Windows/2019-08-21-12-58-18.bpo-1311.BoW1wU.rst +++ /dev/null @@ -1,2 +0,0 @@ -The ``nul`` file on Windows now returns True from :func:`~os.path.exists` -and a valid result from :func:`os.stat` with ``S_IFCHR`` set. diff --git a/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rs= t b/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst deleted file mode 100644 index 5345da80781d..000000000000 --- a/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`os.dup` no longer fails for standard streams on Windows 7. diff --git a/Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst = b/Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst deleted file mode 100644 index 5af07cdb4119..000000000000 --- a/Misc/NEWS.d/next/macOS/2019-07-13-15-58-18.bpo-18049.MklhQQ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Increase the default stack size of threads from 5MB to 16MB on macOS, to -match the stack size of the main thread. This avoids crashes on deep recursi= on -in threads. diff --git a/README.rst b/README.rst index 12ecdf67ed1c..52c79d567703 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.8.0 beta 3 +This is Python version 3.8.0 beta 4 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 .. image:: https://travis-ci.org/python/cpython.svg?branch=3Dmaster